diff --git a/src/pretix/base/templatetags/money.py b/src/pretix/base/templatetags/money.py index 7b3f649f3c..fe9ff7d4b5 100644 --- a/src/pretix/base/templatetags/money.py +++ b/src/pretix/base/templatetags/money.py @@ -48,11 +48,18 @@ def money_filter(value: Decimal, arg='', hide_currency=False): places = settings.CURRENCY_PLACES.get(arg, 2) rounded = value.quantize(Decimal('1') / 10 ** places, ROUND_HALF_UP) if places < 2 and rounded != value: - places = 2 + # We display decimal places even if we shouldn't for this currency if rounding + # would make the numbers incorrect. If this branch executes, it's likely a bug in + # pretix, but we won't show wrong numbers! + if hide_currency: + return floatformat(value, 2) + else: + return '{} {}'.format(arg, floatformat(value, 2)) + if hide_currency: return floatformat(value, places) - locale_parts = translation.get_language().split('-', 1) + locale_parts = translation.get_language().split("-", 1) locale = locale_parts[0] if len(locale_parts) > 1 and len(locale_parts[1]) == 2: try: @@ -61,20 +68,9 @@ def money_filter(value: Decimal, arg='', hide_currency=False): pass try: - if rounded != value: - # We display decimal places even if we shouldn't for this currency if rounding - # would make the numbers incorrect. If this branch executes, it's likely a bug in - # pretix, but we won't show wrong numbers! - return '{} {}'.format( - arg, - floatformat(value, 2) - ) return format_currency(value, arg, locale=locale) except: - return '{} {}'.format( - arg, - floatformat(value, places) - ) + return '{} {}'.format(arg, floatformat(value, places)) @register.filter("money_numberfield") diff --git a/src/tests/base/test_templatetag.py b/src/tests/base/test_templatetag.py index cf9cbeb6a2..13969cc0e6 100644 --- a/src/tests/base/test_templatetag.py +++ b/src/tests/base/test_templatetag.py @@ -19,34 +19,91 @@ # You should have received a copy of the GNU Affero General Public License along with this program. If not, see # . # +from decimal import Decimal + +import pytest from django.template import Context, Template from django.test import RequestFactory +from django.utils import translation -TEMPLATE_REPLACE_PAGE = Template("{% load urlreplace %}{% url_replace request 'page' 3 %}") +from pretix.base.templatetags.money import money_filter + +TEMPLATE_REPLACE_PAGE = Template( + "{% load urlreplace %}{% url_replace request 'page' 3 %}" +) +TEMPLATE_MONEY_FILTER = Template("{% load money %}{{ my_amount|money:my_currency }}") +NBSP = "\xa0" def test_urlreplace_add__first_parameter(): factory = RequestFactory() - request = factory.get('/customer/details') - rendered = TEMPLATE_REPLACE_PAGE.render(Context({ - 'request': request - })).strip() - assert rendered == 'page=3' + request = factory.get("/customer/details") + rendered = TEMPLATE_REPLACE_PAGE.render(Context({"request": request})).strip() + assert rendered == "page=3" def test_urlreplace_add_parameter(): factory = RequestFactory() - request = factory.get('/customer/details?foo=bar') - rendered = TEMPLATE_REPLACE_PAGE.render(Context({ - 'request': request - })).strip() - assert rendered in ('foo=bar&page=3', 'page=3&foo=bar') + request = factory.get("/customer/details?foo=bar") + rendered = TEMPLATE_REPLACE_PAGE.render(Context({"request": request})).strip() + assert rendered in ("foo=bar&page=3", "page=3&foo=bar") def test_urlreplace_replace_parameter(): factory = RequestFactory() - request = factory.get('/customer/details?page=15') - rendered = TEMPLATE_REPLACE_PAGE.render(Context({ - 'request': request - })).strip() - assert rendered == 'page=3' + request = factory.get("/customer/details?page=15") + rendered = TEMPLATE_REPLACE_PAGE.render(Context({"request": request})).strip() + assert rendered == "page=3" + + +@pytest.mark.parametrize( + "locale,amount,currency,expected", + [ + ("en", None, "USD", "$0.00"), + ("en", 1000000, "USD", "$1,000,000.00"), + ("en", Decimal("1000.00"), "USD", "$1,000.00"), + ("de", Decimal("1.23"), "EUR", "1,23" + NBSP + "€"), + ("de", Decimal("1000.00"), "EUR", "1.000,00" + NBSP + "€"), + ("de", Decimal("1023"), "JPY", "1.023" + NBSP + "¥"), + + ("en", Decimal("1023"), "JPY", "¥1,023"), + + ("pt-pt", Decimal("10.00"), "EUR", "10,00" + NBSP + "€"), + ("pt-br", Decimal("10.00"), "EUR", "€" + NBSP + "10,00"), + + # unknown currency + ("de", Decimal("1234.56"), "FOO", "1.234,56" + NBSP + "FOO"), + ("de", Decimal("1234.567"), "FOO", "1.234,57" + NBSP + "FOO"), + + # rounding errors + ("de", Decimal("1.234"), "EUR", "1,23" + NBSP + "€"), + ("de", Decimal("1023.1"), "JPY", "JPY 1023,10"), + ] +) +def test_money_filter(locale, amount, currency, expected): + factory = RequestFactory() + translation.activate(locale) + request = factory.get("/foo/bar") + rendered = TEMPLATE_MONEY_FILTER.render( + Context( + { + "request": request, + "my_amount": amount, + "my_currency": currency, + } + ) + ).strip() + assert rendered == expected + + +@pytest.mark.parametrize( + "locale,amount,currency,expected", + [ + ("de", Decimal("1000.00"), "EUR", "1000,00"), + ("en", Decimal("1000.00"), "EUR", "1000.00"), + ("de", Decimal("1023.1"), "JPY", "1023,10"), + ] +) +def test_money_filter_hidecurrency(locale, amount, currency, expected): + translation.activate(locale) + assert money_filter(amount, currency, hide_currency=True) == expected