diff --git a/src/pretix/base/payment.py b/src/pretix/base/payment.py index 83ec8c7719..0de8c9ee91 100644 --- a/src/pretix/base/payment.py +++ b/src/pretix/base/payment.py @@ -431,7 +431,7 @@ class FreeOrderProvider(BasePaymentProvider): def payment_perform(self, request: HttpRequest, order: Order): from pretix.base.services.orders import mark_order_paid try: - mark_order_paid(order, 'free') + mark_order_paid(order, 'free', send_mail=False) except Quota.QuotaExceededException as e: messages.error(request, str(e)) diff --git a/src/pretix/base/services/invoices.py b/src/pretix/base/services/invoices.py index 8083196c95..b2553f4db1 100644 --- a/src/pretix/base/services/invoices.py +++ b/src/pretix/base/services/invoices.py @@ -325,6 +325,12 @@ def invoice_pdf(invoice: int): return i.file.name +def invoice_qualified(order: Order): + if order.total == Decimal('0.00'): + return False + return True + + if settings.HAS_CELERY: from pretix.celery import app diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index 4d64234445..de75f3af2e 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -1,4 +1,5 @@ from datetime import datetime, timedelta +from decimal import Decimal from django.conf import settings from django.db import transaction @@ -16,7 +17,7 @@ from pretix.base.models import ( from pretix.base.models.orders import InvoiceAddress from pretix.base.payment import BasePaymentProvider from pretix.base.services.invoices import ( - generate_cancellation, generate_invoice, + generate_cancellation, generate_invoice, invoice_qualified, ) from pretix.base.services.mail import mail from pretix.base.signals import ( @@ -46,7 +47,7 @@ error_messages = { def mark_order_paid(order: Order, provider: str=None, info: str=None, date: datetime=None, manual: bool=None, - force: bool=False, user: User=None) -> Order: + force: bool=False, send_mail: bool=True, user: User=None) -> Order: """ Marks an order as paid. This sets the payment provider, info and date and returns the order object. @@ -61,6 +62,8 @@ def mark_order_paid(order: Order, provider: str=None, info: str=None, date: date :param force: Whether this payment should be marked as paid even if no remaining quota is available (default: ``False``). :type force: boolean + :param send_mail: Whether an email should be sent to the user about this event (default: ``True``). + :type send_mail: boolean :param user: The user that performed the change :raises Quota.QuotaExceededException: if the quota is exceeded and ``force`` is ``False`` """ @@ -85,20 +88,21 @@ def mark_order_paid(order: Order, provider: str=None, info: str=None, date: date }, user=user) order_paid.send(order.event, order=order) - with language(order.locale): - mail( - order.email, _('Payment received for your order: %(code)s') % {'code': order.code}, - order.event.settings.mail_text_order_paid, - { - 'event': order.event.name, - 'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={ - 'order': order.code, - 'secret': order.secret - }), - 'downloads': order.event.settings.get('ticket_download', as_type=bool) - }, - order.event, locale=order.locale - ) + if send_mail: + with language(order.locale): + mail( + order.email, _('Payment received for your order: %(code)s') % {'code': order.code}, + order.event.settings.mail_text_order_paid, + { + 'event': order.event.name, + 'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={ + 'order': order.code, + 'secret': order.secret + }), + 'downloads': order.event.settings.get('ticket_download', as_type=bool) + }, + order.event, locale=order.locale + ) return order @@ -289,13 +293,17 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str], except InvoiceAddress.DoesNotExist: pass - if event.settings.get('invoice_generate') == 'True': + if event.settings.get('invoice_generate') == 'True' and invoice_qualified(order): generate_invoice(order) with language(order.locale): + if order.total == Decimal('0.00'): + mailtext = event.settings.mail_text_order_free + else: + mailtext = event.settings.mail_text_order_placed mail( order.email, _('Your order: %(code)s') % {'code': order.code}, - event.settings.mail_text_order_placed, + mailtext, { 'total': LazyNumber(order.total), 'currency': event.currency, diff --git a/src/pretix/base/settings.py b/src/pretix/base/settings.py index 94b0a2949c..c48e21bb74 100644 --- a/src/pretix/base/settings.py +++ b/src/pretix/base/settings.py @@ -147,6 +147,19 @@ to your order for {event}. You can change your order details and view the status of your order at {url} +Best regards, +Your {event} team""")) + }, + 'mail_text_order_free': { + 'type': LazyI18nString, + 'default': LazyI18nString.from_gettext(ugettext_noop("""Hello, + +we successfully received your order for {event}. As you only ordered +free products, no payment is required. + +You can change your order details and view the status of your order at +{url} + Best regards, Your {event} team""")) }, diff --git a/src/pretix/control/forms/event.py b/src/pretix/control/forms/event.py index ba0b0dff4a..a884a7c434 100644 --- a/src/pretix/control/forms/event.py +++ b/src/pretix/control/forms/event.py @@ -298,6 +298,12 @@ class MailSettingsForm(SettingsForm): widget=I18nTextarea, help_text=_("Available placeholders: {event}, {url}") ) + mail_text_order_free = I18nFormField( + label=_("Free order"), + required=False, + widget=I18nTextarea, + help_text=_("Available placeholders: {event}, {url}") + ) mail_text_resend_link = I18nFormField( label=_("Resend link"), required=False, diff --git a/src/pretix/control/templates/pretixcontrol/order/index.html b/src/pretix/control/templates/pretixcontrol/order/index.html index 86d9991cf1..da137ac199 100644 --- a/src/pretix/control/templates/pretixcontrol/order/index.html +++ b/src/pretix/control/templates/pretixcontrol/order/index.html @@ -110,7 +110,7 @@ {% endif %} {% endfor %} - {% elif request.event.settings.invoice_generate == 'admin' or request.event.settings.invoice_generate == 'user' %} + {% elif can_generate_invoice %}