From 0d878dc99e93b61085d746456e422e73a8e23dec Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 28 Sep 2012 14:02:02 +0200 Subject: [PATCH] [FIX] orm: fix the method copy() when an 'inherits' field is given in parameter default bzr revid: rco@openerp.com-20120928120202-6fbayrwb1iszwfwv --- openerp/osv/orm.py | 83 ++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index f324ed67522..651f655617c 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -4744,56 +4744,45 @@ class BaseModel(object): else: raise IndexError( _("Record #%d of %s not found, cannot copy!") %( id, self._name)) - # TODO it seems fields_get can be replaced by _all_columns (no need for translation) - fields = self.fields_get(cr, uid, context=context) - for f in fields: - ftype = fields[f]['type'] - - if self._log_access and f in LOG_ACCESS_COLUMNS: - del data[f] + # build a black list of fields that should not be copied + blacklist = set(MAGIC_COLUMNS + ['parent_left', 'parent_right']) + def blacklist_given_fields(obj): + # blacklist the fields that are given by inheritance + for other, field_to_other in obj._inherits.items(): + blacklist.add(field_to_other) + if field_to_other in default: + # all the fields of 'other' are given by the record: default[field_to_other], + # except the ones redefined in self + blacklist.update(set(self.pool.get(other)._all_columns) - set(self._columns)) + else: + blacklist_given_fields(self.pool.get(other)) + blacklist_given_fields(self) + res = dict(default) + for f, colinfo in self._all_columns.items(): + field = colinfo.column if f in default: - data[f] = default[f] - elif 'function' in fields[f]: - del data[f] - elif ftype == 'many2one': - try: - data[f] = data[f] and data[f][0] - except: - pass - elif ftype == 'one2many': - res = [] - rel = self.pool.get(fields[f]['relation']) - if data[f]: - # duplicate following the order of the ids - # because we'll rely on it later for copying - # translations in copy_translation()! - data[f].sort() - for rel_id in data[f]: - # the lines are first duplicated using the wrong (old) - # parent but then are reassigned to the correct one thanks - # to the (0, 0, ...) - d = rel.copy_data(cr, uid, rel_id, context=context) - if d: - res.append((0, 0, d)) - data[f] = res - elif ftype == 'many2many': - data[f] = [(6, 0, data[f])] + pass + elif f in blacklist: + pass + elif isinstance(field, fields.function): + pass + elif field._type == 'many2one': + res[f] = data[f] and data[f][0] + elif field._type == 'one2many': + other = self.pool.get(field._obj) + # duplicate following the order of the ids because we'll rely on + # it later for copying translations in copy_translation()! + lines = [other.copy_data(cr, uid, line_id, context=context) for line_id in sorted(data[f])] + # the lines are duplicated using the wrong (old) parent, but then + # are reassigned to the correct one thanks to the (0, 0, ...) + res[f] = [(0, 0, line) for line in lines if line] + elif field._type == 'many2many': + res[f] = [(6, 0, data[f])] + else: + res[f] = data[f] - del data['id'] - - # make sure we don't break the current parent_store structure and - # force a clean recompute! - for parent_column in ['parent_left', 'parent_right']: - data.pop(parent_column, None) - # Remove _inherits field's from data recursively, missing parents will - # be created by create() (so that copy() copy everything). - def remove_ids(inherits_dict): - for parent_table in inherits_dict: - del data[inherits_dict[parent_table]] - remove_ids(self.pool.get(parent_table)._inherits) - remove_ids(self._inherits) - return data + return res def copy_translations(self, cr, uid, old_id, new_id, context=None): if context is None: