diff --git a/odoo/addons/test_inherits/models.py b/odoo/addons/test_inherits/models.py index c9eeff60904..b503e8c173b 100644 --- a/odoo/addons/test_inherits/models.py +++ b/odoo/addons/test_inherits/models.py @@ -13,6 +13,7 @@ class Unit(models.Model): surname = fields.Char(compute='_compute_surname') line_ids = fields.One2many('test.unit.line', 'unit_id') readonly_name = fields.Char('Readonly Name', readonly=True) + size = fields.Integer() @api.depends('name') def _compute_surname(self): @@ -38,6 +39,7 @@ class Box(models.Model): unit_id = fields.Many2one('test.unit', 'Unit', required=True, ondelete='cascade') field_in_box = fields.Char('Field1') + size = fields.Integer() # We add a third level of _inherits diff --git a/odoo/addons/test_inherits/tests/test_inherits.py b/odoo/addons/test_inherits/tests/test_inherits.py index 4c32db71864..9822ab19020 100644 --- a/odoo/addons/test_inherits/tests/test_inherits.py +++ b/odoo/addons/test_inherits/tests/test_inherits.py @@ -17,6 +17,24 @@ class test_inherits(common.TransactionCase): self.assertEqual(pallet.field_in_box, 'box') self.assertEqual(pallet.field_in_pallet, 'pallet') + def test_create_3_levels_inherits_with_defaults(self): + unit = self.env['test.unit'].create({ + 'name': 'U', + 'state': 'a', + 'size': 1, + }) + ctx = { + 'default_state': 'b', # 'state' is inherited from 'test.unit' + 'default_size': 2, # 'size' is inherited from 'test.box' + } + pallet = self.env['test.pallet'].with_context(ctx).create({ + 'name': 'P', + 'unit_id': unit.id, # grand-parent field is set + }) + # default 'state' should be ignored, but default 'size' should not + self.assertEqual(pallet.state, 'a') + self.assertEqual(pallet.size, 2) + def test_read_3_levels_inherits(self): """ Check that we can read an inherited field on 3 levels """ pallet = self.env.ref('test_inherits.pallet_a') diff --git a/odoo/models.py b/odoo/models.py index 0a3a08109a2..6489e13e65d 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -1807,18 +1807,33 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): @api.model def _add_missing_default_values(self, values): # avoid overriding inherited values when parent is set - avoid_models = { - parent_model - for parent_model, parent_field in self._inherits.items() - if parent_field in values - } + avoid_models = set() + + def collect_models_to_avoid(model): + for parent_mname, parent_fname in model._inherits.items(): + if parent_fname in values: + avoid_models.add(parent_mname) + else: + # manage the case where an ancestor parent field is set + collect_models_to_avoid(self.env[parent_mname]) + + collect_models_to_avoid(self) + + def avoid(field): + # check whether the field is inherited from one of avoid_models + if avoid_models: + while field.inherited: + field = field.related_field + if field.model_name in avoid_models: + return True + return False # compute missing fields missing_defaults = { name for name, field in self._fields.items() if name not in values - if not (field.inherited and field.related_field.model_name in avoid_models) + if not avoid(field) } if not missing_defaults: