[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:
Denis Ledoux 2015-05-06 17:25:44 +02:00
parent 6553eb3742
commit b7f1b9c01e
2 changed files with 17 additions and 6 deletions

View File

@ -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`. """

View File

@ -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()