Allow to enable ticket downloads for pending orders

This commit is contained in:
Raphael Michel
2018-10-03 12:15:43 +02:00
parent 4b8d4b4792
commit 0dbcfdc5ac
10 changed files with 93 additions and 46 deletions
+4 -2
View File
@@ -77,7 +77,8 @@ class CheckinSerializer(I18nAwareModelSerializer):
class OrderDownloadsField(serializers.Field): class OrderDownloadsField(serializers.Field):
def to_representation(self, instance: Order): def to_representation(self, instance: Order):
if instance.status != Order.STATUS_PAID: 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'] request = self.context['request']
res = [] res = []
@@ -100,7 +101,8 @@ class OrderDownloadsField(serializers.Field):
class PositionDownloadsField(serializers.Field): class PositionDownloadsField(serializers.Field):
def to_representation(self, instance: OrderPosition): def to_representation(self, instance: OrderPosition):
if instance.order.status != Order.STATUS_PAID: 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: if instance.addon_to_id and not instance.order.event.settings.ticket_download_addons:
return [] return []
if not instance.item.admission and not instance.order.event.settings.ticket_download_nonadm: if not instance.item.admission and not instance.order.event.settings.ticket_download_nonadm:
+14
View File
@@ -420,6 +420,20 @@ class Order(LoggedModel):
dl_date = dl_date.datetime(self.event) dl_date = dl_date.datetime(self.event)
return dl_date 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 @property
def payment_term_last(self): def payment_term_last(self):
tz = pytz.timezone(self.event.settings.timezone) tz = pytz.timezone(self.event.settings.timezone)
+1 -1
View File
@@ -634,7 +634,7 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str],
email_subject, email_template, email_context, email_subject, email_template, email_context,
log_entry, log_entry,
invoices=[invoice] if invoice and event.settings.invoice_email_attachment else [], invoices=[invoice] if invoice and event.settings.invoice_email_attachment else [],
attach_tickets=(payment_provider == 'free') attach_tickets=True
) )
except SendMailException: except SendMailException:
logger.exception('Order received email could not be sent') logger.exception('Order received email could not be sent')
+1 -6
View File
@@ -1,7 +1,6 @@
import logging import logging
import os import os
from datetime import timedelta from datetime import timedelta
from decimal import Decimal
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.utils.timezone import now 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)]) can_download = all([r for rr, r in allow_ticket_download.send(order.event, order=order)])
if not can_download: if not can_download:
return [] return []
if order.status != Order.STATUS_PAID and order.total != Decimal("0.00"): if not order.ticket_download_available:
return []
if (not order.event.settings.ticket_download
or (order.event.settings.ticket_download_date is not None
and now() < order.ticket_download_date)):
return [] return []
providers = [ providers = [
+4 -2
View File
@@ -949,12 +949,14 @@ class TicketSettingsForm(SettingsForm):
ticket_download_addons = forms.BooleanField( ticket_download_addons = forms.BooleanField(
label=_("Offer to download tickets separately for add-on products"), label=_("Offer to download tickets separately for add-on products"),
required=False, required=False,
widget=forms.CheckboxInput(attrs={'data-display-dependency': '#id_ticket_download'}),
) )
ticket_download_nonadm = forms.BooleanField( ticket_download_nonadm = forms.BooleanField(
label=_("Generate tickets for non-admission products"), label=_("Generate tickets for non-admission products"),
required=False, 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): def prepare_fields(self):
@@ -19,6 +19,7 @@
{% bootstrap_field form.ticket_download_date layout="control" %} {% bootstrap_field form.ticket_download_date layout="control" %}
{% bootstrap_field form.ticket_download_addons layout="control" %} {% bootstrap_field form.ticket_download_addons layout="control" %}
{% bootstrap_field form.ticket_download_nonadm layout="control" %} {% bootstrap_field form.ticket_download_nonadm layout="control" %}
{% bootstrap_field form.ticket_download_pending layout="control" %}
{% for provider in providers %} {% for provider in providers %}
<div class="panel panel-default ticketoutput-panel"> <div class="panel panel-default ticketoutput-panel">
<div class="panel-heading"> <div class="panel-heading">
@@ -84,28 +84,28 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
{% if order.status == 'p' and event.settings.ticket_download %} {% if can_download and download_buttons %}
{% if can_download and download_buttons %} <div class="alert alert-info">
<div class="alert alert-info"> {% blocktrans trimmed %}
{% blocktrans trimmed %} You can download your tickets using the buttons below. Please have your ticket ready when entering the event.
You can download your tickets using the buttons below. Please have your ticket ready when entering the event. {% endblocktrans %}
{% endblocktrans %} </div>
</div> {% if cart.positions|length > 1 and can_download_multi %}
{% if cart.positions|length > 1 and can_download_multi %} <p>
<p> {% trans "Download all tickets at once:" %}
{% trans "Download all tickets at once:" %} {% for b in download_buttons %}
{% for b in download_buttons %} {% if b.multi %}
{% if b.multi %} <a href="{% eventurl event "presale:event.order.download.combined" secret=order.secret order=order.code output=b.identifier %}"
<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 %}"
class="btn btn-sm {% if b.identifier == "pdf" %}btn-primary{% else %}btn-default{% endif %}" data-asyncdownload>
data-asyncdownload> <span class="fa {{ b.icon }}"></span> {{ b.text }}
<span class="fa {{ b.icon }}"></span> {{ b.text }} </a>
</a> {% endif %}
{% endif %} {% endfor %}
{% endfor %} </p>
</p> {% endif %}
{% endif %} {% elif not download_buttons and ticket_download_date %}
{% elif not download_buttons and ticket_download_date %} {% if order.status == 'p' %}
<div class="alert alert-info"> <div class="alert alert-info">
{% blocktrans trimmed with date=ticket_download_date|date:"SHORT_DATE_FORMAT" %} {% blocktrans trimmed with date=ticket_download_date|date:"SHORT_DATE_FORMAT" %}
You will be able to download your tickets here starting on {{ date }}. You will be able to download your tickets here starting on {{ date }}.
+3 -13
View File
@@ -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)]) 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: if self.request.event.settings.ticket_download_date:
ctx['ticket_download_date'] = self.order.ticket_download_date ctx['ticket_download_date'] = self.order.ticket_download_date
ctx['can_download'] = ( ctx['can_download'] = can_download and self.order.ticket_download_available
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['download_buttons'] = self.download_buttons ctx['download_buttons'] = self.download_buttons
ctx['cart'] = self.get_cart( ctx['cart'] = self.get_cart(
answers=True, downloads=ctx['can_download'], 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.')) return self.error(_('You requested an invalid ticket output type.'))
if not self.order or ('position' in kwargs and not self.order_position): 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.')) raise Http404(_('Unknown order code or not authorized to access this order.'))
if self.order.status != Order.STATUS_PAID: if not self.order.ticket_download_available:
return self.error(_('Order is not paid.')) return self.error(_('Ticket download is not (yet) enabled for this order.'))
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 'position' in kwargs and (self.order_position.addon_to and not self.request.event.settings.ticket_download_addons): 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.')) 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): if 'position' in kwargs and (not self.order_position.item.admission and not self.request.event.settings.ticket_download_nonadm):
+13
View File
@@ -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['downloads']) == 1
assert len(resp.data['positions'][0]['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 @pytest.mark.django_db
def test_payment_list(token_client, organizer, event, order): def test_payment_list(token_client, organizer, event, order):
+30
View File
@@ -306,6 +306,36 @@ class OrdersTest(TestCase):
assert 'alert-success' in response.rendered_content assert 'alert-success' in response.rendered_content
assert self.order.invoices.exists() 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): def test_orders_download(self):
self.event.settings.set('ticket_download', True) self.event.settings.set('ticket_download', True)
del self.event.settings['ticket_download_date'] del self.event.settings['ticket_download_date']