forked from CGM_Public/pretix_original
Let plugins prevent the download of individual tickets in an order (#3858)
* Let plugins allow/prevent the download of individual tickets in an order (#3836)
(extends the functionality of the allow_ticket_download signal)
(cherry picked from commit e20edab98f)
* fix bug where in some cases, only the first ticket could be downloaded
This commit is contained in:
@@ -243,7 +243,7 @@
|
||||
|
||||
{% if download %}
|
||||
<div role="cell" class="download-desktop">
|
||||
{% if line.generate_ticket %}
|
||||
{% if line in tickets_with_download %}
|
||||
{% for b in download_buttons %}
|
||||
<form action="{% if position_page and line.addon_to %}{% eventurl event "presale:event.order.position.download" secret=line.addon_to.web_secret order=order.code output=b.identifier pid=line.pk position=line.addon_to.positionid %}{% elif position_page %}{% eventurl event "presale:event.order.position.download" secret=line.web_secret order=order.code output=b.identifier pid=line.pk position=line.positionid %}{% else %}{% eventurl event "presale:event.order.download" secret=order.secret order=order.code output=b.identifier position=line.pk %}{% endif %}"
|
||||
method="post" data-asynctask data-asynctask-download class="download-btn-form{% if b.javascript_required %} requirejs{% endif %}">
|
||||
|
||||
@@ -35,10 +35,10 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% elif can_download and download_buttons and order.count_positions %}
|
||||
{% elif can_download and download_buttons and order.count_positions and tickets_with_download %}
|
||||
<div class="info-download">
|
||||
<h3 class="sr-only">{% trans "Ticket download" %}</h3>
|
||||
{% if cart.positions|length > 1 and can_download_multi %} {# never True on ticket page #}
|
||||
{% if tickets_with_download|length > 1 and can_download_multi %} {# never True on ticket page #}
|
||||
<div>
|
||||
{% for b in download_buttons %}
|
||||
{% if b.multi %}
|
||||
|
||||
@@ -80,9 +80,7 @@ from pretix.base.services.orders import (
|
||||
)
|
||||
from pretix.base.services.pricing import get_price
|
||||
from pretix.base.services.tickets import generate, invalidate_cache
|
||||
from pretix.base.signals import (
|
||||
allow_ticket_download, order_modified, register_ticket_outputs,
|
||||
)
|
||||
from pretix.base.signals import order_modified, register_ticket_outputs
|
||||
from pretix.base.templatetags.money import money_filter
|
||||
from pretix.base.views.mixins import OrderQuestionsViewMixin
|
||||
from pretix.base.views.tasks import AsyncAction
|
||||
@@ -175,16 +173,14 @@ class TicketPageMixin:
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
|
||||
positions_with_tickets = list(self.order.positions_with_tickets)
|
||||
ctx['order'] = self.order
|
||||
|
||||
can_download = all([r for rr, r in allow_ticket_download.send(self.request.event, order=self.order)])
|
||||
can_download = bool(positions_with_tickets)
|
||||
ctx['plugins_allow_ticket_download'] = can_download
|
||||
if self.request.event.settings.ticket_download_date:
|
||||
ctx['ticket_download_date'] = self.order.ticket_download_date
|
||||
can_download = (
|
||||
can_download and self.order.ticket_download_available and
|
||||
list(self.order.positions_with_tickets)
|
||||
)
|
||||
can_download = can_download and self.order.ticket_download_available
|
||||
ctx['download_email_required'] = can_download and (
|
||||
self.request.event.settings.ticket_download_require_validated_email and
|
||||
self.order.sales_channel == 'web' and
|
||||
@@ -192,6 +188,26 @@ class TicketPageMixin:
|
||||
)
|
||||
ctx['can_download'] = can_download and not ctx['download_email_required']
|
||||
|
||||
qs = self.context_query_set
|
||||
if self.request.event.settings.show_checkin_number_user:
|
||||
qs = qs.annotate(
|
||||
checkin_count=Subquery(
|
||||
Checkin.objects.filter(
|
||||
successful=True,
|
||||
type=Checkin.TYPE_ENTRY,
|
||||
position_id=OuterRef('pk'),
|
||||
list__consider_tickets_used=True,
|
||||
).order_by().values('position').annotate(c=Count('*')).values('c')
|
||||
)
|
||||
)
|
||||
ctx['cart'] = self.get_cart(
|
||||
answers=True, downloads=ctx['can_download'],
|
||||
queryset=qs,
|
||||
order=self.order
|
||||
)
|
||||
|
||||
ctx['tickets_with_download'] = [p for p in ctx['cart']['positions'] if p in positions_with_tickets]
|
||||
|
||||
ctx['download_buttons'] = self.download_buttons
|
||||
|
||||
ctx['backend_user'] = (
|
||||
@@ -200,25 +216,6 @@ class TicketPageMixin:
|
||||
)
|
||||
return ctx
|
||||
|
||||
|
||||
@method_decorator(xframe_options_exempt, 'dispatch')
|
||||
class OrderDetails(EventViewMixin, OrderDetailMixin, CartMixin, TicketPageMixin, TemplateView):
|
||||
template_name = "pretixpresale/event/order.html"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.kwargs = kwargs
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
if self.order.status == Order.STATUS_PENDING:
|
||||
payment_to_complete = self.order.payments.filter(state=OrderPayment.PAYMENT_STATE_CREATED, process_initiated=False).first()
|
||||
if payment_to_complete:
|
||||
return redirect(eventreverse(self.request.event, 'presale:event.order.pay.complete', kwargs={
|
||||
'order': self.order.code,
|
||||
'secret': self.order.secret,
|
||||
'payment': payment_to_complete.pk
|
||||
}))
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
@cached_property
|
||||
def download_buttons(self):
|
||||
buttons = []
|
||||
@@ -239,29 +236,31 @@ class OrderDetails(EventViewMixin, OrderDetailMixin, CartMixin, TicketPageMixin,
|
||||
})
|
||||
return buttons
|
||||
|
||||
|
||||
@method_decorator(xframe_options_exempt, 'dispatch')
|
||||
class OrderDetails(EventViewMixin, OrderDetailMixin, CartMixin, TicketPageMixin, TemplateView):
|
||||
template_name = "pretixpresale/event/order.html"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.kwargs = kwargs
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
if self.order.status == Order.STATUS_PENDING:
|
||||
payment_to_complete = self.order.payments.filter(state=OrderPayment.PAYMENT_STATE_CREATED, process_initiated=False).first()
|
||||
if payment_to_complete:
|
||||
return redirect(eventreverse(self.request.event, 'presale:event.order.pay.complete', kwargs={
|
||||
'order': self.order.code,
|
||||
'secret': self.order.secret,
|
||||
'payment': payment_to_complete.pk
|
||||
}))
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
self.context_query_set = (
|
||||
self.order.positions.prefetch_related('issued_gift_cards', 'owned_gift_cards').select_related('tax_rule')
|
||||
)
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
|
||||
qs = self.order.positions.prefetch_related('issued_gift_cards', 'owned_gift_cards').select_related('tax_rule')
|
||||
if self.request.event.settings.show_checkin_number_user:
|
||||
qs = qs.annotate(
|
||||
checkin_count=Subquery(
|
||||
Checkin.objects.filter(
|
||||
successful=True,
|
||||
type=Checkin.TYPE_ENTRY,
|
||||
position_id=OuterRef('pk'),
|
||||
list__consider_tickets_used=True,
|
||||
).order_by().values('position').annotate(c=Count('*')).values('c')
|
||||
)
|
||||
)
|
||||
|
||||
ctx['cart'] = self.get_cart(
|
||||
answers=True,
|
||||
downloads=ctx['can_download'],
|
||||
queryset=qs,
|
||||
order=self.order
|
||||
)
|
||||
ctx['tickets_with_download'] = [p for p in ctx['cart']['positions'] if p.generate_ticket]
|
||||
ctx['can_download_multi'] = any([b['multi'] for b in self.download_buttons]) and (
|
||||
[p.generate_ticket for p in ctx['cart']['positions']].count(True) > 1
|
||||
)
|
||||
@@ -342,50 +341,13 @@ class OrderPositionDetails(EventViewMixin, OrderPositionDetailMixin, CartMixin,
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
@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)
|
||||
if not provider.is_enabled:
|
||||
continue
|
||||
buttons.append({
|
||||
'text': provider.download_button_text or 'Download',
|
||||
'icon': provider.download_button_icon or 'fa-download',
|
||||
'identifier': provider.identifier,
|
||||
'multi': provider.multi_download_enabled,
|
||||
'multi_text': provider.multi_download_button_text or 'Download',
|
||||
'long_text': provider.long_download_button_text or 'Download',
|
||||
'javascript_required': provider.javascript_required
|
||||
})
|
||||
return buttons
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
qs = self.order.positions.select_related('tax_rule').filter(
|
||||
self.context_query_set = self.order.positions.select_related('tax_rule').filter(
|
||||
Q(pk=self.position.pk) | Q(addon_to__id=self.position.pk)
|
||||
)
|
||||
if self.request.event.settings.show_checkin_number_user:
|
||||
qs = qs.annotate(
|
||||
checkin_count=Subquery(
|
||||
Checkin.objects.filter(
|
||||
successful=True,
|
||||
type=Checkin.TYPE_ENTRY,
|
||||
position_id=OuterRef('pk'),
|
||||
list__consider_tickets_used=True,
|
||||
).order_by().values('position').annotate(c=Count('*')).values('c')
|
||||
)
|
||||
)
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['can_download_multi'] = False
|
||||
ctx['position'] = self.position
|
||||
ctx['cart'] = self.get_cart(
|
||||
answers=True, downloads=ctx['can_download'],
|
||||
queryset=qs,
|
||||
order=self.order
|
||||
)
|
||||
ctx['tickets_with_download'] = [p for p in ctx['cart']['positions'] if p.generate_ticket]
|
||||
ctx['attendee_change_allowed'] = self.position.attendee_change_allowed
|
||||
return ctx
|
||||
|
||||
@@ -1048,8 +1010,6 @@ class OrderDownloadMixin:
|
||||
|
||||
@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)
|
||||
@@ -1068,9 +1028,10 @@ class OrderDownloadMixin:
|
||||
return self.error(OrderError(_('You requested an invalid ticket output type.')))
|
||||
if not self.order or ('position' in kwargs and not self.order_position):
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
if not self.order.ticket_download_available:
|
||||
positions = list(self.order.positions_with_tickets)
|
||||
if not self.order.ticket_download_available or not positions:
|
||||
return self.error(OrderError(_('Ticket download is not (yet) enabled for this order.')))
|
||||
if 'position' in kwargs and not self.order_position.generate_ticket:
|
||||
if 'position' in kwargs and self.order_position not in positions:
|
||||
return self.error(OrderError(_('Ticket download is not enabled for this product.')))
|
||||
|
||||
if (
|
||||
|
||||
Reference in New Issue
Block a user