Skip to content

Commit

Permalink
[FIX] models: ensure recomputation after inversing fields (#15683)
Browse files Browse the repository at this point in the history
When updating record using "record.field = value", we need to ensure that
all fields in cache depending on "record.field" will be recomputed.
  • Loading branch information
rco-odoo committed Mar 23, 2017
1 parent 0cfb7fc commit 9e23458
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 2 deletions.
1 change: 1 addition & 0 deletions odoo/addons/test_new_api/ir.model.access.csv
Expand Up @@ -14,5 +14,6 @@ access_test_new_api_foo,access_test_new_api_foo,model_test_new_api_foo,,1,1,1,1
access_test_new_api_bar,access_test_new_api_bar,model_test_new_api_bar,,1,1,1,1
access_test_new_api_related,access_test_new_api_related,model_test_new_api_related,,1,1,1,1
access_test_new_api_company,access_test_new_api_company,model_test_new_api_company,,1,1,1,1
access_test_new_api_company_attr,access_test_new_api_company_attr,model_test_new_api_company_attr,,1,1,1,1
access_test_new_api_sparse,access_test_new_api_sparse,model_test_new_api_sparse,,1,1,1,1
access_test_new_api_compute_inverse,access_test_new_api_compute_inverse,model_test_new_api_compute_inverse,,1,1,1,1
11 changes: 11 additions & 0 deletions odoo/addons/test_new_api/models.py
Expand Up @@ -338,6 +338,17 @@ class CompanyDependent(models.Model):

foo = fields.Char(company_dependent=True)

class CompanyDependentAttribute(models.Model):
_name = 'test_new_api.company.attr'

company = fields.Many2one('test_new_api.company')
quantity = fields.Integer()
bar = fields.Char(compute='_compute_bar', store=True)

@api.depends('quantity', 'company.foo')
def _compute_bar(self):
for record in self:
record.bar = (record.company.foo or '') * record.quantity

class Sparse(models.Model):
_name = 'test_new_api.sparse'
Expand Down
19 changes: 19 additions & 0 deletions odoo/addons/test_new_api/tests/test_new_fields.py
Expand Up @@ -498,6 +498,25 @@ def test_27_company_dependent(self):
self.assertEqual(record.sudo(user1).foo, 'alpha')
self.assertEqual(record.sudo(user2).foo, 'default')

# create company record and attribute
company_record = self.env['test_new_api.company'].create({'foo': 'ABC'})
attribute_record = self.env['test_new_api.company.attr'].create({
'company': company_record.id,
'quantity': 1,
})
self.assertEqual(attribute_record.bar, 'ABC')

# change quantity, 'bar' should recompute to 'ABCABC'
attribute_record.quantity = 2
self.assertEqual(attribute_record.bar, 'ABCABC')
self.assertFalse(self.env.has_todo())

# change company field 'foo', 'bar' should recompute to 'DEFDEF'
company_record.foo = 'DEF'
self.assertEqual(attribute_record.company.foo, 'DEF')
self.assertEqual(attribute_record.bar, 'DEFDEF')
self.assertFalse(self.env.has_todo())

def test_28_sparse(self):
""" test sparse fields. """
record = self.env['test_new_api.sparse'].create({})
Expand Down
14 changes: 12 additions & 2 deletions odoo/models.py
Expand Up @@ -3556,12 +3556,17 @@ def write(self, vals):

if new_vals:
# put the values of pure new-style fields into cache, and inverse them
self.modified(set(new_vals) - set(old_vals))
for record in self:
record._cache.update(record._convert_to_cache(new_vals, update=True))
for key in new_vals:
self._fields[key].determine_inverse(self)
self.modified(set(new_vals) - set(old_vals))
# check Python constraints for inversed fields
self._validate_fields(set(new_vals) - set(old_vals))
# recompute new-style fields
if self.env.recompute and self._context.get('recompute', True):
self.recompute()

return True

Expand Down Expand Up @@ -3815,14 +3820,19 @@ def create(self, vals):
# create record with old-style fields
record = self.browse(self._create(old_vals))

# put the values of pure new-style fields into cache, and inverse them
record._cache.update(record._convert_to_cache(new_vals))
protected_fields = map(self._fields.get, new_vals)
with self.env.protecting(protected_fields, record):
# put the values of pure new-style fields into cache, and inverse them
record.modified(set(new_vals) - set(old_vals))
record._cache.update(record._convert_to_cache(new_vals))
for key in new_vals:
self._fields[key].determine_inverse(record)
record.modified(set(new_vals) - set(old_vals))
# check Python constraints for inversed fields
record._validate_fields(set(new_vals) - set(old_vals))
# recompute new-style fields
if self.env.recompute and self._context.get('recompute', True):
self.recompute()

return record

Expand Down

0 comments on commit 9e23458

Please sign in to comment.