Allow to enter a voucher before choosing a subevent

This commit is contained in:
Raphael Michel
2021-03-29 11:04:57 +02:00
parent 127c44d699
commit 2b660ccbf7
7 changed files with 49 additions and 17 deletions

View File

@@ -32,7 +32,7 @@
<label class="col-md-3 control-label" for="id_url">{% trans "Voucher link" %}</label> <label class="col-md-3 control-label" for="id_url">{% trans "Voucher link" %}</label>
<div class="col-md-9"> <div class="col-md-9">
<input type="text" name="url" <input type="text" name="url"
value="{% abseventurl request.event "presale:event.redeem" %}?voucher={{ voucher.code }}{% if voucher.subevent_id %}&subevent={{ voucher.subevent_id }}{% endif %}" value="{% abseventurl request.event "presale:event.redeem" %}?voucher={{ voucher.code|urlencode }}{% if voucher.subevent_id %}&subevent={{ voucher.subevent_id }}{% endif %}"
class="form-control" class="form-control"
id="id_url" readonly> id="id_url" readonly>
</div> </div>

View File

@@ -1,7 +1,7 @@
{% load i18n %} {% load i18n %}
{% load eventurl %} {% load eventurl %}
{% for subev in subevent_list %} {% for subev in subevent_list %}
<a href="{% eventurl event "presale:event.index" subevent=subev.id cart_namespace=cart_namespace %}" <a href="{% if request.GET.voucher %}{% eventurl event "presale:event.redeem" cart_namespace=cart_namespace %}?voucher={{ request.GET.voucher|urlencode }}&subevent={{ subev.pk }}{% else %}{% eventurl event "presale:event.index" subevent=subev.id cart_namespace=cart_namespace %}{% endif %}"
class="subevent-row"> class="subevent-row">
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">

View File

@@ -101,6 +101,12 @@
{{ frontpage_text|rich_text }} {{ frontpage_text|rich_text }}
</div> </div>
{% endif %} {% endif %}
{% if request.GET.voucher %}
<div class="alert alert-info">
{% trans "Please select a date to redeem your voucher." %}
</div>
{% endif %}
{% endif %} {% endif %}
{% if subevent and "year" not in request.GET %} {% if subevent and "year" not in request.GET %}

View File

@@ -10,7 +10,13 @@
{% block content %} {% block content %}
<h2>{% trans "Voucher redemption" %}</h2> <h2>{% trans "Voucher redemption" %}</h2>
{% if subevent %} {% if subevent %}
{% if request.GET.subevent and subevent.pk|stringformat:"i" != request.GET.subevent %}
<div class="alert alert-warning">
{% trans "This voucher is valid only for the following specific date and time." %}
</div>
{% endif %}
<h3>{{ subevent.name }}</h3> <h3>{{ subevent.name }}</h3>
{% with ev=subevent %} {% with ev=subevent %}
<div class="info-row"> <div class="info-row">

View File

@@ -518,7 +518,6 @@ class RedeemView(NoSearchIndexViewMixin, EventViewMixin, TemplateView):
kwargs={'cart_namespace': kwargs.get('cart_namespace') or ''}) kwargs={'cart_namespace': kwargs.get('cart_namespace') or ''})
if context['cart_redirect'].startswith('https:'): if context['cart_redirect'].startswith('https:'):
context['cart_redirect'] = '/' + context['cart_redirect'].split('/', 3)[3] context['cart_redirect'] = '/' + context['cart_redirect'].split('/', 3)[3]
return context return context
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
@@ -566,6 +565,10 @@ class RedeemView(NoSearchIndexViewMixin, EventViewMixin, TemplateView):
if hasattr(self, 'voucher') and self.voucher.subevent: if hasattr(self, 'voucher') and self.voucher.subevent:
self.subevent = self.voucher.subevent self.subevent = self.voucher.subevent
if not err and not self.subevent:
return redirect(eventreverse(self.request.event, 'presale:event.index',
kwargs={'cart_namespace': kwargs.get('cart_namespace') or ''}) + '?voucher=' + quote(self.voucher.code))
else: else:
pass pass

View File

