[FIX] web: correctly save many2manys inside one2manys

In a form view, if a one2many list view contained a many2many
field (e.g. widget many2many_tags), the commands for the embedded
many2many weren't generated for newly created one2many subrecords,
so this field couldn't be saved.
This commit is contained in:
Aaron Bohy
2017-04-13 14:31:24 +02:00
parent fce45c3361
commit 6b936ba203
3 changed files with 59 additions and 12 deletions
@@ -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) {
@@ -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}
});
@@ -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: '<form string="Partners">' +
'<sheet>' +
'<field name="p">' +
'<tree editable="top">' +
'<field name="timmy" widget="many2many_tags"/>' +
'</tree>' +
'</field>' +
'</sheet>' +
'</form>',
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();
});
});
});