diff --git a/doc/development/api/general.rst b/doc/development/api/general.rst index 735a3cdb2f..f535b1c179 100644 --- a/doc/development/api/general.rst +++ b/doc/development/api/general.rst @@ -19,7 +19,7 @@ Order events There are multiple signals that will be sent out in the ordering cycle: .. automodule:: pretix.base.signals - :members: validate_cart, fee_calculation_for_cart, order_fee_calculation, order_paid, order_placed, order_fee_type_name + :members: validate_cart, fee_calculation_for_cart, order_fee_calculation, order_paid, order_placed, order_fee_type_name, allow_ticket_download Frontend -------- diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index b0691b62a8..6e3edddd7f 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -35,7 +35,8 @@ from pretix.base.services.locking import LockTimeoutException from pretix.base.services.mail import SendMailException from pretix.base.services.pricing import get_price from pretix.base.signals import ( - order_fee_calculation, order_paid, order_placed, periodic_task, + allow_ticket_download, order_fee_calculation, order_paid, order_placed, + periodic_task, ) from pretix.celery_app import app from pretix.multidomain.urlreverse import build_absolute_uri @@ -567,6 +568,9 @@ def send_download_reminders(sender, **kwargs): if now() < reminder_date: continue for o in e.orders.filter(status=Order.STATUS_PAID, download_reminder_sent=False): + if not all([r for rr, r in allow_ticket_download.send(e, order=o)]): + continue + o.download_reminder_sent = True o.save() email_template = e.settings.mail_text_download_reminder diff --git a/src/pretix/base/signals.py b/src/pretix/base/signals.py index 84ef637409..0d6ed5abde 100644 --- a/src/pretix/base/signals.py +++ b/src/pretix/base/signals.py @@ -261,3 +261,13 @@ expected to return a string or None, if you don't know about this fee. As with all plugin signals, the ``sender`` keyword argument will contain the event. """ + +allow_ticket_download = EventPluginSignal( + providing_args=['order'] +) +""" +This signal is sent out to check if tickets for an order can be downloaded. If any receiver returns false, +a download will not be offered. + +As with all event-plugin signals, the ``sender`` keyword argument will contain the event. +""" diff --git a/src/pretix/presale/views/order.py b/src/pretix/presale/views/order.py index 532aca17fc..538d484ada 100644 --- a/src/pretix/presale/views/order.py +++ b/src/pretix/presale/views/order.py @@ -22,7 +22,7 @@ from pretix.base.services.orders import cancel_order from pretix.base.services.tickets import ( get_cachedticket_for_order, get_cachedticket_for_position, ) -from pretix.base.signals import register_ticket_outputs +from pretix.base.signals import allow_ticket_download, register_ticket_outputs from pretix.helpers.safedownload import check_token from pretix.multidomain.urlreverse import eventreverse from pretix.presale.forms.checkout import InvoiceAddressForm @@ -71,6 +71,7 @@ class OrderDetails(EventViewMixin, OrderDetailMixin, CartMixin, TemplateView): @cached_property def download_buttons(self): buttons = [] + responses = register_ticket_outputs.send(self.request.event) for receiver, response in responses: provider = response(self.request.event) @@ -87,10 +88,11 @@ class OrderDetails(EventViewMixin, OrderDetailMixin, CartMixin, TemplateView): ctx = super().get_context_data(**kwargs) ctx['order'] = self.order + can_download = all([r for rr, r in allow_ticket_download.send(self.request.event, order=self.order)]) if self.request.event.settings.ticket_download_date: ctx['ticket_download_date'] = self.order.ticket_download_date ctx['can_download'] = ( - self.request.event.settings.ticket_download + can_download and self.request.event.settings.ticket_download and ( self.request.event.settings.ticket_download_date is None or now() > self.order.ticket_download_date @@ -547,6 +549,8 @@ class OrderDownload(EventViewMixin, OrderDetailMixin, View): @cached_property def output(self): + if not all([r for rr, r in allow_ticket_download.send(self.request.event, order=self.order)]): + return None responses = register_ticket_outputs.send(self.request.event) for receiver, response in responses: provider = response(self.request.event)