[FIX] web: properly evaluate unset numeric values in domain

Before this commit, when a numeric value was not set (for example, a new
record with no default_get value), then it was not properly evaluated as
0 in a domain.

We also slightly refactored the code so we always use the same method to
compute the evaluation context.
This commit is contained in:
Géry Debongnie
2017-04-11 19:44:38 +02:00
committed by Aaron Bohy
parent a529a928b4
commit 3ff7ff3e94
6 changed files with 40 additions and 44 deletions
@@ -268,6 +268,8 @@ var BasicModel = AbstractModel.extend({
* @param {boolean} [options.env=false] if true, will only return res_id
* (if record) or res_ids (if list)
* @param {boolean} [options.raw=false] if true, will not follow relations
* @param {boolean} [options.noUnsetNumeric=false] if true, will set numeric
* values to 0 if not set
* @returns {Object}
*/
get: function (id, options) {
@@ -311,6 +313,13 @@ var BasicModel = AbstractModel.extend({
if (!field) {
continue;
}
if (options.noUnsetNumeric) {
if (field.type === 'float' ||
field.type === 'integer' ||
field.type === 'monetary') {
element.data[fieldName] = element.data[fieldName] || 0;
}
}
// get relational datapoint
if (field.type === 'many2one') {
@@ -1792,7 +1801,7 @@ var BasicModel = AbstractModel.extend({
* @returns {Object}
*/
_getEvalContext: function (element) {
var evalContext = this.get(element.id, {raw: true}).data;
var evalContext = this.get(element.id, {raw: true, noUnsetNumeric: true}).data;
evalContext.active_model = element.model;
if (evalContext.id) {
evalContext.active_id = evalContext.id;
@@ -51,44 +51,6 @@ return AbstractRenderer.extend({
}
});
},
/**
* Helper method, used to get an object with the 'raw' field values. It is
* important when we want to evaluate if a record matches a given domain.
*
* A basic model record is a tree structure, but we sometimes need 'pure'
* data, so for example, [1,4] for the value of a one2many, not
* [{Object}, {Object}].
*
* @param {Object} record
* @returns {Object}
*/
_getFieldValues: function (record) {
var result = {};
_.each(record.getFieldNames(), function (name) {
var field = record.fields[name];
var value = record.data[name];
result[name] = value;
if (!value) {
return;
}
else if (field.type === 'many2one') {
result[name] = value.data ? value.data.id || false : false;
}
else if (field.type === 'one2many' || field.type === 'many2many') {
if (value) {
result[name] = _.pluck(value.data, 'res_id');
} else {
result[name] = [];
}
}
else if (field.type === 'boolean') {
// we want an explicit false value, not null if it is unset
result[name] = value || false;
}
});
result.id = record.data.id;
return result;
},
/**
* Render the view
*
@@ -29,7 +29,7 @@ return BasicRenderer.extend({
this.idsForLabels = {};
this.widgets = [];
this.mode = params.mode;
this.field_values = this._getFieldValues(this.state);
this.field_values = this.state.getEvalContext();
},
//--------------------------------------------------------------------------
@@ -136,7 +136,7 @@ return BasicRenderer.extend({
// only update the given fields
return this.updateWidgets(params.fieldNames, state);
}
this.field_values = this._getFieldValues(state);
this.field_values = state.getEvalContext();
return this._super.apply(this, arguments);
},
/**
@@ -152,7 +152,7 @@ return BasicRenderer.extend({
*/
updateWidgets: function (fields, state, event) {
this.state = state;
this.field_values = this._getFieldValues(this.state);
this.field_values = this.state.getEvalContext();
var defs = [];
_.each(this.widgets, function (widget) {
if (_.contains(fields, widget.name) || widget.resetOnAnyFieldChange) {
@@ -215,7 +215,7 @@ ListRenderer.include({
return true;
}
if ('readonly' in node.modifiers) {
var fieldValues = this._getFieldValues(record);
var fieldValues = record.getEvalContext();
return new Domain(node.modifiers.readonly).compute(fieldValues);
}
return false;
@@ -223,7 +223,7 @@ var ListRenderer = BasicRenderer.extend({
*/
_isInvisible: function (record, node) {
if ('invisible' in node.modifiers) {
var fieldValues = this._getFieldValues(record);
var fieldValues = record.getEvalContext();
return new Domain(node.modifiers.invisible).compute(fieldValues);
}
return false;
@@ -363,6 +363,31 @@ QUnit.module('Views', {
form.destroy();
});
QUnit.test('invisible attrs with zero value in domain and unset value in data', function (assert) {
assert.expect(1);
this.data.partner.fields.int_field.type = 'monetary';
var form = createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form string="Partners">' +
'<sheet>' +
'<field name="foo"/>' +
'<group attrs=\'{"invisible": [["int_field", "=", 0.0]]}\'>' +
'<div class="hello">this should be invisible</div>' +
'<field name="int_field"/>' +
'</group>' +
'</sheet>' +
'</form>',
});
assert.notOk(form.$('div.hello').is(':visible'),
"attrs invisible should have been computed and applied");
form.destroy();
});
QUnit.test('rendering stat buttons', function (assert) {
assert.expect(3);