From 569bbd7c22094491b183b2b8ad8a7c29a1bbf750 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 24 Jun 2019 13:44:16 +0000 Subject: [PATCH] [FIX] models: onchange handles inconsistent data in all cases closes odoo/odoo#34451 Signed-off-by: Raphael Collet (rco) --- odoo/models.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/odoo/models.py b/odoo/models.py index a96e7d88dab..591a237565c 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -5565,8 +5565,8 @@ Fields: for subname in subnames: new_lines.mapped(subname) - # Isolate changed x2many values, to handle inconsistent data sent from - # the client side: when a form view contains two one2many fields that + # Isolate changed values, to handle inconsistent data sent from the + # client side: when a form view contains two one2many fields that # overlap, the lines that appear in both fields may be sent with # different data. Consider, for instance: # @@ -5581,22 +5581,26 @@ Fields: # The idea is to put 'foo_ids' in cache first, so that the snapshot # contains value=1 for line in 'foo_ids'. The snapshot is then updated # with the value of `bar_ids`, which will contain value=2 on line. - values = dict(values) - changed_x2many = { - name: values.pop(name, []) - for name in names - if self._fields[name].type in ('one2many', 'many2many') - } + # + # The issue also occurs with other fields. For instance, an onchange on + # a move line has a value for the field 'move_id' that contains the + # values of the move, among which the one2many that contains the line + # itself, with old values! + # + changed_values = {name: values[name] for name in names} + # set changed values to null in initial_values; not setting them + # triggers default_get() on the new record when creating snapshot0 + initial_values = dict(values, **dict.fromkeys(names, False)) - # create a new record with values, and attach ``self`` to it - record = self.new(values, origin=self) + # create a new record with values + record = self.new(initial_values, origin=self) # make a snapshot based on the initial values of record snapshot0 = Snapshot(record, nametree) # store changed values in cache, and update snapshot0 - for name, value in changed_x2many.items(): - record._update_cache({name: value}, validate=False) + record._update_cache(changed_values, validate=False) + for name in names: snapshot0.fetch(name) # determine which field(s) should be triggered an onchange