[FIX] web: BasicModel: fetch added x2many records

Suppose that there is a many2many (list) field in a form view,
and there is a many2many (e.g. many2many_tags) field inside the
list.

In edit mode, if the user adds a record in the relation, this
record and its relational data should be fetched.

Before this rev., the relational data wasn't fetched, so the
many2many_tags couldn't be displayed correctly.
This commit is contained in:
Aaron Bohy
2017-05-03 20:48:25 +02:00
parent d56baebc8e
commit c7fc74fb79
2 changed files with 86 additions and 3 deletions
@@ -1119,6 +1119,7 @@ var BasicModel = AbstractModel.extend({
list_records[record.id].data = record;
self._parseServerData(fieldNames, list.fields, record);
});
return self._fetchX2ManysBatched(list);
});
defs.push(def);
}
@@ -1645,11 +1646,21 @@ var BasicModel = AbstractModel.extend({
var fieldsInfo = view ? view.fieldsInfo : fieldInfo.fieldsInfo;
var fields = view ? view.fields : fieldInfo.relatedFields;
var viewType = view ? view.type : fieldInfo.viewType;
var data = list._changes || list.data;
var x2mRecords = [];
// step 1: collect ids
var ids = [];
_.each(list.data, function (dataPoint) {
_.each(data, function (dataPoint) {
var record = self.localData[dataPoint];
if (typeof record.data[fieldName] === 'string') {
// in this case, the value is a local ID, which means that the
// record has already been processed. It can happen for example
// when a user adds a record in a m2m relation, or loads more
// records in a kanban column
return;
}
x2mRecords.push(record);
ids = _.unique(ids.concat(record.data[fieldName] || []));
var m2mList = self._makeDataPoint({
fieldsInfo: fieldsInfo,
@@ -1696,8 +1707,7 @@ var BasicModel = AbstractModel.extend({
});
});
_.each(list.data, function (dataPoint) {
var record = self.localData[dataPoint];
_.each(x2mRecords, function (record) {
var m2mList = self.localData[record.data[fieldName]];
m2mList.data = [];
@@ -3390,6 +3390,79 @@ QUnit.module('relational_fields', {
form.destroy();
});
QUnit.test('many2many list with x2many: add a record', function (assert) {
assert.expect(18);
this.data.partner_type.fields.m2m = {
string: "M2M", type: "many2many", relation: 'turtle',
};
this.data.partner_type.records[0].m2m = [1, 2];
this.data.partner_type.records[1].m2m = [2, 3];
var form = createView({
View: FormView,
model: 'partner',
data: this.data,
arch:'<form string="Partners">' +
'<field name="timmy"/>' +
'</form>',
res_id: 1,
archs: {
'partner_type,false,list': '<tree>' +
'<field name="display_name"/>' +
'<field name="m2m" widget="many2many_tags"/>' +
'</tree>',
'partner_type,false,search': '<search>' +
'<field name="display_name" string="Name"/>' +
'</search>',
},
mockRPC: function (route, args) {
assert.step(_.last(route.split('/')) + ' on ' + args.model);
if (args.model === 'turtle') {
assert.step(args.args[0]); // the read ids
}
return this._super.apply(this, arguments);
},
viewOptions: {
mode: 'edit',
},
});
form.$('.o_form_field_x2many_list_row_add a').click();
$('.modal .o_data_row:first').click(); // add a first record to the relation
assert.strictEqual(form.$('.o_data_row').length, 1,
"the record should have been added to the relation");
assert.strictEqual(form.$('.o_data_row:first .o_badge_text').text(), 'leonardodonatello',
"inner m2m should have been fetched and correctly displayed");
form.$('.o_form_field_x2many_list_row_add a').click();
$('.modal .o_data_row:first').click(); // add a second record to the relation
assert.strictEqual(form.$('.o_data_row').length, 2,
"the second record should have been added to the relation");
assert.strictEqual(form.$('.o_data_row:nth(1) .o_badge_text').text(), 'donatelloraphael',
"inner m2m should have been fetched and correctly displayed");
assert.verifySteps([
'read on partner',
'search_read on partner_type',
'read on turtle',
[1, 2, 3],
'read on partner_type',
'read on turtle',
[1, 2],
'search_read on partner_type',
'read on turtle',
[2, 3],
'read on partner_type',
'read on turtle',
[2, 3],
]);
form.destroy();
});
QUnit.module('FieldStatus');
QUnit.test('static statusbar widget on many2one field', function (assert) {