[FIX] models: recompute nested old-style computed field
The `set` method of the one2many class returns a list
of the fields that require recomputation,
the computing of the function fields being delayed
for performances reasons.
Nevertheless, if the `set` method was called
through another `set` method, in other words,
nested `set` calls, the fields to recompute returned
by the second, nested, call to set were never recomputed,
the result list were simply lost.
e.g.:
```
create/write
│set
└─── create/write with recs.env.recompute set to False
│set
└─── create
with recs.env.recompute set to False
```
To overcome this problem, the list of old api style
compute fields to recompute is stored
within the environment, and this list is cleared
each time the store_set_value has done its job of
recomputing all old api style compute fields.
opw-629650
opw-632624
closes #6053
This commit is contained in:
@@ -907,6 +907,13 @@ class Environment(object):
|
||||
finally:
|
||||
self.all.recompute = tmp
|
||||
|
||||
@property
|
||||
def recompute_old(self):
|
||||
return self.all.recompute_old
|
||||
|
||||
def clear_recompute_old(self):
|
||||
del self.all.recompute_old[:]
|
||||
|
||||
|
||||
class Environments(object):
|
||||
""" A common object for all environments in a request. """
|
||||
@@ -915,6 +922,7 @@ class Environments(object):
|
||||
self.todo = {} # recomputations {field: [records]}
|
||||
self.mode = False # flag for draft/onchange
|
||||
self.recompute = True
|
||||
self.recompute_old = [] # list of old api compute fields to recompute
|
||||
|
||||
def add(self, env):
|
||||
""" Add the environment `env`. """
|
||||
|
||||
+9
-6
@@ -3994,10 +3994,10 @@ class BaseModel(object):
|
||||
recs.invalidate_cache(['parent_left', 'parent_right'])
|
||||
|
||||
result += self._store_get_values(cr, user, ids, vals.keys(), context)
|
||||
result.sort()
|
||||
|
||||
done = {}
|
||||
for order, model_name, ids_to_update, fields_to_recompute in result:
|
||||
recs.env.recompute_old.extend(result)
|
||||
for order, model_name, ids_to_update, fields_to_recompute in sorted(recs.env.recompute_old):
|
||||
key = (model_name, tuple(fields_to_recompute))
|
||||
done.setdefault(key, {})
|
||||
# avoid to do several times the same computation
|
||||
@@ -4008,6 +4008,7 @@ class BaseModel(object):
|
||||
if id not in deleted_related[model_name]:
|
||||
todo.append(id)
|
||||
self.pool[model_name]._store_set_values(cr, user, todo, fields_to_recompute, context)
|
||||
recs.env.clear_recompute_old()
|
||||
|
||||
# recompute new-style fields
|
||||
if recs.env.recompute and context.get('recompute', True):
|
||||
@@ -4257,16 +4258,18 @@ class BaseModel(object):
|
||||
# check Python constraints
|
||||
recs._validate_fields(vals)
|
||||
|
||||
if recs.env.recompute and context.get('recompute', True):
|
||||
result += self._store_get_values(cr, user, [id_new],
|
||||
result += self._store_get_values(cr, user, [id_new],
|
||||
list(set(vals.keys() + self._inherits.values())),
|
||||
context)
|
||||
result.sort()
|
||||
recs.env.recompute_old.extend(result)
|
||||
|
||||
if recs.env.recompute and context.get('recompute', True):
|
||||
done = []
|
||||
for order, model_name, ids, fields2 in result:
|
||||
for order, model_name, ids, fields2 in sorted(recs.env.recompute_old):
|
||||
if not (model_name, ids, fields2) in done:
|
||||
self.pool[model_name]._store_set_values(cr, user, ids, fields2, context)
|
||||
done.append((model_name, ids, fields2))
|
||||
recs.env.clear_recompute_old()
|
||||
# recompute new-style fields
|
||||
recs.recompute()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user