summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Lempereur <nle@odoo.com>2021-01-20 12:19:03 +0000
committerAaron Bohy <aab@odoo.com>2021-01-28 07:18:08 +0000
commit4212f84da83257419d6d98038220ce1dc322fb04 (patch)
treec68e5b2d2b5b4633c1fbce42d663de76dad0bfb8
parent1622aa755bb67e2d9e6efd18366be49b8e4783cb (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.js5
-rw-r--r--addons/web/static/tests/fields/relational_fields/field_one2many_tests.js105
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);