[FIX] core: unexpected cache invalidation when updating one2many
When setting a many2one field, the corresponding one2many fields are updated in cache. When such a one2many field has a domain, the evaluation of the domain may require to fetch some fields from the database. If the `towrite` cache has not been updated yet, the many2one field is overridden by the database value. Fix by setting the `towrite` cache before updating inverse fields. closes odoo/odoo#50788 X-original-commit: c1ebfe05a66cfebc7ced36e25db5f6ff4bfb2d46 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
This commit is contained in:
@@ -437,6 +437,28 @@ class MultiComputeInverse(models.Model):
|
||||
record.write({'foo': '/'.join([record.bar1, record.bar2, record.bar3])})
|
||||
|
||||
|
||||
class Move(models.Model):
|
||||
_name = 'test_new_api.move'
|
||||
_description = 'Move'
|
||||
|
||||
line_ids = fields.One2many('test_new_api.move_line', 'move_id', domain=[('visible', '=', True)])
|
||||
quantity = fields.Integer(compute='_compute_quantity', store=True)
|
||||
|
||||
@api.depends('line_ids.quantity')
|
||||
def _compute_quantity(self):
|
||||
for record in self:
|
||||
record.quantity = sum(line.quantity for line in record.line_ids)
|
||||
|
||||
|
||||
class MoveLine(models.Model):
|
||||
_name = 'test_new_api.move_line'
|
||||
_description = 'Move Line'
|
||||
|
||||
move_id = fields.Many2one('test_new_api.move', required=True, ondelete='cascade')
|
||||
visible = fields.Boolean(default=True)
|
||||
quantity = fields.Integer()
|
||||
|
||||
|
||||
class CompanyDependent(models.Model):
|
||||
_name = 'test_new_api.company'
|
||||
_description = 'Test New API Company'
|
||||
|
||||
@@ -57,3 +57,5 @@ access_test_new_api_monetary_order_line,access_test_new_api_monetary_order_line,
|
||||
access_test_new_api_model_selection_base,access_test_new_api_model_selection_base,model_test_new_api_model_selection_base,,1,1,1,1
|
||||
access_test_new_api_model_selection_required,access_test_new_api_model_selection_required,model_test_new_api_model_selection_required,,1,1,1,1
|
||||
access_test_new_api_model_selection_non_stored,access_test_new_api_model_selection_non_stored,model_test_new_api_model_selection_non_stored,,1,1,1,1
|
||||
access_test_new_api_move,access_test_new_api_move,model_test_new_api_move,,1,1,1,1
|
||||
access_test_new_api_move_line,access_test_new_api_move_line,model_test_new_api_move_line,,1,1,1,1
|
||||
|
||||
|
@@ -1514,6 +1514,22 @@ class TestFields(TransactionCaseWithUserDemo):
|
||||
self.assertEqual(discussion.messages, messages + message)
|
||||
self.assertEqual(demo_discussion.messages, discussion.messages)
|
||||
|
||||
def test_71_relational_inverse(self):
|
||||
""" Check the consistency of relational fields with inverse(s). """
|
||||
move1 = self.env['test_new_api.move'].create({})
|
||||
move2 = self.env['test_new_api.move'].create({})
|
||||
line = self.env['test_new_api.move_line'].create({'move_id': move1.id})
|
||||
line.flush()
|
||||
|
||||
self.env.cache.invalidate()
|
||||
line.with_context(prefetch_fields=False).move_id
|
||||
|
||||
# Setting 'move_id' updates the one2many field that is based on it,
|
||||
# which has a domain. Here we check that evaluating the domain does not
|
||||
# accidentally override 'move_id' (by prefetch).
|
||||
line.move_id = move2
|
||||
self.assertEqual(line.move_id, move2)
|
||||
|
||||
def test_80_copy(self):
|
||||
Translations = self.env['ir.translation']
|
||||
discussion = self.env.ref('test_new_api.discussion_0')
|
||||
|
||||
+3
-3
@@ -2600,9 +2600,6 @@ class Many2one(_Relational):
|
||||
# update the cache of self
|
||||
cache.update(records, self, [cache_value] * len(records))
|
||||
|
||||
# update the cache of one2many fields of new corecord
|
||||
self._update_inverses(records, cache_value)
|
||||
|
||||
# update towrite
|
||||
if self.store:
|
||||
towrite = records.env.all.towrite[self.model_name]
|
||||
@@ -2610,6 +2607,9 @@ class Many2one(_Relational):
|
||||
# cache_value is already in database format
|
||||
towrite[record.id][self.name] = cache_value
|
||||
|
||||
# update the cache of one2many fields of new corecord
|
||||
self._update_inverses(records, cache_value)
|
||||
|
||||
return records
|
||||
|
||||
def _remove_inverses(self, records, value):
|
||||
|
||||
Reference in New Issue
Block a user