[FIX] web: monetary should reset on currency change
This reverts commit 839a07fbed4720fc71c070507c591295722df350. Indeed, the system will need the `resetOnAnyFieldChange` option as the `FieldMonetary` will need to be re-rendered if the currency changes. This does not use the `_fetchSpecialData` system as it will be refactored later and the currency can be fetched without RPC.
This commit is contained in:
@@ -49,6 +49,12 @@ var AbstractField = Widget.extend({
|
||||
* skip the widget when pressing tab
|
||||
*/
|
||||
readonly: false,
|
||||
/**
|
||||
* If this flag is set to true, the field widget will be reset on every
|
||||
* change which is made in the view (if the view supports it). This is
|
||||
* currently a form view feature.
|
||||
*/
|
||||
resetOnAnyFieldChange: false,
|
||||
/**
|
||||
* if true, the widget will replace a cell in an editable list view
|
||||
*/
|
||||
|
||||
@@ -313,6 +313,7 @@ var FieldMonetary = InputField.extend({
|
||||
className: 'o_form_field_monetary o_list_number',
|
||||
replace_element: true,
|
||||
supportedFieldTypes: ['float', 'monetary'],
|
||||
resetOnAnyFieldChange: true, // Have to listen to currency changes
|
||||
|
||||
/**
|
||||
* Float fields using a monetary widget have an additional currency_field
|
||||
@@ -331,18 +332,9 @@ var FieldMonetary = InputField.extend({
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
// Options for _formatValue
|
||||
this.nodeOptions.digits = [16,2];
|
||||
if (this.attrs.currency_field) {
|
||||
this.nodeOptions.currency_field = this.attrs.currency_field;
|
||||
} else {
|
||||
this.nodeOptions.currency_field = this.field.currency_field || 'currency_id';
|
||||
}
|
||||
if (this.record.data[this.nodeOptions.currency_field]) {
|
||||
this.nodeOptions.currency_id = this.record.data[this.nodeOptions.currency_field].res_id;
|
||||
}
|
||||
this._setCurrency();
|
||||
|
||||
if (this.mode === 'edit' && this.nodeOptions.currency_id) {
|
||||
if (this.mode === 'edit' && this.currency) {
|
||||
this.tagName = 'div';
|
||||
}
|
||||
},
|
||||
@@ -372,7 +364,7 @@ var FieldMonetary = InputField.extend({
|
||||
* @private
|
||||
*/
|
||||
_renderEdit: function () {
|
||||
if (!this.nodeOptions.currency_id) {
|
||||
if (!this.currency) {
|
||||
this._super.apply(this, arguments);
|
||||
return;
|
||||
}
|
||||
@@ -381,15 +373,35 @@ var FieldMonetary = InputField.extend({
|
||||
// Prepare and add the input
|
||||
this._prepareInput().appendTo(this.$el);
|
||||
// prepare and add the currency symbol
|
||||
var currency = session.get_currency(this.nodeOptions.currency_id);
|
||||
var $currencySymbol = $('<span>', {text: currency.symbol});
|
||||
if (currency.position === "after") {
|
||||
var $currencySymbol = $('<span>', {text: this.currency.symbol});
|
||||
if (this.currency.position === "after") {
|
||||
this.$el.append($currencySymbol);
|
||||
} else {
|
||||
this.$el.prepend($currencySymbol);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Re-gets the currency as its value may have changed.
|
||||
* @see FieldMonetary.resetOnAnyFieldChange
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_reset: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this._setCurrency();
|
||||
},
|
||||
/**
|
||||
* Deduces the currency description from the field options and view state.
|
||||
* The description is then available at this.currency.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_setCurrency: function () {
|
||||
var currencyField = this.attrs.currency_field || this.field.currency_field || 'currency_id';
|
||||
var currencyID = this.record.data[currencyField] && this.record.data[currencyField].res_id;
|
||||
this.currency = session.get_currency(currencyID);
|
||||
},
|
||||
/**
|
||||
* FieldMonetary overrides _formatValue to use the format monetary method
|
||||
* in readonly.
|
||||
@@ -400,7 +412,10 @@ var FieldMonetary = InputField.extend({
|
||||
*/
|
||||
_formatValue: function (value) {
|
||||
var format = field_utils.format[this.mode === 'edit' ? "float" : "monetary"];
|
||||
return format(value, this.field, this.nodeOptions);
|
||||
return format(value, this.field, {
|
||||
digits: [16, 2],
|
||||
currency: this.currency,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -100,8 +100,8 @@ function formatDateTime(value) {
|
||||
* should be used.
|
||||
* @param {Object} [options] additional options to override the values in the
|
||||
* python description of the field.
|
||||
* @param {integer} [options.digit] the number of digit that should be used,
|
||||
* instead of the default digit precision in the field.
|
||||
* @param {integer[]} [options.digits] the number of digits that should be used,
|
||||
* instead of the default digits precision in the field.
|
||||
* @returns {string}
|
||||
*/
|
||||
function formatFloat(value, field, options) {
|
||||
@@ -191,21 +191,50 @@ function formatMany2Many(value) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representing a monetary value. The result takes into account
|
||||
* the user settings (to display the correct decimal separator, currency, ...).
|
||||
*
|
||||
* @param {float} value the value that should be formatted
|
||||
* @param {Object} [field]
|
||||
* a description of the field (returned by fields_get for example). It
|
||||
* may contain a description of the number of digits that should be used.
|
||||
* @param {Object} [options]
|
||||
* additional options to override the values in the python description of
|
||||
* the field.
|
||||
* @param {Object} [options.currency] - the description of the currency to use
|
||||
* @param {integer} [options.currency_id]
|
||||
* the id of the 'res.currency' to use (ignored if options.currency)
|
||||
* @param {string} [options.currency_field]
|
||||
* the name of the field whose value is the currency id
|
||||
* (ignore if options.currency or options.currency_id)
|
||||
* Note: if not given it will default to the field currency_field value
|
||||
* or to 'currency_id'.
|
||||
* @param {Object} [options.data]
|
||||
* a mapping of field name to field value, required with
|
||||
* options.currency_field
|
||||
* @param {integer[]} [options.digits]
|
||||
* the number of digits that should be used, instead of the default
|
||||
* digits precision in the field. Note: if the currency defines a
|
||||
* precision, the currency's one is used.
|
||||
* @returns {string}
|
||||
*/
|
||||
function formatMonetary(value, field, options) {
|
||||
options = options || {};
|
||||
var currency_id = options.currency_id;
|
||||
if (!currency_id && options.data) {
|
||||
var currency_field = options.currency_field || field.currency_field || 'currency_id';
|
||||
currency_id = options.data[currency_field] && options.data[currency_field].res_id;
|
||||
}
|
||||
var currency = session.get_currency(currency_id);
|
||||
|
||||
var digits_precision = (currency && currency.digits) || [69,2];
|
||||
var precision = digits_precision[1];
|
||||
var formatted = _.str.sprintf('%.' + precision + 'f', value || 0).split('.');
|
||||
formatted[0] = utils.insert_thousand_seps(formatted[0]);
|
||||
var l10n = core._t.database.parameters;
|
||||
var formatted_value = formatted.join(l10n.decimal_point);
|
||||
var currency = options.currency;
|
||||
if (!currency) {
|
||||
var currency_id = options.currency_id;
|
||||
if (!currency_id && options.data) {
|
||||
var currency_field = options.currency_field || field.currency_field || 'currency_id';
|
||||
currency_id = options.data[currency_field] && options.data[currency_field].res_id;
|
||||
}
|
||||
currency = session.get_currency(currency_id);
|
||||
}
|
||||
|
||||
var formatted_value = formatFloat(value, field, {
|
||||
digits: (currency && currency.digits) || options.digits,
|
||||
});
|
||||
|
||||
if (!currency) {
|
||||
return formatted_value;
|
||||
|
||||
@@ -155,7 +155,7 @@ return BasicRenderer.extend({
|
||||
this.field_values = this._getFieldValues(this.state);
|
||||
var defs = [];
|
||||
_.each(this.widgets, function (widget) {
|
||||
if (_.contains(fields, widget.name)) {
|
||||
if (_.contains(fields, widget.name) || widget.resetOnAnyFieldChange) {
|
||||
defs.push(widget.reset(state, event));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -100,10 +100,12 @@ QUnit.module('basic_fields', {
|
||||
},
|
||||
records: [{
|
||||
id: 1,
|
||||
display_name: "$",
|
||||
symbol: "$",
|
||||
position: "before",
|
||||
}, {
|
||||
id: 2,
|
||||
display_name: "€",
|
||||
symbol: "€",
|
||||
position: "after",
|
||||
}]
|
||||
@@ -1333,7 +1335,7 @@ QUnit.module('basic_fields', {
|
||||
});
|
||||
|
||||
QUnit.test('monetary field with real monetary field in model', function (assert) {
|
||||
assert.expect(3);
|
||||
assert.expect(4);
|
||||
|
||||
this.data.partner.fields.qux.type = "monetary";
|
||||
|
||||
@@ -1350,7 +1352,7 @@ QUnit.module('basic_fields', {
|
||||
arch:'<form string="Partners">' +
|
||||
'<sheet>' +
|
||||
'<field name="qux"/>' +
|
||||
'<field name="currency_id" invisible="1"/>' +
|
||||
'<field name="currency_id"/>' +
|
||||
'<field name="bar"/>' +
|
||||
'</sheet>' +
|
||||
'</form>',
|
||||
@@ -1372,6 +1374,12 @@ QUnit.module('basic_fields', {
|
||||
assert.strictEqual(form.$('.o_form_field_monetary > input').length, 1,
|
||||
"After the onchange, the monetary <input/> should not have been duplicated");
|
||||
|
||||
var $dropdown = form.$('.o_form_field_many2one input').autocomplete('widget');
|
||||
form.$('.o_form_field_many2one input').click();
|
||||
$dropdown.find('li:not(.o_m2o_dropdown_option):last').mouseenter().click();
|
||||
assert.strictEqual(form.$('.o_form_field_monetary > span').html(), "€",
|
||||
"After currency change, the monetary field currency should have been updated");
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user