Prevent storing Decimal with too much trailing zero

The trailing zero are kept in the Decimal and rendered in the string
representation which is unexpected for a field with limited digits.

Closes #12587
This commit is contained in:
Cédric Krier committed 2023-10-21 14:12:12 +02:00
1 parent 88edde8e69
commit ff376d7d01
3 files changed
+19 -9

No files matched your search

+4 -2
View File
@@ -2,6 +2,7 @@
# this repository contains the full copyright notices and license terms.
import gettext
import locale
from decimal import Decimal
from gi.repository import Gdk, GObject, Gtk
@@ -60,11 +61,12 @@ class NumberEntry(Gtk.Entry, Gtk.Editable):
value = None
if text not in ['-', self.__decimal_point, self.__thousands_sep]:
try:
value = self.convert(locale.delocalize(text, self.monetary))
value = Decimal(locale.delocalize(text, self.monetary))
except ValueError:
return position
if (value and self.__digits is not None
and round(value, self.__digits) != value):
and (round(value, self.__digits) != value
or value.as_tuple().exponent < -self.__digits)):
return position
buffer_.insert_text(position, new_text, len(new_text))
return position + len(new_text)
+4 -7
View File
@@ -1436,13 +1436,10 @@ class ModelStorage(Model):
or not digits
or any(d is None for d in digits)):
return
if isinstance(value, Decimal):
exp = Decimal('.'.join(['0', '0' * digits[1]]))
if value.quantize(exp) != value:
raise_error(value)
else:
if not (round(value, digits[1]) == float(value)):
raise_error(value)
if (round(value, digits[1]) != value
or (isinstance(value, Decimal)
and value.as_tuple().exponent < -digits[1])):
raise_error(value)
# validate digits
if getattr(field, 'digits', None):
if is_pyson(field.digits):
@@ -167,6 +167,17 @@ class FieldNumericTestCase(unittest.TestCase):
'numeric': Decimal('1.11111111111'),
}])
@with_transaction()
def test_create_trailing_zero_digits_invalid(self):
"Test create numeric with invalid trailing zero digits"
Numeric = Pool().get('test.numeric_digits')
with self.assertRaises(DigitsValidationError):
Numeric.create([{
'digits': 1,
'numeric': Decimal('1.10'),
}])
@with_transaction()
def test_search_equals(self):
"Test search numeric equals"