[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).
This commit is contained in:
Aaron Bohy
2017-04-26 16:35:18 +02:00
parent b9944978e9
commit d20074c555
2 changed files with 49 additions and 7 deletions
@@ -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
@@ -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: '<form>' +
'<group>' +
'<field name="trululu" context="{\'test\': 1}"/>' +
'</group>' +
'</form>',
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();
});
});
});