mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Allow to enable ticket downloads for pending orders
This commit is contained in:
@@ -77,7 +77,8 @@ class CheckinSerializer(I18nAwareModelSerializer):
|
||||
class OrderDownloadsField(serializers.Field):
|
||||
def to_representation(self, instance: Order):
|
||||
if instance.status != Order.STATUS_PAID:
|
||||
return []
|
||||
if instance.status != Order.STATUS_PENDING or instance.require_approval or not instance.event.settings.ticket_download_pending:
|
||||
return []
|
||||
|
||||
request = self.context['request']
|
||||
res = []
|
||||
@@ -100,7 +101,8 @@ class OrderDownloadsField(serializers.Field):
|
||||
class PositionDownloadsField(serializers.Field):
|
||||
def to_representation(self, instance: OrderPosition):
|
||||
if instance.order.status != Order.STATUS_PAID:
|
||||
return []
|
||||
if instance.order.status != Order.STATUS_PENDING or instance.order.require_approval or not instance.order.event.settings.ticket_download_pending:
|
||||
return []
|
||||
if instance.addon_to_id and not instance.order.event.settings.ticket_download_addons:
|
||||
return []
|
||||
if not instance.item.admission and not instance.order.event.settings.ticket_download_nonadm:
|
||||
|
||||
@@ -420,6 +420,20 @@ class Order(LoggedModel):
|
||||
dl_date = dl_date.datetime(self.event)
|
||||
return dl_date
|
||||
|
||||
@property
|
||||
def ticket_download_available(self):
|
||||
return self.event.settings.ticket_download and (
|
||||
self.event.settings.ticket_download_date is None
|
||||
or now() > self.ticket_download_date
|
||||
) and (
|
||||
self.status == Order.STATUS_PAID
|
||||
or (
|
||||
(self.event.settings.ticket_download_pending or self.total == Decimal("0.00")) and
|
||||
self.status == Order.STATUS_PENDING and
|
||||
not self.require_approval
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def payment_term_last(self):
|
||||
tz = pytz.timezone(self.event.settings.timezone)
|
||||
|
||||
@@ -634,7 +634,7 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str],
|
||||
email_subject, email_template, email_context,
|
||||
log_entry,
|
||||
invoices=[invoice] if invoice and event.settings.invoice_email_attachment else [],
|
||||
attach_tickets=(payment_provider == 'free')
|
||||
attach_tickets=True
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order received email could not be sent')
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import logging
|
||||
import os
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
from django.core.files.base import ContentFile
|
||||
from django.utils.timezone import now
|
||||
@@ -155,11 +154,7 @@ def get_tickets_for_order(order):
|
||||
can_download = all([r for rr, r in allow_ticket_download.send(order.event, order=order)])
|
||||
if not can_download:
|
||||
return []
|
||||
if order.status != Order.STATUS_PAID and order.total != Decimal("0.00"):
|
||||
return []
|
||||
if (not order.event.settings.ticket_download
|
||||
or (order.event.settings.ticket_download_date is not None
|
||||
and now() < order.ticket_download_date)):
|
||||
if not order.ticket_download_available:
|
||||
return []
|
||||
|
||||
providers = [
|
||||
|
||||
@@ -949,12 +949,14 @@ class TicketSettingsForm(SettingsForm):
|
||||
ticket_download_addons = forms.BooleanField(
|
||||
label=_("Offer to download tickets separately for add-on products"),
|
||||
required=False,
|
||||
widget=forms.CheckboxInput(attrs={'data-display-dependency': '#id_ticket_download'}),
|
||||
)
|
||||
ticket_download_nonadm = forms.BooleanField(
|
||||
label=_("Generate tickets for non-admission products"),
|
||||
required=False,
|
||||
widget=forms.CheckboxInput(attrs={'data-display-dependency': '#id_ticket_download'}),
|
||||
)
|
||||
ticket_download_pending = forms.BooleanField(
|
||||
label=_("Offer to download tickets even before an order is paid"),
|
||||
required=False,
|
||||
)
|
||||
|
||||
def prepare_fields(self):
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
{% bootstrap_field form.ticket_download_date layout="control" %}
|
||||
{% bootstrap_field form.ticket_download_addons layout="control" %}
|
||||
{% bootstrap_field form.ticket_download_nonadm layout="control" %}
|
||||
{% bootstrap_field form.ticket_download_pending layout="control" %}
|
||||
{% for provider in providers %}
|
||||
<div class="panel panel-default ticketoutput-panel">
|
||||
<div class="panel-heading">
|
||||
|
||||
@@ -84,28 +84,28 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if order.status == 'p' and event.settings.ticket_download %}
|
||||
{% if can_download and download_buttons %}
|
||||
<div class="alert alert-info">
|
||||
{% blocktrans trimmed %}
|
||||
You can download your tickets using the buttons below. Please have your ticket ready when entering the event.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% if cart.positions|length > 1 and can_download_multi %}
|
||||
<p>
|
||||
{% trans "Download all tickets at once:" %}
|
||||
{% for b in download_buttons %}
|
||||
{% if b.multi %}
|
||||
<a href="{% eventurl event "presale:event.order.download.combined" secret=order.secret order=order.code output=b.identifier %}"
|
||||
class="btn btn-sm {% if b.identifier == "pdf" %}btn-primary{% else %}btn-default{% endif %}"
|
||||
data-asyncdownload>
|
||||
<span class="fa {{ b.icon }}"></span> {{ b.text }}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% elif not download_buttons and ticket_download_date %}
|
||||
{% if can_download and download_buttons %}
|
||||
<div class="alert alert-info">
|
||||
{% blocktrans trimmed %}
|
||||
You can download your tickets using the buttons below. Please have your ticket ready when entering the event.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% if cart.positions|length > 1 and can_download_multi %}
|
||||
<p>
|
||||
{% trans "Download all tickets at once:" %}
|
||||
{% for b in download_buttons %}
|
||||
{% if b.multi %}
|
||||
<a href="{% eventurl event "presale:event.order.download.combined" secret=order.secret order=order.code output=b.identifier %}"
|
||||
class="btn btn-sm {% if b.identifier == "pdf" %}btn-primary{% else %}btn-default{% endif %}"
|
||||
data-asyncdownload>
|
||||
<span class="fa {{ b.icon }}"></span> {{ b.text }}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% elif not download_buttons and ticket_download_date %}
|
||||
{% if order.status == 'p' %}
|
||||
<div class="alert alert-info">
|
||||
{% blocktrans trimmed with date=ticket_download_date|date:"SHORT_DATE_FORMAT" %}
|
||||
You will be able to download your tickets here starting on {{ date }}.
|
||||
|
||||
@@ -95,13 +95,7 @@ class OrderDetails(EventViewMixin, OrderDetailMixin, CartMixin, TemplateView):
|
||||
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'] = (
|
||||
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
|
||||
) and self.order.status == Order.STATUS_PAID
|
||||
)
|
||||
ctx['can_download'] = can_download and self.order.ticket_download_available
|
||||
ctx['download_buttons'] = self.download_buttons
|
||||
ctx['cart'] = self.get_cart(
|
||||
answers=True, downloads=ctx['can_download'],
|
||||
@@ -682,12 +676,8 @@ class OrderDownload(EventViewMixin, OrderDetailMixin, View):
|
||||
return self.error(_('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 self.order.status != Order.STATUS_PAID:
|
||||
return self.error(_('Order is not paid.'))
|
||||
if (not self.request.event.settings.ticket_download
|
||||
or (self.request.event.settings.ticket_download_date is not None
|
||||
and now() < self.order.ticket_download_date)):
|
||||
return self.error(_('Ticket download is not (yet) enabled.'))
|
||||
if not self.order.ticket_download_available:
|
||||
return self.error(_('Ticket download is not (yet) enabled for this order.'))
|
||||
if 'position' in kwargs and (self.order_position.addon_to and not self.request.event.settings.ticket_download_addons):
|
||||
return self.error(_('Ticket download is not enabled for add-on products.'))
|
||||
if 'position' in kwargs and (not self.order_position.item.admission and not self.request.event.settings.ticket_download_nonadm):
|
||||
|
||||
@@ -283,6 +283,19 @@ def test_order_detail(token_client, organizer, event, order, item, taxrule, ques
|
||||
assert len(resp.data['downloads']) == 1
|
||||
assert len(resp.data['positions'][0]['downloads']) == 1
|
||||
|
||||
order.status = 'n'
|
||||
order.save()
|
||||
resp = token_client.get('/api/v1/organizers/{}/events/{}/orders/{}/'.format(organizer.slug, event.slug,
|
||||
order.code))
|
||||
assert len(resp.data['downloads']) == 0
|
||||
assert len(resp.data['positions'][0]['downloads']) == 0
|
||||
|
||||
event.settings.ticket_download_pending = True
|
||||
resp = token_client.get('/api/v1/organizers/{}/events/{}/orders/{}/'.format(organizer.slug, event.slug,
|
||||
order.code))
|
||||
assert len(resp.data['downloads']) == 1
|
||||
assert len(resp.data['positions'][0]['downloads']) == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_payment_list(token_client, organizer, event, order):
|
||||
|
||||
@@ -306,6 +306,36 @@ class OrdersTest(TestCase):
|
||||
assert 'alert-success' in response.rendered_content
|
||||
assert self.order.invoices.exists()
|
||||
|
||||
def test_orders_download_pending(self):
|
||||
self.event.settings.set('ticket_download', True)
|
||||
del self.event.settings['ticket_download_date']
|
||||
|
||||
self.order.status = Order.STATUS_PENDING
|
||||
self.order.save()
|
||||
self.event.settings.set('ticket_download_pending', True)
|
||||
response = self.client.get(
|
||||
'/%s/%s/order/%s/%s/download/%d/testdummy' % (self.orga.slug, self.event.slug, self.order.code,
|
||||
self.order.secret, self.ticket_pos.pk),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_orders_download_pending_only_approved(self):
|
||||
self.event.settings.set('ticket_download', True)
|
||||
del self.event.settings['ticket_download_date']
|
||||
|
||||
self.order.status = Order.STATUS_PENDING
|
||||
self.order.require_approval = True
|
||||
self.order.save()
|
||||
self.event.settings.set('ticket_download_pending', True)
|
||||
response = self.client.get(
|
||||
'/%s/%s/order/%s/%s/download/%d/testdummy' % (self.orga.slug, self.event.slug, self.order.code,
|
||||
self.order.secret, self.ticket_pos.pk),
|
||||
)
|
||||
self.assertRedirects(response,
|
||||
'/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code,
|
||||
self.order.secret),
|
||||
target_status_code=200)
|
||||
|
||||
def test_orders_download(self):
|
||||
self.event.settings.set('ticket_download', True)
|
||||
del self.event.settings['ticket_download_date']
|
||||
|
||||
Reference in New Issue
Block a user