[FIX] web: fetch specialData of fields in x2many form

Suppose that there is a one2many list in a form view containing
a field F, displayed with no widget, and that F is also displayed
in the one2many form view (opened when clicking on a record of the
list), but that in this form view, F is displayed with a widget
requiring specialData (additional data to fetch alongside the
record), e.g. widget="domain".

Before this rev., it crashed when this happened because those
specialData weren't loaded when opening the related record.

Credit goes to @pga-odoo for reporting the bug and reproducing it
in a test.
This commit is contained in:
Aaron Bohy
2017-05-19 15:51:57 +02:00
parent c929a81e8f
commit 702835682e
2 changed files with 25 additions and 7 deletions
@@ -67,21 +67,36 @@ var BasicView = AbstractView.extend({
var viewType = this.viewType;
var viewFields = Object.keys(record.fieldsInfo[viewType]);
var fieldNames = _.difference(viewFields, Object.keys(record.data));
var fieldsInfo = record.fieldsInfo[viewType];
// Suppose that in a form view, there is an x2many list view with
// an x2many field F of the related record, and that F is also
// displayed in the x2many form view (e.g. as a list or a kanban).
// In this case, F is represented in record.data
// (as it is known by the x2many list view), but its related fields
// (those displayed in the list or kanban) still need to be fetched.
// a field F, and that F is also displayed in the x2many form view.
// In this case, F is represented in record.data (as it is known by
// the x2many list view), but the loaded information may not suffice
// in the form view (e.g. if field is a many2many list in the form
// view, or if it is displayed by a widget requiring specialData).
// So when this happens, F is added to the list of fieldNames to fetch.
_.each(viewFields, function (name) {
if (!_.contains(fieldNames, name)) {
var fieldType = record.fields[name].type;
var fieldInfo = fieldsInfo[name];
// SpecialData case: field requires specialData that haven't
// been fetched yet.
if (fieldInfo.Widget) {
var requiresSpecialData = fieldInfo.Widget.prototype.specialData;
if (requiresSpecialData && !(name in record.specialData)) {
fieldNames.push(name);
return;
}
}
// X2Many case: field is an x2many displayed as a list or
// kanban view, but the related fields haven't been loaded yet.
if ((fieldType === 'one2many' || fieldType === 'many2many')) {
if (!('fieldsInfo' in record.data[name])) {
fieldNames.push(name);
} else {
var fieldInfo = record.fieldsInfo[viewType][name];
var fieldViews = fieldInfo.views || fieldInfo.fieldsInfo || {};
var fieldViewTypes = Object.keys(fieldViews);
var recordViewTypes = Object.keys(record.data[name].fieldsInfo);
@@ -2482,7 +2482,7 @@ QUnit.module('relational_fields', {
form.destroy();
});
QUnit.test('one2many kanban with edit type action and domain widget (widget wich use SpecialData)', function (assert) {
QUnit.test('one2many kanban with edit type action and domain widget (widget using SpecialData)', function (assert) {
assert.expect(1);
this.data.turtle.fields.model_name = {string: "Domain Condition Model", type: "char"};
@@ -2504,6 +2504,8 @@ QUnit.module('relational_fields', {
'<t t-name="kanban-box">' +
'<div><field name="display_name"/></div>' +
'<div><field name="turtle_foo"/></div>' +
// field without Widget in the list
'<div><field name="condition"/></div>' +
'<div> <a type="edit"> Edit </a> </div>' +
'</t>' +
'</templates>' +
@@ -2511,6 +2513,7 @@ QUnit.module('relational_fields', {
'<form>' +
'<field name="product_id" widget="statusbar"/>' +
'<field name="model_name"/>' +
// field with Widget requiring specialData in the form
'<field name="condition" widget="domain" options="{\'model\': \'model_name\'}"/>' +
'</form>' +
'</field>' +