Cancelling events: Allow to inform waiting list

This commit is contained in:
Raphael Michel
2020-03-05 10:22:59 +01:00
parent 447b6b7fee
commit 9b50ec2d74
5 changed files with 101 additions and 5 deletions

View File

@@ -12,9 +12,10 @@ from pretix.base.email import get_email_context
from pretix.base.i18n import language
from pretix.base.models import (
Event, InvoiceAddress, Order, OrderFee, OrderPosition, SubEvent, User,
WaitingListEntry,
)
from pretix.base.services.locking import LockTimeoutException
from pretix.base.services.mail import SendMailException, TolerantDict
from pretix.base.services.mail import SendMailException, TolerantDict, mail
from pretix.base.services.orders import (
OrderChangeManager, OrderError, _cancel_order, _try_auto_refund,
)
@@ -24,6 +25,22 @@ from pretix.celery_app import app
logger = logging.getLogger(__name__)
def _send_wle_mail(wle: WaitingListEntry, subject: LazyI18nString, message: LazyI18nString, subevent: SubEvent):
with language(wle.locale):
email_context = get_email_context(event_or_subevent=subevent or wle.event, event=wle.event)
try:
mail(
wle.email,
str(subject).format_map(TolerantDict(email_context)),
message,
email_context,
wle.event,
locale=wle.locale
)
except SendMailException:
logger.exception('Waiting list canceled email could not be sent')
def _send_mail(order: Order, subject: LazyI18nString, message: LazyI18nString, subevent: SubEvent,
refund_amount: Decimal, user: User, positions: list):
with language(order.locale):
@@ -68,10 +85,14 @@ def _send_mail(order: Order, subject: LazyI18nString, message: LazyI18nString, s
@app.task(base=ProfiledEventTask, bind=True, max_retries=5, default_retry_delay=1, throws=(OrderError,))
def cancel_event(self, event: Event, subevent: int, auto_refund: bool, keep_fee_fixed: str,
keep_fee_percentage: str, keep_fees: bool, send: bool, send_subject: dict,
send_message: dict, user: int):
keep_fee_percentage: str, keep_fees: bool,
send: bool, send_subject: dict, send_message: dict,
send_waitinglist: bool=False, send_waitinglist_subject: dict={}, send_waitinglist_message: dict={},
user: int=None):
send_subject = LazyI18nString(send_subject)
send_message = LazyI18nString(send_message)
send_waitinglist_subject = LazyI18nString(send_waitinglist_subject)
send_waitinglist_message = LazyI18nString(send_waitinglist_message)
if user:
user = User.objects.get(pk=user)
@@ -115,7 +136,7 @@ def cancel_event(self, event: Event, subevent: int, auto_refund: bool, keep_fee_
)
else:
orders_to_change = event.orders.none()
subevent.log_action(
event.log_action(
'pretix.event.canceled', user=user,
)
@@ -195,4 +216,7 @@ def cancel_event(self, event: Event, subevent: int, auto_refund: bool, keep_fee_
if send:
_send_mail(o, send_subject, send_message, subevent, refund_amount, user, positions)
for wle in event.waitinglistentries.filter(subevent=subevent, voucher__isnull=True):
_send_wle_mail(wle, send_waitinglist_subject, send_waitinglist_message, subevent)
return failed

View File

@@ -552,6 +552,12 @@ class EventCancelForm(forms.Form):
)
send_subject = forms.CharField()
send_message = forms.CharField()
send_waitinglist = forms.BooleanField(
label=_("Send information to waiting list"),
required=False
)
send_waitinglist_subject = forms.CharField()
send_waitinglist_message = forms.CharField()
def _set_field_placeholders(self, fn, base_parameters):
phs = [
@@ -596,6 +602,28 @@ class EventCancelForm(forms.Form):
'order', 'event'])
self._set_field_placeholders('send_message', ['event_or_subevent', 'refund_amount', 'position_or_address',
'order', 'event'])
self.fields['send_waitinglist_subject'] = I18nFormField(
label=_("Subject"),
required=True,
initial=_('Canceled: {event}'),
widget=I18nTextInput,
locales=self.event.settings.get('locales'),
)
self.fields['send_waitinglist_message'] = I18nFormField(
label=_('Message'),
widget=I18nTextarea,
required=True,
locales=self.event.settings.get('locales'),
initial=LazyI18nString.from_gettext(gettext_noop(
'Hello,\n\n'
'with this email, we regret to inform you that {event} has been canceled.\n\n'
'You will therefore not receive a ticket from the waiting list.\n\n'
'Best regards,\n\n'
'Your {event} team'
))
)
self._set_field_placeholders('send_waitinglist_subject', ['event_or_subevent', 'event'])
self._set_field_placeholders('send_waitinglist_message', ['event_or_subevent', 'event'])
if self.event.has_subevents:
self.fields['subevent'].queryset = self.event.subevents.all()

