From dc958192577da38aa9e2e51328f485879467da89 Mon Sep 17 00:00:00 2001 From: std-odoo Date: Wed, 3 May 2023 10:59:17 +0000 Subject: [PATCH] [IMP] base: do not write in database when we have invalid properties names Purpose ======= When we create a new record, we can change the definition on the definition record. If the parent had no definition, in `_add_default_values`, we just return the value. But in some weird cases, if we have invalid properties name in the value, the will be written in database. Now, in that particular case, we propagate the value only if we try to change the definition. Part-of: odoo/odoo#120457 --- .../test_new_api/tests/test_properties.py | 47 ++++++++++++++++++- odoo/fields.py | 12 +++-- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/odoo/addons/test_new_api/tests/test_properties.py b/odoo/addons/test_new_api/tests/test_properties.py index 158915ae7eb..445c656451e 100644 --- a/odoo/addons/test_new_api/tests/test_properties.py +++ b/odoo/addons/test_new_api/tests/test_properties.py @@ -92,7 +92,7 @@ class TestPropertiesMixin(TransactionCase): """, (message.id, ), ) value = self.env.cr.fetchone() - self.assertTrue(value and value[0]) + self.assertTrue(value) return value[0] def _get_sql_definition(self, discussion): @@ -530,6 +530,51 @@ class PropertiesCase(TestPropertiesMixin): msg='Should not take the default value', ) + # default value but no parent are set + record = self.env['test_new_api.message'].create({ + 'attributes': {'my_many2one': self.partner_2.id}, + }) + self.assertFalse(self._get_sql_properties(record)) + + # default value but the parent has no definition + self.discussion_1.attributes_definition = [] + record = self.env['test_new_api.message'].create({ + 'discussion': self.discussion_1.id, + 'attributes': {'my_many2one': self.partner_2.id}, + }) + self.assertFalse(self._get_sql_properties(record)) + + # default value but the parent has no definition and we create a new property + self.discussion_1.attributes_definition = [] + record = self.env['test_new_api.message'].create({ + 'discussion': self.discussion_1.id, + 'attributes': [{ + 'name': 'test', + 'type': 'many2one', + 'comodel': 'test_new_api.partner', + 'default': self.partner_2.id, + 'definition_changed': True, + }], + }) + self.assertEqual(self._get_sql_properties(record), {'test': self.partner_2.id}) + + # default value, a parent is set and change the definition + record = self.env['test_new_api.message'].create({ + 'discussion': self.discussion_1.id, + 'attributes': [{ + 'name': 'test', + 'type': 'many2one', + 'comodel': 'test_new_api.partner', + 'default': self.partner_2.id, + }, { + 'name': 'my_char', + 'type': 'char', + 'default': 'my char', + 'definition_changed': True, + }], + }) + self.assertEqual(self._get_sql_properties(record), {'my_char': 'my char', 'test': self.partner_2.id}) + def test_properties_field_read(self): """Test the behavior of the read method. diff --git a/odoo/fields.py b/odoo/fields.py index 0416886464a..3b230e0a8fe 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -3442,7 +3442,7 @@ class Properties(Field): if not values.get(self.definition_record): # container is not given in the value, can not find properties definition - return properties_values + return {} container_id = values[self.definition_record] if not isinstance(container_id, (int, BaseModel)): @@ -3456,8 +3456,14 @@ class Properties(Field): container_id = env[container_model_name].browse(container_id) properties_definition = container_id[self.definition_record_field] - if not properties_definition: - return properties_values + if not (properties_definition or ( + isinstance(properties_values, list) + and any(d.get('definition_changed') for d in properties_values) + )): + # If a parent is set without properties, we might want to change its definition + # when we create the new record. But if we just set the value without changing + # the definition, in that case we can just ignored the passed values + return {} assert isinstance(properties_values, (list, dict)) if isinstance(properties_values, list):