summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/views/basic/basic_model.js
diff options
context:
space:
mode:
authorAaron Bohy <aab@odoo.com>2021-03-10 15:11:02 +0000
committerAaron Bohy <aab@odoo.com>2021-03-11 13:06:54 +0000
commita8b43d02066b2299ac2f4b88056c37725e9ce6cd (patch)
tree2042ae502051ffc5a1834a513b6254e37e66817c /addons/web/static/src/js/views/basic/basic_model.js
parent58adac24fe9c4900ddabed5b4eec5eaeed60970f (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/views/basic/basic_model.js')
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js8
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 {