View File

@@ -43,6 +43,26 @@
{% bootstrap_field form.send_subject layout="horizontal" %}
{% bootstrap_field form.send_message layout="horizontal" %}
</fieldset>
<fieldset>
<legend>{% trans "Waiting list" %}</legend>
<p>
{% blocktrans trimmed %}
Your waiting list will not be deleted automatically, but it will receive no new tickets due to the
products being disabled. You can choose to inform people on the waiting list by using this option.
{% endblocktrans %}
</p>
<p>
<strong>
{% blocktrans trimmed %}
You should not execute this function multiple times for the same event, or everyone on the
waiting list will get multiple emails.
{% endblocktrans %}
</strong>
</p>
{% bootstrap_field form.send_waitinglist layout="control" %}
{% bootstrap_field form.send_waitinglist_subject layout="horizontal" %}
{% bootstrap_field form.send_waitinglist_message layout="horizontal" %}
</fieldset>
<div class="form-group submit-group">
<button type="submit" class="btn btn-danger btn-save">
{% trans "Cancel all orders" %}

View File

@@ -1915,6 +1915,9 @@ class EventCancel(EventPermissionRequiredMixin, AsyncAction, FormView):
send=form.cleaned_data.get('send'),
send_subject=form.cleaned_data.get('send_subject').data,
send_message=form.cleaned_data.get('send_message').data,
send_waitinglist=form.cleaned_data.get('send'),
send_waitinglist_subject=form.cleaned_data.get('send_waitinglist_subject').data,
send_waitinglist_message=form.cleaned_data.get('send_waitinglist_message').data,
user=self.request.user.pk,
)

View File

@@ -6,7 +6,9 @@ from django.test import TestCase
from django.utils.timezone import now
from django_scopes import scope
from pretix.base.models import Event, Item, Order, OrderPosition, Organizer
from pretix.base.models import (
Event, Item, Order, OrderPosition, Organizer, Voucher, WaitingListEntry,
)
from pretix.base.models.orders import OrderFee, OrderPayment, OrderRefund
from pretix.base.services.cancelevent import cancel_event
from pretix.base.services.invoices import generate_invoice
@@ -310,3 +312,22 @@ class SubEventCancelTests(TestCase):
assert self.order.positions.filter(subevent=self.se1).count() == 0
f = self.order.fees.get(fee_type=OrderFee.FEE_TYPE_CANCELLATION)
assert f.value == Decimal('1.80')
@classscope(attr='o')
def test_cancel_send_mail_waitinglist(self):
v = Voucher.objects.create(event=self.event, block_quota=True, redeemed=1)
WaitingListEntry.objects.create(
event=self.event, item=self.ticket, variation=None, email='foo@bar.com', voucher=v
)
WaitingListEntry.objects.create(
event=self.event, item=self.ticket, variation=None, email='foo@example.org'
)
cancel_event(
self.event.pk, subevent=None,
auto_refund=True, keep_fee_fixed="0.00", keep_fee_percentage="0.00",
keep_fees=True, send=False, send_subject="Event canceled", send_message="Event canceled :-(",
send_waitinglist=True, send_waitinglist_message="Event canceled", send_waitinglist_subject=":(",
user=None
)
assert len(djmail.outbox) == 1
assert djmail.outbox[0].to == ['foo@example.org']