From e61288ba6757ae966926b00f3dbcb740cf361983 Mon Sep 17 00:00:00 2001 From: julia-luna <72915853+julia-luna@users.noreply.github.com> Date: Mon, 26 Oct 2020 10:31:45 +0100 Subject: [PATCH] Add option to send emails to attendees (#1833) --- src/pretix/control/forms/orders.py | 14 +++++ .../templates/pretixcontrol/order/index.html | 8 ++- src/pretix/control/urls.py | 2 + src/pretix/control/views/orders.py | 55 ++++++++++++++++++- src/tests/control/test_permissions.py | 4 ++ 5 files changed, 79 insertions(+), 4 deletions(-) diff --git a/src/pretix/control/forms/orders.py b/src/pretix/control/forms/orders.py index 609c83b7a7..bf06e96b21 100644 --- a/src/pretix/control/forms/orders.py +++ b/src/pretix/control/forms/orders.py @@ -517,6 +517,20 @@ class OrderMailForm(forms.Form): self._set_field_placeholders('message', ['event', 'order']) +class OrderPositionMailForm(OrderMailForm): + def __init__(self, *args, **kwargs): + position = self.position = kwargs.pop('position') + super().__init__(*args, **kwargs) + self.fields['sendto'].initial = position.attendee_email + self.fields['message'] = forms.CharField( + label=_("Message"), + required=True, + widget=forms.Textarea, + initial=self.order.event.settings.mail_text_order_custom_mail.localize(self.order.locale), + ) + self._set_field_placeholders('message', ['event', 'order', 'position']) + + class OrderRefundForm(forms.Form): action = forms.ChoiceField( required=False, diff --git a/src/pretix/control/templates/pretixcontrol/order/index.html b/src/pretix/control/templates/pretixcontrol/order/index.html index 41325dd689..2675a10bc0 100644 --- a/src/pretix/control/templates/pretixcontrol/order/index.html +++ b/src/pretix/control/templates/pretixcontrol/order/index.html @@ -182,7 +182,7 @@ {{ order.email|default_if_none:"" }} {% if order.email and order.email_known_to_work %} - {% endif %}   + {% endif %} @@ -388,8 +388,12 @@ {{ line.attendee_email }} {% if not line.addon_to %}
+ action="{% url "control:event.order.resendlink" event=request.event.slug organizer=request.event.organizer.slug code=order.code position=line.pk %}"> {% csrf_token %} + + + diff --git a/src/pretix/control/urls.py b/src/pretix/control/urls.py index 048f6d3972..7868e5cd79 100644 --- a/src/pretix/control/urls.py +++ b/src/pretix/control/urls.py @@ -253,6 +253,8 @@ urlpatterns = [ name='event.order.info'), url(r'^orders/(?P[0-9A-Z]+)/sendmail$', orders.OrderSendMail.as_view(), name='event.order.sendmail'), + url(r'^orders/(?P[0-9A-Z]+)/(?P[0-9A-Z]+)/sendmail$', orders.OrderPositionSendMail.as_view(), + name='event.order.position.sendmail'), url(r'^orders/(?P[0-9A-Z]+)/mail_history$', orders.OrderEmailHistory.as_view(), name='event.order.mail_history'), url(r'^orders/(?P[0-9A-Z]+)/payments/(?P\d+)/cancel$', orders.OrderPaymentCancel.as_view(), diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index e96a7a4595..a1195867c6 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -80,8 +80,8 @@ from pretix.control.forms.orders import ( CancelForm, CommentForm, ConfirmPaymentForm, EventCancelForm, ExporterForm, ExtendForm, MarkPaidForm, OrderContactForm, OrderFeeChangeForm, OrderLocaleForm, OrderMailForm, OrderPositionAddForm, - OrderPositionAddFormset, OrderPositionChangeForm, OrderRefundForm, - OtherOperationsForm, + OrderPositionAddFormset, OrderPositionChangeForm, OrderPositionMailForm, + OrderRefundForm, OtherOperationsForm, ) from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.views import PaginationMixin @@ -1783,6 +1783,57 @@ class OrderSendMail(EventPermissionRequiredMixin, OrderViewMixin, FormView): return ctx +class OrderPositionSendMail(OrderSendMail): + form_class = OrderPositionMailForm + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + kwargs['position'] = get_object_or_404( + OrderPosition, + order__event=self.request.event, + order__code=self.kwargs['code'].upper(), + pk=self.kwargs['position'], + attendee_email__isnull=False + ) + return kwargs + + def form_valid(self, form): + position = get_object_or_404( + OrderPosition, + order__event=self.request.event, + order__code=self.kwargs['code'].upper(), + pk=self.kwargs['position'], + attendee_email__isnull=False + ) + self.preview_output = {} + with language(position.order.locale): + email_context = get_email_context(event=position.order.event, order=position.order, position=position) + email_template = LazyI18nString(form.cleaned_data['message']) + email_subject = str(form.cleaned_data['subject']).format_map(TolerantDict(email_context)) + email_content = render_mail(email_template, email_context) + if self.request.POST.get('action') == 'preview': + self.preview_output = { + 'subject': _('Subject: {subject}').format(subject=email_subject), + 'html': markdown_compile_email(email_content) + } + return self.get(self.request, *self.args, **self.kwargs) + else: + try: + position.send_mail( + form.cleaned_data['subject'], + email_template, + email_context, + 'pretix.event.order.position.email.custom_sent', + self.request.user + ) + messages.success(self.request, + _('Your message has been queued and will be sent to {}.'.format(position.attendee_email))) + except SendMailException: + messages.error(self.request, + _('Failed to send mail to the following user: {}'.format(position.attendee_email))) + return super(OrderSendMail, self).form_valid(form) + + class OrderEmailHistory(EventPermissionRequiredMixin, OrderViewMixin, ListView): template_name = 'pretixcontrol/order/mail_history.html' permission = 'can_view_orders' diff --git a/src/tests/control/test_permissions.py b/src/tests/control/test_permissions.py index dcdbe7bc04..9c763d3ff9 100644 --- a/src/tests/control/test_permissions.py +++ b/src/tests/control/test_permissions.py @@ -117,6 +117,8 @@ event_urls = [ "orders/ABC/refunds/1/process", "orders/ABC/refunds/1/done", "orders/ABC/delete", + "orders/ABC/sendmail", + "orders/ABC/1/sendmail", "orders/ABC/", "orders/", "orders/import/", @@ -290,6 +292,8 @@ event_permission_urls = [ ("can_change_orders", "orders/FOO/delete", 302), ("can_change_orders", "orders/FOO/comment", 405), ("can_change_orders", "orders/FOO/locale", 200), + ("can_change_orders", "orders/FOO/sendmail", 200), + ("can_change_orders", "orders/FOO/1/sendmail", 404), ("can_change_orders", "orders/import/", 200), ("can_change_orders", "orders/import/0ab7b081-92d3-4480-82de-2f8b056fd32f/", 404), ("can_view_orders", "orders/FOO/answer/5/", 404),