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 e5e7da7867b..4de6ca25187 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1718,6 +1718,8 @@ var BasicModel = AbstractModel.extend({ } else if (type === 'many2one' && fieldName in changes) { var value = changes[fieldName]; changes[fieldName] = value ? this.localData[value].res_id : false; + } else if (changes[fieldName] === null) { + changes[fieldName] = false; } } return changes; @@ -1797,13 +1799,13 @@ var BasicModel = AbstractModel.extend({ // the didChange variable keeps track of the fact that at // least one id was updated var didChange = false; - var command, relRecord; + var changes, command, relRecord; for (var i = 0; i < relIds.length; i++) { if (_.contains(keptIds, relIds[i])) { // this is an id that already existed relRecord = _.findWhere(relData, {res_id: relIds[i]}); if (!_.isEmpty(relRecord._changes)) { - var changes = this._generateChanges(relRecord); + changes = this._generateChanges(relRecord); command = x2ManyCommands.update(relRecord.res_id, changes); didChange = true; } else { @@ -1813,8 +1815,8 @@ var BasicModel = AbstractModel.extend({ } else if (_.contains(addedIds, relIds[i])) { // this is a new id relRecord = _.findWhere(relData, {res_id: relIds[i]}); - relRecord = this.get(relRecord.id, {raw: true}); - commands[fieldName].push(x2ManyCommands.create(_.omit(relRecord.data, 'id'))); + changes = this._generateChanges(relRecord); + commands[fieldName].push(x2ManyCommands.create(changes)); } } if (changesOnly && !didChange && addedIds.length === 0 && removedIds.length === 0) { diff --git a/addons/web/static/tests/views/basic_model_tests.js b/addons/web/static/tests/views/basic_model_tests.js index 15947103e6e..a81c4a13602 100644 --- a/addons/web/static/tests/views/basic_model_tests.js +++ b/addons/web/static/tests/views/basic_model_tests.js @@ -775,6 +775,13 @@ QUnit.module('Views', { this.params.res_id = undefined; this.params.type = 'record'; + var o2mRecordParams = { + fields: this.data.product.fields, + fieldNames: ['name'], + modelName: 'product', + type: 'record', + }; + var model = createModel({ Model: BasicModel, data: this.data, @@ -788,18 +795,15 @@ QUnit.module('Views', { }); model.load(this.params).then(function (resultID) { - var record = model.get(resultID); assert.strictEqual(record.data.product_ids.data.length, 0, "one2many should start with a list of length 0"); - model.makeRecord('product', [{ - name: 'name', - string: "Product Name", - type: "char", - value: "xpod" - } - ]).then(function (relatedRecordID) { + // make a default record for the related model + model.load(o2mRecordParams).then(function (relatedRecordID) { + // update the subrecord + model.notifyChanges(relatedRecordID, {name: 'xpod'}); + // add the subrecord to the o2m of the main record model.notifyChanges(resultID, { product_ids: {operation: "ADD", id: relatedRecordID} }); diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js index 34c65f96914..727db44faa1 100644 --- a/addons/web/static/tests/views/form_tests.js +++ b/addons/web/static/tests/views/form_tests.js @@ -2712,5 +2712,46 @@ QUnit.module('Views', { form.$buttons.find('.o_form_button_save').click(); form.destroy(); }); + + QUnit.test('many2manys inside one2manys are saved correctly', function (assert) { + assert.expect(1); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
', + mockRPC: function (route, args) { + if (args.method === 'create') { + var command = args.args[0].p; + assert.deepEqual(command, [[0, false, { + display_name: false, + timmy: [[6, false, [12]]], + }]], "the default partner_type_id should be equal to 12"); + } + return this._super.apply(this, arguments); + }, + }); + + // add a o2m subrecord with a m2m tag + form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_many2many_tags_cell').click(); + form.$('.o_form_field_many2one input').click(); + var $dropdown = form.$('.o_form_field_many2one input').autocomplete('widget'); + $dropdown.find('li:first()').click(); // select the first tag + + form.$buttons.find('.o_form_button_save').click(); + + form.destroy(); + }); + }); });