From 495d475d1d3ab6726d7e5d5f2dd8044e60d1a3da Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Wed, 6 Feb 2019 09:43:34 +0000 Subject: [PATCH] [FIX] web: only call name_get when necessary For many2one fields, 'default_get' only returns the id, whereas 'onchange' (like 'read') returns an array with id and display_name. Before this rev., when creating a new record, we always called 'name_get' for all many2ones, whether or not their value was obtained by 'default_get' or 'onchange', i.e. even if their display_name was already known. It may just look like unnecessary RPCs, but those RPCs could actually cause a crash when the user has access to the main model (and thus can access the display_name of the many2one thanks to related sudo), but doesn't have access to the many2one comodel. closes odoo/odoo#30892 --- .../static/src/js/views/basic/basic_model.js | 2 +- .../tests/fields/relational_fields_tests.js | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) 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 80ca5bc7917..b21c4b55eff 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -2400,7 +2400,7 @@ var BasicModel = AbstractModel.extend({ if (field.type === 'many2one' && !record.fieldsInfo[record.viewType][name].__no_fetch) { var localId = (record._changes && record._changes[name]) || record.data[name]; var relatedRecord = self.localData[localId]; - if (!relatedRecord) { + if (!relatedRecord || relatedRecord.data.display_name) { return; } toBeFetched.push({ diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index e0ab5ae7a5f..316f5caeffd 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -2644,6 +2644,42 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('do not call name_get if display_name already known', function (assert) { + // default_get only returns the id for many2one fields + // onchange returns an array with the id and the display_name + // thus, when an onchange is performed, there is no need to call + // name_get as the display_name is alreay available + assert.expect(6); + + this.data.partner.fields.product_id.default = 37; + this.data.partner.onchanges = { + trululu: function (obj) { + obj.trululu = [1, 'first record']; + }, + }; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
', + mockRPC: function (route, args) { + assert.step(args.method + ' on ' + args.model); + return this._super.apply(this, arguments); + }, + }); + + assert.strictEqual(form.$('.o_field_widget[name=trululu] input').val(), 'first record'); + assert.strictEqual(form.$('.o_field_widget[name=product_id] input').val(), 'xphone'); + assert.verifySteps([ + 'default_get on partner', + 'onchange on partner', + 'name_get on product', + ]); + + form.destroy(); + }); + QUnit.test('many2one in one2many: domain updated by an onchange', function (assert) { assert.expect(3);