diff --git a/odoo/addons/base/models/ir_model.py b/odoo/addons/base/models/ir_model.py index aa389dad663..c4f019e4209 100644 --- a/odoo/addons/base/models/ir_model.py +++ b/odoo/addons/base/models/ir_model.py @@ -1435,6 +1435,8 @@ class IrModelSelection(models.Model): elif ondelete == 'set default': value = field.convert_to_write(field.default(Model), Model) safe_write(selection._get_records(), field.name, value) + elif ondelete.startswith('set '): + safe_write(selection._get_records(), field.name, ondelete[4:]) elif ondelete == 'cascade': selection._get_records().unlink() else: diff --git a/odoo/addons/test_new_api/models/test_new_api.py b/odoo/addons/test_new_api/models/test_new_api.py index 6b200fb7cd4..31069fabe0c 100644 --- a/odoo/addons/test_new_api/models/test_new_api.py +++ b/odoo/addons/test_new_api/models/test_new_api.py @@ -1179,7 +1179,7 @@ class SelectionRequiredLiteral(models.Model): my_selection = fields.Selection(selection_add=[ ('bacon', "Bacon"), - ], ondelete={'bacon': lambda r: r.write({'my_selection': 'bar'})}) + ], ondelete={'bacon': 'set bar'}) class SelectionRequiredMultiple(models.Model): diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py index 214b5c4708d..2e4db8cf336 100644 --- a/odoo/addons/test_new_api/tests/test_new_fields.py +++ b/odoo/addons/test_new_api/tests/test_new_fields.py @@ -315,10 +315,10 @@ class TestFields(TransactionCaseWithUserDemo): check_stored(discussion1) # switch message from discussion, and check again - + # See YTI FIXME discussion1.invalidate_cache() - + discussion2 = discussion1.copy({'name': 'Another discussion'}) message2 = discussion1.messages[0] message2.discussion = discussion2 @@ -3132,6 +3132,20 @@ class TestSelectionOndeleteAdvanced(common.TransactionCase): with self.assertRaises(AssertionError): self.registry.setup_models(self.env.cr) + def test_ondelete_value_no_valid(self): + class Foo(models.Model): + _module = None + _inherit = self.MODEL_BASE + + my_selection = fields.Selection(selection_add=[ + ('westvleteren', "Westvleteren beers is overrated"), + ], ondelete={'westvleteren': 'set foooo'}) + + Foo._build_model(self.registry, self.env.cr) + + with self.assertRaises(AssertionError): + self.registry.setup_models(self.env.cr) + def test_ondelete_required_null_explicit(self): class Foo(models.Model): _module = None diff --git a/odoo/fields.py b/odoo/fields.py index db5b27f3a9d..a5188251533 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -2347,6 +2347,8 @@ class Selection(Field): deleted along with the option itself. - 'set default' -- all records with this option will be set to the default of the field definition + - 'set VALUE' -- all records with this option will be + set to the given value - -- a callable whose first and only argument will be the set of records containing the specified Selection option, for custom processing @@ -2444,12 +2446,17 @@ class Selection(Field): "as it does not define a default! Either define one in the base " "field, or change the chosen ondelete policy" % self ) - continue - raise ValueError( - "%r: ondelete policy %r for selection value %r is not a valid ondelete " - "policy, please choose one of 'set null', 'set default', 'cascade' or " - "a callable" % (self, val, key) - ) + elif val.startswith('set '): + assert val[4:] in values, ( + "%s: ondelete policy of type 'set %%' must be either 'set null', " + "'set default', or 'set value' where value is a valid selection value." + ) % self + else: + raise ValueError( + "%r: ondelete policy %r for selection value %r is not a valid ondelete" + " policy, please choose one of 'set null', 'set default', " + "'set [value]', 'cascade' or a callable" % (self, val, key) + ) values = merge_sequences(values, [kv[0] for kv in selection_add]) labels.update(kv for kv in selection_add if len(kv) == 2)