From c0fea2cec8f033858a21a7813b75cb7d8d88af4a Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 27 Jun 2022 14:42:59 +0000 Subject: [PATCH] [FIX] core: update inverse of many2many in order Consider two models A and B, a many2many field F from A to B and its inverse relation G from B to A. When F is modified, G is updated accordingly in cache. The statement records.write({F: [Command.link(b.id)]}) is expected to add b.id to records.F, and add records.ids to b.G. In order to avoid nondeterminism, the additions should be done at the end of the recordset, and in order. In other words, if none of "records" are in b.G, then after the statement above, b.G should be updated as b.G = b.G + records This patch ensures that "records" are added in order. closes odoo/odoo#94909 X-original-commit: b8fbc460673827497f6817e1751b5d365d8ae29a Signed-off-by: Vincent Schippefilt (vsc) Signed-off-by: Raphael Collet --- .../test_new_api/tests/test_new_fields.py | 28 +++++++++++++++++++ odoo/fields.py | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py index b1b175a0435..04529592445 100644 --- a/odoo/addons/test_new_api/tests/test_new_fields.py +++ b/odoo/addons/test_new_api/tests/test_new_fields.py @@ -2125,6 +2125,34 @@ class TestFields(TransactionCaseWithUserDemo): moves = self.env['test_new_api.move'].search([('line_ids', 'in', line.id)]) self.assertEqual(moves, move2) + def test_73_relational_inverse(self): + """ Check the consistency of relational fields with inverse(s). """ + discussion1, discussion2 = self.env['test_new_api.discussion'].create([ + {'name': "discussion1"}, {'name': "discussion2"}, + ]) + category1, category2 = self.env['test_new_api.category'].create([ + {'name': "category1"}, {'name': "category2"}, + ]) + + # assumption: category12 and category21 are in different order, but are + # in the same order when put in a set() + category12 = category1 + category2 + category21 = category2 + category1 + self.assertNotEqual(category12.ids, category21.ids) + self.assertEqual(list(set(category12.ids)), list(set(category21.ids))) + + # make sure discussion1.categories is in cache; the write() below should + # update the cache of discussion1.categories by appending category12.ids + discussion1.categories + category12.write({'discussions': [Command.link(discussion1.id)]}) + self.assertEqual(discussion1.categories.ids, category12.ids) + + # make sure discussion2.categories is in cache; the write() below should + # update the cache of discussion2.categories by appending category21.ids + discussion2.categories + category21.write({'discussions': [Command.link(discussion2.id)]}) + self.assertEqual(discussion2.categories.ids, category21.ids) + def test_80_copy(self): Translations = self.env['ir.translation'] discussion = self.env.ref('test_new_api.discussion_0') diff --git a/odoo/fields.py b/odoo/fields.py index 85eb6f94a1b..1f777e6c548 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -3882,7 +3882,7 @@ class Many2many(_RelationalMulti): # determine old and new relation {x: ys} set = OrderedSet - ids = {rid for recs, cs in records_commands_list for rid in recs.ids} + ids = set(rid for recs, cs in records_commands_list for rid in recs.ids) records = model.browse(ids) if self.store: