Merge lp:~jfb-tempo-consulting/unifield-server/us-2075 into lp:unifield-server
- us-2075
- Merge into trunk
Proposed by
jftempo
Status: | Merged |
---|---|
Merged at revision: | 4108 |
Proposed branch: | lp:~jfb-tempo-consulting/unifield-server/us-2075 |
Merge into: | lp:unifield-server |
Diff against target: |
439 lines (+96/-51) 7 files modified
bin/addons/base/ir/ir_model.py (+51/-46) bin/addons/msf_field_access_rights/osv_override.py (+7/-4) bin/addons/msf_partner/partner.py (+6/-1) bin/addons/msf_partner/partner_view.xml (+2/-0) bin/addons/msf_profile/data/patches.xml (+4/-0) bin/addons/msf_profile/i18n/fr_MF.po (+11/-0) bin/addons/msf_profile/msf_profile.py (+15/-0) |
To merge this branch: | bzr merge lp:~jfb-tempo-consulting/unifield-server/us-2075 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
UniField Reviewer Team | Pending | ||
Review via email: mp+312634@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Jeff Allen (jr.allen) : | # |
Revision history for this message
jftempo (jfb-tempo-consulting) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'bin/addons/base/ir/ir_model.py' |
2 | --- bin/addons/base/ir/ir_model.py 2016-09-05 07:47:20 +0000 |
3 | +++ bin/addons/base/ir/ir_model.py 2016-12-07 09:15:11 +0000 |
4 | @@ -94,17 +94,17 @@ |
5 | 'state': fields.selection([('manual','Custom Object'),('base','Base Object')],'Type',readonly=True), |
6 | 'access_ids': fields.one2many('ir.model.access', 'model_id', 'Access'), |
7 | 'osv_memory': fields.function(_is_osv_memory, method=True, string='In-memory model', type='boolean', |
8 | - fnct_search=_search_osv_memory, |
9 | - help="Indicates whether this object model lives in memory only, i.e. is not persisted (osv.osv_memory)"), |
10 | + fnct_search=_search_osv_memory, |
11 | + help="Indicates whether this object model lives in memory only, i.e. is not persisted (osv.osv_memory)"), |
12 | 'modules': fields.function(_in_modules, method=True, type='char', size=128, string='In modules', help='List of modules in which the object is defined or inherited'), |
13 | 'view_ids': fields.function(_view_ids, method=True, type='one2many', obj='ir.ui.view', string='Views'), |
14 | } |
15 | - |
16 | + |
17 | _defaults = { |
18 | 'model': lambda *a: 'x_', |
19 | 'state': lambda self,cr,uid,ctx=None: (ctx and ctx.get('manual',False)) and 'manual' or 'base', |
20 | } |
21 | - |
22 | + |
23 | def _check_model_name(self, cr, uid, ids, context=None): |
24 | for model in self.browse(cr, uid, ids, context=context): |
25 | if model.state=='manual': |
26 | @@ -127,7 +127,7 @@ |
27 | args = [] |
28 | domain = args + ['|', ('model', operator, name), ('name', operator, name)] |
29 | return super(ir_model, self).name_search(cr, uid, None, domain, |
30 | - operator=operator, limit=limit, context=context) |
31 | + operator=operator, limit=limit, context=context) |
32 | |
33 | |
34 | def unlink(self, cr, user, ids, context=None): |
35 | @@ -180,18 +180,18 @@ |
36 | _columns = { |
37 | 'name': fields.char('Name', required=True, size=64, select=1), |
38 | 'model': fields.char('Object Name', size=64, required=True, select=1, |
39 | - help="The technical name of the model this field belongs to"), |
40 | + help="The technical name of the model this field belongs to"), |
41 | 'relation': fields.char('Object Relation', size=64, |
42 | - help="For relationship fields, the technical name of the target model"), |
43 | + help="For relationship fields, the technical name of the target model"), |
44 | 'relation_field': fields.char('Relation Field', size=64, |
45 | - help="For one2many fields, the field on the target model that implement the opposite many2one relationship"), |
46 | + help="For one2many fields, the field on the target model that implement the opposite many2one relationship"), |
47 | 'model_id': fields.many2one('ir.model', 'Model', required=True, select=True, ondelete='cascade', |
48 | - help="The model this field belongs to"), |
49 | + help="The model this field belongs to"), |
50 | 'field_description': fields.char('Field Label', required=True, size=256), |
51 | 'ttype': fields.selection(_get_fields_type, 'Field Type',size=64, required=True), |
52 | 'selection': fields.char('Selection Options',size=128, help="List of options for a selection field, " |
53 | - "specified as a Python expression defining a list of (key, label) pairs. " |
54 | - "For example: [('blue','Blue'),('yellow','Yellow')]"), |
55 | + "specified as a Python expression defining a list of (key, label) pairs. " |
56 | + "For example: [('blue','Blue'),('yellow','Yellow')]"), |
57 | 'required': fields.boolean('Required'), |
58 | 'readonly': fields.boolean('Readonly'), |
59 | 'select_level': fields.selection([('0','Not Searchable'),('1','Always Searchable'),('2','Advanced Search (deprecated)')],'Searchable', required=True), |
60 | @@ -200,8 +200,8 @@ |
61 | 'state': fields.selection([('manual','Custom Field'),('base','Base Field'), ('deprecated', 'Deprecated')],'Type', required=True, readonly=True, select=1), |
62 | 'on_delete': fields.selection([('cascade','Cascade'),('set null','Set NULL')], 'On delete', help='On delete property for many2one fields'), |
63 | 'domain': fields.char('Domain', size=256, help="The optional domain to restrict possible values for relationship fields, " |
64 | - "specified as a Python expression defining a list of triplets. " |
65 | - "For example: [('color','=','red')]"), |
66 | + "specified as a Python expression defining a list of triplets. " |
67 | + "For example: [('color','=','red')]"), |
68 | 'groups': fields.many2many('res.groups', 'ir_model_fields_group_rel', 'field_id', 'group_id', 'Groups'), |
69 | 'view_load': fields.boolean('View Auto-Load'), |
70 | 'selectable': fields.boolean('Selectable'), |
71 | @@ -228,8 +228,8 @@ |
72 | except Exception: |
73 | logging.getLogger('ir.model').warning('Invalid selection list definition for fields.selection', exc_info=True) |
74 | raise except_orm(_('Error'), |
75 | - _("The Selection Options expression is not a valid Pythonic expression." \ |
76 | - "Please provide an expression in the [('key','Label'), ...] format.")) |
77 | + _("The Selection Options expression is not a valid Pythonic expression." \ |
78 | + "Please provide an expression in the [('key','Label'), ...] format.")) |
79 | |
80 | check = True |
81 | if not (isinstance(selection_list, list) and selection_list): |
82 | @@ -241,8 +241,8 @@ |
83 | break |
84 | |
85 | if not check: |
86 | - raise except_orm(_('Error'), |
87 | - _("The Selection Options expression is must be in the [('key','Label'), ...] format!")) |
88 | + raise except_orm(_('Error'), |
89 | + _("The Selection Options expression is must be in the [('key','Label'), ...] format!")) |
90 | return True |
91 | |
92 | def _size_gt_zero_msg(self, cr, user, ids, context=None): |
93 | @@ -281,7 +281,7 @@ |
94 | raise except_orm(_('Error'), _("Custom fields must have a name that starts with 'x_' !")) |
95 | |
96 | if vals.get('relation',False) and not self.pool.get('ir.model').search(cr, user, [('model','=',vals['relation'])]): |
97 | - raise except_orm(_('Error'), _("Model %s does not exist!") % vals['relation']) |
98 | + raise except_orm(_('Error'), _("Model %s does not exist!") % vals['relation']) |
99 | |
100 | if self.pool.get(vals['model']): |
101 | self.pool.get(vals['model']).__init__(self.pool, cr) |
102 | @@ -303,7 +303,7 @@ |
103 | column_rename = None # if set, *one* column can be renamed here |
104 | obj = None |
105 | models_patch = {} # structs of (obj, [(field, prop, change_to),..]) |
106 | - # data to be updated on the orm model |
107 | + # data to be updated on the orm model |
108 | |
109 | # static table of properties |
110 | model_props = [ # (our-name, fields.prop, set_fn) |
111 | @@ -318,7 +318,7 @@ |
112 | ('selectable', 'selectable', bool), |
113 | ('select_level', 'select', int), |
114 | ('selection', 'selection', eval), |
115 | - ] |
116 | + ] |
117 | |
118 | if vals and ids: |
119 | checked_selection = False # need only check it once, so defer |
120 | @@ -329,9 +329,9 @@ |
121 | |
122 | if item.state != 'manual': |
123 | raise except_orm(_('Error!'), |
124 | - _('Properties of base fields cannot be altered in this manner! ' |
125 | - 'Please modify them through Python code, ' |
126 | - 'preferably through a custom addon!')) |
127 | + _('Properties of base fields cannot be altered in this manner! ' |
128 | + 'Please modify them through Python code, ' |
129 | + 'preferably through a custom addon!')) |
130 | |
131 | if item.ttype == 'selection' and 'selection' in vals \ |
132 | and not checked_selection: |
133 | @@ -357,7 +357,7 @@ |
134 | |
135 | if 'ttype' in vals and vals['ttype'] != item.ttype: |
136 | raise except_orm(_("Error!"), _("Changing the type of a column is not yet supported. " |
137 | - "Please drop it and create it again!")) |
138 | + "Please drop it and create it again!")) |
139 | |
140 | # We don't check the 'state', because it might come from the context |
141 | # (thus be set for multiple fields) and will be ignored anyway. |
142 | @@ -444,19 +444,19 @@ |
143 | 'perm_create': fields.boolean('Create Access'), |
144 | 'perm_unlink': fields.boolean('Delete Access'), |
145 | } |
146 | - |
147 | + |
148 | def _ir_model_access_check_groups_hook(self, cr, uid, context=None, *args, **kwargs): |
149 | ''' |
150 | Please copy this to your module's method also. |
151 | This hook belongs to the check_groups method from server/bin/addons/base/ir>ir_model.py>ir_model_access |
152 | - |
153 | + |
154 | - allow to modify the criteria for group display |
155 | ''' |
156 | if context is None: |
157 | context = {} |
158 | res = kwargs['res'] |
159 | group = kwargs['group'] |
160 | - |
161 | + |
162 | grouparr = group.split('.') |
163 | if not grouparr: |
164 | return False |
165 | @@ -486,17 +486,17 @@ |
166 | group_ids = [group_ids] |
167 | for group_id in group_ids: |
168 | cr.execute("SELECT perm_" + mode + " " |
169 | - " FROM ir_model_access a " |
170 | - " JOIN ir_model m ON (m.id = a.model_id) " |
171 | - " WHERE m.model = %s AND a.group_id = %s", (model_name, group_id) |
172 | - ) |
173 | + " FROM ir_model_access a " |
174 | + " JOIN ir_model m ON (m.id = a.model_id) " |
175 | + " WHERE m.model = %s AND a.group_id = %s", (model_name, group_id) |
176 | + ) |
177 | r = cr.fetchone() |
178 | if r is None: |
179 | cr.execute("SELECT perm_" + mode + " " |
180 | - " FROM ir_model_access a " |
181 | - " JOIN ir_model m ON (m.id = a.model_id) " |
182 | - " WHERE m.model = %s AND a.group_id IS NULL", (model_name, ) |
183 | - ) |
184 | + " FROM ir_model_access a " |
185 | + " JOIN ir_model m ON (m.id = a.model_id) " |
186 | + " WHERE m.model = %s AND a.group_id IS NULL", (model_name, ) |
187 | + ) |
188 | r = cr.fetchone() |
189 | |
190 | access = bool(r and r[0]) |
191 | @@ -652,7 +652,7 @@ |
192 | def _get_id(self, cr, uid, module, xml_id): |
193 | """Returns the id of the ir.model.data record corresponding to a given module and xml_id (cached) or raise a ValueError if not found""" |
194 | ids = self.search(cr, uid, [('module','=',module), ('name','=', |
195 | - xml_id)], limit=1, order='NO_ORDER') |
196 | + xml_id)], limit=1, order='NO_ORDER') |
197 | if not ids: |
198 | raise ValueError('No references to %s.%s' % (module, xml_id)) |
199 | # the sql constraints ensure us we have only one result |
200 | @@ -718,7 +718,7 @@ |
201 | cr.execute('''SELECT imd.id, imd.res_id, md.id |
202 | FROM ir_model_data imd LEFT JOIN %s md ON (imd.res_id = md.id) |
203 | WHERE imd.module=%%s AND imd.name=%%s''' % model_obj._table, |
204 | - (module, xml_id)) |
205 | + (module, xml_id)) |
206 | results = cr.fetchall() |
207 | for imd_id2,res_id2,real_id2 in results: |
208 | if not real_id2: |
209 | @@ -733,7 +733,7 @@ |
210 | model_obj.write(cr, uid, [res_id], values, context=context) |
211 | self.write(cr, uid, [action_id], { |
212 | 'date_update': time.strftime('%Y-%m-%d %H:%M:%S'), |
213 | - },context=context) |
214 | + },context=context) |
215 | elif res_id: |
216 | model_obj.write(cr, uid, [res_id], values, context=context) |
217 | if xml_id: |
218 | @@ -743,41 +743,46 @@ |
219 | 'module':module, |
220 | 'res_id':res_id, |
221 | 'noupdate': noupdate, |
222 | - },context=context) |
223 | + },context=context) |
224 | if model_obj._inherits: |
225 | for table in model_obj._inherits: |
226 | inherit_id = model_obj.browse(cr, uid, |
227 | - res_id,context=context)[model_obj._inherits[table]] |
228 | + res_id,context=context)[model_obj._inherits[table]] |
229 | self.create(cr, uid, { |
230 | 'name': xml_id + '_' + table.replace('.', '_'), |
231 | 'model': table, |
232 | 'module': module, |
233 | 'res_id': inherit_id.id, |
234 | 'noupdate': noupdate, |
235 | - },context=context) |
236 | + },context=context) |
237 | else: |
238 | if mode=='init' or (mode=='update' and xml_id): |
239 | res_id = model_obj.create(cr, uid, values, context=context) |
240 | # US-180: Only create ir model data if res_id is valid |
241 | if xml_id and res_id: |
242 | + if context.get('sync_update_execution') and model == 'res.partner' and module == 'sd': |
243 | + # update partner data if created if xmlid does not match the instance id |
244 | + identifier = self.pool.get('sync.client.entity').get_entity(cr, uid).identifier |
245 | + if identifier != xml_id.split('/')[0]: |
246 | + model_obj.write(cr, uid, [res_id], {'locally_created': False}, context=context) |
247 | self.create(cr, uid, { |
248 | 'name': xml_id, |
249 | 'model': model, |
250 | 'module': module, |
251 | 'res_id': res_id, |
252 | 'noupdate': noupdate |
253 | - },context=context) |
254 | + },context=context) |
255 | if model_obj._inherits and not context.get('sync_update_execution', False): |
256 | for table in model_obj._inherits: |
257 | inherit_id = model_obj.browse(cr, uid, |
258 | - res_id,context=context)[model_obj._inherits[table]] |
259 | + res_id,context=context)[model_obj._inherits[table]] |
260 | self.create(cr, uid, { |
261 | 'name': xml_id + '_' + table.replace('.', '_'), |
262 | 'model': table, |
263 | 'module': module, |
264 | 'res_id': inherit_id.id, |
265 | 'noupdate': noupdate, |
266 | - },context=context) |
267 | + },context=context) |
268 | if xml_id: |
269 | if res_id: |
270 | self.loads[(module, xml_id)] = (model, res_id) |
271 | @@ -785,9 +790,9 @@ |
272 | for table in model_obj._inherits: |
273 | inherit_field = model_obj._inherits[table] |
274 | inherit_id = model_obj.read(cr, uid, res_id, |
275 | - [inherit_field])[inherit_field] |
276 | + [inherit_field])[inherit_field] |
277 | self.loads[(module, xml_id + '_' + \ |
278 | - table.replace('.', '_'))] = (table, inherit_id) |
279 | + table.replace('.', '_'))] = (table, inherit_id) |
280 | return res_id |
281 | |
282 | def _unlink(self, cr, uid, model, res_ids): |
283 | |
284 | === modified file 'bin/addons/msf_field_access_rights/osv_override.py' |
285 | --- bin/addons/msf_field_access_rights/osv_override.py 2016-11-11 10:01:02 +0000 |
286 | +++ bin/addons/msf_field_access_rights/osv_override.py 2016-12-07 09:15:11 +0000 |
287 | @@ -27,7 +27,7 @@ |
288 | import copy |
289 | from datetime import datetime |
290 | import netsvc |
291 | - |
292 | +from tools import misc |
293 | |
294 | def _get_instance_level(self, cr, uid): |
295 | """ |
296 | @@ -183,7 +183,7 @@ |
297 | return True |
298 | |
299 | # if one evals to False and the other does not, they are different |
300 | - if field_type != 'many2many' and ((not new_value and current_value) or (new_value and not current_value)): |
301 | + if field_type not in ('many2many', 'one2many') and ((not new_value and current_value) or (new_value and not current_value)): |
302 | return False |
303 | |
304 | # type specifics... |
305 | @@ -191,7 +191,9 @@ |
306 | if isinstance(new_value, (list, tuple)): |
307 | if new_value: |
308 | if isinstance(new_value[0], (list, tuple)): |
309 | - return False |
310 | + return False |
311 | + else: |
312 | + return True |
313 | if field_type == 'date': |
314 | if current_value and new_value: |
315 | try: |
316 | @@ -334,6 +336,7 @@ |
317 | for field_name in no_write_access_fields: |
318 | if not _values_equate(columns[field_name]._type, |
319 | old_values[field_name], vals[field_name]): |
320 | + print old_values[field_name], 'new val', vals[field_name], columns[field_name]._type |
321 | # throw access denied error |
322 | raise osv.except_osv('Access Denied', 'You do not have access to the field (%s). If you did not edit this field, please let an OpenERP administrator know about this error message, and the field name.' % field_name) |
323 | |
324 | @@ -475,7 +478,7 @@ |
325 | |
326 | # add 'hidden by field access rules' flag |
327 | if field_name in self._columns: |
328 | - field.attrib['help'] = '[Field Disabled by Field Access Rights] ' + self._columns[field_name].help |
329 | + field.attrib['help'] = '[Field Disabled by Field Access Rights] %s' % (misc.ustr(self._columns[field_name].help)) |
330 | |
331 | # get the modified xml string and return it |
332 | fields_view['arch'] = etree.tostring(view_xml) |
333 | |
334 | === modified file 'bin/addons/msf_partner/partner.py' |
335 | --- bin/addons/msf_partner/partner.py 2016-11-28 13:39:36 +0000 |
336 | +++ bin/addons/msf_partner/partner.py 2016-12-07 09:15:11 +0000 |
337 | @@ -309,10 +309,12 @@ |
338 | method=True, |
339 | type='boolean', |
340 | string='Is a coordination ?', |
341 | - ) |
342 | + ), |
343 | + 'locally_created': fields.boolean('Locally Created', help='Partner Created on this instance', readonly=1), |
344 | } |
345 | |
346 | _defaults = { |
347 | + 'locally_created': lambda *a: True, |
348 | 'manufacturer': lambda *a: False, |
349 | 'transporter': lambda *a: False, |
350 | 'partner_type': lambda *a: 'external', |
351 | @@ -666,6 +668,9 @@ |
352 | for ftr in fields_to_reset: |
353 | if ftr not in default: |
354 | to_del.append(ftr) |
355 | + if 'locally_created' not in default: |
356 | + default['locally_created'] = True |
357 | + |
358 | res = super(res_partner, self).copy_data(cr, uid, id, default=default, context=context) |
359 | for ftd in to_del: |
360 | if ftd in res: |
361 | |
362 | === modified file 'bin/addons/msf_partner/partner_view.xml' |
363 | --- bin/addons/msf_partner/partner_view.xml 2015-08-06 12:59:04 +0000 |
364 | +++ bin/addons/msf_partner/partner_view.xml 2016-12-07 09:15:11 +0000 |
365 | @@ -15,6 +15,7 @@ |
366 | <xpath expr="/tree/field[@name='ref']" position="after"> |
367 | <field name="active" invisible="1"/> |
368 | <field name="partner_type" /> |
369 | + <field name="locally_created" invisible="1" /> |
370 | <field name="in_product" invisible="1" /> |
371 | <field name="min_qty" invisible="not context.get('choose_supplier')" /> |
372 | <field name="delay" invisible="not context.get('choose_supplier')" /> |
373 | @@ -44,6 +45,7 @@ |
374 | <xpath expr="/form/group/group/field[@name='title']" position="replace"> |
375 | <field name="partner_type" |
376 | on_change="on_change_partner_type(partner_type, property_product_pricelist, property_product_pricelist_purchase)" /> |
377 | + <field name="locally_created" invisible="1" /> |
378 | </xpath> |
379 | <xpath expr="/form/group/group[2]/field[@name='supplier']" position="after"> |
380 | <field name="manufacturer" /> |
381 | |
382 | === modified file 'bin/addons/msf_profile/data/patches.xml' |
383 | --- bin/addons/msf_profile/data/patches.xml 2016-11-22 08:42:04 +0000 |
384 | +++ bin/addons/msf_profile/data/patches.xml 2016-12-07 09:15:11 +0000 |
385 | @@ -138,5 +138,9 @@ |
386 | <record id="us_1671_stopped_products" model="patch.scripts"> |
387 | <field name="method">us_1671_stopped_products</field> |
388 | </record> |
389 | + |
390 | + <record id="us_2075_partner_locally_created" model="patch.scripts"> |
391 | + <field name="method">us_2075_partner_locally_created</field> |
392 | + </record> |
393 | </data> |
394 | </openerp> |
395 | |
396 | === modified file 'bin/addons/msf_profile/i18n/fr_MF.po' |
397 | --- bin/addons/msf_profile/i18n/fr_MF.po 2016-12-06 11:15:12 +0000 |
398 | +++ bin/addons/msf_profile/i18n/fr_MF.po 2016-12-07 09:15:11 +0000 |
399 | @@ -75758,3 +75758,14 @@ |
400 | #, python-format |
401 | msgid "Confirmed delivery date not found. The date from the header has been taken (if any)" |
402 | msgstr "Date de livraison confirmée non trouvée, le système a pris la date de l'en-tête" |
403 | + |
404 | +#. module: msf_partner |
405 | +#: field:res.partner,locally_created:0 |
406 | +msgid "Locally Created" |
407 | +msgstr "Créé localement" |
408 | + |
409 | +#. module: msf_partner |
410 | +#: help:res.partner,locally_created:0 |
411 | +msgid "Partner Created on this instance" |
412 | +msgstr "Partenaire créé sur cette instance" |
413 | + |
414 | |
415 | === modified file 'bin/addons/msf_profile/msf_profile.py' |
416 | --- bin/addons/msf_profile/msf_profile.py 2016-11-30 09:50:52 +0000 |
417 | +++ bin/addons/msf_profile/msf_profile.py 2016-12-07 09:15:11 +0000 |
418 | @@ -46,6 +46,21 @@ |
419 | 'model': lambda *a: 'patch.scripts', |
420 | } |
421 | |
422 | + def us_2075_partner_locally_created(self, cr, uid, *a, **b): |
423 | + entity = self.pool.get('sync.client.entity') |
424 | + if entity: |
425 | + identifier = entity.get_entity(cr, uid).identifier |
426 | + if identifier: |
427 | + cr.execute("""update res_partner set locally_created='f' where id in ( |
428 | + select res_id from ir_model_data d |
429 | + where d.module='sd' |
430 | + and d.model='res.partner' |
431 | + and name not in ('msf_doc_import_supplier_tbd', 'order_types_res_partner_local_market') |
432 | + and name not like '%s%%' |
433 | + ) """ % (identifier, )) |
434 | + self._logger.warn('%s non local partners updated' % (cr.rowcount,)) |
435 | + return True |
436 | + |
437 | def setup_security_on_sync_server(self, cr, uid, *a, **b): |
438 | update_module = self.pool.get('sync.server.update') |
439 | if not update_module: |
Oups. Fixed, thanks.