diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index c3dcf7accf..55229b0c53 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -165,7 +165,7 @@ def mark_order_refunded(order, user=None): @transaction.atomic -def _cancel_order(order, user=None): +def _cancel_order(order, user=None, send_mail: bool=True): """ Mark this order as canceled :param order: The order to change @@ -190,6 +190,21 @@ def _cancel_order(order, user=None): if position.voucher: Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=F('redeemed') - 1) + if send_mail: + with language(order.locale): + mail( + order.email, _('Order canceled: %(code)s') % {'code': order.code}, + order.event.settings.mail_text_order_canceled, + { + 'event': order.event.name, + 'code': order.code, + 'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={ + 'order': order.code, + 'secret': order.secret + }) + }, + order.event, locale=order.locale + ) return order.pk diff --git a/src/pretix/base/settings.py b/src/pretix/base/settings.py index 2c536d8a20..72187c8349 100644 --- a/src/pretix/base/settings.py +++ b/src/pretix/base/settings.py @@ -316,6 +316,18 @@ Please note that this link is only valid within the next {hours} hours! We will reassign the ticket to the next person on the list if you do not redeem the voucher within that timeframe. +Best regards, +Your {event} team""")) + }, + 'mail_text_order_canceled': { + 'type': LazyI18nString, + 'default': LazyI18nString.from_gettext(ugettext_noop("""Hello, + +your order {code} for {event} has been canceled. + +You can view the details 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 cde430b999..8ce3ca34df 100644 --- a/src/pretix/control/forms/event.py +++ b/src/pretix/control/forms/event.py @@ -558,6 +558,13 @@ class MailSettingsForm(SettingsForm): help_text=_("Available placeholders: {event}, {url}, {product}, {hours}, {code}"), validators=[PlaceholderValidator(['{event}', '{url}', '{product}', '{hours}', '{code}'])] ) + mail_text_order_canceled = I18nFormField( + label=_("Text"), + required=False, + widget=I18nTextarea, + help_text=_("Available placeholders: {event}, {code}, {url}"), + validators=[PlaceholderValidator(['{event}', '{code}', '{url}'])] + ) smtp_use_custom = forms.BooleanField( label=_("Use custom SMTP server"), help_text=_("All mail related to your event will be sent over the smtp server specified by you."), diff --git a/src/pretix/control/templates/pretixcontrol/event/mail.html b/src/pretix/control/templates/pretixcontrol/event/mail.html index 900cb038e0..30db5ae0c9 100644 --- a/src/pretix/control/templates/pretixcontrol/event/mail.html +++ b/src/pretix/control/templates/pretixcontrol/event/mail.html @@ -35,6 +35,10 @@ {% blocktrans asvar title_waiting_list_notification %}Waiting list notification{% endblocktrans %} {% include "pretixcontrol/event/mail_settings_fragment.html" with pid="waiting_list" title=title_waiting_list_notification items="mail_text_waiting_list" %} + + {% blocktrans asvar title_order_canceled %}Order canceled{% endblocktrans %} + {% include "pretixcontrol/event/mail_settings_fragment.html" with pid="order_canceled" title=title_order_canceled items="mail_text_order_canceled" %} +
diff --git a/src/pretix/control/views/event.py b/src/pretix/control/views/event.py index b76367d41d..1d0e602e95 100644 --- a/src/pretix/control/views/event.py +++ b/src/pretix/control/views/event.py @@ -439,7 +439,8 @@ class MailSettingsPreview(EventPermissionRequiredMixin, View): 'mail_text_resend_all_links': ['event', 'orders'], 'mail_text_order_changed': ['event', 'url', 'invoice_name', 'invoice_company'], 'mail_text_order_expire_warning': ['event', 'url', 'expire_date', 'invoice_name', 'invoice_company'], - 'mail_text_waiting_list': ['event', 'url', 'product', 'hours', 'code'] + 'mail_text_waiting_list': ['event', 'url', 'product', 'hours', 'code'], + 'mail_text_order_canceled': ['code', 'event', 'url'], } @cached_property diff --git a/src/pretix/locale/de/LC_MESSAGES/django.po b/src/pretix/locale/de/LC_MESSAGES/django.po index 87e410608b..ece9f9af35 100644 --- a/src/pretix/locale/de/LC_MESSAGES/django.po +++ b/src/pretix/locale/de/LC_MESSAGES/django.po @@ -4421,11 +4421,15 @@ msgstr "Zahlungserinnerung" msgid "Waiting list notification" msgstr "Wartelisten-Benachrichtigung" -#: pretix/control/templates/pretixcontrol/event/mail.html:41 +#: pretix/control/templates/pretixcontrol/event/mail.html:39 +msgid "Order canceled" +msgstr "Bestellung storniert" + +#: pretix/control/templates/pretixcontrol/event/mail.html:46 msgid "SMTP settings" msgstr "SMTP-Einstellungen" -#: pretix/control/templates/pretixcontrol/event/mail.html:55 +#: pretix/control/templates/pretixcontrol/event/mail.html:60 msgid "Save and test custom SMTP connection" msgstr "Speichern und SMTP-Einstellung testen" diff --git a/src/pretix/locale/de_Informal/LC_MESSAGES/django.po b/src/pretix/locale/de_Informal/LC_MESSAGES/django.po index e5b3d40d8c..38178cfa17 100644 --- a/src/pretix/locale/de_Informal/LC_MESSAGES/django.po +++ b/src/pretix/locale/de_Informal/LC_MESSAGES/django.po @@ -4411,11 +4411,15 @@ msgstr "Zahlungserinnerung" msgid "Waiting list notification" msgstr "Wartelisten-Benachrichtigung" -#: pretix/control/templates/pretixcontrol/event/mail.html:41 +#: pretix/control/templates/pretixcontrol/event/mail.html:39 +msgid "Order canceled" +msgstr "Bestellung storniert" + +#: pretix/control/templates/pretixcontrol/event/mail.html:46 msgid "SMTP settings" msgstr "SMTP-Einstellungen" -#: pretix/control/templates/pretixcontrol/event/mail.html:55 +#: pretix/control/templates/pretixcontrol/event/mail.html:60 msgid "Save and test custom SMTP connection" msgstr "Speichern und SMTP-Einstellung testen" diff --git a/src/tests/control/test_settings.py b/src/tests/control/test_settings.py index 043ebbec96..16f07f84a8 100644 --- a/src/tests/control/test_settings.py +++ b/src/tests/control/test_settings.py @@ -244,6 +244,19 @@ class MailSettingPreviewTest(SoupTest): assert len(res['msgs']) == 1 assert re.match('.*{.*}.*', res['msgs']['en']) is None + def test_mail_text_order_canceled(self): + text = '{event}{code}{url}' + response = self.client.post(self.target.format( + self.orga1.slug, self.event1.slug), { + 'item': 'mail_text_order_canceled', + 'mail_text_order_canceled_0': text + }) + assert response.status_code == 200 + res = json.loads(response.content.decode()) + assert res['item'] == 'mail_text_order_canceled' + assert len(res['msgs']) == 1 + assert re.match('.*{.*}.*', res['msgs']['en']) is None + def test_unsupported_placeholders(self): text = '{event1}' response = self.client.post(self.target.format(