From 32aa7dc9a0e4a987aff13f93627faa7036798df3 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Wed, 23 Aug 2017 14:54:26 +0200 Subject: [PATCH] [FIX] models: implement `change_default` behavior for fields The behavior is no longer implemented by the web client. Implement it server-side as part of the onchange mechanism, simply by defining onchange methods for the fields that have the flag. --- odoo/addons/test_new_api/models.py | 2 +- .../test_new_api/tests/test_onchange.py | 22 +++++++++++++++++++ odoo/models.py | 12 ++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/odoo/addons/test_new_api/models.py b/odoo/addons/test_new_api/models.py index c84827d47ce..02609521ae0 100644 --- a/odoo/addons/test_new_api/models.py +++ b/odoo/addons/test_new_api/models.py @@ -286,7 +286,7 @@ class Foo(models.Model): _name = 'test_new_api.foo' name = fields.Char() - value1 = fields.Integer() + value1 = fields.Integer(change_default=True) value2 = fields.Integer() diff --git a/odoo/addons/test_new_api/tests/test_onchange.py b/odoo/addons/test_new_api/tests/test_onchange.py index a6e2bff1b35..43c36b5b1d1 100644 --- a/odoo/addons/test_new_api/tests/test_onchange.py +++ b/odoo/addons/test_new_api/tests/test_onchange.py @@ -231,6 +231,28 @@ class TestOnChange(common.TransactionCase): for user in discussion.participants + demo], ) + def test_onchange_default(self): + """ test the effect of a conditional user-default on a field """ + Foo = self.env['test_new_api.foo'] + field_onchange = Foo._onchange_spec() + self.assertTrue(Foo._fields['value1'].change_default) + self.assertEqual(field_onchange.get('value1'), '1') + + # create a user-defined default based on 'value1' + self.env['ir.values'].set_default('test_new_api.foo', 'value2', 666, condition='value1=42') + + # setting 'value1' to 42 should trigger the change of 'value2' + self.env.invalidate_all() + values = {'name': 'X', 'value1': 42, 'value2': False} + result = Foo.onchange(values, 'value1', field_onchange) + self.assertEqual(result['value'], {'value2': 666}) + + # setting 'value1' to 24 should not trigger the change of 'value2' + self.env.invalidate_all() + values = {'name': 'X', 'value1': 24, 'value2': False} + result = Foo.onchange(values, 'value1', field_onchange) + self.assertEqual(result['value'], {}) + def test_onchange_one2many_value(self): """ test the value of the one2many field inside the onchange """ discussion = self.env.ref('test_new_api.discussion_0') diff --git a/odoo/models.py b/odoo/models.py index d5540341b4b..f6139aa3a36 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -573,6 +573,7 @@ class BaseModel(object): def is_onchange(func): return callable(func) and hasattr(func, '_onchange') + # collect onchange methods on the model's class cls = type(self) methods = defaultdict(list) for attr, func in getmembers(cls, is_onchange): @@ -581,6 +582,17 @@ class BaseModel(object): _logger.warning("@onchange%r parameters must be field names", func._onchange) methods[name].append(func) + # add onchange methods to implement "change_default" on fields + def onchange_default(field, self): + value = field.convert_to_write(self[field.name], self) + condition = "%s=%s" % (field.name, value) + defaults = self.env['ir.values'].get_defaults_dict(self._name, condition) + self.update(defaults) + + for name, field in cls._fields.items(): + if field.change_default: + methods[name].append(functools.partial(onchange_default, field)) + # optimization: memoize result on cls, it will not be recomputed cls._onchange_methods = methods return methods