From 4e5eebf96660c5798358a17284fa387ad1351d34 Mon Sep 17 00:00:00 2001 From: Joseph Caburnay Date: Thu, 1 Dec 2022 09:47:32 +0000 Subject: [PATCH] [FIX] web: generalize whitespace separator when parsing **Issue:** When the thousands separator is "nbsp" and the user inputs a value that is "1 234", the parser will crash because the thousands separator is different from what is manually inputted by the user. This is problematic because when typing, it's very difficult for users to enter "nbsp" character in their input. **Solution:** This change proposes that if the thousands separator is a whitespace, we consider all whitespace characters from user input as thousands separator. As a result, even if the thousands separator is "nbsp", the system will successfully parse "1 234" as 1234. X-original-commit: bffddcf015da9cf514fc25cc7f839e923e470d94 Part-of: odoo/odoo#107862 --- addons/web/static/src/views/fields/parsers.js | 9 ++++++++- addons/web/static/tests/views/fields/parsers_tests.js | 6 ++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/addons/web/static/src/views/fields/parsers.js b/addons/web/static/src/views/fields/parsers.js index ec986f66535..908ee41fcfe 100644 --- a/addons/web/static/src/views/fields/parsers.js +++ b/addons/web/static/src/views/fields/parsers.js @@ -44,8 +44,15 @@ function parseNumber(value, options = {}) { value = Math.trunc(value); } } else { + // A whitespace thousands separator is equivalent to any whitespace character. + // E.g. "1 000 000" should be parsed as 1000000 even if the + // thousands separator is nbsp. + const thousandsSepRegex = options.thousandsSep.match(/\s+/) + ? /\s+/g + : new RegExp(escapeRegExp(options.thousandsSep), "g") || ","; + // a number can have the thousand separator multiple times. ex: 1,000,000.00 - value = value.replaceAll(new RegExp(escapeRegExp(options.thousandsSep), "g") || ",", ""); + value = value.replaceAll(thousandsSepRegex, ""); // a number only have one decimal separator value = value.replace(new RegExp(escapeRegExp(options.decimalPoint), "g") || ".", "."); } diff --git a/addons/web/static/tests/views/fields/parsers_tests.js b/addons/web/static/tests/views/fields/parsers_tests.js index ba1c2487c52..68dfe031298 100644 --- a/addons/web/static/tests/views/fields/parsers_tests.js +++ b/addons/web/static/tests/views/fields/parsers_tests.js @@ -11,6 +11,7 @@ import { import { session } from "@web/session"; import { defaultLocalization } from "@web/../tests/helpers/mock_services"; import { patchWithCleanup } from "@web/../tests/helpers/utils"; +import { nbsp } from "@web/core/utils/strings"; function expectInvalidNumberError(assert, func, value, options) { let message = `${func.name} fails on value: "${value}"`; @@ -48,6 +49,11 @@ QUnit.module("Fields", (hooks) => { patchWithCleanup(localization, { decimalPoint: ",", thousandsSep: false }); assert.strictEqual(parseFloat("1234,567"), 1234.567); + + patchWithCleanup(localization, { decimalPoint: ",", thousandsSep: nbsp }); + assert.strictEqual(parseFloat("9 876,543"), 9876.543); + assert.strictEqual(parseFloat("1 234 567,89"), 1234567.89); + assert.strictEqual(parseFloat(`98${nbsp}765 432,1`), 98765432.1); }); QUnit.test("parseFloatTime", function (assert) {