From d30b5c039292000318890d4ab757b3f76a7b80ec Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Wed, 7 Jun 2023 14:38:36 +0000 Subject: [PATCH] [FIX] web: onchange2() format of values in LINK commands The LINK command must include the corresponding record data in the web_read() format instead of the diff() format. The real difference shows up in x2many fields: web_read() returns them as lists of dicts (or list of ids), while diff() returns them as lists of commands. Part-of: odoo/odoo#124612 --- addons/web/models/models.py | 39 +++++++++++++------ .../test_new_api/tests/test_onchange2.py | 10 ++--- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/addons/web/models/models.py b/addons/web/models/models.py index 01834787017..3ca76800190 100644 --- a/addons/web/models/models.py +++ b/addons/web/models/models.py @@ -1195,32 +1195,47 @@ class RecordSnapshot(dict): # for x2many fields: serialize value as commands for field_name, field_spec in x2many_fields_spec.items(): - result[field_name] = commands = [] + commands = [] + + self_value = self[field_name] + other_value = other.get(field_name) or {} + if any(other_value): + # other may be a snapshot for a real record, adapt its x2many ids + other_value = {NewId(id_): snap for id_, snap in other_value.items()} + # commands for removed lines field = self.record._fields[field_name] remove = Command.delete if field.type == 'one2many' else Command.unlink - for id_, line_snapshot in (other.get(field_name) or {}).items(): - if id_ not in self[field_name]: + for id_ in other_value: + if id_ not in self_value: commands.append(remove(id_.origin or id_.ref or 0)) + # commands for modified or extra lines - for id_, line_snapshot in self[field_name].items(): - if not force and id_ in other.get(field_name, ()): - # existing line: check diff - line_diff = line_snapshot.diff(other[field_name][id_]) + for id_, line_snapshot in self_value.items(): + if not force and id_ in other_value: + # existing line: check diff and send update + line_diff = line_snapshot.diff(other_value[id_]) if line_diff: commands.append(Command.update(id_.origin or id_.ref or 0, line_diff)) + elif not id_.origin: # new line: send diff from scratch line_diff = line_snapshot.diff({}) commands.append((Command.CREATE, id_.origin or id_.ref or 0, line_diff)) + else: - # link line: send data to client and possible update - line = line_snapshot.record._origin - base_snapshot = RecordSnapshot(line, field_spec.get('fields') or {}) - line_data = base_snapshot.diff({}) - commands.append((Command.LINK, line.id, line_data)) + # link line: send data to client + base_line = line_snapshot.record._origin + [base_data] = base_line.web_read(field_spec.get('fields') or {}) + commands.append((Command.LINK, base_line.id, base_data)) + + # check diff and send update + base_snapshot = RecordSnapshot(base_line, field_spec.get('fields') or {}) line_diff = line_snapshot.diff(base_snapshot) if line_diff: commands.append(Command.update(id_.origin, line_diff)) + if commands: + result[field_name] = commands + return result diff --git a/odoo/addons/test_new_api/tests/test_onchange2.py b/odoo/addons/test_new_api/tests/test_onchange2.py index d5631c7e8cd..9f020a87078 100644 --- a/odoo/addons/test_new_api/tests/test_onchange2.py +++ b/odoo/addons/test_new_api/tests/test_onchange2.py @@ -48,7 +48,7 @@ class TestOnchange2(SavepointCaseWithUserDemo): fields_spec = {'tags': {}} result = model.onchange2({}, [], fields_spec) - self.assertEqual(result['value'], {'tags': [(Command.LINK, tag.id, {})]}) + self.assertEqual(result['value'], {'tags': [(Command.LINK, tag.id, {'id': tag.id})]}) def test_get_field(self): """ checking that accessing an unknown attribute does nothing special """ @@ -399,7 +399,7 @@ class TestOnchange2(SavepointCaseWithUserDemo): self.assertIn('participants', result['value']) self.assertItemsEqual( result['value']['participants'], - [(Command.LINK, demo.id, {'display_name': demo.display_name})], + [(Command.LINK, demo.id, {'id': demo.id, 'display_name': demo.display_name})], ) def test_onchange_default(self): @@ -856,7 +856,7 @@ class TestOnchange2(SavepointCaseWithUserDemo): self.assertEqual(result['value'], { 'lines': [ Command.update(line.id, { - 'tags': [(Command.LINK, tag.id, {'display_name': 'tag!'})], + 'tags': [(Command.LINK, tag.id, {'id': tag.id, 'display_name': 'tag!'})], }), ], }) @@ -891,10 +891,10 @@ class TestOnchange2(SavepointCaseWithUserDemo): self.assertEqual(result['value'], { 'lines': [ Command.update(line.id, { - 'tags': [(Command.LINK, tag2.id, {})], + 'tags': [(Command.LINK, tag2.id, {'id': tag2.id})], }), Command.update('virtual1', { - 'tags': [(Command.LINK, tag2.id, {})], + 'tags': [(Command.LINK, tag2.id, {'id': tag2.id})], }), ], })