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

@@ -666,10 +666,10 @@ class MailSettingsForm(SettingsForm):
label=_("Text"),
required=False,
widget=I18nTextarea,
help_text=_("Available placeholders: {event}, {total}, {currency}, {date}, {payment_info}, {url}, "
"{invoice_name}, {invoice_company}"),
validators=[PlaceholderValidator(['{event}', '{total}', '{currency}', '{date}', '{payment_info}',
'{url}', '{invoice_name}', '{invoice_company}'])]
help_text=_("Available placeholders: {event}, {total_with_currency}, {total}, {currency}, {date}, "
"{payment_info}, {url}, {invoice_name}, {invoice_company}"),
validators=[PlaceholderValidator(['{event}', '{total_with_currency}', '{total}', '{currency}', '{date}',
'{payment_info}', '{url}', '{invoice_name}', '{invoice_company}'])]
)
mail_text_order_paid = I18nFormField(
label=_("Text"),

View File

@@ -17,6 +17,7 @@ from pretix.base.models import (
from pretix.base.models.items import ItemAddOn
from pretix.control.forms import SplitDateTimePickerWidget
from pretix.control.forms.widgets import Select2
from pretix.helpers.money import change_decimal_field
class CategoryForm(I18nModelForm):
@@ -159,6 +160,7 @@ class ItemCreateForm(I18nModelForm):
self.fields['category'].queryset = self.instance.event.categories.all()
self.fields['tax_rule'].queryset = self.instance.event.tax_rules.all()
change_decimal_field(self.fields['default_price'], self.instance.event.currency)
self.fields['tax_rule'].empty_label = _('No taxation')
self.fields['copy_from'] = forms.ModelChoiceField(
label=_("Copy product information"),
@@ -292,6 +294,7 @@ class ItemUpdateForm(I18nModelForm):
'over 65. This ticket includes access to all parts of the event, except the VIP '
'area.'
)
change_decimal_field(self.fields['default_price'], self.event.currency)
class Meta:
model = Item
@@ -345,8 +348,29 @@ class ItemVariationsFormSet(I18nFormSet):
return False
return form.cleaned_data.get(DELETION_FIELD_NAME, False)
def _construct_form(self, i, **kwargs):
kwargs['event'] = self.event
return super()._construct_form(i, **kwargs)
@property
def empty_form(self):
self.is_valid()
form = self.form(
auto_id=self.auto_id,
prefix=self.add_prefix('__prefix__'),
empty_permitted=True,
locales=self.locales,
event=self.event
)
self.add_fields(form, None)
return form
class ItemVariationForm(I18nModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
change_decimal_field(self.fields['default_price'], self.event.currency)
class Meta:
model = ItemVariation
localized_fields = '__all__'
@@ -399,7 +423,6 @@ class ItemAddOnsFormSet(I18nFormSet):
class ItemAddOnForm(I18nModelForm):
def __init__(self, *args, **kwargs):
self.event = kwargs.pop('event')
super().__init__(*args, **kwargs)
self.fields['addon_category'].queryset = self.event.categories.all()

View File

@@ -2,7 +2,6 @@ from django import forms
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.formats import localize
from django.utils.timezone import now
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
@@ -12,6 +11,8 @@ from pretix.base.models import (
)
from pretix.base.models.event import SubEvent
from pretix.base.services.pricing import get_price
from pretix.base.templatetags.money import money_filter
from pretix.helpers.money import change_decimal_field
class ExtendForm(I18nModelForm):
@@ -76,8 +77,8 @@ class SubEventChoiceField(forms.ModelChoiceField):
p = get_price(self.instance.item, self.instance.variation,
voucher=self.instance.voucher,
subevent=obj)
return '{} {} ({} {})'.format(obj.name, obj.get_date_range_display(),
p, self.instance.order.event.currency)
return '{} {} ({})'.format(obj.name, obj.get_date_range_display(),
money_filter(p, self.instance.order.event.currency))
class OtherOperationsForm(forms.Form):
@@ -120,6 +121,7 @@ class OrderPositionAddForm(forms.Form):
price = forms.DecimalField(
required=False,
max_digits=10, decimal_places=2,
localize=True,
label=_('Gross price'),
help_text=_("Including taxes, if any. Keep empty for the product's default price")
)
@@ -149,10 +151,10 @@ class OrderPositionAddForm(forms.Form):
for v in variations:
p = get_price(i, v, invoice_address=ia)
choices.append(('%d-%d' % (i.pk, v.pk),
'%s %s (%s %s)' % (pname, v.value, p, order.event.currency)))
'%s %s (%s)' % (pname, v.value, p.print(order.event.currency))))
else:
p = get_price(i, invoice_address=ia)
choices.append((str(i.pk), '%s (%s %s)' % (pname, p, order.event.currency)))
choices.append((str(i.pk), '%s (%s)' % (pname, p.print(order.event.currency))))
self.fields['itemvar'].choices = choices
if ItemAddOn.objects.filter(base_item__event=order.event).exists():
self.fields['addon_to'].queryset = order.positions.filter(addon_to__isnull=True).select_related(
@@ -165,6 +167,7 @@ class OrderPositionAddForm(forms.Form):
self.fields['subevent'].queryset = order.event.subevents.all()
else:
del self.fields['subevent']
change_decimal_field(self.fields['price'], order.event.currency)
class OrderPositionChangeForm(forms.Form):
@@ -178,6 +181,7 @@ class OrderPositionChangeForm(forms.Form):
price = forms.DecimalField(
required=False,
max_digits=10, decimal_places=2,
localize=True,
label=_('New price (gross)')
)
operation = forms.ChoiceField(
@@ -236,14 +240,13 @@ class OrderPositionChangeForm(forms.Form):
p = get_price(i, v, voucher=instance.voucher, subevent=instance.subevent,
invoice_address=ia)
choices.append(('%d-%d' % (i.pk, v.pk),
'%s %s (%s %s)' % (pname, v.value, localize(p),
instance.order.event.currency)))
'%s %s (%s)' % (pname, v.value, p.print(instance.order.event.currency))))
else:
p = get_price(i, None, voucher=instance.voucher, subevent=instance.subevent,
invoice_address=ia)
choices.append((str(i.pk), '%s (%s %s)' % (pname, localize(p),
instance.order.event.currency)))
choices.append((str(i.pk), '%s (%s)' % (pname, p.print(instance.order.event.currency))))
self.fields['itemvar'].choices = choices
change_decimal_field(self.fields['price'], instance.order.event.currency)
def clean(self):
if self.cleaned_data.get('operation') == 'price' and not self.cleaned_data.get('price', '') != '':

View File

@@ -5,7 +5,9 @@ from i18nfield.forms import I18nInlineFormSet
from pretix.base.forms import I18nModelForm
from pretix.base.models.event import SubEvent, SubEventMetaValue
from pretix.base.models.items import SubEventItem
from pretix.base.templatetags.money import money_filter
from pretix.control.forms import SplitDateTimePickerWidget
from pretix.helpers.money import change_decimal_field
class SubEventForm(I18nModelForm):
@@ -49,32 +51,35 @@ class SubEventItemOrVariationFormMixin:
self.item = kwargs.pop('item')
self.variation = kwargs.pop('variation', None)
super().__init__(*args, **kwargs)
change_decimal_field(self.fields['price'], self.item.event.currency)
class SubEventItemForm(SubEventItemOrVariationFormMixin, forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['price'].widget.attrs['placeholder'] = '{} {}'.format(
self.item.default_price, self.item.event.currency
)
self.fields['price'].widget.attrs['placeholder'] = money_filter(self.item.default_price, self.item.event.currency, hide_currency=True)
self.fields['price'].label = str(self.item.name)
class Meta:
model = SubEventItem
fields = ['price']
widgets = {
'price': forms.TextInput
}
class SubEventItemVariationForm(SubEventItemOrVariationFormMixin, forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['price'].widget.attrs['placeholder'] = '{} {}'.format(
self.variation.price, self.item.event.currency
)
self.fields['price'].widget.attrs['placeholder'] = money_filter(self.variation.price, self.item.event.currency, hide_currency=True)
self.fields['price'].label = '{} {}'.format(str(self.item.name), self.variation.value)
class Meta:
model = SubEventItem
fields = ['price']
widgets = {
'price': forms.TextInput
}
class QuotaFormSet(I18nInlineFormSet):

View File

@@ -4,7 +4,6 @@ from decimal import Decimal
import dateutil.parser
import pytz
from django.dispatch import receiver
from django.utils import formats
from django.utils.formats import date_format
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
from i18nfield.strings import LazyI18nString
@@ -13,6 +12,7 @@ from pretix.base.models import (
CheckinList, Event, ItemVariation, LogEntry, OrderPosition,
)
from pretix.base.signals import logentry_display
from pretix.base.templatetags.money import money_filter
OVERVIEW_BLACKLIST = [
'pretix.plugins.sendmail.order.email.sent'
@@ -30,42 +30,38 @@ def _display_order_changed(event: Event, logentry: LogEntry):
new_item = str(event.items.get(pk=data['new_item']))
if data['new_variation']:
new_item += ' - ' + str(ItemVariation.objects.get(item__event=event, pk=data['new_variation']))
return text + ' ' + _('Position #{posid}: {old_item} ({old_price} {currency}) changed '
'to {new_item} ({new_price} {currency}).').format(
return text + ' ' + _('Position #{posid}: {old_item} ({old_price}) changed '
'to {new_item} ({new_price}).').format(
posid=data.get('positionid', '?'),
old_item=old_item, new_item=new_item,
old_price=formats.localize(Decimal(data['old_price'])),
new_price=formats.localize(Decimal(data['new_price'])),
currency=event.currency
old_price=money_filter(Decimal(data['old_price']), event.currency),
new_price=money_filter(Decimal(data['new_price']), event.currency),
)
elif logentry.action_type == 'pretix.event.order.changed.subevent':
old_se = str(event.subevents.get(pk=data['old_subevent']))
new_se = str(event.subevents.get(pk=data['new_subevent']))
return text + ' ' + _('Position #{posid}: Event date "{old_event}" ({old_price} {currency}) changed '
'to "{new_event}" ({new_price} {currency}).').format(
return text + ' ' + _('Position #{posid}: Event date "{old_event}" ({old_price}) changed '
'to "{new_event}" ({new_price}).').format(
posid=data.get('positionid', '?'),
old_event=old_se, new_event=new_se,
old_price=formats.localize(Decimal(data['old_price'])),
new_price=formats.localize(Decimal(data['new_price'])),
currency=event.currency
old_price=money_filter(Decimal(data['old_price']), event.currency),
new_price=money_filter(Decimal(data['new_price']), event.currency),
)
elif logentry.action_type == 'pretix.event.order.changed.price':
return text + ' ' + _('Price of position #{posid} changed from {old_price} {currency} '
'to {new_price} {currency}.').format(
return text + ' ' + _('Price of position #{posid} changed from {old_price} '
'to {new_price}.').format(
posid=data.get('positionid', '?'),
old_price=formats.localize(Decimal(data['old_price'])),
new_price=formats.localize(Decimal(data['new_price'])),
currency=event.currency
old_price=money_filter(Decimal(data['old_price']), event.currency),
new_price=money_filter(Decimal(data['new_price']), event.currency),
)
elif logentry.action_type == 'pretix.event.order.changed.cancel':
old_item = str(event.items.get(pk=data['old_item']))
if data['old_variation']:
old_item += ' - ' + str(ItemVariation.objects.get(pk=data['old_variation']))
return text + ' ' + _('Position #{posid} ({old_item}, {old_price} {currency}) removed.').format(
return text + ' ' + _('Position #{posid} ({old_item}, {old_price}) removed.').format(
posid=data.get('positionid', '?'),
old_item=old_item,
old_price=formats.localize(Decimal(data['old_price'])),
currency=event.currency
old_price=money_filter(Decimal(data['old_price']), event.currency),
)
elif logentry.action_type == 'pretix.event.order.changed.add':
item = str(event.items.get(pk=data['item']))
@@ -73,30 +69,27 @@ def _display_order_changed(event: Event, logentry: LogEntry):
item += ' - ' + str(ItemVariation.objects.get(item__event=event, pk=data['variation']))
if data['addon_to']:
addon_to = OrderPosition.objects.get(order__event=event, pk=data['addon_to'])
return text + ' ' + _('Position #{posid} created: {item} ({price} {currency}) as an add-on to '
return text + ' ' + _('Position #{posid} created: {item} ({price}) as an add-on to '
'position #{addon_to}.').format(
posid=data.get('positionid', '?'),
item=item, addon_to=addon_to.positionid,
price=formats.localize(Decimal(data['price'])),
currency=event.currency
price=money_filter(Decimal(data['price']), event.currency),
)
else:
return text + ' ' + _('Position #{posid} created: {item} ({price} {currency}).').format(
return text + ' ' + _('Position #{posid} created: {item} ({price}).').format(
posid=data.get('positionid', '?'),
item=item,
price=formats.localize(Decimal(data['price'])),
currency=event.currency
price=money_filter(Decimal(data['price']), event.currency),
)
elif logentry.action_type == 'pretix.event.order.changed.split':
old_item = str(event.items.get(pk=data['old_item']))
if data['old_variation']:
old_item += ' - ' + str(ItemVariation.objects.get(pk=data['old_variation']))
return text + ' ' + _('Position #{posid} ({old_item}, {old_price} {currency}) split into new order: {order}').format(
return text + ' ' + _('Position #{posid} ({old_item}, {old_price}) split into new order: {order}').format(
old_item=old_item,
posid=data.get('positionid', '?'),
order=data['new_order'],
old_price=formats.localize(Decimal(data['old_price'])),
currency=event.currency
old_price=money_filter(Decimal(data['old_price']), event.currency),
)
elif logentry.action_type == 'pretix.event.order.changed.split_from':
return _('This order has been created by splitting the order {order}').format(

View File

@@ -2,6 +2,7 @@
{% load i18n %}
{% load bootstrap3 %}
{% load eventurl %}
{% load money %}
{% load safelink %}
{% load eventsignal %}
{% block title %}
@@ -257,7 +258,7 @@
</div>
<div class="col-md-3 col-xs-6 price">
{% if event.settings.display_net_prices %}
<strong>{{ event.currency }} {{ line.net_price|floatformat:2 }}</strong>
<strong>{{ line.net_price|money:event.currency }}</strong>
{% if line.tax_rate %}
<br />
<small>
@@ -267,7 +268,7 @@
</small>
{% endif %}
{% else %}
<strong>{{ event.currency }} {{ line.price|floatformat:2 }}</strong>
<strong>{{ line.price|money:event.currency }}</strong>
{% if line.tax_rate and line.price %}
<br />
<small>
@@ -291,7 +292,7 @@
</div>
<div class="col-md-3 col-xs-6 col-md-offset-5 price">
{% if event.settings.display_net_prices %}
<strong>{{ event.currency }} {{ fee.net_value|floatformat:2 }}</strong>
<strong>{{ fee.net_value|money:event.currency }}</strong>
{% if fee.tax_rate %}
<br/>
<small>
@@ -301,7 +302,7 @@
</small>
{% endif %}
{% else %}
<strong>{{ event.currency }} {{ fee.value|floatformat:2 }}</strong>
<strong>{{ fee.value|money:event.currency }}</strong>
{% if fee.tax_rate %}
<br/>
<small>
@@ -321,7 +322,7 @@
<strong>{% trans "Net total" %}</strong>
</div>
<div class="col-md-3 col-xs-6 col-md-offset-5 price">
{{ event.currency }} {{ items.net_total|floatformat:2 }}
{{ items.net_total|money:event.currency }}
</div>
<div class="clearfix"></div>
</div>
@@ -330,7 +331,7 @@
<strong>{% trans "Taxes" %}</strong>
</div>
<div class="col-md-3 col-xs-6 col-md-offset-5 price">
{{ event.currency }} {{ items.tax_total|floatformat:2 }}
{{ items.tax_total|money:event.currency }}
</div>
<div class="clearfix"></div>
</div>
@@ -340,7 +341,7 @@
<strong>{% trans "Total" %}</strong>
</div>
<div class="col-md-3 col-xs-6 col-md-offset-5 price">
<strong>{{ event.currency }} {{ items.total|floatformat:2 }}</strong>
<strong>{{ items.total|money:event.currency }}</strong>
</div>
<div class="clearfix"></div>
</div>

View File

@@ -2,6 +2,7 @@
{% load i18n %}
{% load eventurl %}
{% load urlreplace %}
{% load money %}
{% load bootstrap3 %}
{% block title %}{% trans "Orders" %}{% endblock %}
{% block content %}
@@ -114,7 +115,7 @@
{% endif %}
</td>
<td>{{ o.datetime|date:"SHORT_DATETIME_FORMAT" }}</td>
<td class="text-right">{{ o.total|floatformat:2 }} {{ request.event.currency }}</td>
<td class="text-right">{{ o.total|money:request.event.currency }}</td>
<td class="text-right">{{ o.pcnt }}</td>
<td class="text-right">{% include "pretixcontrol/orders/fragment_order_status.html" with order=o %}</td>
</tr>

View File

@@ -50,12 +50,12 @@
{% if tup.0 %}
<tr class="category">
<th>{{ tup.0.name }}</th>
<th>{{ tup.0.num_canceled|togglesum }}</th>
<th>{{ tup.0.num_refunded|togglesum }}</th>
<th>{{ tup.0.num_expired|togglesum }}</th>
<th>{{ tup.0.num_pending|togglesum }}</th>
<th>{{ tup.0.num_paid|togglesum }}</th>
<th>{{ tup.0.num_total|togglesum }}</th>
<th>{{ tup.0.num_canceled|togglesum:request.event.currency }}</th>
<th>{{ tup.0.num_refunded|togglesum:request.event.currency }}</th>
<th>{{ tup.0.num_expired|togglesum:request.event.currency }}</th>
<th>{{ tup.0.num_pending|togglesum:request.event.currency }}</th>
<th>{{ tup.0.num_paid|togglesum:request.event.currency }}</th>
<th>{{ tup.0.num_total|togglesum:request.event.currency }}</th>
</tr>
{% endif %}
{% for item in tup.1 %}
@@ -63,43 +63,43 @@
<td>{{ item.name }}</td>
<td>
<a href="{{ listurl }}?item={{ item.id }}&amp;status=c&amp;provider={{ item.provider }}">
{{ item.num_canceled|togglesum }}
{{ item.num_canceled|togglesum:request.event.currency }}
</a>
</td>
<td>
<a href="{{ listurl }}?item={{ item.id }}&amp;status=r&amp;provider={{ item.provider }}">
{{ item.num_refunded|togglesum }}
{{ item.num_refunded|togglesum:request.event.currency }}
</a>
</td>
<td>
<a href="{{ listurl }}?item={{ item.id }}&amp;status=e&amp;provider={{ item.provider }}">
{{ item.num_expired|togglesum }}
{{ item.num_expired|togglesum:request.event.currency }}
</a>
</td>
<td>
<a href="{{ listurl }}?item={{ item.id }}&amp;status=n&amp;provider={{ item.provider }}">
{{ item.num_pending|togglesum }}
{{ item.num_pending|togglesum:request.event.currency }}
</a>
</td>
<td>
<a href="{{ listurl }}?item={{ item.id }}&amp;status=p&amp;provider={{ item.provider }}">
{{ item.num_paid|togglesum }}
{{ item.num_paid|togglesum:request.event.currency }}
</a>
</td>
<td>
{{ item.num_total|togglesum }}
{{ item.num_total|togglesum:request.event.currency }}
</td>
</tr>
{% if item.has_variations %}
{% for var in item.all_variations %}
<tr class="variation {% if tup.0 %}categorized{% endif %}">
<td>{{ var }}</td>
<td>{{ var.num_canceled|togglesum }}</td>
<td>{{ var.num_refunded|togglesum }}</td>
<td>{{ var.num_expired|togglesum }}</td>
<td>{{ var.num_pending|togglesum }}</td>
<td>{{ var.num_paid|togglesum }}</td>
<td>{{ var.num_total|togglesum }}</td>
<td>{{ var.num_canceled|togglesum:request.event.currency }}</td>
<td>{{ var.num_refunded|togglesum:request.event.currency }}</td>
<td>{{ var.num_expired|togglesum:request.event.currency }}</td>
<td>{{ var.num_pending|togglesum:request.event.currency }}</td>
<td>{{ var.num_paid|togglesum:request.event.currency }}</td>
<td>{{ var.num_total|togglesum:request.event.currency }}</td>
</tr>
{% endfor %}
{% endif %}
@@ -109,12 +109,12 @@
<tfoot>
<tr class="total">
<th>{% trans "Total" %}</th>
<th>{{ total.num_canceled|togglesum }}</th>
<th>{{ total.num_refunded|togglesum }}</th>
<th>{{ total.num_expired|togglesum }}</th>
<th>{{ total.num_pending|togglesum }}</th>
<th>{{ total.num_paid|togglesum }}</th>
<th>{{ total.num_total|togglesum }}</th>
<th>{{ total.num_canceled|togglesum:request.event.currency }}</th>
<th>{{ total.num_refunded|togglesum:request.event.currency }}</th>
<th>{{ total.num_expired|togglesum:request.event.currency }}</th>
<th>{{ total.num_pending|togglesum:request.event.currency }}</th>
<th>{{ total.num_paid|togglesum:request.event.currency }}</th>
<th>{{ total.num_total|togglesum:request.event.currency }}</th>
</tr>
</tfoot>
</table>

View File

@@ -2,6 +2,7 @@
{% load i18n %}
{% load eventurl %}
{% load urlreplace %}
{% load money %}
{% load bootstrap3 %}
{% block title %}{% trans "Order search" %}{% endblock %}
{% block content %}
@@ -70,7 +71,7 @@
{% endif %}
</td>
<td>{{ o.datetime|date:"SHORT_DATETIME_FORMAT" }}</td>
<td class="text-right">{{ o.total|floatformat:2 }} {{ o.event.currency }}</td>
<td class="text-right">{{ o.total|money:o.event.currency }}</td>
<td class="text-right">{% include "pretixcontrol/orders/fragment_order_status.html" with order=o %}</td>
</tr>
{% empty %}

View File

@@ -120,7 +120,7 @@
<fieldset>
<legend>{% trans "Item prices" %}</legend>
{% for f in itemvar_forms %}
{% bootstrap_field f.price layout="control" %}
{% bootstrap_field f.price addon_after=request.event.currency layout="control" %}
{% endfor %}
</fieldset>
<fieldset>

View File

@@ -1,6 +1,7 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load eventurl %}
{% load money %}
{% load urlreplace %}
{% block title %}{% trans "Waiting list" %}{% endblock %}
{% block content %}
@@ -65,9 +66,9 @@
{% trans "Sales estimate" %}
</div>
<div class="panel-body">
{% blocktrans trimmed with amount=estimate|default:0|floatformat:2 currency=request.event.currency %}
{% blocktrans trimmed with amount=estimate|default:0|money:request.event.currency %}
If you can make enough room at your event to fit all the persons on the waiting list in, you
could sell tickets worth an additional <strong>{{ amount }} {{ currency }}</strong>.
could sell tickets worth an additional <strong>{{ amount }}</strong>.
{% endblocktrans %}
</div>
</div>

View File

@@ -1,5 +1,6 @@
from django import template
from django.utils import formats
from django.conf import settings
from django.template.defaultfilters import floatformat
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
@@ -7,7 +8,7 @@ register = template.Library()
@register.filter(name='togglesum', needs_autoescape=True)
def cut(value, autoescape=True):
def togglesum_filter(value, arg='EUR', autoescape=True):
def noop(x):
return x
@@ -17,6 +18,10 @@ def cut(value, autoescape=True):
esc = conditional_escape
else:
esc = noop
places = settings.CURRENCY_PLACES.get(arg, 2)
return mark_safe('<span class="count">{0}</span><span class="sum-gross">{1}</span><span class="sum-net">{2}</span>'.format(
esc(value[0]), esc(formats.localize(value[1])), esc(formats.localize(value[2]))
esc(value[0]),
esc(floatformat(value[1], places)),
esc(floatformat(value[2], places))
))

View File

@@ -1,6 +1,7 @@
import re
from collections import OrderedDict
from datetime import timedelta
from decimal import Decimal
from urllib.parse import urlsplit
from django.conf import settings
@@ -26,6 +27,7 @@ from django.views.generic.detail import SingleObjectMixin
from i18nfield.strings import LazyI18nString
from pytz import timezone
from pretix.base.i18n import LazyCurrencyNumber
from pretix.base.models import (
CachedCombinedTicket, CachedTicket, Event, Item, ItemVariation, LogEntry,
Order, RequiredAction, TaxRule, Voucher,
@@ -34,6 +36,7 @@ from pretix.base.models.event import EventMetaValue
from pretix.base.services import tickets
from pretix.base.services.invoices import build_preview_invoice_pdf
from pretix.base.signals import event_live_issues, register_ticket_outputs
from pretix.base.templatetags.money import money_filter
from pretix.control.forms.event import (
CommentForm, DisplaySettingsForm, EventDeleteForm, EventMetaValueForm,
EventSettingsForm, EventUpdateForm, InvoiceSettingsForm, MailSettingsForm,
@@ -492,8 +495,8 @@ class MailSettingsPreview(EventPermissionRequiredMixin, View):
return {
'date': date_format(now() + timedelta(days=7), 'SHORT_DATE_FORMAT'),
'expire_date': date_format(now() + timedelta(days=15), 'SHORT_DATE_FORMAT'),
'payment_info': _('{} {} has been transferred to account <9999-9999-9999-9999> at {}').format(
42.23, self.request.event.currency, date_format(now(), 'SHORT_DATETIME_FORMAT'))
'payment_info': _('{} has been transferred to account <9999-9999-9999-9999> at {}').format(
money_filter(Decimal('42.23'), self.request.event.currency), date_format(now(), 'SHORT_DATETIME_FORMAT'))
}
# create index-language mapping
@@ -508,7 +511,7 @@ class MailSettingsPreview(EventPermissionRequiredMixin, View):
@cached_property
def items(self):
return {
'mail_text_order_placed': ['total', 'currency', 'date', 'invoice_company',
'mail_text_order_placed': ['total', 'currency', 'date', 'invoice_company', 'total_with_currency',
'event', 'payment_info', 'url', 'invoice_name'],
'mail_text_order_paid': ['event', 'url', 'invoice_name', 'invoice_company', 'payment_info'],
'mail_text_order_free': ['event', 'url', 'invoice_name', 'invoice_company'],
@@ -536,6 +539,7 @@ class MailSettingsPreview(EventPermissionRequiredMixin, View):
return {
'event': self.request.event.name,
'total': 42.23,
'total_with_currency': LazyCurrencyNumber(42.23, self.request.event.currency),
'currency': self.request.event.currency,
'url': self.generate_order_url(user_orders[0]['code'], user_orders[0]['secret']),
'orders': '\n'.join(orders),