diff --git a/odoo/addons/test_new_api/tests/test_properties.py b/odoo/addons/test_new_api/tests/test_properties.py index d6bd240abee..2574f82cba8 100644 --- a/odoo/addons/test_new_api/tests/test_properties.py +++ b/odoo/addons/test_new_api/tests/test_properties.py @@ -1186,6 +1186,28 @@ class PropertiesCase(TransactionCase): message.attributes, [{'name': 'new_property', 'type': 'char', 'value': 'test value'}]) + # re-write the same parent again and check that value are not reset + message.discussion = message.discussion + self.assertEqual( + message.attributes, + [{'name': 'new_property', 'type': 'char', 'value': 'test value'}]) + + # trigger a other onchange after setting the properties + # and check that it does not impact the properties + message.discussion.attributes_definition = [] + message_form = Form(message) + message.attributes = [{ + 'name': 'new_property', + 'type': 'char', + 'value': 'test value', + 'definition_changed': True, + }] + message_form.body = "a" * 42 + message = message_form.save() + self.assertEqual( + message.attributes, + [{'name': 'new_property', 'type': 'char', 'value': 'test value'}]) + @mute_logger('odoo.fields') def test_properties_field_definition_update(self): """Test the definition update from the child.""" diff --git a/odoo/models.py b/odoo/models.py index a7d8567ed18..3eda64a9170 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -6827,9 +6827,26 @@ class BaseModel(metaclass=MetaModel): for name, subnames in self[''].items(): if name == 'id': continue + field = record._fields[name] + if (field.type == 'properties' and field.definition_record in field_name + and other.get(name) == self[name] == []): + # TODO: The parent field on "record" can be False, if it was changed, + # (even if if was changed to a not Falsy value) because of + # >>> initial_values = dict(values, **dict.fromkeys(names, False)) + # If it's the case when we will read the properties field on this record, + # it will return False as well (no parent == no definition) + # So record at the following line, will always return a empty properties + # because the definition record is always False if it triggered the onchange + # >>> snapshot0 = Snapshot(record, nametree, fetch=(not first_call)) + # but we need "snapshot0" to have the old value to be able + # to compare it with the new one and trigger the onchange if necessary. + # In that particular case, "other.get(name)" must contains the + # non empty properties value. + result[name] = [] + continue + if not force and other.get(name) == self[name]: continue - field = record._fields[name] if field.type not in ('one2many', 'many2many'): result[name] = field.convert_to_onchange(self[name], record, {}) else: @@ -6957,18 +6974,6 @@ class BaseModel(metaclass=MetaModel): # make a snapshot based on the initial values of record snapshot0 = Snapshot(record, nametree, fetch=(not first_call)) - for name in initial_values: - # TODO: The parent field on "record" can be False, if it was changed, - # (even if if was changed to a not Falsy value) because of - # >>> initial_values = dict(values, **dict.fromkeys(names, False)) - # If it's the case when we will read the properties field on this record, - # it will return False as well (no parent == no definition) but we need - # "snapshot0" to have the old value to be able to compare it with the new one - # and trigger the onchange if necessary. - field = self._fields.get(name) - if field and field.type == 'properties': - snapshot0[name] = initial_values[name] - # store changed values in cache; also trigger recomputations based on # subfields (e.g., line.a has been modified, line.b is computed stored # and depends on line.a, but line.b is not in the form view)