From 2b438357417b15b438d70c7201a7ffdbe1c63e84 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Tue, 14 Mar 2023 15:42:27 +0000 Subject: [PATCH] [FIX] web: evaluate inner x2many context after onchange MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit [1] recently restricted the context sent to read records and related records (m2o, x2m) in form views (see commit message for details). It restricted the context in too many cases though. For instance, open an existing record (or create a new one) with an x2many, and add a line in that x2many. If there is an inner x2many inside, and there're records in that inner x2many by default, the context sent to read those records does not need to be restricted, as this is not part of the (initial) read of the whole form view. To reproduce the issue, create a new invoice, add a line: the default tax's name isn't correct ("15% (Sales)" instead of "15%"). [1] fa11f330b8554350a48a099669b5cf36421918b8 closes odoo/odoo#115552 X-original-commit: 81c619113fed0b70c2bb69e016b18e1f93ce5983 Signed-off-by: Géry Debongnie Signed-off-by: Aaron Bohy (aab) --- .../src/legacy/js/views/basic/basic_model.js | 13 +++-- .../views/fields/one2many_field_tests.js | 56 ++++++++++++++++++- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/addons/web/static/src/legacy/js/views/basic/basic_model.js b/addons/web/static/src/legacy/js/views/basic/basic_model.js index 1063455d56e..ee04484b781 100644 --- a/addons/web/static/src/legacy/js/views/basic/basic_model.js +++ b/addons/web/static/src/legacy/js/views/basic/basic_model.js @@ -3128,7 +3128,7 @@ var BasicModel = AbstractModel.extend({ }); record.data[fieldName] = list.id; if (!fieldInfo.__no_fetch) { - var def = self._readUngroupedList(list).then(function () { + var def = self._readUngroupedList(list, { withoutRecordData: true }).then(function () { return Promise.all([ self._fetchX2ManysBatched(list), self._fetchReferencesBatched(list) @@ -4762,7 +4762,7 @@ var BasicModel = AbstractModel.extend({ * @param {string[]} fieldNames to check and read if missing * @returns {Promise} */ - _readMissingFields: function (list, resIDs, fieldNames) { + _readMissingFields: function (list, resIDs, fieldNames, withoutRecordData) { var self = this; var missingIDs = []; @@ -4783,7 +4783,7 @@ var BasicModel = AbstractModel.extend({ var def; if (missingIDs.length && fieldNames.length) { def = self._performRPC({ - context: list.getContext({ withoutRecordData: true }), + context: list.getContext({ withoutRecordData: !!withoutRecordData }), fieldNames: fieldNames, ids: missingIDs, method: 'read', @@ -4989,7 +4989,8 @@ var BasicModel = AbstractModel.extend({ * @param {Object} list a valid resource object * @returns {Promise} resolves to the fetched list object */ - _readUngroupedList: function (list) { + _readUngroupedList: function (list, options) { + options = options || {}; var self = this; var def = Promise.resolve(); @@ -5001,7 +5002,7 @@ var BasicModel = AbstractModel.extend({ if (list.res_ids.length > list.limit && list.orderedBy.length) { if (!list.orderedResIDs) { var fieldNames = _.pluck(list.orderedBy, 'name'); - def = this._readMissingFields(list, _.filter(list.res_ids, _.isNumber), fieldNames); + def = this._readMissingFields(list, _.filter(list.res_ids, _.isNumber), fieldNames, options.withoutRecordData); } def.then(function () { self._sortList(list); @@ -5034,7 +5035,7 @@ var BasicModel = AbstractModel.extend({ resIDs.push(resId); } } - return self._readMissingFields(list, resIDs, fieldNames).then(function () { + return self._readMissingFields(list, resIDs, fieldNames, options.withoutRecordData).then(function () { if (list.res_ids.length <= list.limit) { self._sortList(list); } else { diff --git a/addons/web/static/tests/views/fields/one2many_field_tests.js b/addons/web/static/tests/views/fields/one2many_field_tests.js index 876c12e7751..b7d64efda26 100644 --- a/addons/web/static/tests/views/fields/one2many_field_tests.js +++ b/addons/web/static/tests/views/fields/one2many_field_tests.js @@ -7440,7 +7440,7 @@ QUnit.module("Fields", (hooks) => { arch: `
- + @@ -7491,6 +7491,60 @@ QUnit.module("Fields", (hooks) => { await clickSave(target); }); + QUnit.test("contexts of nested x2manys are correctly sent (add line)", async function (assert) { + assert.expect(2); + + serverData.models.partner.fields.timmy.default = [12]; + + patchWithCleanup(session, { user_context: { someKey: "some value" } }); + + await makeView({ + type: "form", + resModel: "partner", + serverData, + arch: ` + + + + + + + + + `, + mockRPC(route, args) { + if (args.method === "onchange") { + assert.deepEqual( + args.kwargs.context, + { + active_field: 2, + someKey: "some value", + uid: 7, + }, + "onchange context" + ); + } + if (args.method === "read" && args.model === "partner_type") { + assert.deepEqual( + args.kwargs.context, + { + active_field: 2, + key: "yop", + key2: "hello", + someKey: "some value", + uid: 7, + }, + "read timmy context" + ); + } + }, + resId: 1, + context: { active_field: 2 }, + }); + + await click(target.querySelector(".o_field_x2many_list_row_add a")); + }); + QUnit.test("resetting invisible one2manys", async function (assert) { serverData.models.partner.records[0].turtles = []; serverData.models.partner.onchanges.foo = function (obj) {