[FIX] core: fix Field._update() method to take in account archived record

In e0297bd, we fixed the inverse field values of the new record during
the onchange. But we actually filter out inactive records by doing
record[self.name] in _update(). And since the XtoMany field cache
values should always contain inactive records, we need to add
with_context(active_test=False) on records.
Also remove the useless 'if value', value is always truly because it
is always a record.

Note that this solves a performance issue in our production, because
in order to filter out inactive records, we need to fetch the active
field next to every prefechable field.

closes odoo/odoo#148675

Signed-off-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
Rémy Voet (ryv)
2024-01-10 08:51:01 +00:00
parent 4ea715e151
commit e3177646b6
3 changed files with 25 additions and 7 deletions
@@ -159,7 +159,7 @@ class Message(models.Model):
@api.depends('discussion.messages.important')
def _compute_has_important_sibling(self):
for record in self:
siblings = record.discussion.messages - record
siblings = record.discussion.with_context(active_test=False).messages - record
record.has_important_sibling = any(siblings.mapped('important'))
@api.constrains('author', 'discussion')
@@ -1252,3 +1252,22 @@ class TestComputeOnchange2(common.TransactionCase):
self.assertEqual(message_form.has_important_sibling, True)
message_form.body = 'Required Body'
self.assertEqual(len(discussion_form.messages), 2)
# Test the same flow but when the important message is archived.
# The _compute_has_important_sibling should take in account archived siblings.
discussion = self.env['test_new_api.discussion'].create({
'messages': [
Command.create({'body': 'Archived Important sibling', 'important': True, 'active': False}),
],
'name': 'Required field',
'participants': [Command.set(self.env.user.ids)],
})
with Form(discussion, 'test_new_api.discussion_form_2') as discussion_form:
self.assertEqual(len(discussion_form.messages), 0)
with discussion_form.messages.new() as message_form:
# this actually checks that during the onchange, the new message
# has access to its archived sibling messages through the discussion
self.assertEqual(message_form.has_important_sibling, True)
message_form.body = 'Required Body'
self.assertEqual(len(discussion_form.messages), 1)
+5 -6
View File
@@ -4159,12 +4159,11 @@ class _RelationalMulti(_Relational):
def _update(self, records, value):
""" Update the cached value of ``self`` for ``records`` with ``value``. """
if value:
cache = records.env.cache
for record in records:
val = self.convert_to_cache(record[self.name] | value, record, validate=False)
cache.set(record, self, val)
records.modified([self.name])
cache = records.env.cache
for record in records.with_context(active_test=False):
val = self.convert_to_cache(record[self.name] | value, record, validate=False)
cache.set(record, self, val)
records.modified([self.name])
def convert_to_cache(self, value, record, validate=True):
# cache format: tuple(ids)