[FIX] core: computed editable one2many field with a domain
Manually adding a line should not trigger the computation of the field, just like modifying the line fields that occur in the field's domain. In other words, the dependencies of the field should be limited to the ones declared on field or its compute method. closes odoo/odoo#71049 X-original-commit: 1c39814bd729cc08882f1545c7d88b0592e63f9a Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
This commit is contained in:
@@ -694,6 +694,40 @@ class ComputeUnassigned(models.Model):
|
||||
record.bares = record.foo
|
||||
|
||||
|
||||
class ComputeOne2many(models.Model):
|
||||
_name = 'test_new_api.one2many'
|
||||
_description = "A computed editable one2many field with a domain"
|
||||
|
||||
name = fields.Char()
|
||||
line_ids = fields.One2many(
|
||||
'test_new_api.one2many.line', 'container_id',
|
||||
compute='_compute_line_ids', store=True, readonly=False,
|
||||
domain=[('count', '>', 0)],
|
||||
)
|
||||
|
||||
@api.depends('name')
|
||||
def _compute_line_ids(self):
|
||||
# increment counter of line with the same name, or create a new line
|
||||
for record in self:
|
||||
if not record.name:
|
||||
continue
|
||||
for line in record.line_ids:
|
||||
if line.name == record.name:
|
||||
line.count += 1
|
||||
break
|
||||
else:
|
||||
record.line_ids = [(0, 0, {'name': record.name})]
|
||||
|
||||
|
||||
class ComputeOne2manyLine(models.Model):
|
||||
_name = 'test_new_api.one2many.line'
|
||||
_description = "Line of a computed one2many"
|
||||
|
||||
name = fields.Char()
|
||||
count = fields.Integer(default=1)
|
||||
container_id = fields.Many2one('test_new_api.one2many', required=True)
|
||||
|
||||
|
||||
class ModelBinary(models.Model):
|
||||
_name = 'test_new_api.model_binary'
|
||||
_description = 'Test Image field'
|
||||
|
||||
@@ -29,6 +29,8 @@ access_test_new_api_compute_onchange,access_test_new_api_compute_onchange,model_
|
||||
access_test_new_api_compute_onchange_line,access_test_new_api_compute_onchange_line,model_test_new_api_compute_onchange_line,,1,1,1,1
|
||||
access_test_new_api_compute_dynamic_depends,access_test_new_api_compute_dynamic_depends,model_test_new_api_compute_dynamic_depends,,1,1,1,1
|
||||
access_test_new_api_compute_unassigned,access_test_new_api_compute_unassigned,model_test_new_api_compute_unassigned,,1,1,1,1
|
||||
access_test_new_api_one2many,access_test_new_api_one2many,model_test_new_api_one2many,,1,1,1,1
|
||||
access_test_new_api_one2many_line,access_test_new_api_one2many_line,model_test_new_api_one2many_line,,1,1,1,1
|
||||
access_test_new_api_binary_svg,access_test_new_api_binary_svg,model_test_new_api_binary_svg,,1,1,1,1
|
||||
access_test_new_api_monetary_base,access_test_new_api_monetary_base,model_test_new_api_monetary_base,,1,1,1,1
|
||||
access_test_new_api_monetary_related,access_test_new_api_monetary_related,model_test_new_api_monetary_related,,1,1,1,1
|
||||
|
||||
|
@@ -824,3 +824,47 @@ class TestComputeOnchange(common.TransactionCase):
|
||||
]
|
||||
result = record.onchange({'line_ids': line_ids}, 'line_ids', spec)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_computed_editable_one2many_domain(self):
|
||||
""" Test a computed, editable one2many field with a domain. """
|
||||
record = self.env['test_new_api.one2many'].create({'name': 'foo'})
|
||||
self.assertRecordValues(record.line_ids, [
|
||||
{'name': 'foo', 'count': 1},
|
||||
])
|
||||
|
||||
# trigger recomputation by changing name
|
||||
record.name = 'bar'
|
||||
self.assertRecordValues(record.line_ids, [
|
||||
{'name': 'foo', 'count': 1},
|
||||
{'name': 'bar', 'count': 1},
|
||||
])
|
||||
|
||||
# manually adding a line should not trigger recomputation
|
||||
record.line_ids.create({'name': 'baz', 'container_id': record.id})
|
||||
self.assertRecordValues(record.line_ids, [
|
||||
{'name': 'foo', 'count': 1},
|
||||
{'name': 'bar', 'count': 1},
|
||||
{'name': 'baz', 'count': 1},
|
||||
])
|
||||
|
||||
# changing the field in the domain should not trigger recomputation...
|
||||
record.line_ids[-1].count = 2
|
||||
self.assertRecordValues(record.line_ids, [
|
||||
{'name': 'foo', 'count': 1},
|
||||
{'name': 'bar', 'count': 1},
|
||||
{'name': 'baz', 'count': 2},
|
||||
])
|
||||
|
||||
# ...and may show cache inconsistencies
|
||||
record.line_ids[-1].count = 0
|
||||
self.assertRecordValues(record.line_ids, [
|
||||
{'name': 'foo', 'count': 1},
|
||||
{'name': 'bar', 'count': 1},
|
||||
{'name': 'baz', 'count': 0},
|
||||
])
|
||||
record.flush()
|
||||
record.invalidate_cache()
|
||||
self.assertRecordValues(record.line_ids, [
|
||||
{'name': 'foo', 'count': 1},
|
||||
{'name': 'bar', 'count': 1},
|
||||
])
|
||||
|
||||
+1
-1
@@ -3237,7 +3237,7 @@ class _RelationalMulti(_Relational):
|
||||
|
||||
def get_depends(self, model):
|
||||
depends, depends_context = super().get_depends(model)
|
||||
if not self.related and isinstance(self.domain, list):
|
||||
if not self.compute and isinstance(self.domain, list):
|
||||
depends = unique(itertools.chain(depends, (
|
||||
self.name + '.' + arg[0]
|
||||
for arg in self.domain
|
||||
|
||||
Reference in New Issue
Block a user