From 15bfff301c4734efd66c45d83fe7fc8e3d2dc83d Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 20 Feb 2024 12:20:04 +0100 Subject: [PATCH] [FIX] web: onchange() does not handle _inherits parent field in one2many MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consider models A and B such that B inherits from A (with _inherits), and a form view of A with a one2many field that inverses the many2one "delegate" field from B to A. When adding a new record in the one2many, onchange() crashes while trying to update the cache of an empty parent record. The situation is caused by how onchange() initializes the new record of model B, and the fact that the form provides a value for the delegate field. The new record is actually initialized with an empty value for the delegate field, which causes the code to crash. The fix simply consists in updating the parent record only if is nonempty. opw-3744514 closes odoo/odoo#154735 Signed-off-by: Rémy Voet (ryv) Co-authored-by: Lucas Perais --- addons/web/models/models.py | 3 ++- .../test_new_api/tests/test_onchange.py | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/addons/web/models/models.py b/addons/web/models/models.py index e97cecf0873..75486bcd4e1 100644 --- a/addons/web/models/models.py +++ b/addons/web/models/models.py @@ -1018,7 +1018,8 @@ class Base(models.AbstractModel): field = self._fields.get(field_name) if field and field.inherited: parent_name, field_name = field.related.split('.', 1) - record[parent_name]._update_cache({field_name: record[field_name]}) + if parent := record[parent_name]: + parent._update_cache({field_name: record[field_name]}) # make a snapshot based on the initial values of record snapshot0 = RecordSnapshot(record, fields_spec, fetch=(not first_call)) diff --git a/odoo/addons/test_new_api/tests/test_onchange.py b/odoo/addons/test_new_api/tests/test_onchange.py index 5343cbcafe9..e08f472d30f 100644 --- a/odoo/addons/test_new_api/tests/test_onchange.py +++ b/odoo/addons/test_new_api/tests/test_onchange.py @@ -685,6 +685,30 @@ class TestOnchange(SavepointCaseWithUserDemo): self.assertEqual(payment.tag_repeat, 3) self.assertEqual(payment.tag_string, 'BarBarBar') + def test_onchange_inherited_in_one2many(self): + move = self.env['test_new_api.move'].create({}) + view = self.env["ir.ui.view"].create({ + "model": "test_new_api.move", + "type": "form", + "arch": """
+ + + + + + + """ + }) + + with Form(move, view) as form: + with form.payment_ids.new() as line: + line.tag_repeat = 1 + self.assertEqual(len(form.payment_ids), 1) + + self.assertEqual(len(move.payment_ids), 1) + self.assertEqual(move.payment_ids.move_id, move) + self.assertEqual(move.payment_ids.tag_repeat, 1) + def test_display_name(self): self.env['ir.ui.view'].create({ 'name': 'test_new_api.multi.tag form view',