diff options
| author | Aaron Bohy <aab@odoo.com> | 2021-03-10 15:11:02 +0000 |
|---|---|---|
| committer | Aaron Bohy <aab@odoo.com> | 2021-03-11 13:06:54 +0000 |
| commit | a8b43d02066b2299ac2f4b88056c37725e9ce6cd (patch) | |
| tree | 2042ae502051ffc5a1834a513b6254e37e66817c /addons/web/static/src/js | |
| parent | 58adac24fe9c4900ddabed5b4eec5eaeed60970f (diff) | |
[FIX] web: nested one2manys, onchange and no command
Let's assume the following situation. We have a form view with a
one2many field A displayed as a list. In the list, there is a
one2many field B. B can't be edited, its value is computed by
an onchange. By default, it contains a single record (i.e. the
first value returned by the onchange is [[5], [0, 0, {...}]]).
When another field (say C) changes, B's value is re-computed to
[[5]]. Moreover, there is an onchange on A.
In this form view, let's assume the following scenario. Create a
new record and add a line to A. In this new line, B already
contains a record. Change C. This triggers an onchange that
returns [[5]], and B is now empty. It triggers a second onchange,
on the main record (as field A changed).
Before this commit, in this second onchange, B's value wasn't sent
among the other values of the new line.
The spec says that for onchanges, we must send all data, not only
what has really changed. From that perspective, the above scenario
highlights an issue.
That issue had two root causes. First, commit [1] wrongly fixed
another issue, and as a consequence, when building what to send
for the onchange, we didn't generate the values for fields that
hadn't changed inside an x2many (for added subrecords at least).
This commit reverts the fix of [1], and fixes it differently by
only sending a command 1 (update) after a command 4 (link to)
when the record is dirty (i.e. when it has been modified). See
[1] for context and details.
Second, the code that generates the values to send to onchanges is
the same as the one that generates the values to save records
(write or create). However, when saving, we only send what has
really changed. The values are at some point processed to remove
empty command lists from the list of changes (as it means that
nothing changed). However, here we ignored the flag that stated
whether we want all field values or just what has changed. This
commit takes the flag into account before removing the field's
value.
[1] https://github.com/odoo/odoo/commit/3e3a244e1afc4d74920a6302a14fa2590e8b6648
Issue reported in task~2352524
Model: account.move
One2Many (A): account.move.lines
Nested computed One2Many (B): tax_detail_ids
Field triggering the onchange (C): tax_ids
closes odoo/odoo#67679
Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
Co-authored-by: Géry Debongnie <ged@odoo.com>
Diffstat (limited to 'addons/web/static/src/js')
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_model.js | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 4864417dbee..78606e717d7 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -3170,7 +3170,7 @@ var BasicModel = AbstractModel.extend({ var type = record.fields[fieldName].type; var value; if (type === 'one2many' || type === 'many2many') { - if (commands[fieldName] && commands[fieldName].length) { // replace localId by commands + if (!options.changesOnly || (commands[fieldName] && commands[fieldName].length)) { // replace localId by commands changes[fieldName] = commands[fieldName]; } else { // no command -> no change for that field delete changes[fieldName]; @@ -3341,12 +3341,12 @@ var BasicModel = AbstractModel.extend({ commands[fieldName].push(x2ManyCommands.link_to(list.res_ids[i])); continue; } - changes = this._generateChanges(relRecord, _.extend({}, options, {changesOnly: true})); + changes = this._generateChanges(relRecord, options); if (!this.isNew(relRecord.id)) { // the subrecord already exists in db commands[fieldName].push(x2ManyCommands.link_to(relRecord.res_id)); - delete changes.id; - if (!_.isEmpty(changes)) { + if (this.isDirty(relRecord.id)) { + delete changes.id; commands[fieldName].push(x2ManyCommands.update(relRecord.res_id, changes)); } } else { |
