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 99bf22cc6bd..82bb9e586a8 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -2578,6 +2578,11 @@ var BasicModel = AbstractModel.extend({ relationField: field.relation_field, viewType: view ? view.type : fieldInfo.viewType, }); + // set existing changes to the list + if (record._changes && record._changes[fieldName]) { + list._changes = self.localData[record._changes[fieldName]]._changes; + record._changes[fieldName] = list.id; + } record.data[fieldName] = list.id; if (!fieldInfo.__no_fetch) { var def = self._readUngroupedList(list).then(function () { diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index 753e62ad02c..f11da4d323a 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -143,10 +143,12 @@ QUnit.module('relational_fields', { user: { fields: { name: {string: "Name", type: "char"}, + partner_ids: {string: "one2many partners field", type: "one2many", relation: 'partner', relation_field: 'user_id'}, }, records: [{ id: 17, name: "Aline", + partner_ids: [1, 2], }, { id: 19, name: "Christine", @@ -9383,6 +9385,94 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('onchange affecting inline unopened list view', function (assert) { + // when we got onchange result for fields of record that were not + // already available because they were in a inline view not already + // opened, in a given configuration the change were applied ignoring + // existing data, thus a line of a one2many field inside a one2many + // field could be duplicated unexplectedly + assert.expect(5); + + var numUserOnchange = 0; + + this.data.user.onchanges = { + partner_ids: function (obj) { + if (numUserOnchange === 0) { + // simulate proper server onchange after save of modal with new record + obj.partner_ids = [ + [5], + [1, 1, { + display_name: 'first record', + turtles: [ + [5], + [1, 2, {'display_name': 'donatello'}], + ], + }], + [1, 2, { + display_name: 'second record', + turtles: [ + [5], + obj.partner_ids[1][2].turtles[0], + ], + }], + ]; + } + numUserOnchange++; + }, + }; + + var form = createView({ + View: FormView, + model: 'user', + data: this.data, + arch: '
' + + '' + + ''+ + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 17, + }); + + // add a turtle on second partner + form.$buttons.find('.o_form_button_edit').click(); + form.$('.o_data_row:eq(1)').click(); + $('.modal .o_field_x2many_list_row_add a').click(); + $('.modal input[name="display_name"]').val('michelangelo').change(); + $('.modal .btn-primary').click(); + // open first partner so changes from previous action are applied + form.$('.o_data_row:eq(0)').click(); + $('.modal .btn-primary').click(); + form.$buttons.find('.o_form_button_save').click(); + + assert.strictEqual(numUserOnchange, 2, + 'there should 2 and only 2 onchange from closing the partner modal'); + + form.$('.o_data_row:eq(0)').click(); + assert.strictEqual($('.modal .o_data_row').length, 1, + 'only 1 turtle for first partner'); + assert.strictEqual($('.modal .o_data_row').text(), 'donatello', + 'first partner turtle is donatello'); + $('.modal .o_form_button_cancel').click(); + + form.$('.o_data_row:eq(1)').click(); + assert.strictEqual($('.modal .o_data_row').length, 1, + 'only 1 turtle for second partner'); + assert.strictEqual($('.modal .o_data_row').text(), 'michelangelo', + 'second partner turtle is michelangelo'); + $('.modal .o_form_button_cancel').click(); + + form.destroy(); + }); + QUnit.module('FieldMany2Many'); QUnit.test('many2many kanban: edition', function (assert) {