summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuewen Baconnier <guewen.baconnier@camptocamp.com>2021-01-04 08:20:38 +0000
committerRaphael Collet <rco@odoo.com>2021-01-05 16:52:28 +0000
commit9fe4fe404b73e9ab18ab6b3b913f075c64bb6954 (patch)
tree664fab0832f9fd2666efdf6b25794b3cca85be35
parenta23a47457d98aba4ec643f4422f3735d98fab2b4 (diff)
[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#64031 X-original-commit: 79634eefb225a7aaa6c3c26af126fb69078c22ac Signed-off-by: Raphael Collet (rco) <rco@openerp.com> Co-authored-by: Raphael Collet (rco) <rco@openerp.com>
-rw-r--r--odoo/addons/test_new_api/models/test_new_api.py16
-rw-r--r--odoo/addons/test_new_api/security/ir.model.access.csv1
-rw-r--r--odoo/addons/test_new_api/tests/test_new_fields.py8
-rw-r--r--odoo/models.py23
4 files changed, 36 insertions, 12 deletions
diff --git a/odoo/addons/test_new_api/models/test_new_api.py b/odoo/addons/test_new_api/models/test_new_api.py
index 0f40589636c..1f36dfe7bad 100644
--- a/odoo/addons/test_new_api/models/test_new_api.py
+++ b/odoo/addons/test_new_api/models/test_new_api.py
@@ -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'
diff --git a/odoo/addons/test_new_api/security/ir.model.access.csv b/odoo/addons/test_new_api/security/ir.model.access.csv
index 37f20cf852e..09ac7f1fc83 100644
--- a/odoo/addons/test_new_api/security/ir.model.access.csv
+++ b/odoo/addons/test_new_api/security/ir.model.access.csv
@@ -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
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 3a95a6c10f2..2191bee7096 100644
--- a/odoo/addons/test_new_api/tests/test_new_fields.py
+++ b/odoo/addons/test_new_api/tests/test_new_fields.py
@@ -492,6 +492,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')
diff --git a/odoo/models.py b/odoo/models.py
index 9339c731cbd..ae7b6f2f995 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -5779,36 +5779,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():