[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
This commit is contained in:
Raphael Collet
2023-06-13 12:49:22 +02:00
parent 67a402edb5
commit d30b5c0392
2 changed files with 32 additions and 17 deletions
+27 -12
View File
@@ -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
@@ -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})],
}),
],
})