summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odoo/addons/test_new_api/models/test_new_api.py32
-rw-r--r--odoo/addons/test_new_api/security/ir.model.access.csv2
-rw-r--r--odoo/addons/test_new_api/tests/test_new_fields.py2
-rw-r--r--odoo/addons/test_new_api/tests/test_onchange.py38
-rw-r--r--odoo/addons/test_new_api/views/test_new_api_views.xml26
-rw-r--r--odoo/fields.py5
-rw-r--r--odoo/models.py2
7 files changed, 102 insertions, 5 deletions
diff --git a/odoo/addons/test_new_api/models/test_new_api.py b/odoo/addons/test_new_api/models/test_new_api.py
index 27af01e335b..2cb28702520 100644
--- a/odoo/addons/test_new_api/models/test_new_api.py
+++ b/odoo/addons/test_new_api/models/test_new_api.py
@@ -1147,3 +1147,35 @@ class ComputeMember(models.Model):
container = self.env['test_new_api.compute.container']
for member in self:
member.container_id = container.search([('name', '=', member.name)], limit=1)
+
+
+class ComputeEditable(models.Model):
+ _name = _description = 'test_new_api.compute_editable'
+
+ line_ids = fields.One2many('test_new_api.compute_editable.line', 'parent_id')
+
+ @api.onchange('line_ids')
+ def _onchange_line_ids(self):
+ for line in self.line_ids:
+ # even if 'same' is not in the view, it should be the same as 'value'
+ line.count += line.same
+
+
+class ComputeEditableLine(models.Model):
+ _name = _description = 'test_new_api.compute_editable.line'
+
+ parent_id = fields.Many2one('test_new_api.compute_editable')
+ value = fields.Integer()
+ same = fields.Integer(compute='_compute_same', store=True)
+ edit = fields.Integer(compute='_compute_edit', store=True, readonly=False)
+ count = fields.Integer()
+
+ @api.depends('value')
+ def _compute_same(self):
+ for line in self:
+ line.same = line.value
+
+ @api.depends('value')
+ def _compute_edit(self):
+ for line in self:
+ line.edit = line.value
diff --git a/odoo/addons/test_new_api/security/ir.model.access.csv b/odoo/addons/test_new_api/security/ir.model.access.csv
index 71a309d5d1a..021d7127b05 100644
--- a/odoo/addons/test_new_api/security/ir.model.access.csv
+++ b/odoo/addons/test_new_api/security/ir.model.access.csv
@@ -66,3 +66,5 @@ access_test_new_api_model_shared_cache_compute_parent,access_test_new_api.model_
access_test_new_api_model_shared_cache_compute_line,access_test_new_api.model_shared_cache_compute_line,model_test_new_api_model_shared_cache_compute_line,,1,1,1,1
access_test_new_api_compute_container,access_test_new_api_compute_container,model_test_new_api_compute_container,,1,1,1,1
access_test_new_api_compute_member,access_test_new_api_compute_member,model_test_new_api_compute_member,,1,1,1,1
+access_test_new_api_compute_editable,access_test_new_api_compute_editable,model_test_new_api_compute_editable,,1,1,1,1
+access_test_new_api_compute_editable_line,access_test_new_api_compute_editable_line,model_test_new_api_compute_editable_line,,1,1,1,1
diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py
index 9986cd674c3..4c9aaf00f5e 100644
--- a/odoo/addons/test_new_api/tests/test_new_fields.py
+++ b/odoo/addons/test_new_api/tests/test_new_fields.py
@@ -1345,7 +1345,7 @@ class TestFields(TransactionCaseWithUserDemo):
new_origin = Model.new({'name': 'Bar'}, origin=real_record)
new_record = Model.new({'name': 'Baz'})
self.assertEqual(real_record.display_name, 'Foo')
- self.assertEqual(new_origin.display_name, 'Foo')
+ self.assertEqual(new_origin.display_name, 'Bar')
self.assertEqual(new_record.display_name, 'Baz')
# computed stored field with recomputation: always computed
diff --git a/odoo/addons/test_new_api/tests/test_onchange.py b/odoo/addons/test_new_api/tests/test_onchange.py
index 38c7b8be531..1b424777bc0 100644
--- a/odoo/addons/test_new_api/tests/test_onchange.py
+++ b/odoo/addons/test_new_api/tests/test_onchange.py
@@ -4,7 +4,7 @@
from unittest.mock import patch
from odoo.addons.base.tests.common import SavepointCaseWithUserDemo
-from odoo.tests import common
+from odoo.tests import common, Form
def strip_prefix(prefix, names):
size = len(prefix)
@@ -751,3 +751,39 @@ class TestComputeOnchange(common.TransactionCase):
with form.child_ids.edit(2) as line:
line.cost = 30
self.assertEqual(form.cost, 61)
+
+ def test_onchange_editable_compute_one2many(self):
+ # create a record with a computed editable field ('edit') on lines
+ record = self.env['test_new_api.compute_editable'].create({'line_ids': [(0, 0, {'value': 7})]})
+ record.flush()
+ line = record.line_ids
+ self.assertRecordValues(line, [{'value': 7, 'edit': 7, 'count': 0}])
+
+ # retrieve the onchange spec for calling 'onchange'
+ spec = Form(record)._view['onchange']
+
+ # The onchange on 'line_ids' should increment 'count' and keep the value
+ # of 'edit' (this field should not be recomputed), whatever the order of
+ # the fields in the dictionary. This ensures that the value set by the
+ # user on a computed editable field on a line is not lost.
+ line_ids = [
+ (1, line.id, {'value': 8, 'edit': 9, 'count': 0}),
+ (0, 0, {'value': 8, 'edit': 9, 'count': 0}),
+ ]
+ result = record.onchange({'line_ids': line_ids}, 'line_ids', spec)
+ expected = {'value': {
+ 'line_ids': [
+ (5,),
+ (1, line.id, {'value': 8, 'edit': 9, 'count': 8}),
+ (0, 0, {'value': 8, 'edit': 9, 'count': 8}),
+ ],
+ }}
+ self.assertEqual(result, expected)
+
+ # change dict order in lines, and try again
+ line_ids = [
+ (op, id_, dict(reversed(list(vals.items()))))
+ for op, id_, vals in line_ids
+ ]
+ result = record.onchange({'line_ids': line_ids}, 'line_ids', spec)
+ self.assertEqual(result, expected)
diff --git a/odoo/addons/test_new_api/views/test_new_api_views.xml b/odoo/addons/test_new_api/views/test_new_api_views.xml
index cd995456def..2595be58e6c 100644
--- a/odoo/addons/test_new_api/views/test_new_api_views.xml
+++ b/odoo/addons/test_new_api/views/test_new_api_views.xml
@@ -341,5 +341,31 @@
</form>
</field>
</record>
+
+ <!-- compute_editable view -->
+ <record id="compute_editable_form" model="ir.ui.view">
+ <field name="name">test_new_api.compute_editable.form</field>
+ <field name="model">test_new_api.compute_editable</field>
+ <field name="arch" type="xml">
+ <form>
+ <sheet>
+ <field name="line_ids" mode="tree">
+ <tree editable="bottom">
+ <field name="value"/>
+ <field name="edit"/>
+ <field name="count"/>
+ </tree>
+ <form>
+ <!-- this view makes sure that field "same" is not considered -->
+ <field name="value"/>
+ <field name="edit"/>
+ <field name="count"/>
+ </form>
+ </field>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
</data>
</odoo>
diff --git a/odoo/fields.py b/odoo/fields.py
index 603e2a90a3e..8ddc0c1b422 100644
--- a/odoo/fields.py
+++ b/odoo/fields.py
@@ -956,7 +956,8 @@ class Field(MetaField('DummyField', (object,), {})):
# not stored and not computed -> default
#
# on a new record w/ origin:
- # stored -> fetch from origin (computation done above)
+ # stored and not (computed and readonly) -> fetch from origin
+ # stored and computed and readonly -> compute
# not stored and computed -> compute
# not stored and not computed -> default
#
@@ -982,7 +983,7 @@ class Field(MetaField('DummyField', (object,), {})):
]))
value = env.cache.get(record, self)
- elif self.store and record._origin:
+ elif self.store and record._origin and not (self.compute and self.readonly):
# new record with origin: fetch from origin
value = self.convert_to_cache(record._origin[self.name], record)
env.cache.set(record, self, value)
diff --git a/odoo/models.py b/odoo/models.py
index 23e51ed9be0..1102cd93f7f 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -6148,7 +6148,7 @@ Fields:
# store changed values in cache; also trigger recomputations based on
# subfields (e.g., line.a has been modified, line.b is computed stored
# and depends on line.a, but line.b is not in the form view)
- record._update_cache(changed_values, validate=True)
+ record._update_cache(changed_values, validate=False)
# update snapshot0 with changed values
for name in names: