[FIX] web: parseMonetary of decimal value without leading 0
Steps to reproduce ================== - Open a product form view - Enter .5 in the Cost field It is parsed as 5 but it should be 0.5 Cause of the issue ================== When trying to strip the currency symbol from the input, the leading decimal separator was also removed Solution ======== The decimalPoint can have multiple characters. This means that we can't simply add the decimal separator inside the negated character class. Instead, what we can do is skip everything until we find a interesting substring. (more details in the comment) We then remove everything that is not a digit at the end. Finally, we can pass that to `parseFloat` closes odoo/odoo#123358 X-original-commit: fa466d75da3b30ac1e512a95436075ef1461a95c Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com> Signed-off-by: Hubert Van De Walle <huvw@odoo.com>
This commit is contained in:
@@ -159,20 +159,26 @@ export function parsePercentage(value) {
|
||||
|
||||
/**
|
||||
* Try to extract a monetary value from a string. The localization is considered in the process.
|
||||
* This is a very lenient function such that it just strips non-numeric characters at the
|
||||
* beginning and end of the string, and then tries to parse the remaining string as a float.
|
||||
* This is a very lenient function such that it ignores everything before we encounter a substring consisting of either
|
||||
* - a sign (- or +)
|
||||
* - an equals sign (signaling the start of a mathematical expression)
|
||||
* - a decimal point
|
||||
* - a number
|
||||
* We then remove any non-numeric characters at the end
|
||||
*
|
||||
*
|
||||
* @param {string} value
|
||||
* @returns {number}
|
||||
*/
|
||||
export function parseMonetary(value) {
|
||||
value = value.trim();
|
||||
const regex = new RegExp(`^[^\\d\\-+=]*(?<strToParse>.*?)[^\\d]*$`);
|
||||
const match = value.match(regex);
|
||||
if (!match) {
|
||||
throw new InvalidNumberError(`"${value}" is not a valid number.`);
|
||||
const startMatch = value.match(
|
||||
new RegExp(`[\\d\\-+=]|${escapeRegExp(localization.decimalPoint)}`)
|
||||
);
|
||||
if (startMatch) {
|
||||
value = value.substring(startMatch.index);
|
||||
}
|
||||
value = match.groups.strToParse;
|
||||
value = value.replace(/\D*$/, "");
|
||||
return parseFloat(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ QUnit.module("Fields", (hooks) => {
|
||||
assert.strictEqual(parseMonetary("100.00\u00a0€"), 100);
|
||||
assert.strictEqual(parseMonetary("-100.00"), -100);
|
||||
assert.strictEqual(parseMonetary("1,000.00"), 1000);
|
||||
assert.strictEqual(parseMonetary(".1"), 0.1);
|
||||
assert.strictEqual(parseMonetary("1,000,000.00"), 1000000);
|
||||
assert.strictEqual(parseMonetary("$\u00a0125.00"), 125);
|
||||
assert.strictEqual(parseMonetary("1,000.00\u00a0€"), 1000);
|
||||
@@ -165,6 +166,30 @@ QUnit.module("Fields", (hooks) => {
|
||||
assert.strictEqual(parseMonetary("1\u00a0000,14DOLLARS"), 1000.14);
|
||||
assert.strictEqual(parseMonetary("DOLLARS+1\u00a0000,15"), 1000.15);
|
||||
assert.strictEqual(parseMonetary("EURO-1\u00a0000,16DOGE"), -1000.16);
|
||||
|
||||
// comma as decimal point and dot as thousands separator
|
||||
patchWithCleanup(localization, { thousandsSep: ".", decimalPoint: "," });
|
||||
assert.strictEqual(parseMonetary("10,08"), 10.08);
|
||||
assert.strictEqual(parseMonetary(""), 0);
|
||||
assert.strictEqual(parseMonetary("0"), 0);
|
||||
assert.strictEqual(parseMonetary("100,12\u00a0€"), 100.12);
|
||||
assert.strictEqual(parseMonetary("-100,12"), -100.12);
|
||||
assert.strictEqual(parseMonetary("1.000,12"), 1000.12);
|
||||
assert.strictEqual(parseMonetary(",1"), 0.1);
|
||||
assert.strictEqual(parseMonetary("1.000.000,12"), 1000000.12);
|
||||
assert.strictEqual(parseMonetary("$\u00a0125,12"), 125.12);
|
||||
assert.strictEqual(parseMonetary("1.000,00\u00a0€"), 1000);
|
||||
assert.strictEqual(parseMonetary(","), 0);
|
||||
assert.strictEqual(parseMonetary("1\u00a0"), 1);
|
||||
assert.strictEqual(parseMonetary("\u00a01"), 1);
|
||||
assert.strictEqual(parseMonetary("12,34 €"), 12.34);
|
||||
assert.strictEqual(parseMonetary("$ 12,34"), 12.34);
|
||||
|
||||
// Can evaluate expression
|
||||
assert.strictEqual(parseMonetary("=1.000,1 + 2.000,2"), 3000.3);
|
||||
assert.strictEqual(parseMonetary("=1.000,00 + 11.121,00"), 12121);
|
||||
assert.strictEqual(parseMonetary("=1000,00 + 11122,00"), 12122);
|
||||
assert.strictEqual(parseMonetary("=1000 + 11123"), 12123);
|
||||
});
|
||||
|
||||
QUnit.test("parsers fallback on english localisation", function (assert) {
|
||||
|
||||
Reference in New Issue
Block a user