From b7f1b9c01ec108ba06a6eea23dee6815ca7fc48e Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 6 May 2015 17:25:44 +0200 Subject: [PATCH] [FIX] models: recompute nested old-style computed field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- openerp/api.py | 8 ++++++++ openerp/models.py | 15 +++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/openerp/api.py b/openerp/api.py index b377076cf55..62dd2e5f0f3 100644 --- a/openerp/api.py +++ b/openerp/api.py @@ -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`. """ diff --git a/openerp/models.py b/openerp/models.py index f584c72ada6..858993f94d4 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -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()