From be278780f75ca42b4f5586bc4e446ad1ae0cfbd4 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 7 Mar 2023 16:43:35 +0000 Subject: [PATCH] [FIX] core: first onchange when adding a line in a one2many field Consider a form view with a one2many field, which has no form subview. Also the form view of the comodel (the one2many field's lines) contains the inverse many2one field of the one2many field. When adding a new line on some existing record, the form view shows the many2one field as empty, instead of being the main record. Explanation: the form view of the line invokes onchange() with the main record's values (dict) as the value of the many2one field. Inside onchange(), the field is actually set to a new record corresponding to the main record. Alas, when that value is sent back to the form, the new record is serialized as False. Solution: let onchange() serialize the new record as its origin record instead. closes odoo/odoo#114648 X-original-commit: d137ea4915da8d46909fcb082b5a88fd347874a4 Signed-off-by: Raphael Collet --- odoo/addons/test_new_api/tests/test_onchange.py | 14 ++++++++++++++ odoo/fields.py | 5 ++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/odoo/addons/test_new_api/tests/test_onchange.py b/odoo/addons/test_new_api/tests/test_onchange.py index b43e495b0f7..2e21f106a77 100644 --- a/odoo/addons/test_new_api/tests/test_onchange.py +++ b/odoo/addons/test_new_api/tests/test_onchange.py @@ -535,6 +535,20 @@ class TestOnChange(SavepointCaseWithUserDemo): self.assertFalse(called[0], "discussion.messages has been read") + def test_onchange_one2many_many2one_in_form(self): + order = self.env['test_new_api.monetary_order'].create({ + 'currency_id': self.env.ref('base.USD').id, + }) + + # this call to onchange() is made when creating a new line in field + # order.line_ids; check what happens when the line's form view contains + # the inverse many2one field + values = {'order_id': {'id': order.id, 'currency_id': order.currency_id.id}} + field_onchange = dict.fromkeys(['order_id', 'subtotal'], '') + result = self.env['test_new_api.monetary_order_line'].onchange(values, [], field_onchange) + + self.assertEqual(result['value']['order_id'], (order.id, order.display_name)) + 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'}]) diff --git a/odoo/fields.py b/odoo/fields.py index 1b86947ae40..fc6ccb6b327 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -3019,9 +3019,8 @@ class Many2one(_Relational): return value.display_name def convert_to_onchange(self, value, record, names): - if not value.id: - return False - return super(Many2one, self).convert_to_onchange(value, record, names) + # if value is a new record, serialize its origin instead + return super().convert_to_onchange(value._origin, record, names) def write(self, records, value): # discard recomputation of self on records