[FIX] web: properly parse expression
**Issue:**
- Set the decimal point to "," and the thousand separator to ".".
- In a float or monetary field, enter "=1.000,1+2.000,2"
- BUG: It's evaluated to: 30003
**Solution:**
Problematic evaluation steps:
```
-> parseNumber("=1.000,1+2.000,2")
- thousands separator are removed and decimals are converted to "."
so the string becomes "=1000.1+2000.2".
-> parseNumber("1000.1") + parseNumber("2000.1")
- since "." is the thousands separator, it will be removed
(replaced by empty string)
-> 10001 + 20001
-> 30003
```
Because the main parser `parseNumber` is recursive in nature, we
need to make sure that the logic that removes the thousands separator
and replaces the decimal point to "." is not called in the branch
that evaluates an input expression.
With this change, the new evaluation steps are:
```
-> parseNumber("=1.000,1+2.000,2")
-> parseNumber("1.000,1") + parseNumber("2.000,1")
-> 1000.1 + 2000.1
-> 3000.3
```
X-original-commit: 91eb5c40ce898428fb15d945d70510b92e9ebb03
Part-of: odoo/odoo#107862
This commit is contained in:
@@ -38,16 +38,16 @@ function evaluateMathematicalExpression(expr, context = {}) {
|
||||
* @returns {number}
|
||||
*/
|
||||
function parseNumber(value, options = {}) {
|
||||
// a number can have the thousand separator multiple times. ex: 1,000,000.00
|
||||
value = value.replaceAll(new RegExp(escapeRegExp(options.thousandsSep), "g") || ",", "");
|
||||
// a number only have one decimal separator
|
||||
value = value.replace(new RegExp(escapeRegExp(options.decimalPoint), "g") || ".", ".");
|
||||
|
||||
if (value.startsWith("=")) {
|
||||
value = evaluateMathematicalExpression(value.substring(1));
|
||||
if (options.truncate) {
|
||||
value = Math.trunc(value);
|
||||
}
|
||||
} else {
|
||||
// a number can have the thousand separator multiple times. ex: 1,000,000.00
|
||||
value = value.replaceAll(new RegExp(escapeRegExp(options.thousandsSep), "g") || ",", "");
|
||||
// a number only have one decimal separator
|
||||
value = value.replace(new RegExp(escapeRegExp(options.decimalPoint), "g") || ".", ".");
|
||||
}
|
||||
|
||||
return Number(value);
|
||||
|
||||
@@ -40,6 +40,12 @@ QUnit.module("Fields", (hooks) => {
|
||||
patchWithCleanup(localization, { decimalPoint: ",", thousandsSep: "." });
|
||||
assert.strictEqual(parseFloat("1.234,567"), 1234.567);
|
||||
|
||||
// Can evaluate expression from locale with decimal point different from ".".
|
||||
assert.strictEqual(parseFloat("=1.000,1 + 2.000,2"), 3000.3);
|
||||
assert.strictEqual(parseFloat("=1.000,00 + 11.121,00"), 12121);
|
||||
assert.strictEqual(parseFloat("=1000,00 + 11122,00"), 12122);
|
||||
assert.strictEqual(parseFloat("=1000 + 11123"), 12123);
|
||||
|
||||
patchWithCleanup(localization, { decimalPoint: ",", thousandsSep: false });
|
||||
assert.strictEqual(parseFloat("1234,567"), 1234.567);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user