From 2ed845b7e0331abfd6a82708d469af3db98c7a8d 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 --- 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 2b8e04612f..c32e80b233 100644 --- a/sao/src/common.js +++ b/sao/src/common.js @@ -2138,8 +2138,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]; @@ -2148,6 +2147,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 7c6a536010..304545c63e 100644 --- a/tryton/tryton/common/domain_parser.py +++ b/tryton/tryton/common/domain_parser.py @@ -5,6 +5,7 @@ import decimal import gettext import io import locale +import math from collections import OrderedDict from decimal import Decimal from shlex import shlex @@ -336,17 +337,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)