Merge lp:~openerp-dev/openobject-server/trunk-missing-default-values-pza into lp:openobject-server

Proposed by Pooja Zankhariya(OpenERP)
Status: Work in progress
Proposed branch: lp:~openerp-dev/openobject-server/trunk-missing-default-values-pza
Merge into: lp:openobject-server
Diff against target: 215 lines (+190/-1)
1 file modified
openerp/addons/base/ir/ir_model.py (+190/-1)
To merge this branch: bzr merge lp:~openerp-dev/openobject-server/trunk-missing-default-values-pza
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+201171@code.launchpad.net
To post a comment you must log in.
5021. By Pooja Zankhariya(OpenERP)

[IMP]Misc

5022. By Pooja Zankhariya(OpenERP)

[IMP]Improved code

5023. By Pooja Zankhariya(OpenERP)

[IMP]Unused import

5024. By Pooja Zankhariya(OpenERP)

[MISC]Misc Imp

5025. By Pooja Zankhariya(OpenERP)

[MERGE]Sync with Trunk

Unmerged revisions

5025. By Pooja Zankhariya(OpenERP)

[MERGE]Sync with Trunk

5024. By Pooja Zankhariya(OpenERP)

[MISC]Misc Imp

5023. By Pooja Zankhariya(OpenERP)

[IMP]Unused import

5022. By Pooja Zankhariya(OpenERP)

[IMP]Improved code

5021. By Pooja Zankhariya(OpenERP)

[IMP]Misc

5020. By Pooja Zankhariya(OpenERP)

[IMP]Under dev- temporary working.

5019. By Pooja Zankhariya(OpenERP)

[MERGE]Merge with Trunk

5018. By Pooja Zankhariya(OpenERP)

[IMP]Under dev

5017. By Pooja Zankhariya(OpenERP)

[IMP]Changes on 1-jan

5016. By Pooja Zankhariya(OpenERP)

