[IMP] core: allow set [value] in selection ondelete

In some cases we migh want to change to a value that isn't the default
one when uninstalling.
For instance: when we uninstall the module `event_sale`, a product has
the field `detailed_type` set to `event`, which is a subtype of `service`.
So we want to update the value to `service` when uninstalling instead of
the default value, which would be `consu` and wouldn't make any sense.

Part-of: odoo/odoo#77876
This commit is contained in:
william-andre
2021-10-11 10:15:48 +00:00
parent e4926a24da
commit d3f4ce1152
4 changed files with 32 additions and 9 deletions
+2
View File
@@ -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:
@@ -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):
@@ -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
+13 -6
View File
@@ -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
- <callable> -- 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)