[FIX] web: default value for o2m inside o2m

A traceback was raised when opening a new record for a model with a
one2many displayed inside a one2many (e.g. simply displaying the
number of records in the relation), and with an onchange setting a
default value to the inner one2many (for example, linking it to
existing records).

As the inner o2m has no subviews, it has no fieldsInfo, and the
code assumed that fieldsInfo was always set.

This was for example reproducible from v11 as follows:
  - create a product (with MTO/Buy and call for tender (need
    purchase agreement module))
  - create an SO with this product and confirm it
  - go to purchase order form view and add a move_dest_ids field in
    the tree definition of field order_line
  - go to menu purchase agreement and choose the PA generated by
    your SO
  - add a vendor, confirm the PA and click on 'New Quotation'.
This commit is contained in:
Aaron Bohy
2017-10-26 08:19:43 +02:00
parent 7b8001a847
commit 6fa63eb15c
2 changed files with 42 additions and 2 deletions
@@ -2881,7 +2881,8 @@ var BasicModel = AbstractModel.extend({
* @returns {boolean}
*/
_isFieldProtected: function (record, fieldName, viewType) {
var fieldInfo = record.fieldsInfo[viewType || record.viewType][fieldName];
var fieldInfo = record.fieldsInfo &&
(record.fieldsInfo[viewType || record.viewType][fieldName]);
if (fieldInfo) {
var rawModifiers = JSON.parse(fieldInfo.modifiers || "{}");
var modifiers = this._evalModifiers(record, rawModifiers);
@@ -5990,6 +5990,46 @@ QUnit.module('relational_fields', {
form.destroy();
});
QUnit.test('default value for nested one2manys (coming from onchange)', function (assert) {
assert.expect(3);
this.data.partner.onchanges.p = function (obj) {
obj.p = [
[5],
[0, 0, {turtles: [[5], [4, 1]]}], // link record 1 by default
];
};
var form = createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form>' +
'<sheet>' +
'<field name="p">' +
'<tree><field name="turtles"/></tree>' +
'</field>' +
'</sheet>' +
'</form>',
mockRPC: function (route, args) {
if (args.method === 'create') {
assert.strictEqual(args.args[0].p[0][0], 0,
"should send a command 0 (CREATE) for p");
assert.deepEqual(args.args[0].p[0][2], {turtles: [[4, 1, false]]},
"should send the correct values");
}
return this._super.apply(this, arguments);
},
});
assert.strictEqual(form.$('.o_data_cell').text(), '1 record',
"should correctly display the value of the inner o2m");
form.$buttons.find('.o_form_button_save').click();
form.destroy();
});
QUnit.test('display correct value after validation error', function (assert) {
assert.expect(4);
@@ -6079,7 +6119,6 @@ QUnit.module('relational_fields', {
form.destroy();
});
QUnit.module('FieldMany2Many');
QUnit.test('many2many kanban: edition', function (assert) {