[IMP]Under Dev

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openerp/addons/base/ir/ir_model.py'
2--- openerp/addons/base/ir/ir_model.py 2014-01-29 17:29:49 +0000
3+++ openerp/addons/base/ir/ir_model.py 2014-01-31 06:08:51 +0000
4@@ -34,6 +34,11 @@
5 from openerp.tools import config
6 from openerp.tools.translate import _
7 from openerp.osv.orm import except_orm, browse_record
8+import re
9+import inspect
10+from openerp.tools import misc
11+from lxml import etree
12+from openerp.tools.yaml_import import *
13
14 _logger = logging.getLogger(__name__)
15
16@@ -948,7 +953,102 @@
17 self.clear_caches()
18 return super(ir_model_data,self).unlink(cr, uid, ids, context=context)
19
20- def _update(self,cr, uid, model, module, values, xml_id=False, store=True, noupdate=False, mode='init', res_id=False, context=None):
21+ ##Temporary Added - _get_id also exists
22+ def get_id(self, cr, uid, xml_id, module):
23+ if xml_id is False or xml_id is None:
24+ return False
25+ elif isinstance(xml_id, types.IntType):
26+ id = xml_id
27+ elif isinstance(xml_id, (list,tuple)):
28+ id = xml_id[-1]
29+ else:
30+ if '.' in xml_id:
31+ module, checked_xml_id = xml_id.split('.', 1)
32+ else:
33+ checked_xml_id = xml_id
34+ try:
35+ _, id = self.pool['ir.model.data'].get_object_reference(cr, uid, module, checked_xml_id)
36+ except ValueError:
37+ raise ValueError("""%s not found when processing.""" % (checked_xml_id))
38+
39+ return id
40+
41+ def _eval_field(self, cr, SUPERUSER_ID, module, model, field_name, expression, view_info=False, parent={}, default=True):
42+ if field_name in model._columns:
43+ column = model._columns[field_name]
44+ elif field_name in model._inherit_fields:
45+ column = model._inherit_fields[field_name][2]
46+ else:
47+ raise KeyError("Object '%s' does not contain field '%s'" % (model, field_name))
48+# if is_ref(expression):
49+# elements = self.process_ref(expression, column)
50+# if column._type in ("many2many", "one2many"):
51+# value = [(6, 0, elements)]
52+# else: # many2one
53+# if isinstance(elements, (list,tuple)):
54+# value = self._get_first_result(elements)
55+# else:
56+# value = elements
57+ if column._type == "many2one":
58+ value = self.get_id(cr, SUPERUSER_ID, expression, module)
59+ elif column._type == "one2many":
60+ other_model = self.get_model(column._obj)
61+ value = [(0, 0, self._create_record(other_model, fields, view_info, parent, default=default)) for fields in expression]
62+ elif column._type == "many2many":
63+ ids = [self.get_id(cr, SUPERUSER_ID, xml_id, module) for xml_id in expression]
64+ value = [(6, 0, ids)]
65+ elif column._type == "date" and isinstance(expression, basestring):
66+ # enforce ISO format for string date values, to be locale-agnostic during tests
67+ time.strptime(expression, misc.DEFAULT_SERVER_DATE_FORMAT)
68+ value = expression
69+ elif column._type == "datetime" and isinstance(expression, basestring):
70+ # enforce ISO format for string datetime values, to be locale-agnostic during tests
71+ time.strptime(expression, misc.DEFAULT_SERVER_DATETIME_FORMAT)
72+ value = expression
73+ else: # scalar field
74+ #if is_eval(expression):
75+ # value = self.process_eval(expression)
76+ #else:
77+ value = expression
78+ # raise YamlImportException('Unsupported column "%s" or value %s:%s' % (field_name, type(expression), expression))
79+ return value
80+
81+ def _update(self, cr, uid, model, module, values, xml_id=False, store=True, noupdate=False, mode='init', res_id=False, context=None):
82+
83+ def process_val(key, val):
84+ if fg[key]['type'] == 'many2one':
85+ if type(val) in (tuple,list):
86+ val = val[0]
87+ elif fg[key]['type'] == 'one2many':
88+ if val and isinstance(val, (list,tuple)) and isinstance(val[0], dict):
89+ # we want to return only the fields that aren't readonly
90+ # For that, we need to first get the right tree view to consider for the field `key´
91+ one2many_tree_view = _get_right_one2many_view(fg, key, 'tree')
92+ arch = etree.fromstring(one2many_tree_view['arch'].encode('utf-8'))
93+ for rec in val:
94+ # make a copy for the iteration, as we will alter `rec´
95+ rec_copy = rec.copy()
96+ for field_key in rec_copy:
97+ # if field is missing in view or has a readonly modifier, drop it
98+ field_elem = arch.xpath("//field[@name='%s']" % field_key)
99+ if field_elem and (field_elem[0].get('modifiers', '{}').find('"readonly": true') >= 0):
100+ # TODO: currently we only support if readonly is True in the modifiers. Some improvement may be done in
101+ # order to support also modifiers that look like {"readonly": [["state", "not in", ["draft", "confirm"]]]}
102+ del rec[field_key]
103+ # now that unwanted values have been removed from val, we can encapsulate it in a tuple as returned value
104+ val = map(lambda x: (0,0,x), val)
105+ elif fg[key]['type'] == 'many2many':
106+ if val and isinstance(val,(list,tuple)) and isinstance(val[0], (int,long)):
107+ val = [(6,0,val)]
108+
109+ # we want to return only the fields that aren't readonly
110+ if el.get('modifiers', '{}').find('"readonly": true') >= 0:
111+ # TODO: currently we only support if readonly is True in the modifiers. Some improvement may be done in
112+ # order to support also modifiers that look like {"readonly": [["state", "not in", ["draft", "confirm"]]]}
113+ return False
114+
115+ return val
116+
117 model_obj = self.pool[model]
118 if not context:
119 context = {}
120@@ -960,6 +1060,95 @@
121 if (not xml_id) and (not self.doinit):
122 return False
123 action_id = False
124+
125+ view_info = self.pool[model].fields_view_get(cr, SUPERUSER_ID, False, 'form', context)
126+ if view_info:
127+ arch = etree.fromstring(view_info['arch'].decode('utf-8'))
128+ view = arch if len(arch) else False
129+ else:
130+ view = False
131+ ###To find default
132+ try:
133+ self.pool['ir.model.data']._get_id(cr, SUPERUSER_ID, module, xml_id)
134+ default = False
135+ except ValueError:
136+ default = True
137+ fields = values or {}
138+ if view is not False:
139+ fg = view_info['fields']
140+ # gather the default values on the object. (Can't use `fields´ as parameter instead of {} because we may
141+ # have references like `base.main_company´ in the yaml file and it's not compatible with the function)
142+ defaults = default and self._add_missing_default_values(cr, SUPERUSER_ID, {}, context=context) or {}
143+ # copy the default values in record_dict, only if they are in the view (because that's what the client does)
144+ # the other default values will be added later on by the create().
145+ record_dict = dict([(key, val) for key, val in defaults.items() if key in fg])
146+
147+ # Process all on_change calls
148+ nodes = [view]
149+ while nodes:
150+ el = nodes.pop(0)
151+ if el.tag =='field':
152+
153+# if not el.attrib.get('on_change', False):
154+# continue
155+# match = re.match("([a-z_1-9A-Z]+)\((.*)\)", el.attrib['on_change'])
156+# assert match, "Unable to parse the on_change '%s'!" % (el.attrib['on_change'],)
157+
158+ field_name = el.attrib['name']
159+ assert field_name in fg, "The field '%s' is defined in the form view but not on the object '%s'!" % (field_name, model._name)
160+ if field_name in fields:
161+ one2many_form_view = None
162+ if (view is not False) and (fg[field_name]['type']=='one2many'):
163+ # for one2many fields, we want to eval them using the inline form view defined on the parent
164+ one2many_form_view = _get_right_one2many_view(fg, field_name, 'form')
165+ field_value = self._eval_field(cr, uid, module, self.pool[model], field_name, fields[field_name], one2many_form_view or view_info, parent=record_dict, default=default)
166+
167+ #call process_val to not update record_dict if values were given for readonly fields
168+ val = process_val(field_name, field_value)
169+ if val:
170+ record_dict[field_name] = val
171+ #if (field_name in defaults) and defaults[field_name] == field_value:
172+ # print '*** You can remove these lines:', field_name, field_value
173+
174+ #if field_name has a default value or a value is given in the yaml file, we must call its on_change()
175+ elif field_name not in defaults:
176+ continue
177+
178+ if not el.attrib.get('on_change', False):
179+ continue
180+ match = re.match("([a-z_1-9A-Z]+)\((.*)\)", el.attrib['on_change'])
181+ assert match, "Unable to parse the on_change '%s'!" % (el.attrib['on_change'],)
182+#####nedd to test whether needed or not
183+ # creating the context
184+ class parent2(object):
185+ def __init__(self, d):
186+ self.d = d
187+ def __getattr__(self, name):
188+ return self.d.get(name, False)
189+
190+ parent=record_dict#Same done above
191+ ctx = record_dict.copy()
192+ ctx['context'] = context
193+ ctx['uid'] = SUPERUSER_ID
194+ ctx['parent'] = parent2(parent)
195+ for a in fg:
196+ if a not in ctx:
197+ ctx[a] = process_val(a, defaults.get(a, False))
198+
199+# # Evaluation args
200+ args = map(lambda x: eval(x, ctx), match.group(2).split(','))#[36]
201+ result = getattr(self.pool[model], match.group(1))(cr, SUPERUSER_ID, [], *args)#{'value': {'bom_id': False, 'routing_id': False, 'product_uom': 2}}
202+ for key, val in (result or {}).get('value', {}).items():
203+ assert key in fg, "The returning field '%s' from your on_change call '%s' does not exist either on the object '%s', either in the view '%s' used for the creation" % (key, match.group(1), model._name, view_info['name'])
204+ if key not in fields:
205+ # do not shadow values explicitly set in yaml.
206+ record_dict[key] = process_val(key, val)
207+ else:
208+ nodes = list(el) + nodes
209+ else:
210+ record_dict = {}
211+ values.update(record_dict)
212+
213 if xml_id:
214 cr.execute('''SELECT imd.id, imd.res_id, md.id, imd.model, imd.noupdate
215 FROM ir_model_data imd LEFT JOIN %s md ON (imd.res_id = md.id)