Skip to content

Commit

Permalink
[FIX] web: BasicModel: clear x2many changes after save
Browse files Browse the repository at this point in the history
Before this commit, after a save, we didn't remove the changes in
x2many fields (StaticList). As a consequence, if save was called
twice on a record with changes in a x2many, those changes were
sent twice to the server. In particular, if those changes involved
a command 0 (create), the record was created twice.

To reproduce the issue, go to a sale order, add a line, select a
product, click out to validate the row, then click several times
on the product. As you clicked several times, several doAction are
asked to the action service. For each of them, the form view is
asked to save its changes, and thus the same row is created multiple
times.

After this fix, the changes in x2manys are cleared after the first
save, so there's no change the save for the subsequent calls.

opw-3268947
opw-3324848

closes odoo#123394

X-original-commit: 0fd8358
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
  • Loading branch information
aab-odoo committed Jun 2, 2023
1 parent 3df7312 commit 3839f0e
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
9 changes: 9 additions & 0 deletions addons/web/static/src/legacy/js/views/basic/basic_model.js
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,15 @@ var BasicModel = AbstractModel.extend({

// Erase changes as they have been applied
record._changes = {};
var data = Object.assign({}, record.data, record._changes);
for (var fieldName in record.fields) {
var type = record.fields[fieldName].type;
if (type === 'many2many' || type === 'one2many') {
if (data[fieldName]) {
self.localData[data[fieldName]]._changes = [];
}
}
}

// Optionally clear the DataManager's cache
self._invalidateCache(record);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10188,6 +10188,53 @@ QUnit.module('Legacy fields', {}, function () {

form.destroy();
});

QUnit.test('add a row to an x2many and ask canBeRemoved twice', async function (assert) {
// This test simulates that the view is asked twice to save its changes because the user
// is leaving. Before the corresponding fix, the changes in the x2many field weren't
// removed after the save, and as a consequence they were saved twice (i.e. the row was
// created twice).

const form = await createView({
View: FormView,
model: 'partner',
data: this.data,
arch: `
<form>
<field name="p">
<tree editable="bottom">
<field name="display_name"/>
</tree>
</field>
</form>`,
res_id: 1,
async mockRPC(route, args) {
if (args.method === "write") {
assert.step("write");
assert.deepEqual(args.args[1], {
p: [[0, args.args[1].p[0][1], { display_name: "a name" }]],
});
}
return this._super(route, args);
},
viewOptions: {
mode: 'edit',
},
});

// click add food
await testUtils.dom.click(form.$('.o_field_x2many_list_row_add a'));
await testUtils.fields.editInput(form.$('.o_input[name="display_name"]'), 'a name');
assert.containsOnce(form, ".o_data_row");

form.canBeRemoved();
form.canBeRemoved();
await testUtils.nextTick();
assert.containsOnce(form, ".o_data_row");
assert.verifySteps(["write"]);

form.destroy();
});
});
});
});

0 comments on commit 3839f0e

Please sign in to comment.