Allow more decimal places for tax rates (#6092)

* Allow more decimal places for tax rates

* Fix normalization

* More tax rate handling

* Add uncommitted tests

* Rebase migration

* Update src/pretix/base/migrations/0304_tax_rate_decimals.py

Co-authored-by: robbi5 <richt@rami.io>

---------

Co-authored-by: robbi5 <richt@rami.io>
This commit is contained in:
Raphael Michel
2026-07-15 16:20:45 +02:00
committed by GitHub
co-authored by robbi5
parent d007fb9566
commit eb29101d09
19 changed files with 228 additions and 59 deletions
+32
View File
@@ -20,9 +20,11 @@
# <https://www.gnu.org/licenses/>.
#
import copy
from decimal import Decimal
from django.core.files import File
from django.db import models
from django.db.models.fields import DecimalField
class Thumbnail(models.Model):
@@ -54,3 +56,33 @@ def flatten_choices(choices):
yield from label_or_nested
else:
yield value_or_group, label_or_nested
def _normalize_decimal(d: Decimal) -> Decimal:
"""
Strips trailing zeros, e.g.
20.000 → 20
20.010 → 20.01
20.100 → 20.1
But unlike of Decimal.normalize(), 20.000 will not become 2e+1. Very small decimals might still be represented
in scientific notation when printed.
"""
normalized = d.normalize()
sign, digit, exponent = normalized.as_tuple()
if exponent > 0:
return normalized.quantize(1)
return normalized
class NormalizedDecimalField(DecimalField):
"""
Variant of DecimalField that never outputs the trailing zeros, so we always have normalized decimals internally.
Use this only for fields where the trailing zeros are pointless (e.g. percentages), not for monetary amounts.
"""
def from_db_value(self, value, expression, connection):
if value is not None:
value = _normalize_decimal(value)
return value