@@ -23,7 +23,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.views.generic import TemplateView from django.views.generic import TemplateView
from pretix.base.channels import get_all_sales_channels from pretix.base.channels import get_all_sales_channels
from pretix.base.models import ItemVariation, Quota, SeatCategoryMapping from pretix.base.models import ItemVariation, Quota, SeatCategoryMapping, Voucher
from pretix.base.models.event import SubEvent from pretix.base.models.event import SubEvent
from pretix.base.models.items import ( from pretix.base.models.items import (
ItemBundle, SubEventItem, SubEventItemVariation, ItemBundle, SubEventItem, SubEventItemVariation,
@@ -375,6 +375,7 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
if vouchers_exist is None: if vouchers_exist is None:
vouchers_exist = self.request.event.vouchers.exists() vouchers_exist = self.request.event.vouchers.exists()
self.request.event.cache.set('vouchers_exist', vouchers_exist) self.request.event.cache.set('vouchers_exist', vouchers_exist)
context['show_vouchers'] = context['vouchers_exist'] = vouchers_exist
if not self.request.event.has_subevents or self.subevent: if not self.request.event.has_subevents or self.subevent:
# Fetch all items # Fetch all items
@@ -399,12 +400,6 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
context['items_by_category'] = item_group_by_category(items) context['items_by_category'] = item_group_by_category(items)
context['display_add_to_cart'] = display_add_to_cart context['display_add_to_cart'] = display_add_to_cart
context['show_vouchers'] = vouchers_exist
context['vouchers_exist'] = vouchers_exist
else:
context['show_vouchers'] = False
context['vouchers_exist'] = vouchers_exist
context['ev'] = self.subevent or self.request.event context['ev'] = self.subevent or self.request.event
context['subevent'] = self.subevent context['subevent'] = self.subevent
context['cart'] = self.get_cart() context['cart'] = self.get_cart()
@@ -434,6 +429,13 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
return context return context
def _subevent_list_context(self): def _subevent_list_context(self):
voucher = None
if self.request.GET.get('voucher'):
try:
voucher = Voucher.objects.get(code__iexact=self.request.GET.get('voucher'), event=self.request.event)
except Voucher.DoesNotExist:
pass
context = {} context = {}
context['list_type'] = self.request.GET.get("style", self.request.event.settings.event_list_type) context['list_type'] = self.request.GET.get("style", self.request.event.settings.event_list_type)
if context['list_type'] not in ("calendar", "week") and self.request.event.subevents.filter(date_from__gt=now()).count() > 50: if context['list_type'] not in ("calendar", "week") and self.request.event.subevents.filter(date_from__gt=now()).count() > 50:
@@ -456,7 +458,8 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
add_subevents_for_days( add_subevents_for_days(
filter_qs_by_attr(self.request.event.subevents_annotated(self.request.sales_channel.identifier).using(settings.DATABASE_REPLICA), self.request), filter_qs_by_attr(self.request.event.subevents_annotated(self.request.sales_channel.identifier).using(settings.DATABASE_REPLICA), self.request),
before, after, ebd, set(), self.request.event, before, after, ebd, set(), self.request.event,
self.kwargs.get('cart_namespace') self.kwargs.get('cart_namespace'),
voucher,
) )
context['show_names'] = ebd.get('_subevents_different_names', False) or sum( context['show_names'] = ebd.get('_subevents_different_names', False) or sum(
@@ -484,7 +487,9 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
add_subevents_for_days( add_subevents_for_days(
filter_qs_by_attr(self.request.event.subevents_annotated(self.request.sales_channel.identifier).using(settings.DATABASE_REPLICA), self.request), filter_qs_by_attr(self.request.event.subevents_annotated(self.request.sales_channel.identifier).using(settings.DATABASE_REPLICA), self.request),
before, after, ebd, set(), self.request.event, before, after, ebd, set(), self.request.event,
self.kwargs.get('cart_namespace') self.kwargs.get('cart_namespace'),
self.request.GET.get('voucher'),
voucher,
) )
context['show_names'] = ebd.get('_subevents_different_names', False) or sum( context['show_names'] = ebd.get('_subevents_different_names', False) or sum(
@@ -503,7 +508,7 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
context['subevent_list'] = self.request.event.subevents_sorted( context['subevent_list'] = self.request.event.subevents_sorted(
filter_qs_by_attr(self.request.event.subevents_annotated(self.request.sales_channel.identifier).using(settings.DATABASE_REPLICA), self.request) filter_qs_by_attr(self.request.event.subevents_annotated(self.request.sales_channel.identifier).using(settings.DATABASE_REPLICA), self.request)
) )
if self.request.event.settings.event_list_available_only: if self.request.event.settings.event_list_available_only and not voucher:
context['subevent_list'] = [ context['subevent_list'] = [
se for se in context['subevent_list'] se for se in context['subevent_list']
if not se.presale_has_ended and se.best_availability_state >= Quota.AVAILABILITY_RESERVED if not se.presale_has_ended and se.best_availability_state >= Quota.AVAILABILITY_RESERVED

View File

@@ -1,6 +1,7 @@
import calendar import calendar
from collections import defaultdict from collections import defaultdict
from datetime import date, datetime, time, timedelta from datetime import date, datetime, time, timedelta
from urllib.parse import quote
import isoweek import isoweek
import pytz import pytz
@@ -357,7 +358,7 @@ def add_events_for_days(request, baseqs, before, after, ebd, timezones):
}) })
def add_subevents_for_days(qs, before, after, ebd, timezones, event=None, cart_namespace=None): def add_subevents_for_days(qs, before, after, ebd, timezones, event=None, cart_namespace=None, voucher=None):
qs = qs.filter(active=True, is_public=True).filter( qs = qs.filter(active=True, is_public=True).filter(
Q(Q(date_to__gte=before) & Q(date_from__lte=after)) | Q(Q(date_to__gte=before) & Q(date_from__lte=after)) |
Q(Q(date_from__lte=after) & Q(date_to__gte=before)) | Q(Q(date_from__lte=after) & Q(date_to__gte=before)) |
@@ -365,6 +366,7 @@ def add_subevents_for_days(qs, before, after, ebd, timezones, event=None, cart_n
).order_by( ).order_by(
'date_from' 'date_from'
) )
quotas_to_compute = [] quotas_to_compute = []
for se in qs: for se in qs:
if se.presale_is_running: if se.presale_is_running:
@@ -388,7 +390,7 @@ def add_subevents_for_days(qs, before, after, ebd, timezones, event=None, cart_n
s = event.settings if event else se.event.settings s = event.settings if event else se.event.settings
if s.event_list_available_only: if s.event_list_available_only:
if se.presale_has_ended or se.best_availability_state < Quota.AVAILABILITY_RESERVED: if se.presale_has_ended or ((not voucher or not voucher.allow_ignore_quota) and se.best_availability_state < Quota.AVAILABILITY_RESERVED):
continue continue
timezones.add(s.timezones) timezones.add(s.timezones)
@@ -417,7 +419,12 @@ def add_subevents_for_days(qs, before, after, ebd, timezones, event=None, cart_n
else None else None
), ),
'event': se, 'event': se,
'url': eventreverse(se.event, 'presale:event.index', kwargs=kwargs) 'url': (
eventreverse(se.event, 'presale:event.redeem',
kwargs={k: v for k, v in kwargs.items() if k != 'subevent'}) + f'?subevent={se.pk}&voucher={quote(voucher.code)}'
if voucher
else eventreverse(se.event, 'presale:event.index', kwargs=kwargs)
)
}) })
d += timedelta(days=1) d += timedelta(days=1)
@@ -426,7 +433,12 @@ def add_subevents_for_days(qs, before, after, ebd, timezones, event=None, cart_n
'event': se, 'event': se,
'continued': False, 'continued': False,
'time': datetime_from.time().replace(tzinfo=None) if s.show_times else None, 'time': datetime_from.time().replace(tzinfo=None) if s.show_times else None,
'url': eventreverse(se.event, 'presale:event.index', kwargs=kwargs), 'url': (
eventreverse(se.event, 'presale:event.redeem',
kwargs={k: v for k, v in kwargs.items() if k != 'subevent'}) + f'?subevent={se.pk}&voucher={quote(voucher.code)}'
if voucher
else eventreverse(se.event, 'presale:event.index', kwargs=kwargs)
),
'timezone': s.timezone, 'timezone': s.timezone,
}) })