Refs #99 -- Improve support for currencies with less than 2 decimal places (#783)

* Refs #99 -- Fix stripe support for zero-decimal currencies

* Add new money formatting method

* Force decimal places in many places

* Locale-aware currency rendering

* Fix currencies in more places

* More currency fixes
This commit is contained in:
Raphael Michel
2018-02-26 10:46:07 +01:00
committed by GitHub
parent 29e22a0c6c
commit 3c3e59e932
49 changed files with 467 additions and 211 deletions

View File

@@ -1,10 +1,11 @@
import logging
from collections import OrderedDict
from decimal import Decimal
from decimal import ROUND_HALF_UP, Decimal
from typing import Any, Dict, Union
import pytz
from django import forms
from django.conf import settings
from django.contrib import messages
from django.dispatch import receiver
from django.forms import Form
@@ -15,11 +16,11 @@ from django.utils.translation import pgettext_lazy, ugettext_lazy as _
from i18nfield.forms import I18nFormField, I18nTextarea
from i18nfield.strings import LazyI18nString
from pretix.base.decimal import round_decimal
from pretix.base.models import CartPosition, Event, Order, Quota
from pretix.base.reldate import RelativeDateField, RelativeDateWrapper
from pretix.base.settings import SettingsSandbox
from pretix.base.signals import register_payment_providers
from pretix.helpers.money import DecimalTextInput
from pretix.presale.views import get_cart_total
from pretix.presale.views.cart import get_or_create_cart_id
@@ -91,10 +92,15 @@ class BasePaymentProvider:
fee_abs = self.settings.get('_fee_abs', as_type=Decimal, default=0)
fee_percent = self.settings.get('_fee_percent', as_type=Decimal, default=0)
fee_reverse_calc = self.settings.get('_fee_reverse_calc', as_type=bool, default=True)
places = settings.CURRENCY_PLACES.get(self.event.currency, 2)
if fee_reverse_calc:
return round_decimal((price + fee_abs) * (1 / (1 - fee_percent / 100)) - price)
return ((price + fee_abs) * (1 / (1 - fee_percent / 100)) - price).quantize(
Decimal('1') / 10 ** places, ROUND_HALF_UP
)
else:
return round_decimal(price * fee_percent / 100) + fee_abs
return (price * fee_percent / 100 + fee_abs).quantize(
Decimal('1') / 10 ** places, ROUND_HALF_UP
)
@property
def verbose_name(self) -> str:
@@ -156,6 +162,7 @@ class BasePaymentProvider:
.. WARNING:: It is highly discouraged to alter the ``_enabled`` field of the default
implementation.
"""
places = settings.CURRENCY_PLACES.get(self.event.currency, 2)
return OrderedDict([
('_enabled',
forms.BooleanField(
@@ -166,7 +173,10 @@ class BasePaymentProvider:
forms.DecimalField(
label=_('Additional fee'),
help_text=_('Absolute value'),
required=False
localize=True,
required=False,
decimal_places=places,
widget=DecimalTextInput(places=places)
)),
('_fee_percent',
forms.DecimalField(
@@ -174,7 +184,8 @@ class BasePaymentProvider:
help_text=_('Percentage of the order total. Note that this percentage will currently only '
'be calculated on the summed price of sold tickets, not on other fees like e.g. shipping '
'fees, if there are any.'),
required=False
localize=True,
required=False,
)),
('_availability_date',
RelativeDateField(