[FIX] web: basic_model: save a paged nested o2m
In a form view, have a o2m field (A), with a nested o2m field (B). The A field should have multiple pages, with each record having at least one record in their B field. Have a (C) field that will modify a record in the nested o2m when changed. Change the C field, and save. Before this commit, the record's nested o2m from the other page had a wrong value (a mere 4 command). After this commit, their value is a command 4 and a command 1, with the right values. closes odoo/odoo#99986 X-original-commit: e45e3b83f0f3116cc983c6bd8a9212e815b4d4f5 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
committed by
Aaron Bohy
parent
e9aac69e6b
commit
b3489af4c1
@@ -3311,6 +3311,7 @@ var BasicModel = AbstractModel.extend({
|
||||
_generateX2ManyCommands: function (record, options) {
|
||||
var self = this;
|
||||
options = options || {};
|
||||
const changesOnly = options.changesOnly;
|
||||
var fields = record.fields;
|
||||
if (options.fieldNames) {
|
||||
fields = _.pick(fields, options.fieldNames);
|
||||
@@ -3403,7 +3404,7 @@ var BasicModel = AbstractModel.extend({
|
||||
if (!this.isNew(relRecord.id)) {
|
||||
// the subrecord already exists in db
|
||||
commands[fieldName].push(x2ManyCommands.link_to(relRecord.res_id));
|
||||
if (this.isDirty(relRecord.id)) {
|
||||
if (changesOnly ? Object.keys(changes).length : this.isDirty(relRecord.id)) {
|
||||
delete changes.id;
|
||||
commands[fieldName].push(x2ManyCommands.update(relRecord.res_id, changes));
|
||||
}
|
||||
|
||||
@@ -10135,6 +10135,59 @@ QUnit.module('Legacy fields', {}, function () {
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('nested one2manys, multi page, onchange', async function (assert) {
|
||||
assert.expect(5);
|
||||
|
||||
this.data.partner.records[2].int_field = 5;
|
||||
this.data.partner.records[0].p = [2, 4]; // limit 1 -> record 4 will be on second page
|
||||
this.data.partner.records[1].turtles = [1];
|
||||
this.data.partner.records[2].turtles = [2];
|
||||
this.data.turtle.records[0].turtle_int = 1;
|
||||
this.data.turtle.records[1].turtle_int = 2;
|
||||
|
||||
this.data.partner.onchanges.int_field = function (obj) {
|
||||
assert.step('onchange')
|
||||
obj.p = [[5]]
|
||||
obj.p.push([1, 2, { turtles: [[5], [1, 1, { turtle_int: obj.int_field }]] }]);
|
||||
obj.p.push([1, 4, { turtles: [[5], [1, 2, { turtle_int: obj.int_field }]] }]);
|
||||
};
|
||||
|
||||
var form = await createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form string="Partner">' +
|
||||
'<field name="int_field"/>' +
|
||||
'<field name="p">' +
|
||||
'<tree editable="bottom" limit="1" default_order="display_name">' +
|
||||
'<field name="display_name" />' +
|
||||
'<field name="int_field" />' +
|
||||
'<field name="turtles">' +
|
||||
'<tree editable="bottom">' +
|
||||
'<field name="turtle_int"/>' +
|
||||
'</tree>' +
|
||||
'</field>' +
|
||||
'</tree>' +
|
||||
'</field>' +
|
||||
'</form>',
|
||||
res_id: 1,
|
||||
viewOptions: {
|
||||
mode: 'edit',
|
||||
},
|
||||
});
|
||||
|
||||
await testUtils.fields.editInput(form.$('.o_field_widget[name="int_field"]'), '5');
|
||||
assert.verifySteps(['onchange'])
|
||||
|
||||
await testUtils.form.clickSave(form);
|
||||
|
||||
assert.strictEqual(this.data.partner.records[0].int_field, 5, 'Value should have been updated')
|
||||
assert.strictEqual(this.data.turtle.records[1].turtle_int, 5, 'Shown data should have been updated');
|
||||
assert.strictEqual(this.data.turtle.records[0].turtle_int, 5, 'Hidden data should have been updated');
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12596,4 +12596,51 @@ QUnit.module("Fields", (hooks) => {
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test('nested one2manys, multi page, onchange', async function (assert) {
|
||||
serverData.models.partner.records[2].int_field = 5;
|
||||
serverData.models.partner.records[0].p = [2, 4]; // limit 1 -> record 4 will be on second page
|
||||
serverData.models.partner.records[1].turtles = [1];
|
||||
serverData.models.partner.records[2].turtles = [2];
|
||||
serverData.models.turtle.records[0].turtle_int = 1;
|
||||
serverData.models.turtle.records[1].turtle_int = 2;
|
||||
|
||||
serverData.models.partner.onchanges.int_field = function (obj) {
|
||||
assert.step('onchange')
|
||||
obj.p = [[5]]
|
||||
obj.p.push([1, 2, { turtles: [[5], [1, 1, { turtle_int: obj.int_field }]] }]);
|
||||
obj.p.push([1, 4, { turtles: [[5], [1, 2, { turtle_int: obj.int_field }]] }]);
|
||||
};
|
||||
|
||||
await makeView({
|
||||
type: "form",
|
||||
resModel: "partner",
|
||||
serverData,
|
||||
arch: `
|
||||
<form>
|
||||
<field name="int_field"/>
|
||||
<field name="p">
|
||||
<tree editable="bottom" limit="1" default_order="display_name">
|
||||
<field name="display_name" />
|
||||
<field name="int_field" />
|
||||
<field name="turtles">
|
||||
<tree editable="bottom">
|
||||
<field name="turtle_int"/>
|
||||
</tree>
|
||||
</field>
|
||||
</tree>
|
||||
</field>
|
||||
</form>`,
|
||||
resId: 1,
|
||||
mode: 'edit',
|
||||
});
|
||||
|
||||
await editInput(target, ".o_field_widget[name=int_field] input", "5");
|
||||
assert.verifySteps(['onchange'])
|
||||
|
||||
await clickSave(target);
|
||||
assert.strictEqual(serverData.models.partner.records[0].int_field, 5)
|
||||
assert.strictEqual(serverData.models.turtle.records[1].turtle_int, 5);
|
||||
assert.strictEqual(serverData.models.turtle.records[0].turtle_int, 5);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user