Merge lp:~camptocamp/openerp-product-attributes/6.1-backport-lot-custom-attributes-lep into lp:~product-core-editors/openerp-product-attributes/6.1
- 6.1-backport-lot-custom-attributes-lep
- Merge into 6.1
Status: | Merged |
---|---|
Merged at revision: | 195 |
Proposed branch: | lp:~camptocamp/openerp-product-attributes/6.1-backport-lot-custom-attributes-lep |
Merge into: | lp:~product-core-editors/openerp-product-attributes/6.1 |
Diff against target: |
2143 lines (+2048/-0) 18 files modified
base_custom_attributes/__init__.py (+29/-0) base_custom_attributes/__openerp__.py (+48/-0) base_custom_attributes/custom_attributes.py (+440/-0) base_custom_attributes/custom_attributes_view.xml (+312/-0) base_custom_attributes/i18n/base_custom_attributes.pot (+291/-0) base_custom_attributes/i18n/fr.po (+291/-0) base_custom_attributes/ir_model.py (+39/-0) base_custom_attributes/security/attribute_security.xml (+11/-0) base_custom_attributes/security/ir.model.access.csv (+13/-0) production_lot_custom_attributes/__init__.py (+25/-0) production_lot_custom_attributes/__openerp__.py (+62/-0) production_lot_custom_attributes/custom_attributes_view.xml (+58/-0) production_lot_custom_attributes/lot.py (+207/-0) production_lot_custom_attributes/lot_view.xml (+52/-0) production_lot_custom_attributes/test/lot_attribute_test.yml (+48/-0) production_lot_custom_attributes/wizard/__init__.py (+25/-0) production_lot_custom_attributes/wizard/open_lot_by_attribute_set.py (+67/-0) production_lot_custom_attributes/wizard/open_lot_by_attribute_set.xml (+30/-0) |
To merge this branch: | bzr merge lp:~camptocamp/openerp-product-attributes/6.1-backport-lot-custom-attributes-lep |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Omar (Pexego) | code review, no test | Approve | |
Review via email: mp+196538@code.launchpad.net |
Commit message
[mrg] new modules: base_custom_
Description of the change
This is to backport the modules base_custom_
I added some docstrings and comments that should make creating a new similar module easier.
Warning: in v7.0 the module product_
Thanks to Akretion for the original modules this is based on.
Omar (Pexego) (omar7r) wrote : | # |
- 200. By Leonardo Pistone
-
[imp] production_
lot_custom_ attributes: refactor wizard
Leonardo Pistone (lepistone) wrote : | # |
Thanks Omar.
I improved the code of the wizard in a similar fashion to the corresponding 7.0 branch.
L
- 201. By Leonardo Pistone
-
[fix] typo lenght -> length. yaml test now passes
- 202. By Leonardo Pistone
-
[add] method to search in all serialized fields
- 203. By Leonardo Pistone
-
[FIX] prevent KeyError if no 'attribute_ids' is present in 'vals'
Preview Diff
1 | === added directory 'base_custom_attributes' | |||
2 | === added file 'base_custom_attributes/__init__.py' | |||
3 | --- base_custom_attributes/__init__.py 1970-01-01 00:00:00 +0000 | |||
4 | +++ base_custom_attributes/__init__.py 2013-12-11 14:54:36 +0000 | |||
5 | @@ -0,0 +1,29 @@ | |||
6 | 1 | # -*- encoding: utf-8 -*- | ||
7 | 2 | ############################################################################### | ||
8 | 3 | # # | ||
9 | 4 | # product_custom_attributes for OpenERP # | ||
10 | 5 | # Copyright (C) 2011 Akretion Benoît GUILLOT <benoit.guillot@akretion.com> # | ||
11 | 6 | # # | ||
12 | 7 | # This program is free software: you can redistribute it and/or modify # | ||
13 | 8 | # it under the terms of the GNU Affero General Public License as # | ||
14 | 9 | # published by the Free Software Foundation, either version 3 of the # | ||
15 | 10 | # License, or (at your option) any later version. # | ||
16 | 11 | # # | ||
17 | 12 | # This program is distributed in the hope that it will be useful, # | ||
18 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | ||
19 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | ||
20 | 15 | # GNU Affero General Public License for more details. # | ||
21 | 16 | # # | ||
22 | 17 | # You should have received a copy of the GNU Affero General Public License # | ||
23 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | ||
24 | 19 | # # | ||
25 | 20 | ############################################################################### | ||
26 | 21 | |||
27 | 22 | |||
28 | 23 | |||
29 | 24 | import ir_model | ||
30 | 25 | import custom_attributes | ||
31 | 26 | |||
32 | 27 | |||
33 | 28 | |||
34 | 29 | |||
35 | 0 | 30 | ||
36 | === added file 'base_custom_attributes/__openerp__.py' | |||
37 | --- base_custom_attributes/__openerp__.py 1970-01-01 00:00:00 +0000 | |||
38 | +++ base_custom_attributes/__openerp__.py 2013-12-11 14:54:36 +0000 | |||
39 | @@ -0,0 +1,48 @@ | |||
40 | 1 | # -*- encoding: utf-8 -*- | ||
41 | 2 | ############################################################################### | ||
42 | 3 | # # | ||
43 | 4 | # base_custom_attributes for OpenERP # | ||
44 | 5 | # Copyright (C) 2011 Akretion Benoît GUILLOT <benoit.guillot@akretion.com> # | ||
45 | 6 | # # | ||
46 | 7 | # This program is free software: you can redistribute it and/or modify # | ||
47 | 8 | # it under the terms of the GNU Affero General Public License as # | ||
48 | 9 | # published by the Free Software Foundation, either version 3 of the # | ||
49 | 10 | # License, or (at your option) any later version. # | ||
50 | 11 | # # | ||
51 | 12 | # This program is distributed in the hope that it will be useful, # | ||
52 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | ||
53 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | ||
54 | 15 | # GNU Affero General Public License for more details. # | ||
55 | 16 | # # | ||
56 | 17 | # You should have received a copy of the GNU Affero General Public License # | ||
57 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | ||
58 | 19 | # # | ||
59 | 20 | ############################################################################### | ||
60 | 21 | |||
61 | 22 | |||
62 | 23 | |||
63 | 24 | { | ||
64 | 25 | 'name': 'base_custom_attributes', | ||
65 | 26 | 'version': '0.1', | ||
66 | 27 | 'category': 'Generic Modules/Others', | ||
67 | 28 | 'license': 'AGPL-3', | ||
68 | 29 | 'description': """This module adds the possibility to easily create custom attributes in any OpenERP business object. See the product_custom_attributes module for instance. | ||
69 | 30 | """, | ||
70 | 31 | 'author': 'Akretion', | ||
71 | 32 | 'website': 'http://www.akretion.com/', | ||
72 | 33 | 'depends': ['base'], | ||
73 | 34 | 'init_xml': [], | ||
74 | 35 | 'update_xml': [ | ||
75 | 36 | 'security/ir.model.access.csv', | ||
76 | 37 | 'security/attribute_security.xml', | ||
77 | 38 | 'custom_attributes_view.xml', | ||
78 | 39 | ], | ||
79 | 40 | 'demo_xml': [], | ||
80 | 41 | 'installable': True, | ||
81 | 42 | 'active': False, | ||
82 | 43 | 'external_dependencies' : { | ||
83 | 44 | 'python' : ['unidecode'], | ||
84 | 45 | } | ||
85 | 46 | |||
86 | 47 | } | ||
87 | 48 | |||
88 | 0 | 49 | ||
89 | === added file 'base_custom_attributes/custom_attributes.py' | |||
90 | --- base_custom_attributes/custom_attributes.py 1970-01-01 00:00:00 +0000 | |||
91 | +++ base_custom_attributes/custom_attributes.py 2013-12-11 14:54:36 +0000 | |||
92 | @@ -0,0 +1,440 @@ | |||
93 | 1 | # -*- encoding: utf-8 -*- | ||
94 | 2 | ############################################################################### | ||
95 | 3 | # # | ||
96 | 4 | # base_attribute.attributes for OpenERP # | ||
97 | 5 | # Copyright (C) 2011 Akretion Benoît GUILLOT <benoit.guillot@akretion.com> | ||
98 | 6 | # Copyright (C) 2013 Akretion Raphaël VALYI <raphael.valyi@akretion.com> | ||
99 | 7 | # # | ||
100 | 8 | # This program is free software: you can redistribute it and/or modify # | ||
101 | 9 | # it under the terms of the GNU Affero General Public License as # | ||
102 | 10 | # published by the Free Software Foundation, either version 3 of the # | ||
103 | 11 | # License, or (at your option) any later version. # | ||
104 | 12 | # # | ||
105 | 13 | # This program is distributed in the hope that it will be useful, # | ||
106 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | ||
107 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | ||
108 | 16 | # GNU Affero General Public License for more details. # | ||
109 | 17 | # # | ||
110 | 18 | # You should have received a copy of the GNU Affero General Public License # | ||
111 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | ||
112 | 20 | # # | ||
113 | 21 | ############################################################################### | ||
114 | 22 | |||
115 | 23 | import ast | ||
116 | 24 | from openerp.osv import orm, fields | ||
117 | 25 | from openerp.osv.osv import except_osv | ||
118 | 26 | from openerp.tools.translate import _ | ||
119 | 27 | from lxml import etree | ||
120 | 28 | from unidecode import unidecode # Debian package python-unidecode | ||
121 | 29 | import re | ||
122 | 30 | |||
123 | 31 | |||
124 | 32 | def safe_column_name(string): | ||
125 | 33 | """This function prevent portability problem in database column name | ||
126 | 34 | with other DBMS system | ||
127 | 35 | Use case : if you synchronise attributes with other applications """ | ||
128 | 36 | string = unidecode(string.replace(' ', '_').lower()) | ||
129 | 37 | return re.sub(r'[^0-9a-z_]','', string) | ||
130 | 38 | |||
131 | 39 | |||
132 | 40 | class attribute_option(orm.Model): | ||
133 | 41 | _name = "attribute.option" | ||
134 | 42 | _description = "Attribute Option" | ||
135 | 43 | _order="sequence" | ||
136 | 44 | |||
137 | 45 | def _get_model_list(self, cr, uid, context=None): | ||
138 | 46 | model_pool = self.pool.get('ir.model') | ||
139 | 47 | ids = model_pool.search(cr, uid, [], context=context) | ||
140 | 48 | res = model_pool.read(cr, uid, ids, ['model', 'name'], context=context) | ||
141 | 49 | return [(r['model'], r['name']) for r in res] | ||
142 | 50 | |||
143 | 51 | _columns = { | ||
144 | 52 | 'name': fields.char( | ||
145 | 53 | 'Name', | ||
146 | 54 | size=128, | ||
147 | 55 | translate=True, | ||
148 | 56 | required=True), | ||
149 | 57 | 'value_ref': fields.reference( | ||
150 | 58 | 'Reference', | ||
151 | 59 | selection=_get_model_list, | ||
152 | 60 | size=128), | ||
153 | 61 | 'attribute_id': fields.many2one( | ||
154 | 62 | 'attribute.attribute', | ||
155 | 63 | 'Product Attribute', | ||
156 | 64 | required=True), | ||
157 | 65 | 'sequence': fields.integer('Sequence'), | ||
158 | 66 | } | ||
159 | 67 | |||
160 | 68 | def name_change(self, cr, uid, ids, name, relation_model_id, context=None): | ||
161 | 69 | if relation_model_id: | ||
162 | 70 | warning = {'title': _('Error!'), | ||
163 | 71 | 'message': _("Use the 'Load Options' button " | ||
164 | 72 | "instead to select appropriate " | ||
165 | 73 | "model references'")} | ||
166 | 74 | return {"value": {"name": False}, "warning": warning} | ||
167 | 75 | else: | ||
168 | 76 | return True | ||
169 | 77 | |||
170 | 78 | |||
171 | 79 | class attribute_option_wizard(orm.TransientModel): | ||
172 | 80 | _name = "attribute.option.wizard" | ||
173 | 81 | _rec_name = 'attribute_id' | ||
174 | 82 | |||
175 | 83 | _columns = { | ||
176 | 84 | 'attribute_id': fields.many2one( | ||
177 | 85 | 'attribute.attribute', | ||
178 | 86 | 'Product Attribute', | ||
179 | 87 | required=True), | ||
180 | 88 | } | ||
181 | 89 | |||
182 | 90 | _defaults = { | ||
183 | 91 | 'attribute_id': lambda self, cr, uid, context: | ||
184 | 92 | context.get('attribute_id',False) | ||
185 | 93 | } | ||
186 | 94 | |||
187 | 95 | def validate(self, cr, uid, ids, context=None): | ||
188 | 96 | return True | ||
189 | 97 | |||
190 | 98 | def create(self, cr, uid, vals, context=None): | ||
191 | 99 | attr_obj = self.pool.get("attribute.attribute") | ||
192 | 100 | attr = attr_obj.browse(cr, uid, vals['attribute_id']) | ||
193 | 101 | op_ids = [op.id for op in attr.option_ids] | ||
194 | 102 | opt_obj = self.pool.get("attribute.option") | ||
195 | 103 | opt_obj.unlink(cr, uid, op_ids) | ||
196 | 104 | for op_id in (vals.get("option_ids") and vals['option_ids'][0][2] or []): | ||
197 | 105 | model = attr.relation_model_id.model | ||
198 | 106 | name = self.pool.get(model).name_get(cr, uid, [op_id], context)[0][1] | ||
199 | 107 | opt_obj.create(cr, uid, { | ||
200 | 108 | 'attribute_id': vals['attribute_id'], | ||
201 | 109 | 'name': name, | ||
202 | 110 | 'value_ref': "%s,%s" % (attr.relation_model_id.model, op_id) | ||
203 | 111 | }) | ||
204 | 112 | res = super(attribute_option_wizard, self).create(cr, uid, vals, context) | ||
205 | 113 | return res | ||
206 | 114 | |||
207 | 115 | def fields_view_get(self, cr, uid, view_id=None, view_type='form', | ||
208 | 116 | context=None, toolbar=False, submenu=False): | ||
209 | 117 | res = super(attribute_option_wizard, self).fields_view_get( | ||
210 | 118 | cr, uid, view_id, view_type, context, toolbar, submenu) | ||
211 | 119 | if view_type == 'form' and context and context.get("attribute_id"): | ||
212 | 120 | attr_obj = self.pool.get("attribute.attribute") | ||
213 | 121 | model_id = attr_obj.read(cr, uid, [context.get("attribute_id")], | ||
214 | 122 | ['relation_model_id'])[0]['relation_model_id'][0] | ||
215 | 123 | relation = self.pool.get("ir.model").read(cr, uid, [model_id], | ||
216 | 124 | ["model"])[0]["model"] | ||
217 | 125 | res['fields'].update({'option_ids': { | ||
218 | 126 | 'domain': [], | ||
219 | 127 | 'string': "Options", | ||
220 | 128 | 'type': 'many2many', | ||
221 | 129 | 'relation': relation, | ||
222 | 130 | 'required': True, | ||
223 | 131 | } | ||
224 | 132 | }) | ||
225 | 133 | eview = etree.fromstring(res['arch']) | ||
226 | 134 | options = etree.Element('field', name='option_ids', colspan='6') | ||
227 | 135 | placeholder = eview.xpath("//separator[@string='options_placeholder']")[0] | ||
228 | 136 | placeholder.getparent().replace(placeholder, options) | ||
229 | 137 | res['arch'] = etree.tostring(eview, pretty_print=True) | ||
230 | 138 | return res | ||
231 | 139 | |||
232 | 140 | |||
233 | 141 | class attribute_attribute(orm.Model): | ||
234 | 142 | _name = "attribute.attribute" | ||
235 | 143 | _description = "Attribute" | ||
236 | 144 | _inherits = {'ir.model.fields': 'field_id'} | ||
237 | 145 | |||
238 | 146 | def _build_attribute_field(self, cr, uid, page, attribute, context=None): | ||
239 | 147 | parent = etree.SubElement(page, 'group', colspan="2", col="4") | ||
240 | 148 | kwargs = {'name': "%s" % attribute.name} | ||
241 | 149 | if attribute.ttype in ['many2many', 'text']: | ||
242 | 150 | parent = etree.SubElement(parent, 'group', colspan="2", col="4") | ||
243 | 151 | etree.SubElement(parent, | ||
244 | 152 | 'separator', | ||
245 | 153 | string="%s" % attribute.field_description, | ||
246 | 154 | colspan="4") | ||
247 | 155 | kwargs['nolabel'] = "1" | ||
248 | 156 | if attribute.ttype in ['many2one', 'many2many']: | ||
249 | 157 | if attribute.relation_model_id: | ||
250 | 158 | # attribute.domain is a string, it may be an empty list | ||
251 | 159 | try: | ||
252 | 160 | domain = ast.literal_eval(attribute.domain) | ||
253 | 161 | except ValueError: | ||
254 | 162 | domain = None | ||
255 | 163 | if domain: | ||
256 | 164 | kwargs['domain'] = attribute.domain | ||
257 | 165 | else: | ||
258 | 166 | ids = [op.value_ref.id for op in attribute.option_ids] | ||
259 | 167 | kwargs['domain'] = "[('id', 'in', %s)]" % ids | ||
260 | 168 | else: | ||
261 | 169 | kwargs['domain'] = "[('attribute_id', '=', %s)]" % attribute.attribute_id.id | ||
262 | 170 | kwargs['context'] = "{'default_attribute_id': %s}" % attribute.attribute_id.id | ||
263 | 171 | kwargs['required'] = str(attribute.required or | ||
264 | 172 | attribute.required_on_views) | ||
265 | 173 | field = etree.SubElement(parent, 'field', **kwargs) | ||
266 | 174 | orm.setup_modifiers(field, self.fields_get(cr, uid, attribute.name, | ||
267 | 175 | context)) | ||
268 | 176 | return parent | ||
269 | 177 | |||
270 | 178 | def _build_attributes_notebook(self, cr, uid, attribute_group_ids, | ||
271 | 179 | context=None): | ||
272 | 180 | notebook = etree.Element('notebook', name="attributes_notebook", | ||
273 | 181 | colspan="4") | ||
274 | 182 | toupdate_fields = [] | ||
275 | 183 | grp_obj = self.pool.get('attribute.group') | ||
276 | 184 | for group in grp_obj.browse(cr, uid, attribute_group_ids, | ||
277 | 185 | context=context): | ||
278 | 186 | page = etree.SubElement(notebook, 'page', | ||
279 | 187 | string=group.name.capitalize()) | ||
280 | 188 | for attribute in group.attribute_ids: | ||
281 | 189 | if attribute.name not in toupdate_fields: | ||
282 | 190 | toupdate_fields.append(attribute.name) | ||
283 | 191 | self._build_attribute_field(cr, uid, page, attribute, | ||
284 | 192 | context=context) | ||
285 | 193 | return notebook, toupdate_fields | ||
286 | 194 | |||
287 | 195 | def relation_model_id_change(self, cr, uid, ids, relation_model_id, | ||
288 | 196 | option_ids, context=None): | ||
289 | 197 | "removed selected options as they would be inconsistent" | ||
290 | 198 | return {'value': {'option_ids': [(2, i[1]) for i in option_ids]}} | ||
291 | 199 | |||
292 | 200 | def button_add_options(self, cr, uid, ids, context=None): | ||
293 | 201 | return { | ||
294 | 202 | 'context': "{'attribute_id': %s}" % (ids[0]), | ||
295 | 203 | 'name': _('Options Wizard'), | ||
296 | 204 | 'view_type': 'form', | ||
297 | 205 | 'view_mode': 'form', | ||
298 | 206 | 'res_model': 'attribute.option.wizard', | ||
299 | 207 | 'type': 'ir.actions.act_window', | ||
300 | 208 | 'target': 'new', | ||
301 | 209 | } | ||
302 | 210 | |||
303 | 211 | _columns = { | ||
304 | 212 | 'field_id': fields.many2one( | ||
305 | 213 | 'ir.model.fields', | ||
306 | 214 | 'Ir Model Fields', | ||
307 | 215 | required=True, | ||
308 | 216 | ondelete="cascade"), | ||
309 | 217 | 'attribute_type': fields.selection([ | ||
310 | 218 | ('char', 'Char'), | ||
311 | 219 | ('text', 'Text'), | ||
312 | 220 | ('select', 'Select'), | ||
313 | 221 | ('multiselect', 'Multiselect'), | ||
314 | 222 | ('boolean', 'Boolean'), | ||
315 | 223 | ('integer', 'Integer'), | ||
316 | 224 | ('date', 'Date'), | ||
317 | 225 | ('datetime', 'Datetime'), | ||
318 | 226 | ('binary', 'Binary'), | ||
319 | 227 | ('float', 'Float')], | ||
320 | 228 | 'Type', required=True), | ||
321 | 229 | 'serialized': fields.boolean( | ||
322 | 230 | 'Field serialized', | ||
323 | 231 | help="If serialized, the field will be stocked in the serialized " | ||
324 | 232 | "field: attribute_custom_tmpl or attribute_custom_variant " | ||
325 | 233 | "depending on the field based_on"), | ||
326 | 234 | 'option_ids': fields.one2many( | ||
327 | 235 | 'attribute.option', | ||
328 | 236 | 'attribute_id', | ||
329 | 237 | 'Attribute Options'), | ||
330 | 238 | 'create_date': fields.datetime('Created date', readonly=True), | ||
331 | 239 | 'relation_model_id': fields.many2one( | ||
332 | 240 | 'ir.model', | ||
333 | 241 | 'Model'), | ||
334 | 242 | 'required_on_views': fields.boolean( | ||
335 | 243 | 'Required (on views)', | ||
336 | 244 | help="If activated, the attribute will be mandatory on the views, " | ||
337 | 245 | "but not in the database"), | ||
338 | 246 | } | ||
339 | 247 | |||
340 | 248 | def create(self, cr, uid, vals, context=None): | ||
341 | 249 | if vals.get('relation_model_id'): | ||
342 | 250 | relation = self.pool.get('ir.model').read( | ||
343 | 251 | cr, uid, [vals.get('relation_model_id')], ['model'])[0]['model'] | ||
344 | 252 | else: | ||
345 | 253 | relation = 'attribute.option' | ||
346 | 254 | if vals['attribute_type'] == 'select': | ||
347 | 255 | vals['ttype'] = 'many2one' | ||
348 | 256 | vals['relation'] = relation | ||
349 | 257 | elif vals['attribute_type'] == 'multiselect': | ||
350 | 258 | vals['ttype'] = 'many2many' | ||
351 | 259 | vals['relation'] = relation | ||
352 | 260 | vals['serialized'] = True | ||
353 | 261 | else: | ||
354 | 262 | vals['ttype'] = vals['attribute_type'] | ||
355 | 263 | |||
356 | 264 | if vals.get('serialized'): | ||
357 | 265 | field_obj = self.pool.get('ir.model.fields') | ||
358 | 266 | serialized_ids = field_obj.search(cr, uid, [ | ||
359 | 267 | ('ttype', '=', 'serialized'), | ||
360 | 268 | ('model_id', '=', vals['model_id']), | ||
361 | 269 | ('name', '=', 'x_custom_json_attrs')], | ||
362 | 270 | context=context) | ||
363 | 271 | if serialized_ids: | ||
364 | 272 | vals['serialization_field_id'] = serialized_ids[0] | ||
365 | 273 | else: | ||
366 | 274 | f_vals = { | ||
367 | 275 | 'name': u'x_custom_json_attrs', | ||
368 | 276 | 'field_description': u'Serialized JSON Attributes', | ||
369 | 277 | 'ttype': 'serialized', | ||
370 | 278 | 'model_id': vals['model_id'], | ||
371 | 279 | } | ||
372 | 280 | vals['serialization_field_id'] = field_obj.create( | ||
373 | 281 | cr, uid, f_vals, {'manual': True}) | ||
374 | 282 | vals['state'] = 'manual' | ||
375 | 283 | return super(attribute_attribute, self).create(cr, uid, vals, context) | ||
376 | 284 | |||
377 | 285 | def onchange_field_description(self, cr, uid, ids, field_description, | ||
378 | 286 | name, create_date, context=None): | ||
379 | 287 | name = name or u'x_' | ||
380 | 288 | if field_description and not create_date: | ||
381 | 289 | name = unicode('x_' + safe_column_name(field_description)) | ||
382 | 290 | return {'value': {'name': name}} | ||
383 | 291 | |||
384 | 292 | def onchange_name(self, cr, uid, ids, name, context=None): | ||
385 | 293 | res = {} | ||
386 | 294 | if not name.startswith('x_'): | ||
387 | 295 | name = u'x_%s' % name | ||
388 | 296 | else: | ||
389 | 297 | name = u'%s' % name | ||
390 | 298 | res = {'value': {'name': unidecode(name)}} | ||
391 | 299 | |||
392 | 300 | #FILTER ON MODEL | ||
393 | 301 | model_name = context.get('force_model') | ||
394 | 302 | if not model_name: | ||
395 | 303 | model_id = context.get('default_model_id') | ||
396 | 304 | if model_id: | ||
397 | 305 | model = self.pool['ir.model'].browse(cr, uid, model_id, | ||
398 | 306 | context=context) | ||
399 | 307 | model_name = model.model | ||
400 | 308 | if model_name: | ||
401 | 309 | model_obj = self.pool[model_name] | ||
402 | 310 | allowed_model = [x for x in model_obj._inherits] + [model_name] | ||
403 | 311 | res['domain'] = {'model_id': [['model', 'in', allowed_model]]} | ||
404 | 312 | |||
405 | 313 | return res | ||
406 | 314 | |||
407 | 315 | def _get_default_model(self, cr, uid, context=None): | ||
408 | 316 | if context and context.get('force_model'): | ||
409 | 317 | model_id = self.pool['ir.model'].search(cr, uid, [ | ||
410 | 318 | ('model', '=', context['force_model']) | ||
411 | 319 | ], context=context) | ||
412 | 320 | if model_id: | ||
413 | 321 | return model_id[0] | ||
414 | 322 | return None | ||
415 | 323 | |||
416 | 324 | _defaults = { | ||
417 | 325 | 'model_id': _get_default_model | ||
418 | 326 | } | ||
419 | 327 | |||
420 | 328 | |||
421 | 329 | class attribute_group(orm.Model): | ||
422 | 330 | _name = "attribute.group" | ||
423 | 331 | _description = "Attribute Group" | ||
424 | 332 | _order ="sequence" | ||
425 | 333 | |||
426 | 334 | _columns = { | ||
427 | 335 | 'name': fields.char( | ||
428 | 336 | 'Name', | ||
429 | 337 | size=128, | ||
430 | 338 | required=True, | ||
431 | 339 | translate=True), | ||
432 | 340 | 'sequence': fields.integer('Sequence'), | ||
433 | 341 | 'attribute_set_id': fields.many2one( | ||
434 | 342 | 'attribute.set', | ||
435 | 343 | 'Attribute Set'), | ||
436 | 344 | 'attribute_ids': fields.one2many( | ||
437 | 345 | 'attribute.location', | ||
438 | 346 | 'attribute_group_id', | ||
439 | 347 | 'Attributes'), | ||
440 | 348 | 'model_id': fields.many2one( | ||
441 | 349 | 'ir.model', | ||
442 | 350 | 'Model', | ||
443 | 351 | required=True), | ||
444 | 352 | } | ||
445 | 353 | |||
446 | 354 | def create(self, cr, uid, vals, context=None): | ||
447 | 355 | for attribute in vals.get('attribute_ids', []): | ||
448 | 356 | if (vals.get('attribute_set_id') and attribute[2] and | ||
449 | 357 | not attribute[2].get('attribute_set_id')): | ||
450 | 358 | attribute[2]['attribute_set_id'] = vals['attribute_set_id'] | ||
451 | 359 | return super(attribute_group, self).create(cr, uid, vals, context) | ||
452 | 360 | |||
453 | 361 | def _get_default_model(self, cr, uid, context=None): | ||
454 | 362 | if context and context.get('force_model'): | ||
455 | 363 | model_id = self.pool['ir.model'].search( | ||
456 | 364 | cr, uid, [['model', '=', context['force_model']]], | ||
457 | 365 | context=context) | ||
458 | 366 | if model_id: | ||
459 | 367 | return model_id[0] | ||
460 | 368 | return None | ||
461 | 369 | |||
462 | 370 | _defaults = { | ||
463 | 371 | 'model_id': _get_default_model | ||
464 | 372 | } | ||
465 | 373 | |||
466 | 374 | |||
467 | 375 | class attribute_set(orm.Model): | ||
468 | 376 | _name = "attribute.set" | ||
469 | 377 | _description = "Attribute Set" | ||
470 | 378 | _columns = { | ||
471 | 379 | 'name': fields.char( | ||
472 | 380 | 'Name', | ||
473 | 381 | size=128, | ||
474 | 382 | required=True, | ||
475 | 383 | translate=True), | ||
476 | 384 | 'attribute_group_ids': fields.one2many( | ||
477 | 385 | 'attribute.group', | ||
478 | 386 | 'attribute_set_id', | ||
479 | 387 | 'Attribute Groups'), | ||
480 | 388 | 'model_id': fields.many2one( | ||
481 | 389 | 'ir.model', | ||
482 | 390 | 'Model', | ||
483 | 391 | required=True), | ||
484 | 392 | } | ||
485 | 393 | |||
486 | 394 | def _get_default_model(self, cr, uid, context=None): | ||
487 | 395 | if context and context.get('force_model'): | ||
488 | 396 | model_id = self.pool['ir.model'].search( | ||
489 | 397 | cr, uid, [['model', '=', context['force_model']]], | ||
490 | 398 | context=context) | ||
491 | 399 | if model_id: | ||
492 | 400 | return model_id[0] | ||
493 | 401 | return None | ||
494 | 402 | |||
495 | 403 | _defaults = { | ||
496 | 404 | 'model_id': _get_default_model | ||
497 | 405 | } | ||
498 | 406 | |||
499 | 407 | |||
500 | 408 | class attribute_location(orm.Model): | ||
501 | 409 | _name = "attribute.location" | ||
502 | 410 | _description = "Attribute Location" | ||
503 | 411 | _order="sequence" | ||
504 | 412 | _inherits = {'attribute.attribute': 'attribute_id'} | ||
505 | 413 | |||
506 | 414 | def _get_attribute_loc_from_group(self, cr, uid, ids, context=None): | ||
507 | 415 | return self.pool.get('attribute.location').search( | ||
508 | 416 | cr, uid, [('attribute_group_id', 'in', ids)], context=context) | ||
509 | 417 | |||
510 | 418 | _columns = { | ||
511 | 419 | 'attribute_id': fields.many2one( | ||
512 | 420 | 'attribute.attribute', | ||
513 | 421 | 'Product Attribute', | ||
514 | 422 | required=True, | ||
515 | 423 | ondelete="cascade"), | ||
516 | 424 | 'attribute_set_id': fields.related( | ||
517 | 425 | 'attribute_group_id', | ||
518 | 426 | 'attribute_set_id', | ||
519 | 427 | type='many2one', | ||
520 | 428 | relation='attribute.set', | ||
521 | 429 | string='Attribute Set', | ||
522 | 430 | readonly=True, | ||
523 | 431 | store={ | ||
524 | 432 | 'attribute.group': (_get_attribute_loc_from_group, | ||
525 | 433 | ['attribute_set_id'], 10), | ||
526 | 434 | }), | ||
527 | 435 | 'attribute_group_id': fields.many2one( | ||
528 | 436 | 'attribute.group', | ||
529 | 437 | 'Attribute Group', | ||
530 | 438 | required=True), | ||
531 | 439 | 'sequence': fields.integer('Sequence'), | ||
532 | 440 | } | ||
533 | 0 | 441 | ||
534 | === added file 'base_custom_attributes/custom_attributes_view.xml' | |||
535 | --- base_custom_attributes/custom_attributes_view.xml 1970-01-01 00:00:00 +0000 | |||
536 | +++ base_custom_attributes/custom_attributes_view.xml 2013-12-11 14:54:36 +0000 | |||
537 | @@ -0,0 +1,312 @@ | |||
538 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
539 | 2 | <!-- | ||
540 | 3 | base_custom_attributes for OpenERP | ||
541 | 4 | Copyright (C) 2011-2013 Akretion (http://www.akretion.com/) | ||
542 | 5 | @author: Benoît GUILLOT <benoit.guillot@akretion.com> | ||
543 | 6 | The licence is in the file __openerp__.py | ||
544 | 7 | --> | ||
545 | 8 | |||
546 | 9 | <openerp> | ||
547 | 10 | <data> | ||
548 | 11 | |||
549 | 12 | <menuitem | ||
550 | 13 | id="menu_attribute_in_admin" name="Attributes" | ||
551 | 14 | parent="base.next_id_9" sequence="1"/> | ||
552 | 15 | |||
553 | 16 | <!-- ATTRIBUTE SET VIEW --> | ||
554 | 17 | |||
555 | 18 | <record id="attribute_set_form_view" model="ir.ui.view"> | ||
556 | 19 | <field name="name">attribute.set.form</field> | ||
557 | 20 | <field name="model">attribute.set</field> | ||
558 | 21 | <field name="type">form</field> | ||
559 | 22 | <field name="arch" type="xml"> | ||
560 | 23 | <form string="Attribute Set"> | ||
561 | 24 | <field name="name"/> | ||
562 | 25 | <field name="model_id" invisible="context.get('force_model')"/> | ||
563 | 26 | <field name="attribute_group_ids" colspan="4" | ||
564 | 27 | context="{'default_model_id': model_id, 'from_attribute_set':True}"> | ||
565 | 28 | </field> | ||
566 | 29 | </form> | ||
567 | 30 | </field> | ||
568 | 31 | </record> | ||
569 | 32 | |||
570 | 33 | <record id="attribute_set_tree_view" model="ir.ui.view"> | ||
571 | 34 | <field name="name">attribute.set.tree</field> | ||
572 | 35 | <field name="model">attribute.set</field> | ||
573 | 36 | <field name="type">tree</field> | ||
574 | 37 | <field name="arch" type="xml"> | ||
575 | 38 | <tree string="Attribute Set" > | ||
576 | 39 | <field name="name" /> | ||
577 | 40 | <field name="model_id" /> | ||
578 | 41 | </tree> | ||
579 | 42 | </field> | ||
580 | 43 | </record> | ||
581 | 44 | |||
582 | 45 | <record id="view_attribute_set_search" model="ir.ui.view"> | ||
583 | 46 | <field name="name">attribute.set.list</field> | ||
584 | 47 | <field name="model">attribute.set</field> | ||
585 | 48 | <field name="type">search</field> | ||
586 | 49 | <field name="arch" type="xml"> | ||
587 | 50 | <search string="Search Attribute Sets"> | ||
588 | 51 | <field name="name"/> | ||
589 | 52 | <field name="model_id" /> | ||
590 | 53 | </search> | ||
591 | 54 | </field> | ||
592 | 55 | </record> | ||
593 | 56 | |||
594 | 57 | <record id="attribute_set_form_action" model="ir.actions.act_window"> | ||
595 | 58 | <field name="name">Attribute Sets</field> | ||
596 | 59 | <field name="res_model">attribute.set</field> | ||
597 | 60 | <field name="view_type">form</field> | ||
598 | 61 | <field name="view_mode">tree,form</field> | ||
599 | 62 | <field name="search_view_id" ref="view_attribute_set_search"/> | ||
600 | 63 | <field name="context">{"search_default_user_id":uid}</field> | ||
601 | 64 | <field name="help"></field> | ||
602 | 65 | </record> | ||
603 | 66 | |||
604 | 67 | <menuitem | ||
605 | 68 | action="attribute_set_form_action" id="menu_attribute_set_action" | ||
606 | 69 | parent="menu_attribute_in_admin" sequence="10"/> | ||
607 | 70 | |||
608 | 71 | |||
609 | 72 | |||
610 | 73 | <!-- ATTRIBUTE GROUP VIEW --> | ||
611 | 74 | |||
612 | 75 | <record id="attribute_group_form_view" model="ir.ui.view"> | ||
613 | 76 | <field name="name">attribute.group.form</field> | ||
614 | 77 | <field name="model">attribute.group</field> | ||
615 | 78 | <field name="type">form</field> | ||
616 | 79 | <field name="arch" type="xml"> | ||
617 | 80 | <form string="Attribute Group"> | ||
618 | 81 | <field name="name" /> | ||
619 | 82 | <field name="sequence" /> | ||
620 | 83 | <field name="model_id" invisible="context.get('from_attribute_set') or context.get('force_model')"/> | ||
621 | 84 | <field name="attribute_set_id" invisible="context.get('from_attribute_set')"/> | ||
622 | 85 | <field name="attribute_ids" colspan="4" nolabel="1"> | ||
623 | 86 | <form string="Attribute Location"> | ||
624 | 87 | <field name="attribute_id" context="{'default_model_id': parent.model_id}"/> | ||
625 | 88 | <field name="sequence" /> | ||
626 | 89 | </form> | ||
627 | 90 | <tree string="Attribute Location" editable="top"> | ||
628 | 91 | <field name="attribute_id" context="{'default_model_id': parent.model_id}"/> | ||
629 | 92 | <field name="sequence" /> | ||
630 | 93 | </tree> | ||
631 | 94 | </field> | ||
632 | 95 | </form> | ||
633 | 96 | </field> | ||
634 | 97 | </record> | ||
635 | 98 | |||
636 | 99 | <record id="attribute_group_tree_view" model="ir.ui.view"> | ||
637 | 100 | <field name="name">attribute.group.tree</field> | ||
638 | 101 | <field name="model">attribute.group</field> | ||
639 | 102 | <field name="type">tree</field> | ||
640 | 103 | <field name="arch" type="xml"> | ||
641 | 104 | <tree string="Attribute Group"> | ||
642 | 105 | <field name="name" /> | ||
643 | 106 | <field name="sequence" /> | ||
644 | 107 | <field name="attribute_set_id" invisible="context.get('from_attribute_set')"/> | ||
645 | 108 | <field name="model_id" invisible="context.get('from_attribute_set')"/> | ||
646 | 109 | </tree> | ||
647 | 110 | </field> | ||
648 | 111 | </record> | ||
649 | 112 | |||
650 | 113 | <record id="view_attribute_group_search" model="ir.ui.view"> | ||
651 | 114 | <field name="name">attribute.group.list</field> | ||
652 | 115 | <field name="model">attribute.group</field> | ||
653 | 116 | <field name="type">search</field> | ||
654 | 117 | <field name="arch" type="xml"> | ||
655 | 118 | <search string="Search Attribute Groups"> | ||
656 | 119 | <field name="name"/> | ||
657 | 120 | <field name="attribute_set_id"/> | ||
658 | 121 | <field name="model_id" /> | ||
659 | 122 | </search> | ||
660 | 123 | </field> | ||
661 | 124 | </record> | ||
662 | 125 | |||
663 | 126 | |||
664 | 127 | <record id="attribute_group_form_action" model="ir.actions.act_window"> | ||
665 | 128 | <field name="name">Attribute Groups</field> | ||
666 | 129 | <field name="res_model">attribute.group</field> | ||
667 | 130 | <field name="view_type">form</field> | ||
668 | 131 | <field name="view_mode">tree,form</field> | ||
669 | 132 | <field name="context">{"search_default_user_id":uid}</field> | ||
670 | 133 | <field name="help"></field> | ||
671 | 134 | </record> | ||
672 | 135 | |||
673 | 136 | <menuitem | ||
674 | 137 | action="attribute_group_form_action" id="menu_attribute_group_action" | ||
675 | 138 | parent="menu_attribute_in_admin" sequence="20"/> | ||
676 | 139 | |||
677 | 140 | <!-- ATTRIBUTE VIEW --> | ||
678 | 141 | |||
679 | 142 | <record id="attribute_attribute_form_view" model="ir.ui.view"> | ||
680 | 143 | <field name="name">attribute.attribute.form</field> | ||
681 | 144 | <field name="model">attribute.attribute</field> | ||
682 | 145 | <field name="type">form</field> | ||
683 | 146 | <field name="arch" type="xml"> | ||
684 | 147 | <form string="Attribute"> | ||
685 | 148 | <field name="field_description" on_change="onchange_field_description(field_description, name, create_date, context)"/> | ||
686 | 149 | <field name="name" attrs="{'readonly':[('create_date', '!=', False)]}" on_change="onchange_name(name, context)"/> | ||
687 | 150 | <field name="attribute_type" /> | ||
688 | 151 | <field name="model_id" /> | ||
689 | 152 | <field name="serialized" attrs="{'invisible':[('attribute_type', '=', 'multiselect')]}"/> | ||
690 | 153 | <field name="size" attrs="{'invisible':[('attribute_type', '!=', 'char')]}"/> | ||
691 | 154 | <field name="required_on_views"/> | ||
692 | 155 | <field name="translate" attrs="{'invisible':[('attribute_type', 'not in', ('char', 'text'))]}"/> | ||
693 | 156 | <newline /> | ||
694 | 157 | <group colspan="4" attrs="{'invisible':[('attribute_type', 'not in', ['select', 'multiselect'])]}"> | ||
695 | 158 | <group groups="base.group_advanced_attribute"> | ||
696 | 159 | <field name="relation_model_id" on_change="relation_model_id_change(relation_model_id, option_ids, context)"/> | ||
697 | 160 | <field name="domain" attrs="{'invisible':[('relation_model_id', '=', False)]}"/> | ||
698 | 161 | <button name="button_add_options" attrs="{'invisible':[('relation_model_id', '=', False), ('domain', '!=', False)]}" type="object" string="Load Options"/> | ||
699 | 162 | </group> | ||
700 | 163 | <field name="option_ids" colspan="4" nolabel="1"> | ||
701 | 164 | <tree string="Attribute Options" editable="top"> | ||
702 | 165 | <field name="sequence" invisible="1"/> | ||
703 | 166 | <field name="name" on_change="name_change(name, parent.relation_model_id, context)"/> | ||
704 | 167 | </tree> | ||
705 | 168 | </field> | ||
706 | 169 | </group> | ||
707 | 170 | <field name="create_date" invisible="1"/> | ||
708 | 171 | </form> | ||
709 | 172 | </field> | ||
710 | 173 | </record> | ||
711 | 174 | |||
712 | 175 | <record id="attribute_attribute_tree_view" model="ir.ui.view"> | ||
713 | 176 | <field name="name">attribute.attribute.tree</field> | ||
714 | 177 | <field name="model">attribute.attribute</field> | ||
715 | 178 | <field name="type">tree</field> | ||
716 | 179 | <field name="arch" type="xml"> | ||
717 | 180 | <tree string="Attribute"> | ||
718 | 181 | <field name="name" /> | ||
719 | 182 | <field name="attribute_type" /> | ||
720 | 183 | </tree> | ||
721 | 184 | </field> | ||
722 | 185 | </record> | ||
723 | 186 | |||
724 | 187 | <record id="view_attribute_attribute_search" model="ir.ui.view"> | ||
725 | 188 | <field name="name">attribute.attribute.list</field> | ||
726 | 189 | <field name="model">attribute.attribute</field> | ||
727 | 190 | <field name="type">search</field> | ||
728 | 191 | <field name="arch" type="xml"> | ||
729 | 192 | <search string="Search Attributes"> | ||
730 | 193 | <field name="name"/> | ||
731 | 194 | </search> | ||
732 | 195 | </field> | ||
733 | 196 | </record> | ||
734 | 197 | |||
735 | 198 | <record id="attribute_attribute_form_action" model="ir.actions.act_window"> | ||
736 | 199 | <field name="name">Attributes</field> | ||
737 | 200 | <field name="res_model">attribute.attribute</field> | ||
738 | 201 | <field name="view_type">form</field> | ||
739 | 202 | <field name="view_mode">tree,form</field> | ||
740 | 203 | <field name="search_view_id" ref="view_attribute_attribute_search"/> | ||
741 | 204 | <field name="context">{"search_default_user_id":uid}</field> | ||
742 | 205 | <field name="help"></field> | ||
743 | 206 | </record> | ||
744 | 207 | <menuitem | ||
745 | 208 | action="attribute_attribute_form_action" id="menu_attribute_attribute_action" | ||
746 | 209 | parent="menu_attribute_in_admin" sequence="30"/> | ||
747 | 210 | |||
748 | 211 | <!-- ATTRIBUTE OPTION VIEW --> | ||
749 | 212 | <record id="attribute_option_form_popup_view" model="ir.ui.view"> | ||
750 | 213 | <field name="name">attribute.option.form.popup</field> | ||
751 | 214 | <field name="model">attribute.option</field> | ||
752 | 215 | <field name="priority" eval="6"/> | ||
753 | 216 | <field name="type">form</field> | ||
754 | 217 | <field name="arch" type="xml"> | ||
755 | 218 | <form string="Attribute Option"> | ||
756 | 219 | <field name="name" colspan="2"/> | ||
757 | 220 | <field name="value_ref" colspan="2" groups="base.group_advanced_attribute"/> | ||
758 | 221 | <field name="sequence" colspan="2"/> | ||
759 | 222 | </form> | ||
760 | 223 | </field> | ||
761 | 224 | </record> | ||
762 | 225 | |||
763 | 226 | <record id="attribute_option_form_view" model="ir.ui.view"> | ||
764 | 227 | <field name="name">attribute.option.form</field> | ||
765 | 228 | <field name="model">attribute.option</field> | ||
766 | 229 | <field name="type">form</field> | ||
767 | 230 | <field name="arch" type="xml"> | ||
768 | 231 | <form string="Attribute Option"> | ||
769 | 232 | <field name="name" colspan="2"/> | ||
770 | 233 | <field name="value_ref" colspan="2" groups="base.group_advanced_attribute"/> | ||
771 | 234 | <field name="sequence" colspan="2"/> | ||
772 | 235 | <field name="attribute_id" colspan="2"/> | ||
773 | 236 | </form> | ||
774 | 237 | </field> | ||
775 | 238 | </record> | ||
776 | 239 | |||
777 | 240 | <record id="attribute_option_tree_view" model="ir.ui.view"> | ||
778 | 241 | <field name="name">attribute.option.tree</field> | ||
779 | 242 | <field name="model">attribute.option</field> | ||
780 | 243 | <field eval="20" name="priority"/> | ||
781 | 244 | <field name="type">tree</field> | ||
782 | 245 | <field name="arch" type="xml"> | ||
783 | 246 | <tree string="Attribute Option"> | ||
784 | 247 | <field name="name" /> | ||
785 | 248 | <field name="sequence" /> | ||
786 | 249 | <field name="value_ref" groups="base.group_advanced_attribute"/> | ||
787 | 250 | <field name="attribute_id" /> | ||
788 | 251 | </tree> | ||
789 | 252 | </field> | ||
790 | 253 | </record> | ||
791 | 254 | |||
792 | 255 | <record id="view_attribute_option_search" model="ir.ui.view"> | ||
793 | 256 | <field name="name">attribute.option.list</field> | ||
794 | 257 | <field name="model">attribute.option</field> | ||
795 | 258 | <field name="type">search</field> | ||
796 | 259 | <field name="arch" type="xml"> | ||
797 | 260 | <search string="Search Attribute Options"> | ||
798 | 261 | <field name="name" /> | ||
799 | 262 | <field name="attribute_id"/> | ||
800 | 263 | </search> | ||
801 | 264 | </field> | ||
802 | 265 | </record> | ||
803 | 266 | |||
804 | 267 | <record id="attribute_option_form_action" model="ir.actions.act_window"> | ||
805 | 268 | <field name="name">Attribute Options</field> | ||
806 | 269 | <field name="res_model">attribute.option</field> | ||
807 | 270 | <field name="view_type">form</field> | ||
808 | 271 | <field name="view_mode">tree,form</field> | ||
809 | 272 | <field name="view_id" ref="attribute_option_tree_view"/> | ||
810 | 273 | <field name="search_view_id" ref="view_attribute_option_search"/> | ||
811 | 274 | <field name="context">{"search_default_user_id":uid}</field> | ||
812 | 275 | <field name="help"></field> | ||
813 | 276 | </record> | ||
814 | 277 | |||
815 | 278 | <record id="attribute_option_form_action_tree" model="ir.actions.act_window.view"> | ||
816 | 279 | <field name="sequence" eval="1"/> | ||
817 | 280 | <field name="act_window_id" ref="attribute_option_form_action"/> | ||
818 | 281 | <field name="view_id" ref="attribute_option_tree_view"/> | ||
819 | 282 | <field name="view_mode">tree</field> | ||
820 | 283 | </record> | ||
821 | 284 | |||
822 | 285 | <record id="attribute_option_form_action_form" model="ir.actions.act_window.view"> | ||
823 | 286 | <field name="sequence" eval="2"/> | ||
824 | 287 | <field name="act_window_id" ref="attribute_option_form_action"/> | ||
825 | 288 | <field name="view_id" ref="attribute_option_form_view"/> | ||
826 | 289 | <field name="view_mode">form</field> | ||
827 | 290 | </record> | ||
828 | 291 | |||
829 | 292 | <menuitem | ||
830 | 293 | action="attribute_option_form_action" id="menu_attribute_option_action" | ||
831 | 294 | parent="menu_attribute_in_admin" sequence="40"/> | ||
832 | 295 | |||
833 | 296 | <!-- ATTRIBUTE OPTION WIZARD --> | ||
834 | 297 | <record id="attribute_option_wizard_form_view" model="ir.ui.view"> | ||
835 | 298 | <field name="name">attribute.option.wizard</field> | ||
836 | 299 | <field name="model">attribute.option.wizard</field> | ||
837 | 300 | <field name="type">form</field> | ||
838 | 301 | <field name="arch" type="xml"> | ||
839 | 302 | <form string="Options Wizard" col="6"> | ||
840 | 303 | <field name="attribute_id" invisible="1" colspan="2"/> | ||
841 | 304 | <separator string="options_placeholder"/> | ||
842 | 305 | <button special="cancel" string="Cancel" icon="gtk-cancel"/> | ||
843 | 306 | <button name="validate" string="Validate" type="object" icon="gtk-convert"/> | ||
844 | 307 | </form> | ||
845 | 308 | </field> | ||
846 | 309 | </record> | ||
847 | 310 | |||
848 | 311 | </data> | ||
849 | 312 | </openerp> | ||
850 | 0 | 313 | ||
851 | === added directory 'base_custom_attributes/i18n' | |||
852 | === added file 'base_custom_attributes/i18n/base_custom_attributes.pot' | |||
853 | --- base_custom_attributes/i18n/base_custom_attributes.pot 1970-01-01 00:00:00 +0000 | |||
854 | +++ base_custom_attributes/i18n/base_custom_attributes.pot 2013-12-11 14:54:36 +0000 | |||
855 | @@ -0,0 +1,291 @@ | |||
856 | 1 | # Translation of OpenERP Server. | ||
857 | 2 | # This file contains the translation of the following modules: | ||
858 | 3 | # * base_custom_attributes | ||
859 | 4 | # | ||
860 | 5 | msgid "" | ||
861 | 6 | msgstr "" | ||
862 | 7 | "Project-Id-Version: OpenERP Server 7.0\n" | ||
863 | 8 | "Report-Msgid-Bugs-To: \n" | ||
864 | 9 | "POT-Creation-Date: 2013-10-16 10:39+0000\n" | ||
865 | 10 | "PO-Revision-Date: 2013-10-16 10:39+0000\n" | ||
866 | 11 | "Last-Translator: <>\n" | ||
867 | 12 | "Language-Team: \n" | ||
868 | 13 | "MIME-Version: 1.0\n" | ||
869 | 14 | "Content-Type: text/plain; charset=UTF-8\n" | ||
870 | 15 | "Content-Transfer-Encoding: \n" | ||
871 | 16 | "Plural-Forms: \n" | ||
872 | 17 | |||
873 | 18 | #. module: base_custom_attributes | ||
874 | 19 | #: code:addons/base_custom_attributes/custom_attributes.py:44 | ||
875 | 20 | #, python-format | ||
876 | 21 | msgid "Use the 'Load Options' button instead to select appropriate model references." | ||
877 | 22 | msgstr "" | ||
878 | 23 | |||
879 | 24 | #. module: base_custom_attributes | ||
880 | 25 | #: selection:attribute.attribute,attribute_type:0 | ||
881 | 26 | msgid "Binary" | ||
882 | 27 | msgstr "" | ||
883 | 28 | |||
884 | 29 | #. module: base_custom_attributes | ||
885 | 30 | #: view:attribute.attribute:0 | ||
886 | 31 | msgid "Search Attributes" | ||
887 | 32 | msgstr "" | ||
888 | 33 | |||
889 | 34 | #. module: base_custom_attributes | ||
890 | 35 | #: view:attribute.group:0 | ||
891 | 36 | #: field:attribute.location,attribute_group_id:0 | ||
892 | 37 | #: model:ir.model,name:base_custom_attributes.model_attribute_group | ||
893 | 38 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_attribute_group_id | ||
894 | 39 | msgid "Attribute Group" | ||
895 | 40 | msgstr "" | ||
896 | 41 | |||
897 | 42 | #. module: base_custom_attributes | ||
898 | 43 | #: view:attribute.group:0 | ||
899 | 44 | #: model:ir.model,name:base_custom_attributes.model_attribute_location | ||
900 | 45 | msgid "Attribute Location" | ||
901 | 46 | msgstr "" | ||
902 | 47 | |||
903 | 48 | #. module: base_custom_attributes | ||
904 | 49 | #: code:addons/base_custom_attributes/custom_attributes.py:154 | ||
905 | 50 | #: view:attribute.option.wizard:0 | ||
906 | 51 | #, python-format | ||
907 | 52 | msgid "Options Wizard" | ||
908 | 53 | msgstr "" | ||
909 | 54 | |||
910 | 55 | #. module: base_custom_attributes | ||
911 | 56 | #: view:attribute.group:0 | ||
912 | 57 | msgid "Search Attribute Groups" | ||
913 | 58 | msgstr "" | ||
914 | 59 | |||
915 | 60 | #. module: base_custom_attributes | ||
916 | 61 | #: field:attribute.attribute,attribute_type:0 | ||
917 | 62 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_attribute_type | ||
918 | 63 | msgid "Type" | ||
919 | 64 | msgstr "" | ||
920 | 65 | |||
921 | 66 | #. module: base_custom_attributes | ||
922 | 67 | #: field:attribute.set,attribute_group_ids:0 | ||
923 | 68 | #: model:ir.actions.act_window,name:base_custom_attributes.attribute_group_form_action | ||
924 | 69 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_set_attribute_group_ids | ||
925 | 70 | #: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_group_action | ||
926 | 71 | msgid "Attribute Groups" | ||
927 | 72 | msgstr "" | ||
928 | 73 | |||
929 | 74 | #. module: base_custom_attributes | ||
930 | 75 | #: field:attribute.attribute,create_date:0 | ||
931 | 76 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_create_date | ||
932 | 77 | msgid "Created date" | ||
933 | 78 | msgstr "" | ||
934 | 79 | |||
935 | 80 | #. module: base_custom_attributes | ||
936 | 81 | #: view:attribute.set:0 | ||
937 | 82 | msgid "Search Attribute Sets" | ||
938 | 83 | msgstr "" | ||
939 | 84 | |||
940 | 85 | #. module: base_custom_attributes | ||
941 | 86 | #: view:attribute.option:0 | ||
942 | 87 | #: model:ir.model,name:base_custom_attributes.model_attribute_option | ||
943 | 88 | msgid "Attribute Option" | ||
944 | 89 | msgstr "" | ||
945 | 90 | |||
946 | 91 | #. module: base_custom_attributes | ||
947 | 92 | #: selection:attribute.attribute,attribute_type:0 | ||
948 | 93 | msgid "Date" | ||
949 | 94 | msgstr "" | ||
950 | 95 | |||
951 | 96 | #. module: base_custom_attributes | ||
952 | 97 | #: help:attribute.attribute,required_on_views:0 | ||
953 | 98 | msgid "If activated, the attribute will be mandatory on the views, but not in the database" | ||
954 | 99 | msgstr "" | ||
955 | 100 | |||
956 | 101 | #. module: base_custom_attributes | ||
957 | 102 | #: field:attribute.attribute,field_id:0 | ||
958 | 103 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_field_id | ||
959 | 104 | msgid "Ir Model Fields" | ||
960 | 105 | msgstr "" | ||
961 | 106 | |||
962 | 107 | #. module: base_custom_attributes | ||
963 | 108 | #: view:attribute.option.wizard:0 | ||
964 | 109 | msgid "options_placeholder" | ||
965 | 110 | msgstr "" | ||
966 | 111 | |||
967 | 112 | #. module: base_custom_attributes | ||
968 | 113 | #: field:attribute.group,name:0 | ||
969 | 114 | #: field:attribute.option,name:0 | ||
970 | 115 | #: field:attribute.set,name:0 | ||
971 | 116 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_name | ||
972 | 117 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_name | ||
973 | 118 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_set_name | ||
974 | 119 | msgid "Name" | ||
975 | 120 | msgstr "" | ||
976 | 121 | |||
977 | 122 | #. module: base_custom_attributes | ||
978 | 123 | #: help:attribute.attribute,serialized:0 | ||
979 | 124 | msgid "If serialized, the field will be stocked in the serialized field: attribute_custom_tmpl or attribute_custom_variant depending on the field based_on" | ||
980 | 125 | msgstr "" | ||
981 | 126 | |||
982 | 127 | #. module: base_custom_attributes | ||
983 | 128 | #: field:attribute.attribute,required_on_views:0 | ||
984 | 129 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_required_on_views | ||
985 | 130 | msgid "Required (on views)" | ||
986 | 131 | msgstr "" | ||
987 | 132 | |||
988 | 133 | #. module: base_custom_attributes | ||
989 | 134 | #: model:ir.model,name:base_custom_attributes.model_ir_model_fields | ||
990 | 135 | msgid "Fields" | ||
991 | 136 | msgstr "" | ||
992 | 137 | |||
993 | 138 | #. module: base_custom_attributes | ||
994 | 139 | #: view:attribute.attribute:0 | ||
995 | 140 | #: field:attribute.attribute,option_ids:0 | ||
996 | 141 | #: model:ir.actions.act_window,name:base_custom_attributes.attribute_option_form_action | ||
997 | 142 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_option_ids | ||
998 | 143 | #: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_option_action | ||
999 | 144 | msgid "Attribute Options" | ||
1000 | 145 | msgstr "" | ||
1001 | 146 | |||
1002 | 147 | #. module: base_custom_attributes | ||
1003 | 148 | #: field:attribute.attribute,serialized:0 | ||
1004 | 149 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_serialized | ||
1005 | 150 | msgid "Field serialized" | ||
1006 | 151 | msgstr "" | ||
1007 | 152 | |||
1008 | 153 | #. module: base_custom_attributes | ||
1009 | 154 | #: code:addons/base_custom_attributes/custom_attributes.py:44 | ||
1010 | 155 | #, python-format | ||
1011 | 156 | msgid "Error!" | ||
1012 | 157 | msgstr "" | ||
1013 | 158 | |||
1014 | 159 | #. module: base_custom_attributes | ||
1015 | 160 | #: view:attribute.option.wizard:0 | ||
1016 | 161 | msgid "Validate" | ||
1017 | 162 | msgstr "" | ||
1018 | 163 | |||
1019 | 164 | #. module: base_custom_attributes | ||
1020 | 165 | #: selection:attribute.attribute,attribute_type:0 | ||
1021 | 166 | msgid "Multiselect" | ||
1022 | 167 | msgstr "" | ||
1023 | 168 | |||
1024 | 169 | #. module: base_custom_attributes | ||
1025 | 170 | #: view:attribute.option:0 | ||
1026 | 171 | msgid "Search Attribute Options" | ||
1027 | 172 | msgstr "" | ||
1028 | 173 | |||
1029 | 174 | #. module: base_custom_attributes | ||
1030 | 175 | #: selection:attribute.attribute,attribute_type:0 | ||
1031 | 176 | msgid "Integer" | ||
1032 | 177 | msgstr "" | ||
1033 | 178 | |||
1034 | 179 | #. module: base_custom_attributes | ||
1035 | 180 | #: field:attribute.group,attribute_ids:0 | ||
1036 | 181 | #: model:ir.actions.act_window,name:base_custom_attributes.attribute_attribute_form_action | ||
1037 | 182 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_attribute_ids | ||
1038 | 183 | #: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_attribute_action | ||
1039 | 184 | #: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_in_admin | ||
1040 | 185 | msgid "Attributes" | ||
1041 | 186 | msgstr "" | ||
1042 | 187 | |||
1043 | 188 | #. module: base_custom_attributes | ||
1044 | 189 | #: field:attribute.attribute,relation_model_id:0 | ||
1045 | 190 | #: field:attribute.group,model_id:0 | ||
1046 | 191 | #: field:attribute.set,model_id:0 | ||
1047 | 192 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_relation_model_id | ||
1048 | 193 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_model_id | ||
1049 | 194 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_set_model_id | ||
1050 | 195 | msgid "Model" | ||
1051 | 196 | msgstr "" | ||
1052 | 197 | |||
1053 | 198 | #. module: base_custom_attributes | ||
1054 | 199 | #: model:ir.actions.act_window,name:base_custom_attributes.attribute_set_form_action | ||
1055 | 200 | #: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_set_action | ||
1056 | 201 | msgid "Attribute Sets" | ||
1057 | 202 | msgstr "" | ||
1058 | 203 | |||
1059 | 204 | #. module: base_custom_attributes | ||
1060 | 205 | #: view:attribute.attribute:0 | ||
1061 | 206 | msgid "Load Options" | ||
1062 | 207 | msgstr "" | ||
1063 | 208 | |||
1064 | 209 | #. module: base_custom_attributes | ||
1065 | 210 | #: field:attribute.option,value_ref:0 | ||
1066 | 211 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_value_ref | ||
1067 | 212 | msgid "Reference" | ||
1068 | 213 | msgstr "" | ||
1069 | 214 | |||
1070 | 215 | #. module: base_custom_attributes | ||
1071 | 216 | #: field:attribute.group,sequence:0 | ||
1072 | 217 | #: field:attribute.location,sequence:0 | ||
1073 | 218 | #: field:attribute.option,sequence:0 | ||
1074 | 219 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_sequence | ||
1075 | 220 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_sequence | ||
1076 | 221 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_sequence | ||
1077 | 222 | msgid "Sequence" | ||
1078 | 223 | msgstr "" | ||
1079 | 224 | |||
1080 | 225 | #. module: base_custom_attributes | ||
1081 | 226 | #: view:attribute.attribute:0 | ||
1082 | 227 | #: field:attribute.location,attribute_id:0 | ||
1083 | 228 | #: field:attribute.option,attribute_id:0 | ||
1084 | 229 | #: field:attribute.option.wizard,attribute_id:0 | ||
1085 | 230 | #: model:ir.model,name:base_custom_attributes.model_attribute_attribute | ||
1086 | 231 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_attribute_id | ||
1087 | 232 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_attribute_id | ||
1088 | 233 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_wizard_attribute_id | ||
1089 | 234 | msgid "Attribute" | ||
1090 | 235 | msgstr "" | ||
1091 | 236 | |||
1092 | 237 | #. module: base_custom_attributes | ||
1093 | 238 | #: selection:attribute.attribute,attribute_type:0 | ||
1094 | 239 | msgid "Float" | ||
1095 | 240 | msgstr "" | ||
1096 | 241 | |||
1097 | 242 | #. module: base_custom_attributes | ||
1098 | 243 | #: field:attribute.group,attribute_set_id:0 | ||
1099 | 244 | #: field:attribute.location,attribute_set_id:0 | ||
1100 | 245 | #: view:attribute.set:0 | ||
1101 | 246 | #: model:ir.model,name:base_custom_attributes.model_attribute_set | ||
1102 | 247 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_attribute_set_id | ||
1103 | 248 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_attribute_set_id | ||
1104 | 249 | msgid "Attribute Set" | ||
1105 | 250 | msgstr "" | ||
1106 | 251 | |||
1107 | 252 | #. module: base_custom_attributes | ||
1108 | 253 | #: selection:attribute.attribute,attribute_type:0 | ||
1109 | 254 | msgid "Datetime" | ||
1110 | 255 | msgstr "" | ||
1111 | 256 | |||
1112 | 257 | #. module: base_custom_attributes | ||
1113 | 258 | #: selection:attribute.attribute,attribute_type:0 | ||
1114 | 259 | msgid "Char" | ||
1115 | 260 | msgstr "" | ||
1116 | 261 | |||
1117 | 262 | #. module: base_custom_attributes | ||
1118 | 263 | #: selection:attribute.attribute,attribute_type:0 | ||
1119 | 264 | msgid "Boolean" | ||
1120 | 265 | msgstr "" | ||
1121 | 266 | |||
1122 | 267 | #. module: base_custom_attributes | ||
1123 | 268 | #: selection:attribute.attribute,attribute_type:0 | ||
1124 | 269 | msgid "Text" | ||
1125 | 270 | msgstr "" | ||
1126 | 271 | |||
1127 | 272 | #. module: base_custom_attributes | ||
1128 | 273 | #: view:attribute.option.wizard:0 | ||
1129 | 274 | msgid "Cancel" | ||
1130 | 275 | msgstr "" | ||
1131 | 276 | |||
1132 | 277 | #. module: base_custom_attributes | ||
1133 | 278 | #: model:ir.model,name:base_custom_attributes.model_attribute_option_wizard | ||
1134 | 279 | msgid "attribute.option.wizard" | ||
1135 | 280 | msgstr "" | ||
1136 | 281 | |||
1137 | 282 | #. module: base_custom_attributes | ||
1138 | 283 | #: sql_constraint:ir.model.fields:0 | ||
1139 | 284 | msgid "The name of the field has to be uniq for a given model !" | ||
1140 | 285 | msgstr "" | ||
1141 | 286 | |||
1142 | 287 | #. module: base_custom_attributes | ||
1143 | 288 | #: selection:attribute.attribute,attribute_type:0 | ||
1144 | 289 | msgid "Select" | ||
1145 | 290 | msgstr "" | ||
1146 | 291 | |||
1147 | 0 | 292 | ||
1148 | === added file 'base_custom_attributes/i18n/fr.po' | |||
1149 | --- base_custom_attributes/i18n/fr.po 1970-01-01 00:00:00 +0000 | |||
1150 | +++ base_custom_attributes/i18n/fr.po 2013-12-11 14:54:36 +0000 | |||
1151 | @@ -0,0 +1,291 @@ | |||
1152 | 1 | # Translation of OpenERP Server. | ||
1153 | 2 | # This file contains the translation of the following modules: | ||
1154 | 3 | # * base_custom_attributes | ||
1155 | 4 | # | ||
1156 | 5 | msgid "" | ||
1157 | 6 | msgstr "" | ||
1158 | 7 | "Project-Id-Version: OpenERP Server 7.0\n" | ||
1159 | 8 | "Report-Msgid-Bugs-To: \n" | ||
1160 | 9 | "POT-Creation-Date: 2013-10-16 09:03+0000\n" | ||
1161 | 10 | "PO-Revision-Date: 2013-10-16 09:03+0000\n" | ||
1162 | 11 | "Last-Translator: <>\n" | ||
1163 | 12 | "Language-Team: \n" | ||
1164 | 13 | "MIME-Version: 1.0\n" | ||
1165 | 14 | "Content-Type: text/plain; charset=UTF-8\n" | ||
1166 | 15 | "Content-Transfer-Encoding: \n" | ||
1167 | 16 | "Plural-Forms: \n" | ||
1168 | 17 | |||
1169 | 18 | #. module: base_custom_attributes | ||
1170 | 19 | #: code:addons/base_custom_attributes/custom_attributes.py:44 | ||
1171 | 20 | #, python-format | ||
1172 | 21 | msgid "Use the 'Load Options' button instead to select appropriate model references." | ||
1173 | 22 | msgstr "Utiliser le bouton 'Charger les options' pour sélectionner le modèle de référence approprié." | ||
1174 | 23 | |||
1175 | 24 | #. module: base_custom_attributes | ||
1176 | 25 | #: selection:attribute.attribute,attribute_type:0 | ||
1177 | 26 | msgid "Binary" | ||
1178 | 27 | msgstr "Binary" | ||
1179 | 28 | |||
1180 | 29 | #. module: base_custom_attributes | ||
1181 | 30 | #: view:attribute.attribute:0 | ||
1182 | 31 | msgid "Search Attributes" | ||
1183 | 32 | msgstr "Rechercher des attributs" | ||
1184 | 33 | |||
1185 | 34 | #. module: base_custom_attributes | ||
1186 | 35 | #: view:attribute.group:0 | ||
1187 | 36 | #: field:attribute.location,attribute_group_id:0 | ||
1188 | 37 | #: model:ir.model,name:base_custom_attributes.model_attribute_group | ||
1189 | 38 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_attribute_group_id | ||
1190 | 39 | msgid "Attribute Group" | ||
1191 | 40 | msgstr "Groupe d'attributs" | ||
1192 | 41 | |||
1193 | 42 | #. module: base_custom_attributes | ||
1194 | 43 | #: view:attribute.group:0 | ||
1195 | 44 | #: model:ir.model,name:base_custom_attributes.model_attribute_location | ||
1196 | 45 | msgid "Attribute Location" | ||
1197 | 46 | msgstr "Attribute Location" | ||
1198 | 47 | |||
1199 | 48 | #. module: base_custom_attributes | ||
1200 | 49 | #: code:addons/base_custom_attributes/custom_attributes.py:154 | ||
1201 | 50 | #: view:attribute.option.wizard:0 | ||
1202 | 51 | #, python-format | ||
1203 | 52 | msgid "Options Wizard" | ||
1204 | 53 | msgstr "Options Wizard" | ||
1205 | 54 | |||
1206 | 55 | #. module: base_custom_attributes | ||
1207 | 56 | #: view:attribute.group:0 | ||
1208 | 57 | msgid "Search Attribute Groups" | ||
1209 | 58 | msgstr "Rechercher des groupes d'attributs" | ||
1210 | 59 | |||
1211 | 60 | #. module: base_custom_attributes | ||
1212 | 61 | #: field:attribute.attribute,attribute_type:0 | ||
1213 | 62 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_attribute_type | ||
1214 | 63 | msgid "Type" | ||
1215 | 64 | msgstr "Type" | ||
1216 | 65 | |||
1217 | 66 | #. module: base_custom_attributes | ||
1218 | 67 | #: field:attribute.set,attribute_group_ids:0 | ||
1219 | 68 | #: model:ir.actions.act_window,name:base_custom_attributes.attribute_group_form_action | ||
1220 | 69 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_set_attribute_group_ids | ||
1221 | 70 | #: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_group_action | ||
1222 | 71 | msgid "Attribute Groups" | ||
1223 | 72 | msgstr "Groupes d'attributs" | ||
1224 | 73 | |||
1225 | 74 | #. module: base_custom_attributes | ||
1226 | 75 | #: field:attribute.attribute,create_date:0 | ||
1227 | 76 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_create_date | ||
1228 | 77 | msgid "Created date" | ||
1229 | 78 | msgstr "Date de création" | ||
1230 | 79 | |||
1231 | 80 | #. module: base_custom_attributes | ||
1232 | 81 | #: view:attribute.set:0 | ||
1233 | 82 | msgid "Search Attribute Sets" | ||
1234 | 83 | msgstr "Rechercher des jeux d'attributs" | ||
1235 | 84 | |||
1236 | 85 | #. module: base_custom_attributes | ||
1237 | 86 | #: view:attribute.option:0 | ||
1238 | 87 | #: model:ir.model,name:base_custom_attributes.model_attribute_option | ||
1239 | 88 | msgid "Attribute Option" | ||
1240 | 89 | msgstr "Option d'attribut" | ||
1241 | 90 | |||
1242 | 91 | #. module: base_custom_attributes | ||
1243 | 92 | #: selection:attribute.attribute,attribute_type:0 | ||
1244 | 93 | msgid "Date" | ||
1245 | 94 | msgstr "Date" | ||
1246 | 95 | |||
1247 | 96 | #. module: base_custom_attributes | ||
1248 | 97 | #: help:attribute.attribute,required_on_views:0 | ||
1249 | 98 | msgid "If activated, the attribute will be mandatory on the views, but not in the database" | ||
1250 | 99 | msgstr "Si activé, l'attribut sera obligatoire dans les vues, mais pas dans la base de données." | ||
1251 | 100 | |||
1252 | 101 | #. module: base_custom_attributes | ||
1253 | 102 | #: field:attribute.attribute,field_id:0 | ||
1254 | 103 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_field_id | ||
1255 | 104 | msgid "Ir Model Fields" | ||
1256 | 105 | msgstr "Ir Model Fields" | ||
1257 | 106 | |||
1258 | 107 | #. module: base_custom_attributes | ||
1259 | 108 | #: view:attribute.option.wizard:0 | ||
1260 | 109 | msgid "options_placeholder" | ||
1261 | 110 | msgstr "options_placeholder" | ||
1262 | 111 | |||
1263 | 112 | #. module: base_custom_attributes | ||
1264 | 113 | #: field:attribute.group,name:0 | ||
1265 | 114 | #: field:attribute.option,name:0 | ||
1266 | 115 | #: field:attribute.set,name:0 | ||
1267 | 116 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_name | ||
1268 | 117 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_name | ||
1269 | 118 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_set_name | ||
1270 | 119 | msgid "Name" | ||
1271 | 120 | msgstr "Nom" | ||
1272 | 121 | |||
1273 | 122 | #. module: base_custom_attributes | ||
1274 | 123 | #: help:attribute.attribute,serialized:0 | ||
1275 | 124 | msgid "If serialized, the field will be stocked in the serialized field: attribute_custom_tmpl or attribute_custom_variant depending on the field based_on" | ||
1276 | 125 | msgstr "Si serialisé, le champ sera stocké dans un champ serialisé : attribute_custom_tmpl ou attribut_custom_variant selon la valeur du champ based_on" | ||
1277 | 126 | |||
1278 | 127 | #. module: base_custom_attributes | ||
1279 | 128 | #: field:attribute.attribute,required_on_views:0 | ||
1280 | 129 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_required_on_views | ||
1281 | 130 | msgid "Required (on views)" | ||
1282 | 131 | msgstr "Obligatoire (dans les vues)" | ||
1283 | 132 | |||
1284 | 133 | #. module: base_custom_attributes | ||
1285 | 134 | #: model:ir.model,name:base_custom_attributes.model_ir_model_fields | ||
1286 | 135 | msgid "Fields" | ||
1287 | 136 | msgstr "Champs" | ||
1288 | 137 | |||
1289 | 138 | #. module: base_custom_attributes | ||
1290 | 139 | #: view:attribute.attribute:0 | ||
1291 | 140 | #: field:attribute.attribute,option_ids:0 | ||
1292 | 141 | #: model:ir.actions.act_window,name:base_custom_attributes.attribute_option_form_action | ||
1293 | 142 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_option_ids | ||
1294 | 143 | #: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_option_action | ||
1295 | 144 | msgid "Attribute Options" | ||
1296 | 145 | msgstr "Options d'attribut" | ||
1297 | 146 | |||
1298 | 147 | #. module: base_custom_attributes | ||
1299 | 148 | #: field:attribute.attribute,serialized:0 | ||
1300 | 149 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_serialized | ||
1301 | 150 | msgid "Field serialized" | ||
1302 | 151 | msgstr "Champ serialisé" | ||
1303 | 152 | |||
1304 | 153 | #. module: base_custom_attributes | ||
1305 | 154 | #: code:addons/base_custom_attributes/custom_attributes.py:44 | ||
1306 | 155 | #, python-format | ||
1307 | 156 | msgid "Error!" | ||
1308 | 157 | msgstr "Erreur !" | ||
1309 | 158 | |||
1310 | 159 | #. module: base_custom_attributes | ||
1311 | 160 | #: view:attribute.option.wizard:0 | ||
1312 | 161 | msgid "Validate" | ||
1313 | 162 | msgstr "Valider" | ||
1314 | 163 | |||
1315 | 164 | #. module: base_custom_attributes | ||
1316 | 165 | #: selection:attribute.attribute,attribute_type:0 | ||
1317 | 166 | msgid "Multiselect" | ||
1318 | 167 | msgstr "Multiselect" | ||
1319 | 168 | |||
1320 | 169 | #. module: base_custom_attributes | ||
1321 | 170 | #: view:attribute.option:0 | ||
1322 | 171 | msgid "Search Attribute Options" | ||
1323 | 172 | msgstr "Rechercher des options d'attribut" | ||
1324 | 173 | |||
1325 | 174 | #. module: base_custom_attributes | ||
1326 | 175 | #: selection:attribute.attribute,attribute_type:0 | ||
1327 | 176 | msgid "Integer" | ||
1328 | 177 | msgstr "Integer" | ||
1329 | 178 | |||
1330 | 179 | #. module: base_custom_attributes | ||
1331 | 180 | #: field:attribute.group,attribute_ids:0 | ||
1332 | 181 | #: model:ir.actions.act_window,name:base_custom_attributes.attribute_attribute_form_action | ||
1333 | 182 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_attribute_ids | ||
1334 | 183 | #: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_attribute_action | ||
1335 | 184 | #: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_in_admin | ||
1336 | 185 | msgid "Attributes" | ||
1337 | 186 | msgstr "Attributs" | ||
1338 | 187 | |||
1339 | 188 | #. module: base_custom_attributes | ||
1340 | 189 | #: field:attribute.attribute,relation_model_id:0 | ||
1341 | 190 | #: field:attribute.group,model_id:0 | ||
1342 | 191 | #: field:attribute.set,model_id:0 | ||
1343 | 192 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_relation_model_id | ||
1344 | 193 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_model_id | ||
1345 | 194 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_set_model_id | ||
1346 | 195 | msgid "Model" | ||
1347 | 196 | msgstr "Modèle" | ||
1348 | 197 | |||
1349 | 198 | #. module: base_custom_attributes | ||
1350 | 199 | #: model:ir.actions.act_window,name:base_custom_attributes.attribute_set_form_action | ||
1351 | 200 | #: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_set_action | ||
1352 | 201 | msgid "Attribute Sets" | ||
1353 | 202 | msgstr "Jeux d'attributs" | ||
1354 | 203 | |||
1355 | 204 | #. module: base_custom_attributes | ||
1356 | 205 | #: view:attribute.attribute:0 | ||
1357 | 206 | msgid "Load Options" | ||
1358 | 207 | msgstr "Charger les options" | ||
1359 | 208 | |||
1360 | 209 | #. module: base_custom_attributes | ||
1361 | 210 | #: field:attribute.option,value_ref:0 | ||
1362 | 211 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_value_ref | ||
1363 | 212 | msgid "Reference" | ||
1364 | 213 | msgstr "Référence" | ||
1365 | 214 | |||
1366 | 215 | #. module: base_custom_attributes | ||
1367 | 216 | #: field:attribute.group,sequence:0 | ||
1368 | 217 | #: field:attribute.location,sequence:0 | ||
1369 | 218 | #: field:attribute.option,sequence:0 | ||
1370 | 219 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_sequence | ||
1371 | 220 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_sequence | ||
1372 | 221 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_sequence | ||
1373 | 222 | msgid "Sequence" | ||
1374 | 223 | msgstr "Séquence" | ||
1375 | 224 | |||
1376 | 225 | #. module: base_custom_attributes | ||
1377 | 226 | #: view:attribute.attribute:0 | ||
1378 | 227 | #: field:attribute.location,attribute_id:0 | ||
1379 | 228 | #: field:attribute.option,attribute_id:0 | ||
1380 | 229 | #: field:attribute.option.wizard,attribute_id:0 | ||
1381 | 230 | #: model:ir.model,name:base_custom_attributes.model_attribute_attribute | ||
1382 | 231 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_attribute_id | ||
1383 | 232 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_attribute_id | ||
1384 | 233 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_wizard_attribute_id | ||
1385 | 234 | msgid "Attribute" | ||
1386 | 235 | msgstr "Attribut" | ||
1387 | 236 | |||
1388 | 237 | #. module: base_custom_attributes | ||
1389 | 238 | #: selection:attribute.attribute,attribute_type:0 | ||
1390 | 239 | msgid "Float" | ||
1391 | 240 | msgstr "Float" | ||
1392 | 241 | |||
1393 | 242 | #. module: base_custom_attributes | ||
1394 | 243 | #: field:attribute.group,attribute_set_id:0 | ||
1395 | 244 | #: field:attribute.location,attribute_set_id:0 | ||
1396 | 245 | #: view:attribute.set:0 | ||
1397 | 246 | #: model:ir.model,name:base_custom_attributes.model_attribute_set | ||
1398 | 247 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_attribute_set_id | ||
1399 | 248 | #: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_attribute_set_id | ||
1400 | 249 | msgid "Attribute Set" | ||
1401 | 250 | msgstr "Jeux d'attributs" | ||
1402 | 251 | |||
1403 | 252 | #. module: base_custom_attributes | ||
1404 | 253 | #: selection:attribute.attribute,attribute_type:0 | ||
1405 | 254 | msgid "Datetime" | ||
1406 | 255 | msgstr "Datetime" | ||
1407 | 256 | |||
1408 | 257 | #. module: base_custom_attributes | ||
1409 | 258 | #: selection:attribute.attribute,attribute_type:0 | ||
1410 | 259 | msgid "Char" | ||
1411 | 260 | msgstr "Char" | ||
1412 | 261 | |||
1413 | 262 | #. module: base_custom_attributes | ||
1414 | 263 | #: selection:attribute.attribute,attribute_type:0 | ||
1415 | 264 | msgid "Boolean" | ||
1416 | 265 | msgstr "Boolean" | ||
1417 | 266 | |||
1418 | 267 | #. module: base_custom_attributes | ||
1419 | 268 | #: selection:attribute.attribute,attribute_type:0 | ||
1420 | 269 | msgid "Text" | ||
1421 | 270 | msgstr "Text" | ||
1422 | 271 | |||
1423 | 272 | #. module: base_custom_attributes | ||
1424 | 273 | #: view:attribute.option.wizard:0 | ||
1425 | 274 | msgid "Cancel" | ||
1426 | 275 | msgstr "Annuler" | ||
1427 | 276 | |||
1428 | 277 | #. module: base_custom_attributes | ||
1429 | 278 | #: model:ir.model,name:base_custom_attributes.model_attribute_option_wizard | ||
1430 | 279 | msgid "attribute.option.wizard" | ||
1431 | 280 | msgstr "attribute.option.wizard" | ||
1432 | 281 | |||
1433 | 282 | #. module: base_custom_attributes | ||
1434 | 283 | #: sql_constraint:ir.model.fields:0 | ||
1435 | 284 | msgid "The name of the field has to be uniq for a given model !" | ||
1436 | 285 | msgstr "Le nom du champ doit être unique pour un modèle donné !" | ||
1437 | 286 | |||
1438 | 287 | #. module: base_custom_attributes | ||
1439 | 288 | #: selection:attribute.attribute,attribute_type:0 | ||
1440 | 289 | msgid "Select" | ||
1441 | 290 | msgstr "Select" | ||
1442 | 291 | |||
1443 | 0 | 292 | ||
1444 | === added file 'base_custom_attributes/ir_model.py' | |||
1445 | --- base_custom_attributes/ir_model.py 1970-01-01 00:00:00 +0000 | |||
1446 | +++ base_custom_attributes/ir_model.py 2013-12-11 14:54:36 +0000 | |||
1447 | @@ -0,0 +1,39 @@ | |||
1448 | 1 | # -*- encoding: utf-8 -*- | ||
1449 | 2 | ############################################################################### | ||
1450 | 3 | # # | ||
1451 | 4 | # product_custom_attributes for OpenERP | ||
1452 | 5 | # Copyright (C) 2011 Akretion Benoît GUILLOT <benoit.guillot@akretion.com> | ||
1453 | 6 | # # | ||
1454 | 7 | # This program is free software: you can redistribute it and/or modify # | ||
1455 | 8 | # it under the terms of the GNU Affero General Public License as # | ||
1456 | 9 | # published by the Free Software Foundation, either version 3 of the # | ||
1457 | 10 | # License, or (at your option) any later version. # | ||
1458 | 11 | # # | ||
1459 | 12 | # This program is distributed in the hope that it will be useful, # | ||
1460 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | ||
1461 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | ||
1462 | 15 | # GNU Affero General Public License for more details. # | ||
1463 | 16 | # # | ||
1464 | 17 | # You should have received a copy of the GNU Affero General Public License # | ||
1465 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | ||
1466 | 19 | # # | ||
1467 | 20 | ############################################################################### | ||
1468 | 21 | |||
1469 | 22 | from openerp.osv.orm import Model | ||
1470 | 23 | from openerp.osv import fields | ||
1471 | 24 | |||
1472 | 25 | |||
1473 | 26 | class ir_model_fields(Model): | ||
1474 | 27 | |||
1475 | 28 | _inherit = "ir.model.fields" | ||
1476 | 29 | _columns = { | ||
1477 | 30 | 'field_description': fields.char( | ||
1478 | 31 | 'Field Label', | ||
1479 | 32 | required=True, | ||
1480 | 33 | size=256, | ||
1481 | 34 | translate=True), | ||
1482 | 35 | } | ||
1483 | 36 | _sql_constraints = [ | ||
1484 | 37 | ('name_model_uniq', 'unique (name, model_id)', | ||
1485 | 38 | 'The name of the field has to be uniq for a given model !'), | ||
1486 | 39 | ] | ||
1487 | 0 | 40 | ||
1488 | === added directory 'base_custom_attributes/security' | |||
1489 | === added file 'base_custom_attributes/security/attribute_security.xml' | |||
1490 | --- base_custom_attributes/security/attribute_security.xml 1970-01-01 00:00:00 +0000 | |||
1491 | +++ base_custom_attributes/security/attribute_security.xml 2013-12-11 14:54:36 +0000 | |||
1492 | @@ -0,0 +1,11 @@ | |||
1493 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
1494 | 2 | <openerp> | ||
1495 | 3 | <data noupdate="0"> | ||
1496 | 4 | |||
1497 | 5 | <record id="base.group_advanced_attribute" model="res.groups"> | ||
1498 | 6 | <field name="name">Advanced Attribute Option</field> | ||
1499 | 7 | <field name="category_id" ref="base.module_category_hidden"/> | ||
1500 | 8 | </record> | ||
1501 | 9 | |||
1502 | 10 | </data> | ||
1503 | 11 | </openerp> | ||
1504 | 0 | 12 | ||
1505 | === added file 'base_custom_attributes/security/ir.model.access.csv' | |||
1506 | --- base_custom_attributes/security/ir.model.access.csv 1970-01-01 00:00:00 +0000 | |||
1507 | +++ base_custom_attributes/security/ir.model.access.csv 2013-12-11 14:54:36 +0000 | |||
1508 | @@ -0,0 +1,13 @@ | |||
1509 | 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink | ||
1510 | 2 | access_base_custom_attributes_attribute_group_salemanager,base_custom_attributes_attribute_group,base_custom_attributes.model_attribute_group,base.group_sale_manager,1,1,1,1 | ||
1511 | 3 | access_base_custom_attributes_attribute_attribute_salemanager,base_custom_attributes_product_attribute,base_custom_attributes.model_attribute_attribute,base.group_sale_manager,1,1,1,1 | ||
1512 | 4 | access_base_custom_attributes_attribute_option_salemanager,base_custom_attributes_attribute_option,base_custom_attributes.model_attribute_option,base.group_sale_manager,1,1,1,1 | ||
1513 | 5 | access_base_custom_attributes_attribute_location_salemanager,base_custom_attributes_attribute_location,base_custom_attributes.model_attribute_location,base.group_sale_manager,1,1,1,1 | ||
1514 | 6 | access_base_custom_attributes_attribute_group_manager,base_custom_attributes_attribute_group,base_custom_attributes.model_attribute_group,base.group_no_one,1,1,1,1 | ||
1515 | 7 | access_base_custom_attributes_attribute_attribute_manager,base_custom_attributes_attribute_attribute,base_custom_attributes.model_attribute_attribute,base.group_no_one,1,1,1,1 | ||
1516 | 8 | access_base_custom_attributes_attribute_option_manager,base_custom_attributes_attribute_option,base_custom_attributes.model_attribute_option,base.group_no_one,1,1,1,1 | ||
1517 | 9 | access_base_custom_attributes_attribute_location_manager,base_custom_attributes_attribute_location,base_custom_attributes.model_attribute_location,base.group_no_one,1,1,1,1 | ||
1518 | 10 | access_base_custom_attributes_attribute_group_user,base_custom_attributes_attribute_group,base_custom_attributes.model_attribute_group,base.group_user,1,0,0,0 | ||
1519 | 11 | access_base_custom_attributes_attribute_attribute_user,base_custom_attributes_attribute_attribute,base_custom_attributes.model_attribute_attribute,base.group_user,1,0,0,0 | ||
1520 | 12 | access_base_custom_attributes_attribute_option_user,base_custom_attributes_attribute_option,base_custom_attributes.model_attribute_option,base.group_user,1,0,0,0 | ||
1521 | 13 | access_base_custom_attributes_attribute_location_user,base_custom_attributes_attribute_location,base_custom_attributes.model_attribute_location,base.group_user,1,1,1,0 | ||
1522 | 0 | 14 | ||
1523 | === added directory 'production_lot_custom_attributes' | |||
1524 | === added file 'production_lot_custom_attributes/__init__.py' | |||
1525 | --- production_lot_custom_attributes/__init__.py 1970-01-01 00:00:00 +0000 | |||
1526 | +++ production_lot_custom_attributes/__init__.py 2013-12-11 14:54:36 +0000 | |||
1527 | @@ -0,0 +1,25 @@ | |||
1528 | 1 | # -*- coding: utf-8 -*- | ||
1529 | 2 | ############################################################################### | ||
1530 | 3 | # # | ||
1531 | 4 | # Author: Leonardo Pistone <leonardo.pistone@camptocamp.com> # | ||
1532 | 5 | # Copyright 2013 Camptocamp SA # | ||
1533 | 6 | # # | ||
1534 | 7 | # Inspired by the module product_custom_attributes # | ||
1535 | 8 | # by Benoît GUILLOT <benoit.guillot@akretion.com>, Akretion # | ||
1536 | 9 | # # | ||
1537 | 10 | # This program is free software: you can redistribute it and/or modify # | ||
1538 | 11 | # it under the terms of the GNU Affero General Public License as # | ||
1539 | 12 | # published by the Free Software Foundation, either version 3 of the # | ||
1540 | 13 | # License, or (at your option) any later version. # | ||
1541 | 14 | # # | ||
1542 | 15 | # This program is distributed in the hope that it will be useful, # | ||
1543 | 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | ||
1544 | 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | ||
1545 | 18 | # GNU Affero General Public License for more details. # | ||
1546 | 19 | # # | ||
1547 | 20 | # You should have received a copy of the GNU Affero General Public License # | ||
1548 | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | ||
1549 | 22 | # # | ||
1550 | 23 | ############################################################################### | ||
1551 | 24 | from . import lot | ||
1552 | 25 | from . import wizard | ||
1553 | 0 | 26 | ||
1554 | === added file 'production_lot_custom_attributes/__openerp__.py' | |||
1555 | --- production_lot_custom_attributes/__openerp__.py 1970-01-01 00:00:00 +0000 | |||
1556 | +++ production_lot_custom_attributes/__openerp__.py 2013-12-11 14:54:36 +0000 | |||
1557 | @@ -0,0 +1,62 @@ | |||
1558 | 1 | # -*- coding: utf-8 -*- | ||
1559 | 2 | ############################################################################### | ||
1560 | 3 | # # | ||
1561 | 4 | # Author: Leonardo Pistone <leonardo.pistone@camptocamp.com> # | ||
1562 | 5 | # Copyright 2013 Camptocamp SA # | ||
1563 | 6 | # # | ||
1564 | 7 | # Inspired by the module product_custom_attributes # | ||
1565 | 8 | # by Benoît GUILLOT <benoit.guillot@akretion.com>, Akretion # | ||
1566 | 9 | # # | ||
1567 | 10 | # This program is free software: you can redistribute it and/or modify # | ||
1568 | 11 | # it under the terms of the GNU Affero General Public License as # | ||
1569 | 12 | # published by the Free Software Foundation, either version 3 of the # | ||
1570 | 13 | # License, or (at your option) any later version. # | ||
1571 | 14 | # # | ||
1572 | 15 | # This program is distributed in the hope that it will be useful, # | ||
1573 | 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | ||
1574 | 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | ||
1575 | 18 | # GNU Affero General Public License for more details. # | ||
1576 | 19 | # # | ||
1577 | 20 | # You should have received a copy of the GNU Affero General Public License # | ||
1578 | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | ||
1579 | 22 | # # | ||
1580 | 23 | ############################################################################### | ||
1581 | 24 | |||
1582 | 25 | {'name': 'production_lot_custom_attributes', | ||
1583 | 26 | 'version': '0.1', | ||
1584 | 27 | 'category': 'Generic Modules/Others', | ||
1585 | 28 | 'license': 'AGPL-3', | ||
1586 | 29 | 'description': """ | ||
1587 | 30 | Production lot custom attributes | ||
1588 | 31 | ================================ | ||
1589 | 32 | |||
1590 | 33 | This module adds the possibility to easily create custom fields on stock | ||
1591 | 34 | production lots. Each lot can be linked to an attribute set. | ||
1592 | 35 | Each attribute has custom fields (for example, you don't need the same field | ||
1593 | 36 | for a frigde and a camera). | ||
1594 | 37 | In particular it's used by the Magento Magentoerpconnect module to match the | ||
1595 | 38 | EAV flexibility of Magento. | ||
1596 | 39 | |||
1597 | 40 | Warning: This module is not compatible with product_custom_attributes from 6.1. | ||
1598 | 41 | To make the two compatible, product_custom_attributes should be split to depend | ||
1599 | 42 | from base_custom_attributes, like it is already in 7.0. | ||
1600 | 43 | |||
1601 | 44 | This module is inspired by the module product_custom_attributes by | ||
1602 | 45 | Benoît GUILLOT, Akretion | ||
1603 | 46 | |||
1604 | 47 | """, | ||
1605 | 48 | 'complexity': 'normal', | ||
1606 | 49 | 'author': 'Camptocamp', | ||
1607 | 50 | 'website': 'http://www.camptocamp.com/', | ||
1608 | 51 | 'depends': ['stock', 'base_custom_attributes'], | ||
1609 | 52 | 'init_xml': [], | ||
1610 | 53 | 'update_xml': ['lot_view.xml', | ||
1611 | 54 | 'custom_attributes_view.xml', | ||
1612 | 55 | 'wizard/open_lot_by_attribute_set.xml' | ||
1613 | 56 | ], | ||
1614 | 57 | 'test': ['test/lot_attribute_test.yml', | ||
1615 | 58 | ], | ||
1616 | 59 | 'demo_xml': [], | ||
1617 | 60 | 'installable': True, | ||
1618 | 61 | 'active': False, | ||
1619 | 62 | } | ||
1620 | 0 | 63 | ||
1621 | === added file 'production_lot_custom_attributes/custom_attributes_view.xml' | |||
1622 | --- production_lot_custom_attributes/custom_attributes_view.xml 1970-01-01 00:00:00 +0000 | |||
1623 | +++ production_lot_custom_attributes/custom_attributes_view.xml 2013-12-11 14:54:36 +0000 | |||
1624 | @@ -0,0 +1,58 @@ | |||
1625 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
1626 | 2 | <openerp> | ||
1627 | 3 | <data> | ||
1628 | 4 | |||
1629 | 5 | <menuitem | ||
1630 | 6 | id="menu_lot_attribute_in_warehouse_config" | ||
1631 | 7 | name="Serial Number Attributes" | ||
1632 | 8 | parent="stock.menu_warehouse_config" | ||
1633 | 9 | sequence="20"/> | ||
1634 | 10 | |||
1635 | 11 | <record id="lot_attribute_set_form_action" model="ir.actions.act_window"> | ||
1636 | 12 | <field name="name">Lot Attribute Sets</field> | ||
1637 | 13 | <field name="res_model">attribute.set</field> | ||
1638 | 14 | <field name="view_type">form</field> | ||
1639 | 15 | <field name="view_mode">tree,form</field> | ||
1640 | 16 | <field name="search_view_id" ref="base_custom_attributes.view_attribute_set_search"/> | ||
1641 | 17 | <field name="context">{"force_model": 'stock.production.lot'}</field> | ||
1642 | 18 | <field name="help"></field> | ||
1643 | 19 | </record> | ||
1644 | 20 | |||
1645 | 21 | <record id="lot_attribute_group_form_action" model="ir.actions.act_window"> | ||
1646 | 22 | <field name="name">Attribute Groups</field> | ||
1647 | 23 | <field name="res_model">attribute.group</field> | ||
1648 | 24 | <field name="view_type">form</field> | ||
1649 | 25 | <field name="view_mode">tree,form</field> | ||
1650 | 26 | <field name="search_view_id" ref="base_custom_attributes.view_attribute_attribute_search"/> | ||
1651 | 27 | <field name="context">{"force_model": 'stock.production.lot'}</field> | ||
1652 | 28 | <field name="help"></field> | ||
1653 | 29 | </record> | ||
1654 | 30 | |||
1655 | 31 | <record id="lot_attribute_attribute_form_action" model="ir.actions.act_window"> | ||
1656 | 32 | <field name="name">Lot Attributes</field> | ||
1657 | 33 | <field name="res_model">attribute.attribute</field> | ||
1658 | 34 | <field name="view_type">form</field> | ||
1659 | 35 | <field name="view_mode">tree,form</field> | ||
1660 | 36 | <field name="search_view_id" ref="base_custom_attributes.view_attribute_attribute_search"/> | ||
1661 | 37 | <field name="context">{"force_model": 'stock.production.lot'}</field> | ||
1662 | 38 | <field name="help"></field> | ||
1663 | 39 | </record> | ||
1664 | 40 | |||
1665 | 41 | <menuitem | ||
1666 | 42 | action="lot_attribute_set_form_action" | ||
1667 | 43 | id="menu_lot_attribute_set_action" | ||
1668 | 44 | parent="menu_lot_attribute_in_warehouse_config" | ||
1669 | 45 | sequence="1"/> | ||
1670 | 46 | <menuitem | ||
1671 | 47 | action="lot_attribute_group_form_action" | ||
1672 | 48 | id="menu_lot_attribute_group_action" | ||
1673 | 49 | parent="menu_lot_attribute_in_warehouse_config" | ||
1674 | 50 | sequence="2"/> | ||
1675 | 51 | <menuitem | ||
1676 | 52 | action="lot_attribute_attribute_form_action" | ||
1677 | 53 | id="menu_lot_attribute_attribute_action" | ||
1678 | 54 | parent="menu_lot_attribute_in_warehouse_config" | ||
1679 | 55 | sequence="4"/> | ||
1680 | 56 | |||
1681 | 57 | </data> | ||
1682 | 58 | </openerp> | ||
1683 | 0 | 59 | ||
1684 | === added file 'production_lot_custom_attributes/lot.py' | |||
1685 | --- production_lot_custom_attributes/lot.py 1970-01-01 00:00:00 +0000 | |||
1686 | +++ production_lot_custom_attributes/lot.py 2013-12-11 14:54:36 +0000 | |||
1687 | @@ -0,0 +1,207 @@ | |||
1688 | 1 | # -*- coding: utf-8 -*- | ||
1689 | 2 | ############################################################################### | ||
1690 | 3 | # # | ||
1691 | 4 | # Author: Leonardo Pistone <leonardo.pistone@camptocamp.com> # | ||
1692 | 5 | # Copyright 2013 Camptocamp SA # | ||
1693 | 6 | # # | ||
1694 | 7 | # Inspired by the module product_custom_attributes # | ||
1695 | 8 | # by Benoît GUILLOT <benoit.guillot@akretion.com>, Akretion # | ||
1696 | 9 | # # | ||
1697 | 10 | # This program is free software: you can redistribute it and/or modify # | ||
1698 | 11 | # it under the terms of the GNU Affero General Public License as # | ||
1699 | 12 | # published by the Free Software Foundation, either version 3 of the # | ||
1700 | 13 | # License, or (at your option) any later version. # | ||
1701 | 14 | # # | ||
1702 | 15 | # This program is distributed in the hope that it will be useful, # | ||
1703 | 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | ||
1704 | 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | ||
1705 | 18 | # GNU Affero General Public License for more details. # | ||
1706 | 19 | # # | ||
1707 | 20 | # You should have received a copy of the GNU Affero General Public License # | ||
1708 | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | ||
1709 | 22 | # # | ||
1710 | 23 | ############################################################################### | ||
1711 | 24 | |||
1712 | 25 | from openerp.osv import fields, osv | ||
1713 | 26 | from tools.translate import _ | ||
1714 | 27 | from lxml import etree | ||
1715 | 28 | import re | ||
1716 | 29 | |||
1717 | 30 | |||
1718 | 31 | class stock_production_lot(osv.Model): | ||
1719 | 32 | _inherit = "stock.production.lot" | ||
1720 | 33 | |||
1721 | 34 | def _search_all_attributes(self, cr, uid, obj, name, args, context): | ||
1722 | 35 | """Search in all serialized attributes | ||
1723 | 36 | |||
1724 | 37 | Receives a domain in args, and expands all relevant terms into ids | ||
1725 | 38 | to search into all attributes. The ORM will take care of security | ||
1726 | 39 | afterwards, so it' OK to use SQL here. | ||
1727 | 40 | |||
1728 | 41 | In the future, we could consider storing attributes as native PostgreSQL | ||
1729 | 42 | hstore or JSON instead of strings, and substitute this rough regexp | ||
1730 | 43 | search with native PostgreSQL goodness. | ||
1731 | 44 | |||
1732 | 45 | """ | ||
1733 | 46 | |||
1734 | 47 | def expand_arg(arg): | ||
1735 | 48 | """Takes a single argument of the domain, and when possible expands | ||
1736 | 49 | it to a trivial domain ('in', 'in', list) | ||
1737 | 50 | |||
1738 | 51 | """ | ||
1739 | 52 | if isinstance(arg, tuple) and arg[0] == name: | ||
1740 | 53 | if arg[1] == 'like': | ||
1741 | 54 | operator = '~' | ||
1742 | 55 | elif arg[1] == 'ilike': | ||
1743 | 56 | operator = '~*' | ||
1744 | 57 | else: | ||
1745 | 58 | raise osv.except_osv( | ||
1746 | 59 | _('Not Implemented!'), | ||
1747 | 60 | _('Search not supported for this field')) | ||
1748 | 61 | |||
1749 | 62 | cr.execute( | ||
1750 | 63 | """ | ||
1751 | 64 | select id | ||
1752 | 65 | from {0} | ||
1753 | 66 | where x_custom_json_attrs {1} %s; | ||
1754 | 67 | """.format( | ||
1755 | 68 | self._table, | ||
1756 | 69 | operator | ||
1757 | 70 | ), | ||
1758 | 71 | (ur'.*: "[^"]*%s' % re.escape(arg[2]) ,) | ||
1759 | 72 | ) | ||
1760 | 73 | sql_ids = [line[0] for line in cr.fetchall()] | ||
1761 | 74 | return ('id', 'in', sql_ids) | ||
1762 | 75 | else: | ||
1763 | 76 | return arg | ||
1764 | 77 | |||
1765 | 78 | return [expand_arg(arg) for arg in args] | ||
1766 | 79 | |||
1767 | 80 | _columns = { | ||
1768 | 81 | 'attribute_set_id': fields.many2one('attribute.set', 'Attribute Set'), | ||
1769 | 82 | 'attribute_group_ids': fields.related( | ||
1770 | 83 | 'attribute_set_id', | ||
1771 | 84 | 'attribute_group_ids', | ||
1772 | 85 | type='many2many', | ||
1773 | 86 | relation='attribute.group' | ||
1774 | 87 | ), | ||
1775 | 88 | 'search_all_attributes': fields.function( | ||
1776 | 89 | lambda self, cr, uid, ids, field, args, context: u'', | ||
1777 | 90 | type="char", | ||
1778 | 91 | fnct_search=_search_all_attributes, | ||
1779 | 92 | method=True, | ||
1780 | 93 | string="Search all Attributes"), | ||
1781 | 94 | } | ||
1782 | 95 | |||
1783 | 96 | def _fix_size_bug(self, cr, uid, result, context=None): | ||
1784 | 97 | """When created a field text dynamicaly, its size is limited to 64 in | ||
1785 | 98 | the view. The bug is fixed but not merged | ||
1786 | 99 | https://code.launchpad.net/~openerp-dev/openerp-web/6.1-opw-579462-cpa | ||
1787 | 100 | To remove when the fix will be merged | ||
1788 | 101 | |||
1789 | 102 | """ | ||
1790 | 103 | for field in result['fields']: | ||
1791 | 104 | if result['fields'][field]['type'] == 'text': | ||
1792 | 105 | if 'size' in result['fields'][field]: | ||
1793 | 106 | del result['fields'][field]['size'] | ||
1794 | 107 | return result | ||
1795 | 108 | |||
1796 | 109 | def open_attributes(self, cr, uid, ids, context=None): | ||
1797 | 110 | """Open the attributes of an object | ||
1798 | 111 | |||
1799 | 112 | This method is called when the user presses the Open Attributes button | ||
1800 | 113 | in the form view of the object. It opens a dinamically-built form view. | ||
1801 | 114 | |||
1802 | 115 | :param ids: this is normally a singleton. If a longer list is passed, | ||
1803 | 116 | we consider only the first item. | ||
1804 | 117 | |||
1805 | 118 | """ | ||
1806 | 119 | |||
1807 | 120 | if context is None: | ||
1808 | 121 | context = {} | ||
1809 | 122 | |||
1810 | 123 | model_data_pool = self.pool.get('ir.model.data') | ||
1811 | 124 | |||
1812 | 125 | for lot in self.browse(cr, uid, ids, context=context): | ||
1813 | 126 | view_id = model_data_pool.get_object_reference( | ||
1814 | 127 | cr, uid, | ||
1815 | 128 | 'production_lot_custom_attributes', | ||
1816 | 129 | 'lot_attributes_form_view')[1] | ||
1817 | 130 | ctx = { | ||
1818 | 131 | 'open_attributes': True, | ||
1819 | 132 | 'attribute_group_ids': [ | ||
1820 | 133 | group.id for group in lot.attribute_group_ids | ||
1821 | 134 | ] | ||
1822 | 135 | } | ||
1823 | 136 | |||
1824 | 137 | return { | ||
1825 | 138 | 'name': 'Lot Attributes', | ||
1826 | 139 | 'view_type': 'form', | ||
1827 | 140 | 'view_mode': 'form', | ||
1828 | 141 | 'view_id': [view_id], | ||
1829 | 142 | 'res_model': self._name, | ||
1830 | 143 | 'context': ctx, | ||
1831 | 144 | 'type': 'ir.actions.act_window', | ||
1832 | 145 | 'nodestroy': True, | ||
1833 | 146 | 'target': 'new', | ||
1834 | 147 | 'res_id': lot.id, | ||
1835 | 148 | } | ||
1836 | 149 | |||
1837 | 150 | def save_and_close_lot_attributes(self, cr, uid, ids, context=None): | ||
1838 | 151 | return {'type': 'ir.actions.act_window_close'} | ||
1839 | 152 | |||
1840 | 153 | def fields_view_get(self, cr, uid, view_id=None, view_type='form', | ||
1841 | 154 | context=None, toolbar=False, submenu=False): | ||
1842 | 155 | """Dinamically adds attributes to the view | ||
1843 | 156 | |||
1844 | 157 | Modifies dinamically the view to show the attributes. If the users | ||
1845 | 158 | presses the Open Attributes button, the attributes are shown in a | ||
1846 | 159 | new form field. Otherwise, if the attribute set is known beforehand, | ||
1847 | 160 | attributes are added to a new tab in the main form view. | ||
1848 | 161 | |||
1849 | 162 | """ | ||
1850 | 163 | if context is None: | ||
1851 | 164 | context = {} | ||
1852 | 165 | attr_pool = self.pool.get('attribute.attribute') | ||
1853 | 166 | result = super(stock_production_lot, self).fields_view_get( | ||
1854 | 167 | cr, uid, view_id, view_type, context, toolbar=toolbar, | ||
1855 | 168 | submenu=submenu | ||
1856 | 169 | ) | ||
1857 | 170 | if view_type == 'form' and context.get('attribute_group_ids'): | ||
1858 | 171 | eview = etree.fromstring(result['arch']) | ||
1859 | 172 | #hide button under the name | ||
1860 | 173 | button = eview.xpath("//button[@name='open_attributes']") | ||
1861 | 174 | if button: | ||
1862 | 175 | button = button[0] | ||
1863 | 176 | button.getparent().remove(button) | ||
1864 | 177 | attributes_notebook, toupdate_fields = ( | ||
1865 | 178 | attr_pool._build_attributes_notebook( | ||
1866 | 179 | cr, uid, context['attribute_group_ids'], context=context | ||
1867 | 180 | ) | ||
1868 | 181 | ) | ||
1869 | 182 | result['fields'].update( | ||
1870 | 183 | self.fields_get(cr, uid, toupdate_fields, context) | ||
1871 | 184 | ) | ||
1872 | 185 | if context.get('open_attributes'): | ||
1873 | 186 | # i.e. the user pressed the open attributes button on the | ||
1874 | 187 | # form view. We put the attributes in a separate form view | ||
1875 | 188 | placeholder = eview.xpath( | ||
1876 | 189 | "//separator[@string='attributes_placeholder']" | ||
1877 | 190 | )[0] | ||
1878 | 191 | placeholder.getparent().replace( | ||
1879 | 192 | placeholder, attributes_notebook | ||
1880 | 193 | ) | ||
1881 | 194 | elif context.get('open_lot_by_attribute_set'): | ||
1882 | 195 | # in this case, we know the attribute set beforehand, and we | ||
1883 | 196 | # add the attributes to the current view | ||
1884 | 197 | main_page = etree.Element( | ||
1885 | 198 | 'page', string=_('Custom Attributes') | ||
1886 | 199 | ) | ||
1887 | 200 | main_page.append(attributes_notebook) | ||
1888 | 201 | info_page = eview.xpath( | ||
1889 | 202 | "//page[@string='%s']" % (_('Stock Moves'),) | ||
1890 | 203 | )[0] | ||
1891 | 204 | info_page.addnext(main_page) | ||
1892 | 205 | result['arch'] = etree.tostring(eview, pretty_print=True) | ||
1893 | 206 | result = self._fix_size_bug(cr, uid, result, context=context) | ||
1894 | 207 | return result | ||
1895 | 0 | 208 | ||
1896 | === added file 'production_lot_custom_attributes/lot_view.xml' | |||
1897 | --- production_lot_custom_attributes/lot_view.xml 1970-01-01 00:00:00 +0000 | |||
1898 | +++ production_lot_custom_attributes/lot_view.xml 2013-12-11 14:54:36 +0000 | |||
1899 | @@ -0,0 +1,52 @@ | |||
1900 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
1901 | 2 | |||
1902 | 3 | <openerp> | ||
1903 | 4 | <data> | ||
1904 | 5 | |||
1905 | 6 | <record model="ir.ui.view" id="lot_form_view_set_button"> | ||
1906 | 7 | <field name="name">attributes.lot.normal.form</field> | ||
1907 | 8 | <field name="model">stock.production.lot</field> | ||
1908 | 9 | <field name="inherit_id" ref="stock.view_production_lot_form"/> | ||
1909 | 10 | <field name="arch" type="xml"> | ||
1910 | 11 | <notebook position="inside"> | ||
1911 | 12 | <page string="Attributes"> | ||
1912 | 13 | <group name="attribute_fields"> | ||
1913 | 14 | <field name="attribute_set_id" /> | ||
1914 | 15 | <button name="open_attributes" string="Open Attributes" type="object" icon="gtk-ok" attrs="{'invisible':[('attribute_set_id', '=', False)]}"/> | ||
1915 | 16 | </group> | ||
1916 | 17 | </page> | ||
1917 | 18 | </notebook> | ||
1918 | 19 | </field> | ||
1919 | 20 | </record> | ||
1920 | 21 | |||
1921 | 22 | <record model="ir.ui.view" id="search_product_lot_filter"> | ||
1922 | 23 | <field name="model">stock.production.lot</field> | ||
1923 | 24 | <field name="inherit_id" ref="stock.search_product_lot_filter"/> | ||
1924 | 25 | <field name="arch" type="xml"> | ||
1925 | 26 | <field name="date" position="after"> | ||
1926 | 27 | <field name="search_all_attributes"/> | ||
1927 | 28 | </field> | ||
1928 | 29 | </field> | ||
1929 | 30 | </record> | ||
1930 | 31 | |||
1931 | 32 | <record model="ir.ui.view" id="lot_attributes_form_view"> | ||
1932 | 33 | <field name="name">lot.attributes.normal.wizard</field> | ||
1933 | 34 | <field name="model">stock.production.lot</field> | ||
1934 | 35 | <field name="priority">20</field> | ||
1935 | 36 | <field name="arch" type="xml"> | ||
1936 | 37 | <form string="Lot"> | ||
1937 | 38 | <group name="name_set" colspan='4' col='8'> | ||
1938 | 39 | <field name="name"/> | ||
1939 | 40 | <field name="attribute_set_id" /> | ||
1940 | 41 | </group> | ||
1941 | 42 | <separator string="attributes_placeholder" colspan="4"/> | ||
1942 | 43 | <group colspan='4' col='4'> | ||
1943 | 44 | <button icon="gtk-cancel" special="cancel" string="Cancel"/> | ||
1944 | 45 | <button icon="gtk-ok" name="save_and_close_lot_attributes" string="Save and Close" type="object"/> | ||
1945 | 46 | </group> | ||
1946 | 47 | </form> | ||
1947 | 48 | </field> | ||
1948 | 49 | </record> | ||
1949 | 50 | |||
1950 | 51 | </data> | ||
1951 | 52 | </openerp> | ||
1952 | 0 | 53 | ||
1953 | === added directory 'production_lot_custom_attributes/test' | |||
1954 | === added file 'production_lot_custom_attributes/test/lot_attribute_test.yml' | |||
1955 | --- production_lot_custom_attributes/test/lot_attribute_test.yml 1970-01-01 00:00:00 +0000 | |||
1956 | +++ production_lot_custom_attributes/test/lot_attribute_test.yml 2013-12-11 14:54:36 +0000 | |||
1957 | @@ -0,0 +1,48 @@ | |||
1958 | 1 | - | ||
1959 | 2 | In order to test Production Lot Custom Fields | ||
1960 | 3 | - | ||
1961 | 4 | First I create an Attribute Set | ||
1962 | 5 | - | ||
1963 | 6 | !record {model: attribute.set, id: lot_attribute_set_A}: | ||
1964 | 7 | name: Serial Number Attribute Set A | ||
1965 | 8 | model_id: stock.model_stock_production_lot | ||
1966 | 9 | attribute_group_ids: | ||
1967 | 10 | - name: Components | ||
1968 | 11 | model_id: stock.model_stock_production_lot | ||
1969 | 12 | sequence: 1 | ||
1970 | 13 | attribute_ids: | ||
1971 | 14 | - name: x_ram_amount | ||
1972 | 15 | model_id: stock.model_stock_production_lot | ||
1973 | 16 | field_description: Amount of RAM | ||
1974 | 17 | attribute_type: float | ||
1975 | 18 | - name: x_has_display | ||
1976 | 19 | model_id: stock.model_stock_production_lot | ||
1977 | 20 | field_description: Has Display | ||
1978 | 21 | attribute_type: boolean | ||
1979 | 22 | - name: Characteristics | ||
1980 | 23 | model_id: stock.model_stock_production_lot | ||
1981 | 24 | sequence: 2 | ||
1982 | 25 | attribute_ids: | ||
1983 | 26 | - name: x_color | ||
1984 | 27 | model_id: stock.model_stock_production_lot | ||
1985 | 28 | field_description: Color | ||
1986 | 29 | attribute_type: char | ||
1987 | 30 | - name: x_length | ||
1988 | 31 | model_id: stock.model_stock_production_lot | ||
1989 | 32 | field_description: Length | ||
1990 | 33 | attribute_type: float | ||
1991 | 34 | - | ||
1992 | 35 | Then I create a Serial Number and set some Attributes | ||
1993 | 36 | - | ||
1994 | 37 | !record {model: stock.production.lot, id: lot_A}: | ||
1995 | 38 | product_id: product.product_product_pc2 | ||
1996 | 39 | name: 0005 | ||
1997 | 40 | attribute_set_id: lot_attribute_set_A | ||
1998 | 41 | x_color: green | ||
1999 | 42 | x_length: 12.5 | ||
2000 | 43 | - | ||
2001 | 44 | Now I check that my attributes are there | ||
2002 | 45 | - | ||
2003 | 46 | !assert {model: stock.production.lot, id: lot_A, string: Lot Attributes do not work}: | ||
2004 | 47 | - x_color == 'green' | ||
2005 | 48 | - x_length == 12.5 | ||
2006 | 0 | 49 | ||
2007 | === added directory 'production_lot_custom_attributes/wizard' | |||
2008 | === added file 'production_lot_custom_attributes/wizard/__init__.py' | |||
2009 | --- production_lot_custom_attributes/wizard/__init__.py 1970-01-01 00:00:00 +0000 | |||
2010 | +++ production_lot_custom_attributes/wizard/__init__.py 2013-12-11 14:54:36 +0000 | |||
2011 | @@ -0,0 +1,25 @@ | |||
2012 | 1 | # -*- coding: utf-8 -*- | ||
2013 | 2 | ############################################################################### | ||
2014 | 3 | # # | ||
2015 | 4 | # Author: Leonardo Pistone <leonardo.pistone@camptocamp.com> # | ||
2016 | 5 | # Copyright 2013 Camptocamp SA # | ||
2017 | 6 | # # | ||
2018 | 7 | # Inspired by the module product_custom_attributes # | ||
2019 | 8 | # by Benoît GUILLOT <benoit.guillot@akretion.com>, Akretion # | ||
2020 | 9 | # # | ||
2021 | 10 | # This program is free software: you can redistribute it and/or modify # | ||
2022 | 11 | # it under the terms of the GNU Affero General Public License as # | ||
2023 | 12 | # published by the Free Software Foundation, either version 3 of the # | ||
2024 | 13 | # License, or (at your option) any later version. # | ||
2025 | 14 | # # | ||
2026 | 15 | # This program is distributed in the hope that it will be useful, # | ||
2027 | 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | ||
2028 | 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | ||
2029 | 18 | # GNU Affero General Public License for more details. # | ||
2030 | 19 | # # | ||
2031 | 20 | # You should have received a copy of the GNU Affero General Public License # | ||
2032 | 21 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | ||
2033 | 22 | # # | ||
2034 | 23 | ############################################################################### | ||
2035 | 24 | |||
2036 | 25 | from . import open_lot_by_attribute_set | ||
2037 | 0 | 26 | ||
2038 | === added file 'production_lot_custom_attributes/wizard/open_lot_by_attribute_set.py' | |||
2039 | --- production_lot_custom_attributes/wizard/open_lot_by_attribute_set.py 1970-01-01 00:00:00 +0000 | |||
2040 | +++ production_lot_custom_attributes/wizard/open_lot_by_attribute_set.py 2013-12-11 14:54:36 +0000 | |||
2041 | @@ -0,0 +1,67 @@ | |||
2042 | 1 | # -*- coding: utf-8 -*- | ||
2043 | 2 | ############################################################################### | ||
2044 | 3 | # # | ||
2045 | 4 | # Author: Leonardo Pistone <leonardo.pistone@camptocamp.com> # | ||
2046 | 5 | # Copyright 2013 Camptocamp SA # | ||
2047 | 6 | # # | ||
2048 | 7 | # This program is free software: you can redistribute it and/or modify # | ||
2049 | 8 | # it under the terms of the GNU Affero General Public License as # | ||
2050 | 9 | # published by the Free Software Foundation, either version 3 of the # | ||
2051 | 10 | # License, or (at your option) any later version. # | ||
2052 | 11 | # # | ||
2053 | 12 | # This program is distributed in the hope that it will be useful, # | ||
2054 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | ||
2055 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | ||
2056 | 15 | # GNU Affero General Public License for more details. # | ||
2057 | 16 | # # | ||
2058 | 17 | # You should have received a copy of the GNU Affero General Public License # | ||
2059 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | ||
2060 | 19 | # # | ||
2061 | 20 | ############################################################################### | ||
2062 | 21 | |||
2063 | 22 | from openerp.osv.orm import TransientModel | ||
2064 | 23 | from osv import fields | ||
2065 | 24 | |||
2066 | 25 | |||
2067 | 26 | class open_lot_by_attribute_set(TransientModel): | ||
2068 | 27 | _name = 'open.lot.by.attribute.set' | ||
2069 | 28 | _description = 'Wizard to open lots by attributes set' | ||
2070 | 29 | |||
2071 | 30 | _columns = { | ||
2072 | 31 | 'attribute_set_id': fields.many2one('attribute.set', 'Attribute Set'), | ||
2073 | 32 | } | ||
2074 | 33 | |||
2075 | 34 | def open_lot_by_attribute(self, cr, uid, ids, context=None): | ||
2076 | 35 | """Opens a lot by attributes | ||
2077 | 36 | |||
2078 | 37 | Returns a custom action built modifying the original one. | ||
2079 | 38 | """ | ||
2080 | 39 | |||
2081 | 40 | mod_obj = self.pool.get('ir.model.data') | ||
2082 | 41 | act_obj = self.pool.get('ir.actions.act_window') | ||
2083 | 42 | |||
2084 | 43 | if context is None: | ||
2085 | 44 | context = {} | ||
2086 | 45 | |||
2087 | 46 | # we expect one wizard instance at a time | ||
2088 | 47 | for wiz in self.browse(cr, uid, ids, context=context): | ||
2089 | 48 | action_id = mod_obj.get_object_reference( | ||
2090 | 49 | cr, uid, 'stock', 'action_production_lot_form')[1] | ||
2091 | 50 | action = act_obj.read(cr, uid, [action_id], context=context)[0] | ||
2092 | 51 | |||
2093 | 52 | ctx = ( | ||
2094 | 53 | "{'open_lot_by_attribute_set': True, " | ||
2095 | 54 | "'attribute_group_ids': %s}" | ||
2096 | 55 | % [ | ||
2097 | 56 | group.id | ||
2098 | 57 | for group in wiz.attribute_set_id.attribute_group_ids | ||
2099 | 58 | ] | ||
2100 | 59 | ) | ||
2101 | 60 | |||
2102 | 61 | action['context'] = ctx | ||
2103 | 62 | action['domain'] = ( | ||
2104 | 63 | "[('attribute_set_id', '=', %s)]" | ||
2105 | 64 | % wiz.attribute_set_id.id | ||
2106 | 65 | ) | ||
2107 | 66 | action['name'] = wiz.attribute_set_id.name | ||
2108 | 67 | return action | ||
2109 | 0 | 68 | ||
2110 | === added file 'production_lot_custom_attributes/wizard/open_lot_by_attribute_set.xml' | |||
2111 | --- production_lot_custom_attributes/wizard/open_lot_by_attribute_set.xml 1970-01-01 00:00:00 +0000 | |||
2112 | +++ production_lot_custom_attributes/wizard/open_lot_by_attribute_set.xml 2013-12-11 14:54:36 +0000 | |||
2113 | @@ -0,0 +1,30 @@ | |||
2114 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
2115 | 2 | |||
2116 | 3 | <openerp> | ||
2117 | 4 | <data> | ||
2118 | 5 | |||
2119 | 6 | <record id="open_lot_by_attribute_set_view" model="ir.ui.view"> | ||
2120 | 7 | <field name="name">open.lot.by.attribute.set.view</field> | ||
2121 | 8 | <field name="model">open.lot.by.attribute.set</field> | ||
2122 | 9 | <field name="arch" type="xml"> | ||
2123 | 10 | <form string="Open lot by attributes set"> | ||
2124 | 11 | <field name="attribute_set_id" colspan="4"/> | ||
2125 | 12 | <button icon="gtk-cancel" special="cancel" string="Cancel"/> | ||
2126 | 13 | <button icon="gtk-ok" name="open_lot_by_attribute" string="Open Product By attribute" type="object"/> | ||
2127 | 14 | </form> | ||
2128 | 15 | </field> | ||
2129 | 16 | </record> | ||
2130 | 17 | |||
2131 | 18 | <record id="open_lot_by_attribute_set" model="ir.actions.act_window"> | ||
2132 | 19 | <field name="name">Open lot By Attribute Set</field> | ||
2133 | 20 | <field name="res_model">open.lot.by.attribute.set</field> | ||
2134 | 21 | <field name="view_type">form</field> | ||
2135 | 22 | <field name="target">new</field> | ||
2136 | 23 | <field name="view_id" ref="open_lot_by_attribute_set_view"/> | ||
2137 | 24 | <field name="help"></field> | ||
2138 | 25 | </record> | ||
2139 | 26 | |||
2140 | 27 | <menuitem action="open_lot_by_attribute_set" id="open_lot_wizard" parent="stock.menu_traceability"/> | ||
2141 | 28 | |||
2142 | 29 | </data> | ||
2143 | 30 | </openerp> |
LGTM