Skip to content
Snippets Groups Projects
Commit 9d367227 authored by Hubert Van de Walle (huvw)'s avatar Hubert Van de Walle (huvw)
Browse files

[FIX] web: parseMonetary with NBSP as a thousands separator

Steps to reproduce:

  - Switch odoo language to french
  - Create a client bill for Azure Interior of $1 000 000
  - Confirm it
  - Go to the accounting dashboard
  - On the bank, click on reconcile
  - Select Azure interior
  - Click on the correct bill
  - Switch to Manual operations
  -> $1 000 000 is not a correct monetary field

Cause of the issue:

  Recently in https://github.com/odoo/odoo/pull/94126

 , `formatMonetary`
  switched from joining the currency and symbol from ` ` to a non
  breaking space, NBSP.
  To parse monetary values, the behavior was to split around NBSP to
  get the symbol on one side and the value on the other which is then
  passed to `parseFloat`.

  For the following examples, NBSP is replaced with an underscore.
  So `$_1000` becomes `$, 1000`
  But some languages such as french uses the same char as thousands
  separator.

  In that case, `$_1_000` becomes `$, 1, 000` and then the parse fails.

opw-2937403

closes odoo/odoo#97425

Signed-off-by: default avatarJorge Pinna Puissant (jpp) <jpp@odoo.com>
parent 56f9e90d
Branches
Tags
No related merge requests found
......@@ -553,16 +553,9 @@ function parseFloat(value) {
* @throws {Error} if no float is found or if parameter does not respect monetary condition
*/
function parseMonetary(value, field, options) {
var values = value.split('&nbsp;');
if (values.length === 1) {
values = value.split(NBSP);
}
if (values.length === 1) {
if (!value.includes(NBSP) && !value.includes('&nbsp;')) {
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) {
......@@ -573,7 +566,18 @@ function parseMonetary(value, field, options) {
}
currency = session.get_currency(currency_id);
}
return parseFloat(values[0] === currency.symbol ? values[1] : values[0]);
if (!value.includes(currency.symbol)) {
throw new Error(_.str.sprintf(core._t("'%s' is not a correct monetary field"), value));
}
if (currency.position === 'before') {
return parseFloat(value
.replace(`${ currency.symbol }${ NBSP }`, '')
.replace(`${ currency.symbol }&nbsp;`, ''));
} else {
return parseFloat(value
.replace(`${ NBSP }${ currency.symbol }`, '')
.replace(`&nbsp;${ currency.symbol }`, ''));
}
}
/**
......
......@@ -243,8 +243,9 @@ QUnit.test('parse integer', function(assert) {
});
QUnit.test('parse monetary', function(assert) {
assert.expect(11);
assert.expect(13);
var originalCurrencies = session.currencies;
const originalParameters = _.clone(core._t.database.parameters);
session.currencies = {
1: {
digits: [69, 2],
......@@ -270,7 +271,18 @@ QUnit.test('parse monetary', function(assert) {
assert.throws(function() {fieldUtils.parse.monetary("$&nbsp;12.00", {}, {currency_id: 1})}, /is not a correct/);
assert.throws(function() {fieldUtils.parse.monetary("$&nbsp;12.00&nbsp;34", {}, {currency_id: 3})}, /is not a correct/);
// In some languages, the non-breaking space character is used as thousands separator.
const nbsp = '\u00a0';
_.extend(core._t.database.parameters, {
grouping: [3, 0],
decimal_point: ',',
thousands_sep: nbsp,
});
assert.strictEqual(fieldUtils.parse.monetary(`1${nbsp}000.00${nbsp}€`, {}, {currency_id: 1}), 1000);
assert.strictEqual(fieldUtils.parse.monetary(`$${nbsp}1${nbsp}000.00`, {}, {currency_id: 3}), 1000);
session.currencies = originalCurrencies;
core._t.database.parameters = originalParameters;
});
QUnit.test('parse percentage', function(assert) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment