From beeef130fb279130a22e790e6f078b4d9dfdf272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 4 Apr 2025 18:51:30 +0200 Subject: [PATCH] Compute digits of float value before applying factor When applying the factor, we introduce new rounding issue which falsify the computation of digits. So it is better to compute the digits using the initial value (coming from the string parsing) and update the digits based on the order of the factor. Closes #13964 (grafted from 3606a9f176d0312d9645d05902b74192391538e4) --HG-- branch : 6.0 --- sao/src/common.js | 5 +++-- tryton/tryton/common/domain_parser.py | 14 ++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/sao/src/common.js b/sao/src/common.js index e5bbc08c2c..c5858cb84b 100644 --- a/sao/src/common.js +++ b/sao/src/common.js @@ -2085,8 +2085,7 @@ return ''; } var digit = 0; - var factor = Number(field.factor || 1); - var string = String(value * factor); + var string = String(value); if (string.contains('e')) { var exp = string.split('e')[1]; string = string.split('e')[0]; @@ -2095,6 +2094,8 @@ if (string.contains('.')) { digit += string.replace(/0+$/, '').split('.')[1].length; } + var factor = Number(field.factor || 1); + digit -= Math.round(Math.log10(factor)); return (value * factor).toFixed(digit); }; var format_selection = function() { diff --git a/tryton/tryton/common/domain_parser.py b/tryton/tryton/common/domain_parser.py index 2c3e56bec4..df46a1c3a8 100644 --- a/tryton/tryton/common/domain_parser.py +++ b/tryton/tryton/common/domain_parser.py @@ -1,5 +1,6 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. +import math from shlex import shlex from types import GeneratorType import gettext @@ -334,17 +335,18 @@ def format_value(field, value, target=None, context=None, _quote_empty=False): or isinstance(value, bool))): return '' digit = 0 - if isinstance(value, Decimal): - cast = Decimal - else: - cast = float - factor = cast(field.get('factor', 1)) - string_ = str(value * factor) + string_ = str(value) if 'e' in string_: string_, exp = string_.split('e') digit -= int(exp) if '.' in string_: digit += len(string_.rstrip('0').split('.')[1]) + if isinstance(value, Decimal): + cast = Decimal + else: + cast = float + factor = cast(field.get('factor', 1)) + digit -= round(math.log10(factor)) return locale.localize( '{0:.{1}f}'.format(value * factor or 0, digit), True)