diff options
| author | Nicolas Lempereur <nle@odoo.com> | 2021-01-20 12:19:03 +0000 |
|---|---|---|
| committer | Aaron Bohy <aab@odoo.com> | 2021-01-28 07:18:08 +0000 |
| commit | 4212f84da83257419d6d98038220ce1dc322fb04 (patch) | |
| tree | c68e5b2d2b5b4633c1fbce42d663de76dad0bfb8 | |
| parent | 1622aa755bb67e2d9e6efd18366be49b8e4783cb (diff) | |
[FIX] web: nested x2many with no widget and onchanges
Let's assume the following situation: in a form view, there is a
one2many field A displayed as a list (non editable). In the list,
there is another one2many field B displayed with no widget (it
basically displays "X records"). In A's form view, B is also
displayed, but this time as a list.
There is an onchange on the main form view that adds a line in A,
(and simply sets B to [[5]], i.e. 'No record').
Before this commit, if the user opened the newly added sub record in
A, and clicked on 'Add a line' of B, it crashed.
The cause of the crash was that the wrong viewType was used to
create the new (default) record in B: it used the original
viewType, which was undefined (B is displayed with no widget in
A's list). With this commit, we use the viewType of B that is used
to edit it, in this case 'list'.
In the slighlty different scenario where B is displayed with
widget many2many_tags in A's list, there were no crash, but wrong
fieldNames were sent to the 'default_get' RPC. As a consequence,
default values for fields in B's list were potentially not loaded.
opw-2422806
closes #64793
closes odoo/odoo#65157
Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Co-authored-by: Aaron Bohy <aab@odoo.com>
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_model.js | 5 | ||||
| -rw-r--r-- | addons/web/static/tests/fields/relational_fields/field_one2many_tests.js | 105 |
2 files changed, 108 insertions, 2 deletions
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 ca21cb6824d..d4d640d2739 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1431,7 +1431,7 @@ var BasicModel = AbstractModel.extend({ fieldsInfo: list.fieldsInfo, parentID: list.id, position: position, - viewType: list.viewType, + viewType: options.viewType || list.viewType, allowWarning: options && options.allowWarning }; @@ -2003,6 +2003,7 @@ var BasicModel = AbstractModel.extend({ context: command.context, position: command.position }, options || {}); + createOptions.viewType = fieldInfo.mode; def = this._addX2ManyDefaultRecord(list, createOptions).then(function (ids) { _.each(ids, function(id){ @@ -4029,7 +4030,7 @@ var BasicModel = AbstractModel.extend({ // Hence preventing their value to crash when getting back to the originating view var parentRecord = params.parentID && this.localData[params.parentID].type === 'list' ? this.localData[params.parentID] : null; - if (parentRecord) { + if (parentRecord && parentRecord.viewType in parentRecord.fieldsInfo) { var originView = parentRecord.viewType; fieldNames = _.union(fieldNames, Object.keys(parentRecord.fieldsInfo[originView])); fieldsInfo[targetView] = _.defaults({}, fieldsInfo[targetView], parentRecord.fieldsInfo[originView]); diff --git a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js index bb64e3f0775..c10fede6f7b 100644 --- a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js +++ b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js @@ -1548,6 +1548,111 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + QUnit.test('onchange on one2many with x2many in list (no widget) and form view (list)', async function (assert) { + assert.expect(6); + + this.data.turtle.fields.turtle_foo.default = "a default value"; + this.data.partner.onchanges = { + foo: function (obj) { + obj.p = [[0, false, { turtles: [[0, false, { turtle_foo: 'hello'}]] }]]; + }, + }; + + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '<form>' + + '<field name="foo"/>' + + '<field name="p">' + + '<tree>' + + '<field name="turtles"/>' + + '</tree>' + + '<form>' + + '<field name="turtles">' + + '<tree editable="top">' + + '<field name="turtle_foo"/>' + + '</tree>' + + '</field>' + + '</form>' + + '</field>' + + '</form>', + }); + + + assert.containsOnce(form, '.o_data_row', + "the onchange should have created one record in the relation"); + + // open the created o2m record in a form view + await testUtils.dom.click(form.$('.o_data_row')); + + assert.containsOnce(document.body, '.modal', "should have opened a dialog"); + assert.containsOnce(document.body, '.modal .o_data_row'); + assert.strictEqual($('.modal .o_data_row').text(), 'hello'); + + // add a one2many subrecord and check if the default value is correctly applied + await testUtils.dom.click($('.modal .o_field_x2many_list_row_add a')); + + assert.containsN(document.body, '.modal .o_data_row', 2); + assert.strictEqual($('.modal .o_data_row:first .o_field_widget[name=turtle_foo]').val(), + 'a default value'); + + form.destroy(); + }); + + QUnit.test('onchange on one2many with x2many in list (many2many_tags) and form view (list)', async function (assert) { + assert.expect(6); + + this.data.turtle.fields.turtle_foo.default = "a default value"; + this.data.partner.onchanges = { + foo: function (obj) { + obj.p = [[0, false, { turtles: [[0, false, { turtle_foo: 'hello'}]] }]]; + }, + }; + + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '<form>' + + '<field name="foo"/>' + + '<field name="p">' + + '<tree>' + + '<field name="turtles" widget="many2many_tags"/>' + + '</tree>' + + '<form>' + + '<field name="turtles">' + + '<tree editable="top">' + + '<field name="turtle_foo"/>' + + '</tree>' + + '</field>' + + '</form>' + + '</field>' + + '</form>', + debug: 1, + }); + + + assert.containsOnce(form, '.o_data_row', + "the onchange should have created one record in the relation"); + + // open the created o2m record in a form view + await testUtils.dom.click(form.$('.o_data_row')); + + assert.containsOnce(document.body, '.modal', "should have opened a dialog"); + assert.containsOnce(document.body, '.modal .o_data_row'); + assert.strictEqual($('.modal .o_data_row').text(), 'hello'); + + // add a one2many subrecord and check if the default value is correctly applied + await testUtils.dom.click($('.modal .o_field_x2many_list_row_add a')); + + assert.containsN(document.body, '.modal .o_data_row', 2); + assert.strictEqual($('.modal .o_data_row:first .o_field_widget[name=turtle_foo]').val(), + 'a default value'); + + form.destroy(); + }); + QUnit.test('embedded one2many with handle widget with minimum setValue calls', async function (assert) { var done = assert.async(); assert.expect(20); |
