From d20074c555bf3b25155264d09ced81997eb632ff Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Wed, 26 Apr 2017 15:44:40 +0200 Subject: [PATCH] [FIX] web: BasicModel: don't mix fields and action contexts The context sent when performing RPCs is a mix of several contexts (user_context, action's context, context defined in a field's node in an arch...). In general, the action's context should not be mixed with the field's context: - for global RPCs (read a record, write a record, default_get...) only the action's context should be given - for RPCs triggered by fields (e.g. name_search in a m2o), only the field's context should be sent. The exception is for onchange RPCs, as in this case, both action and field's contexts should be sent. Before this rev, the action context was always sent, which might produced tracebacks (e.g. go to Sales > My Pipeline > New > click on Customer field > Create and Edit > boom). --- .../static/src/js/views/basic/basic_model.js | 23 +++++++++---- addons/web/static/tests/views/form_tests.js | 33 +++++++++++++++++++ 2 files changed, 49 insertions(+), 7 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 d6cda54ef5d..ad9e3fbeed1 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1851,18 +1851,22 @@ var BasicModel = AbstractModel.extend({ * @param {string|Object} [options.additionalContext] * another context to evaluate and merge to the returned context * @param {string} [options.fieldName] - * the name of the field whose context needs to be added to the - * result (and evaluated) + * if given, this field's context is added to the context, instead of + * the element's context (except if options.full is true) + * @param {boolean} [options.full=false] + * if true and fieldName given in options, the element's context + * is added to the context * @returns {Object} the evaluated context */ _getContext: function (element, options) { - var context = new Context(session.user_context, element.context); + options = options || {}; + var context = new Context(session.user_context); context.set_eval_context(this._getEvalContext(element)); - if (options && options.additionalContext) { - context.add(options.additionalContext); + if (options.full || !options.fieldName) { + context.add(element.context); } - if (options && options.fieldName) { + if (options.fieldName) { var viewType = options.viewType || element.viewType; var fieldInfo = element.fieldsInfo[viewType][options.fieldName]; if (fieldInfo && fieldInfo.context) { @@ -1874,6 +1878,9 @@ var BasicModel = AbstractModel.extend({ } } } + if (options.additionalContext) { + context.add(options.additionalContext); + } if (element.rawContext) { var rawContext = new Context(element.rawContext); var evalContext = this._getEvalContext(this.localData[element.parentID]); @@ -2319,7 +2326,9 @@ var BasicModel = AbstractModel.extend({ var self = this; var onchange_spec = this._buildOnchangeSpecs(record); var idList = record.data.id ? [record.data.id] : []; - var options = {}; + var options = { + full: true, + }; if (fields.length === 1) { fields = fields[0]; // if only one field changed, add its context to the RPC context diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js index 0091ea3e6e6..76ab818809e 100644 --- a/addons/web/static/tests/views/form_tests.js +++ b/addons/web/static/tests/views/form_tests.js @@ -3612,5 +3612,38 @@ QUnit.module('Views', { $firstModal.find('.modal-footer button:first').click(); // Save & close form.destroy(); }); + + QUnit.test('fields and record contexts are not mixed', function (assert) { + assert.expect(2); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '
', + mockRPC: function (route, args) { + if (args.method === 'name_search') { + assert.strictEqual(args.kwargs.context.test, 1, + "field's context should be sent"); + assert.notOk('mainContext' in args.kwargs.context, + "record's context should not be sent"); + } + return this._super.apply(this, arguments); + }, + res_id: 2, + viewOptions: { + mode: 'edit', + context: {mainContext: 3}, + }, + }); + + form.$('.o_form_input:first').click(); // trigger the name_search + + form.destroy(); + }); }); });