[FIX] core: marking of stored computed recursive fields during creation
Fixes 3a6ac95 that ignores computation of recursive stored fields during creation of records. The problem happens when we have: * a recursive stored computed field * an `api.depends` of this field which is a relation to another record When this "another record" is created and should recompute the recursive field, it is ignored. closes odoo/odoo#64117 X-original-commit: 9fe4fe404b73e9ab18ab6b3b913f075c64bb6954 Signed-off-by: Raphael Collet (rco) <rco@openerp.com> Co-authored-by: Raphael Collet (rco) <rco@openerp.com>
This commit is contained in:
committed by
Raphael Collet
co-authored by
Raphael Collet
parent
c314cb4e98
commit
e14b52a56d
@@ -513,6 +513,22 @@ class ComputeRecursive(models.Model):
|
||||
rec.display_name = rec.name
|
||||
|
||||
|
||||
class ComputeRecursiveTree(models.Model):
|
||||
_name = 'test_new_api.recursive.tree'
|
||||
_description = 'Test New API Recursive with one2many field'
|
||||
|
||||
name = fields.Char(required=True)
|
||||
parent_id = fields.Many2one('test_new_api.recursive.tree', ondelete='cascade')
|
||||
children_ids = fields.One2many('test_new_api.recursive.tree', 'parent_id')
|
||||
display_name = fields.Char(compute='_compute_display_name', store=True)
|
||||
|
||||
@api.depends('name', 'children_ids.display_name')
|
||||
def _compute_display_name(self):
|
||||
for rec in self:
|
||||
children_names = rec.mapped('children_ids.display_name')
|
||||
rec.display_name = '%s(%s)' % (rec.name, ', '.join(children_names))
|
||||
|
||||
|
||||
class ComputeCascade(models.Model):
|
||||
_name = 'test_new_api.cascade'
|
||||
_description = 'Test New API Cascade'
|
||||
|
||||
@@ -22,6 +22,7 @@ access_test_new_api_compute_inverse,access_test_new_api_compute_inverse,model_te
|
||||
access_test_new_api_compute_readonly,access_test_new_api_compute_readonly,model_test_new_api_compute_readonly,,1,1,1,1
|
||||
access_test_new_api_multi_compute_inverse,access_test_new_api_multi_compute_inverse,model_test_new_api_multi_compute_inverse,,1,1,1,1
|
||||
access_test_new_api_recursive,access_test_new_api_recursive,model_test_new_api_recursive,,1,1,1,1
|
||||
access_test_new_api_recursive_tree,access_test_new_api_recursive_tree,model_test_new_api_recursive_tree,,1,1,1,1
|
||||
access_test_new_api_cascade,access_test_new_api_cascade,model_test_new_api_cascade,,1,1,1,1
|
||||
access_test_new_api_compute_readwrite,access_test_new_api_compute_readwrite,model_test_new_api_compute_readwrite,,1,1,1,1
|
||||
access_test_new_api_compute_onchange,access_test_new_api_compute_onchange,model_test_new_api_compute_onchange,,1,1,1,1
|
||||
|
||||
|
@@ -495,6 +495,14 @@ class TestFields(TransactionCaseWithUserDemo):
|
||||
b.unlink()
|
||||
self.assertEqual((a + b + c + d).exists(), a)
|
||||
|
||||
def test_12_recursive_tree(self):
|
||||
foo = self.env['test_new_api.recursive.tree'].create({'name': 'foo'})
|
||||
self.assertEqual(foo.display_name, 'foo()')
|
||||
bar = foo.create({'name': 'bar', 'parent_id': foo.id})
|
||||
self.assertEqual(foo.display_name, 'foo(bar())')
|
||||
baz = foo.create({'name': 'baz', 'parent_id': bar.id})
|
||||
self.assertEqual(foo.display_name, 'foo(bar(baz()))')
|
||||
|
||||
def test_12_cascade(self):
|
||||
""" test computed field depending on computed field """
|
||||
message = self.env.ref('test_new_api.message_0_0')
|
||||
|
||||
+11
-12
@@ -5782,36 +5782,35 @@ Fields:
|
||||
tocompute = list(tocompute)
|
||||
|
||||
# process what to compute
|
||||
for field, records in tocompute:
|
||||
for field, records, create in tocompute:
|
||||
records -= self.env.protected(field)
|
||||
if not records:
|
||||
continue
|
||||
# Dont force the recomputation of compute fields which are
|
||||
# not stored as this is not really necessary.
|
||||
recursive = not create and field.recursive
|
||||
if field.compute and field.store:
|
||||
if recursive:
|
||||
marked_records = self.env.not_to_compute(field, records)
|
||||
if field.recursive:
|
||||
recursively_marked = self.env.not_to_compute(field, records)
|
||||
self.env.add_to_compute(field, records)
|
||||
else:
|
||||
if recursive:
|
||||
marked_records = records & self.env.cache.get_records(records, field)
|
||||
# Dont force the recomputation of compute fields which are
|
||||
# not stored as this is not really necessary.
|
||||
if field.recursive:
|
||||
recursively_marked = records & self.env.cache.get_records(records, field)
|
||||
self.env.cache.invalidate([(field, records._ids)])
|
||||
# recursively trigger recomputation of field's dependents
|
||||
if recursive:
|
||||
marked_records.modified([field.name])
|
||||
if field.recursive:
|
||||
recursively_marked.modified([field.name], create)
|
||||
|
||||
def _modified_triggers(self, tree, create=False):
|
||||
""" Return an iterator traversing a tree of field triggers on ``self``,
|
||||
traversing backwards field dependencies along the way, and yielding
|
||||
pairs ``(field, records)`` to recompute.
|
||||
tuple ``(field, records, created)`` to recompute.
|
||||
"""
|
||||
if not self:
|
||||
return
|
||||
|
||||
# first yield what to compute
|
||||
for field in tree.get(None, ()):
|
||||
yield field, self
|
||||
yield field, self, create
|
||||
|
||||
# then traverse dependencies backwards, and proceed recursively
|
||||
for key, val in tree.items():
|
||||
|
||||
Reference in New Issue
Block a user