diff --git a/addons/web/static/src/js/fields/field_utils.js b/addons/web/static/src/js/fields/field_utils.js index becb1e124ef..ac4c06454ea 100644 --- a/addons/web/static/src/js/fields/field_utils.js +++ b/addons/web/static/src/js/fields/field_utils.js @@ -427,6 +427,52 @@ function parseFloat(value) { return parsed; } +/** + * Parse a String containing currency symbol and returns amount + * + * @param {string} value + * The string to be parsed + * We assume that a monetary is always a pair (symbol, amount) separated + * by a non breaking space. A simple float can also be accepted as value + * @param {Object} [field] + * a description of the field (returned by fields_get for example). + * @param {Object} [options] additional options. + * @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 + * + * @returns {float} the float value contained in the string representation + * @throws {Error} if no float is found or if parameter does not respect monetary condition + */ +function parseMonetary(value, field, options) { + var values = value.split(' '); + if (values.length === 1) { + return parseFloat(value); + } + else if (values.length !== 2) { + throw new Error(_.str.sprintf(core._t("'%s' is not a correct monetary field"), value)); + } + options = options || {}; + 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); + } + return parseFloat(values[0] === currency.symbol ? values[1] : values[0]); +} + function parseFloatTime(value) { var factor = 1; if (value[0] === '-') { @@ -510,7 +556,7 @@ return { integer: parseInteger, many2many: _.identity, // todo many2one: parseMany2one, - monetary: parseFloat, + monetary: parseMonetary, one2many: _.identity, reference: parseMany2one, selection: _.identity, // todo diff --git a/addons/web/static/tests/fields/field_utils_tests.js b/addons/web/static/tests/fields/field_utils_tests.js index e00d45ef91f..a49197f6e65 100644 --- a/addons/web/static/tests/fields/field_utils_tests.js +++ b/addons/web/static/tests/fields/field_utils_tests.js @@ -2,6 +2,7 @@ odoo.define('web.field_utils_tests', function (require) { "use strict"; var core = require('web.core'); +var session = require('web.session'); var fieldUtils = require('web.field_utils'); QUnit.module('fields', {}, function () { @@ -122,7 +123,20 @@ QUnit.test('parse float', function(assert) { }); QUnit.test('parse monetary', function(assert) { - assert.expect(6); + assert.expect(11); + var originalCurrencies = session.currencies; + session.currencies = { + 1: { + digits: [69, 2], + position: "after", + symbol: "€" + }, + 3: { + digits: [69, 2], + position: "before", + symbol: "$" + } + }; assert.strictEqual(fieldUtils.parse.monetary(""), 0); assert.strictEqual(fieldUtils.parse.monetary("0"), 0); @@ -130,6 +144,13 @@ QUnit.test('parse monetary', function(assert) { assert.strictEqual(fieldUtils.parse.monetary("-100.00"), -100); assert.strictEqual(fieldUtils.parse.monetary("1,000.00"), 1000); assert.strictEqual(fieldUtils.parse.monetary("1,000,000.00"), 1000000); + assert.strictEqual(fieldUtils.parse.monetary("$ 125.00", {}, {currency_id: 3}), 125); + assert.strictEqual(fieldUtils.parse.monetary("1,000.00 €", {}, {currency_id: 1}), 1000); + assert.throws(function() {fieldUtils.parse.monetary("$ 12.00", {}, {currency_id: 3})}, /is not a correct/); + assert.throws(function() {fieldUtils.parse.monetary("$ 12.00", {}, {currency_id: 1})}, /is not a correct/); + assert.throws(function() {fieldUtils.parse.monetary("$ 12.00 34", {}, {currency_id: 3})}, /is not a correct/); + + session.currencies = originalCurrencies; }); }); });