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
=== modified file 'openerp/addons/base/ir/ir_model.py'
--- openerp/addons/base/ir/ir_model.py 2014-01-29 17:29:49 +0000
+++ openerp/addons/base/ir/ir_model.py 2014-01-31 06:08:51 +0000
@@ -34,6 +34,11 @@
34from openerp.tools import config34from openerp.tools import config
35from openerp.tools.translate import _35from openerp.tools.translate import _
36from openerp.osv.orm import except_orm, browse_record36from openerp.osv.orm import except_orm, browse_record
37import re
38import inspect
39from openerp.tools import misc
40from lxml import etree
41from openerp.tools.yaml_import import *
3742
38_logger = logging.getLogger(__name__)43_logger = logging.getLogger(__name__)
3944
@@ -948,7 +953,102 @@
948 self.clear_caches()953 self.clear_caches()
949 return super(ir_model_data,self).unlink(cr, uid, ids, context=context)954 return super(ir_model_data,self).unlink(cr, uid, ids, context=context)
950955
951 def _update(self,cr, uid, model, module, values, xml_id=False, store=True, noupdate=False, mode='init', res_id=False, context=None):956 ##Temporary Added - _get_id also exists
957 def get_id(self, cr, uid, xml_id, module):
958 if xml_id is False or xml_id is None:
959 return False
960 elif isinstance(xml_id, types.IntType):
961 id = xml_id
962 elif isinstance(xml_id, (list,tuple)):
963 id = xml_id[-1]
964 else:
965 if '.' in xml_id:
966 module, checked_xml_id = xml_id.split('.', 1)
967 else:
968 checked_xml_id = xml_id
969 try:
970 _, id = self.pool['ir.model.data'].get_object_reference(cr, uid, module, checked_xml_id)
971 except ValueError:
972 raise ValueError("""%s not found when processing.""" % (checked_xml_id))
973
974 return id
975
976 def _eval_field(self, cr, SUPERUSER_ID, module, model, field_name, expression, view_info=False, parent={}, default=True):
977 if field_name in model._columns:
978 column = model._columns[field_name]
979 elif field_name in model._inherit_fields:
980 column = model._inherit_fields[field_name][2]
981 else:
982 raise KeyError("Object '%s' does not contain field '%s'" % (model, field_name))
983# if is_ref(expression):
984# elements = self.process_ref(expression, column)
985# if column._type in ("many2many", "one2many"):
986# value = [(6, 0, elements)]
987# else: # many2one
988# if isinstance(elements, (list,tuple)):
989# value = self._get_first_result(elements)
990# else:
991# value = elements
992 if column._type == "many2one":
993 value = self.get_id(cr, SUPERUSER_ID, expression, module)
994 elif column._type == "one2many":
995 other_model = self.get_model(column._obj)
996 value = [(0, 0, self._create_record(other_model, fields, view_info, parent, default=default)) for fields in expression]
997 elif column._type == "many2many":
998 ids = [self.get_id(cr, SUPERUSER_ID, xml_id, module) for xml_id in expression]
999 value = [(6, 0, ids)]
1000 elif column._type == "date" and isinstance(expression, basestring):
1001 # enforce ISO format for string date values, to be locale-agnostic during tests
1002 time.strptime(expression, misc.DEFAULT_SERVER_DATE_FORMAT)
1003 value = expression
1004 elif column._type == "datetime" and isinstance(expression, basestring):
1005 # enforce ISO format for string datetime values, to be locale-agnostic during tests
1006 time.strptime(expression, misc.DEFAULT_SERVER_DATETIME_FORMAT)
1007 value = expression
1008 else: # scalar field
1009 #if is_eval(expression):
1010 # value = self.process_eval(expression)
1011 #else:
1012 value = expression
1013 # raise YamlImportException('Unsupported column "%s" or value %s:%s' % (field_name, type(expression), expression))
1014 return value
1015
1016 def _update(self, cr, uid, model, module, values, xml_id=False, store=True, noupdate=False, mode='init', res_id=False, context=None):
1017
1018 def process_val(key, val):
1019 if fg[key]['type'] == 'many2one':
1020 if type(val) in (tuple,list):
1021 val = val[0]
1022 elif fg[key]['type'] == 'one2many':
1023 if val and isinstance(val, (list,tuple)) and isinstance(val[0], dict):
1024 # we want to return only the fields that aren't readonly
1025 # For that, we need to first get the right tree view to consider for the field `key´
1026 one2many_tree_view = _get_right_one2many_view(fg, key, 'tree')
1027 arch = etree.fromstring(one2many_tree_view['arch'].encode('utf-8'))
1028 for rec in val:
1029 # make a copy for the iteration, as we will alter `rec´
1030 rec_copy = rec.copy()
1031 for field_key in rec_copy:
1032 # if field is missing in view or has a readonly modifier, drop it
1033 field_elem = arch.xpath("//field[@name='%s']" % field_key)
1034 if field_elem and (field_elem[0].get('modifiers', '{}').find('"readonly": true') >= 0):
1035 # TODO: currently we only support if readonly is True in the modifiers. Some improvement may be done in
1036 # order to support also modifiers that look like {"readonly": [["state", "not in", ["draft", "confirm"]]]}
1037 del rec[field_key]
1038 # now that unwanted values have been removed from val, we can encapsulate it in a tuple as returned value
1039 val = map(lambda x: (0,0,x), val)
1040 elif fg[key]['type'] == 'many2many':
1041 if val and isinstance(val,(list,tuple)) and isinstance(val[0], (int,long)):
1042 val = [(6,0,val)]
1043
1044 # we want to return only the fields that aren't readonly
1045 if el.get('modifiers', '{}').find('"readonly": true') >= 0:
1046 # TODO: currently we only support if readonly is True in the modifiers. Some improvement may be done in
1047 # order to support also modifiers that look like {"readonly": [["state", "not in", ["draft", "confirm"]]]}
1048 return False
1049
1050 return val
1051
952 model_obj = self.pool[model]1052 model_obj = self.pool[model]
953 if not context:1053 if not context:
954 context = {}1054 context = {}
@@ -960,6 +1060,95 @@
960 if (not xml_id) and (not self.doinit):1060 if (not xml_id) and (not self.doinit):
961 return False1061 return False
962 action_id = False1062 action_id = False
1063
1064 view_info = self.pool[model].fields_view_get(cr, SUPERUSER_ID, False, 'form', context)
1065 if view_info:
1066 arch = etree.fromstring(view_info['arch'].decode('utf-8'))
1067 view = arch if len(arch) else False
1068 else:
1069 view = False
1070 ###To find default
1071 try:
1072 self.pool['ir.model.data']._get_id(cr, SUPERUSER_ID, module, xml_id)
1073 default = False
1074 except ValueError:
1075 default = True
1076 fields = values or {}
1077 if view is not False:
1078 fg = view_info['fields']
1079 # gather the default values on the object. (Can't use `fields´ as parameter instead of {} because we may
1080 # have references like `base.main_company´ in the yaml file and it's not compatible with the function)
1081 defaults = default and self._add_missing_default_values(cr, SUPERUSER_ID, {}, context=context) or {}
1082 # copy the default values in record_dict, only if they are in the view (because that's what the client does)
1083 # the other default values will be added later on by the create().
1084 record_dict = dict([(key, val) for key, val in defaults.items() if key in fg])
1085
1086 # Process all on_change calls
1087 nodes = [view]
1088 while nodes:
1089 el = nodes.pop(0)
1090 if el.tag =='field':
1091
1092# if not el.attrib.get('on_change', False):
1093# continue
1094# match = re.match("([a-z_1-9A-Z]+)\((.*)\)", el.attrib['on_change'])
1095# assert match, "Unable to parse the on_change '%s'!" % (el.attrib['on_change'],)
1096
1097 field_name = el.attrib['name']
1098 assert field_name in fg, "The field '%s' is defined in the form view but not on the object '%s'!" % (field_name, model._name)
1099 if field_name in fields:
1100 one2many_form_view = None
1101 if (view is not False) and (fg[field_name]['type']=='one2many'):
1102 # for one2many fields, we want to eval them using the inline form view defined on the parent
1103 one2many_form_view = _get_right_one2many_view(fg, field_name, 'form')
1104 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)
1105
1106 #call process_val to not update record_dict if values were given for readonly fields
1107 val = process_val(field_name, field_value)
1108 if val:
1109 record_dict[field_name] = val
1110 #if (field_name in defaults) and defaults[field_name] == field_value:
1111 # print '*** You can remove these lines:', field_name, field_value
1112
1113 #if field_name has a default value or a value is given in the yaml file, we must call its on_change()
1114 elif field_name not in defaults:
1115 continue
1116
1117 if not el.attrib.get('on_change', False):
1118 continue
1119 match = re.match("([a-z_1-9A-Z]+)\((.*)\)", el.attrib['on_change'])
1120 assert match, "Unable to parse the on_change '%s'!" % (el.attrib['on_change'],)
1121#####nedd to test whether needed or not
1122 # creating the context
1123 class parent2(object):
1124 def __init__(self, d):
1125 self.d = d
1126 def __getattr__(self, name):
1127 return self.d.get(name, False)
1128
1129 parent=record_dict#Same done above
1130 ctx = record_dict.copy()
1131 ctx['context'] = context
1132 ctx['uid'] = SUPERUSER_ID
1133 ctx['parent'] = parent2(parent)
1134 for a in fg:
1135 if a not in ctx:
1136 ctx[a] = process_val(a, defaults.get(a, False))
1137
1138# # Evaluation args
1139 args = map(lambda x: eval(x, ctx), match.group(2).split(','))#[36]
1140 result = getattr(self.pool[model], match.group(1))(cr, SUPERUSER_ID, [], *args)#{'value': {'bom_id': False, 'routing_id': False, 'product_uom': 2}}
1141 for key, val in (result or {}).get('value', {}).items():
1142 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'])
1143 if key not in fields:
1144 # do not shadow values explicitly set in yaml.
1145 record_dict[key] = process_val(key, val)
1146 else:
1147 nodes = list(el) + nodes
1148 else:
1149 record_dict = {}
1150 values.update(record_dict)
1151
963 if xml_id:1152 if xml_id:
964 cr.execute('''SELECT imd.id, imd.res_id, md.id, imd.model, imd.noupdate1153 cr.execute('''SELECT imd.id, imd.res_id, md.id, imd.model, imd.noupdate
965 FROM ir_model_data imd LEFT JOIN %s md ON (imd.res_id = md.id)1154 FROM ir_model_data imd LEFT JOIN %s md ON (imd.res_id = md.id)