From 2b8f96f8aaa3a131fc332181f552a293f44791a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Mon, 19 May 2025 11:31:28 +0200 Subject: [PATCH] Use the initial precision when applying factor to a field without digits Without digits the full representation of the number is used which might not be the expected behaviour because applying the factor will result in a number which short representation could be surprising to the user. Closes #10460 --- sao/src/model.js | 11 +++++++++++ tryton/tryton/gui/window/view_form/model/field.py | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/sao/src/model.js b/sao/src/model.js index 6d0ac60a09..df6926c6c8 100644 --- a/sao/src/model.js +++ b/sao/src/model.js @@ -2062,12 +2062,23 @@ }, apply_factor: function(record, value, factor) { if (value !== null) { + // The default precision is the one used by value (before + // applying the factor), per the ecmascript specification + // it's the shortest representation of said value. + // Once the factor is applied the number might become even + // more inexact thus we should rely on the initial + // precision + the effect factor will have + // https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-number-tostring + let default_precision = (value.toString().split('.')[1] || '').length; + default_precision += Math.ceil(Math.log10(factor)); value /= factor; var digits = this.digits(record); if (digits && (digits[1] !== null)) { // Round to avoid float precision error // after the division by factor value = value.toFixed(digits[1]); + } else { + value = value.toFixed(default_precision); } value = this.convert(value); } diff --git a/tryton/tryton/gui/window/view_form/model/field.py b/tryton/tryton/gui/window/view_form/model/field.py index 0312a2c865..36abd46c47 100644 --- a/tryton/tryton/gui/window/view_form/model/field.py +++ b/tryton/tryton/gui/window/view_form/model/field.py @@ -459,10 +459,20 @@ class FloatField(Field): def apply_factor(self, record, value, factor): if value is not None: + # The default precision is the one used by value (before + # applying the factor), as python uses the shortest representation + # of said value. + # Once the factor is applied the number might become even + # more inexact thus we should rely on the initial + # precision + the effect factor will have + default_precision = len((str(value).split('.', 2) + [''])[1]) + default_precision += math.ceil(math.log10(factor)) value /= factor digits = self.digits(record) if digits: value = round(value, digits[1]) + else: + value = round(value, default_precision) value = self.convert(value) return value