[FIX] orm: fix the method copy() when an 'inherits' field is given in parameter default
authorRaphael Collet <rco@openerp.com>
Fri, 28 Sep 2012 12:02:02 +0000 (14:02 +0200)
committerRaphael Collet <rco@openerp.com>
Fri, 28 Sep 2012 12:02:02 +0000 (14:02 +0200)
bzr revid: rco@openerp.com-20120928120202-6fbayrwb1iszwfwv

openerp/osv/orm.py

index f324ed6..651f655 100644 (file)
@@ -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])]
-
-        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
+                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]
+
+        return res
 
     def copy_translations(self, cr, uid, old_id, new_id, context=None):
         if context is None: