[FIX] core: in onchange, assign inherited fields that have changed
This allows onchange to recompute fields that depend on the inherited field that has changed. The use-case we have is a model that inherits from 'account.move'. On its form view, setting the (inherited) journal field does not recompute the (inherited) company field. When the field 'journal_id' is modified, the onchange should: - assign the new value to move_id.journal_id (*) - recompute move_id.company_id (related='journal_id.company_id') - recompute company_id This commit adds the missing part (*). X-original-commit: 2e05d0a361aa06a34eecf64613821f2e92295298
This commit is contained in:
@@ -455,6 +455,8 @@ class Move(models.Model):
|
||||
|
||||
line_ids = fields.One2many('test_new_api.move_line', 'move_id', domain=[('visible', '=', True)])
|
||||
quantity = fields.Integer(compute='_compute_quantity', store=True)
|
||||
tag_id = fields.Many2one('test_new_api.multi.tag')
|
||||
tag_name = fields.Char(related='tag_id.name')
|
||||
|
||||
@api.depends('line_ids.quantity')
|
||||
def _compute_quantity(self):
|
||||
@@ -471,6 +473,14 @@ class MoveLine(models.Model):
|
||||
quantity = fields.Integer()
|
||||
|
||||
|
||||
class Payment(models.Model):
|
||||
_name = 'test_new_api.payment'
|
||||
_description = 'Payment inherits from Move'
|
||||
_inherits = {'test_new_api.move': 'move_id'}
|
||||
|
||||
move_id = fields.Many2one('test_new_api.move', required=True, ondelete='cascade')
|
||||
|
||||
|
||||
class CompanyDependent(models.Model):
|
||||
_name = 'test_new_api.company'
|
||||
_description = 'Test New API Company'
|
||||
|
||||
@@ -66,6 +66,7 @@ access_test_new_api_model_selection_non_stored,access_test_new_api_model_selecti
|
||||
access_test_new_api_model_selection_required_for_write_override,access_test_new_api_model_selection_required_for_write_override,model_test_new_api_model_selection_required_for_write_override,,1,1,1,1
|
||||
access_test_new_api_move,access_test_new_api_move,model_test_new_api_move,,1,1,1,1
|
||||
access_test_new_api_move_line,access_test_new_api_move_line,model_test_new_api_move_line,,1,1,1,1
|
||||
access_test_new_api_payment,access_test_new_api_payment,model_test_new_api_payment,,1,1,1,1
|
||||
access_test_new_api_model_shared_cache_compute_parent,access_test_new_api.model_shared_cache_compute_parent,model_test_new_api_model_shared_cache_compute_parent,,1,1,1,1
|
||||
access_test_new_api_model_shared_cache_compute_line,access_test_new_api.model_shared_cache_compute_line,model_test_new_api_model_shared_cache_compute_line,,1,1,1,1
|
||||
access_test_new_api_compute_container,access_test_new_api_compute_container,model_test_new_api_compute_container,,1,1,1,1
|
||||
|
||||
|
@@ -537,6 +537,38 @@ class TestOnChange(SavepointCaseWithUserDemo):
|
||||
|
||||
self.assertFalse(called[0], "discussion.messages has been read")
|
||||
|
||||
def test_onchange_inherited(self):
|
||||
""" Setting an inherited field should assign the field on the parent record. """
|
||||
foo, bar = self.env['test_new_api.multi.tag'].create([{'name': 'Foo'}, {'name': 'Bar'}])
|
||||
view = self.env['ir.ui.view'].create({
|
||||
'name': 'Payment form view',
|
||||
'model': 'test_new_api.payment',
|
||||
'arch': """
|
||||
<form>
|
||||
<field name="tag_id"/>
|
||||
<field name="tag_name"/>
|
||||
</form>
|
||||
""",
|
||||
})
|
||||
|
||||
# both fields 'tag_id' and 'tag_name' are inherited through 'move_id';
|
||||
# assigning 'tag_id' should modify 'move_id.tag_id' accordingly, which
|
||||
# should in turn recompute `move.tag_name` and `tag_name`
|
||||
form = Form(self.env['test_new_api.payment'], view)
|
||||
form.tag_id = foo
|
||||
self.assertEqual(form.tag_name, 'Foo')
|
||||
|
||||
payment = form.save()
|
||||
self.assertEqual(payment.tag_id, foo)
|
||||
self.assertEqual(payment.tag_name, 'Foo')
|
||||
|
||||
with Form(payment, view) as form:
|
||||
form.tag_id = bar
|
||||
self.assertEqual(form.tag_name, 'Bar')
|
||||
|
||||
self.assertEqual(payment.tag_id, bar)
|
||||
self.assertEqual(payment.tag_name, 'Bar')
|
||||
|
||||
|
||||
class TestComputeOnchange(common.TransactionCase):
|
||||
|
||||
|
||||
+10
-1
@@ -6111,7 +6111,7 @@ Fields:
|
||||
presence of ``other_fields``.
|
||||
"""
|
||||
return (field.name in self._onchange_methods) or any(
|
||||
dep in other_fields for dep in self._dependent_fields(field)
|
||||
dep in other_fields for dep in self._dependent_fields(field.base_field)
|
||||
)
|
||||
|
||||
@api.model
|
||||
@@ -6404,6 +6404,15 @@ Fields:
|
||||
protected = [self._fields[name] for name in names]
|
||||
with self.env.protecting(protected, record):
|
||||
record.modified(todo)
|
||||
for name in todo:
|
||||
field = self._fields[name]
|
||||
if field.inherited:
|
||||
# modifying an inherited field should modify the parent
|
||||
# record accordingly; because we don't actually assign the
|
||||
# modified field on the record, the modification on the
|
||||
# parent record has to be done explicitly
|
||||
parent = record[field.related.split('.')[0]]
|
||||
parent[name] = record[name]
|
||||
|
||||
result = {'warnings': OrderedSet()}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user