Fix #785 -- Show availability in (sub)event list (#1112)

This commit is contained in:
Raphael Michel
2018-12-11 13:59:49 +01:00
committed by GitHub
parent eed220f14a
commit d267dfc682
17 changed files with 421 additions and 45 deletions

View File

@@ -2,10 +2,9 @@ from itertools import chain
from django import forms
from django.core.exceptions import ValidationError
from django.db.models import Count, Prefetch, Q
from django.db.models import Count, Prefetch
from django.utils.encoding import force_text
from django.utils.formats import number_format
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from pretix.base.forms.questions import (
@@ -204,12 +203,9 @@ class AddOnsForm(forms.Form):
ckey = '{}-{}'.format(subevent.pk if subevent else 0, category.pk)
if ckey not in item_cache:
# Get all items to possibly show
items = category.items.filter(
Q(active=True)
& Q(Q(available_from__isnull=True) | Q(available_from__lte=now()))
& Q(Q(available_until__isnull=True) | Q(available_until__gte=now()))
& Q(hide_without_voucher=False)
& Q(sales_channels__contains=self.sales_channel)
items = category.items.filter_available(
channel=self.sales_channel,
allow_addons=True
).select_related('tax_rule').prefetch_related(
Prefetch('quotas',
to_attr='_subevent_quotas',

View File

@@ -38,4 +38,4 @@
</div>
</div>
</form>
{% include "pretixpresale/fragment_calendar.html" %}
{% include "pretixpresale/fragment_calendar.html" with show_avail=event.settings.event_list_availability %}

View File

@@ -1,6 +1,6 @@
{% load i18n %}
{% load eventurl %}
{% for subev in event.subevent_list_subevents %}
{% for subev in subevent_list %}
<a href="{% eventurl event "presale:event.index" subevent=subev.id cart_namespace=cart_namespace %}"
class="subevent-row">
<div class="row">
@@ -16,7 +16,17 @@
{% endif %}
</div>
<div class="col-md-2 text-right">
{% if subev.presale_is_running %}
{% if subev.presale_is_running and event.settings.event_list_availability %}
{% if subev.best_availability_state == 100 %}
<span class="label label-success">{% trans "Tickets on sale" %}</span>
{% elif event.settings.waiting_list_enabled and subev.best_availability_state >= 0 %}
<span class="label label-warning">{% trans "Waiting list" %}</span>
{% elif subev.best_availability_state == 20 %}
<span class="label label-warning">{% trans "Reserved" %}</span>
{% elif subev.best_availability_state < 20 %}
<span class="label label-danger">{% trans "Sold out" %}</span>
{% endif %}
{% elif subev.presale_is_running %}
<span class="label label-success">{% trans "Tickets on sale" %}</span>
{% elif subev.presale_has_ended %}
<span class="label label-danger">{% trans "Sale over" %}</span>

View File

@@ -38,7 +38,17 @@
</span>
{% endif %}
<span class="event-status">
{% if event.event.presale_is_running %}
{% if event.event.presale_is_running and show_avail %}
{% if event.event.best_availability_state == 100 %}
<span class="fa fa-ticket"></span> {% trans "Tickets on sale" %}
{% elif event.event.settings.waiting_list_enabled and event.event.best_availability_state >= 0 %}
<span class="fa fa-ticket"></span> {% trans "Waiting list" %}
{% elif event.event.best_availability_state == 20 %}
<span class="fa fa-ticket"></span> {% trans "Reserved" %}
{% elif event.event.best_availability_state < 20 %}
<span class="fa fa-ticket"></span> {% trans "Sold out" %}
{% endif %}
{% elif event.event.presale_is_running %}
<span class="fa fa-ticket"></span> {% trans "Tickets on sale" %}
{% elif event.event.presale_has_ended %}
<span class="fa fa-ticket"></span> {% trans "Sale over" %}

View File

@@ -64,7 +64,7 @@
</div>
</div>
</form>
{% include "pretixpresale/fragment_calendar.html" %}
{% include "pretixpresale/fragment_calendar.html" with show_avail=request.organizer.settings.event_list_availability %}
{% if multiple_timezones %}
<div class="alert alert-info">

View File

@@ -45,19 +45,50 @@
<tr>
<th>{% trans "Name" %}</th>
<th>{% trans "Date" %}</th>
<th>{% trans "Status" %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for e in events %}{% eventurl e "presale:event.index" as url %}
<tr>
<td><a href="{{ url }}">{{ e.name }}</a></td>
<td>
<a href="{{ url }}">{{ e.name }}</a>
</td>
<td>
{{ e.daterange|default:e.get_date_range_display }}
</td>
<td>
{% if e.has_subevents %}
<span class="label label-default">{% trans "Event series" %}</span>
{% elif e.presale_is_running and request.organizer.settings.event_list_availability %}
{% if e.best_availability_state == 100 %}
<span class="label label-success">{% trans "Tickets on sale" %}</span>
{% elif e.settings.waiting_list_enabled and e.best_availability_state >= 0 %}
<span class="label label-warning">{% trans "Waiting list" %}</span>
{% elif e.best_availability_state == 20 %}
<span class="label label-warning">{% trans "Reserved" %}</span>
{% elif e.best_availability_state < 20 %}
<span class="label label-danger">{% trans "Sold out" %}</span>
{% endif %}
{% elif e.presale_is_running %}
<span class="label label-success">{% trans "Tickets on sale" %}</span>
{% elif e.presale_has_ended %}
<span class="label label-danger">{% trans "Sale over" %}</span>
{% elif e.settings.presale_start_show_date %}
<span class="label label-warning">
{% blocktrans trimmed with date=subev.presale_start|date:"SHORT_DATE_FORMAT" %}
Sale starts {{ date }}
{% endblocktrans %}
</span>
{% else %}
<span class="label label-warning">{% trans "Not yet on sale" %}</span>
{% endif %}
</td>
<td class="text-right">
<a class="btn btn-primary" href="{{ url }}">
{% if e.presale_is_running %}{% trans "Buy tickets" %}
{% if e.has_subevents %}{% trans "Buy tickets" %}
{% elif e.presale_is_running and e.best_availability_state == 100 %}{% trans "Buy tickets" %}
{% else %}{% trans "More info" %}
{% endif %}
</a>

View File

@@ -7,7 +7,7 @@ from importlib import import_module
import pytz
from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.db.models import Count, Prefetch, Q
from django.db.models import Count, Prefetch
from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.decorators import method_decorator
@@ -48,23 +48,7 @@ def item_group_by_category(items):
def get_grouped_items(event, subevent=None, voucher=None, channel='web'):
items = event.items.all().filter(
Q(active=True)
& Q(Q(available_from__isnull=True) | Q(available_from__lte=now()))
& Q(Q(available_until__isnull=True) | Q(available_until__gte=now()))
& Q(Q(category__isnull=True) | Q(category__is_addon=False))
& Q(sales_channels__contains=channel)
)
vouchq = Q(hide_without_voucher=False)
if voucher:
if voucher.item_id:
vouchq |= Q(pk=voucher.item_id)
items = items.filter(pk=voucher.item_id)
elif voucher.quota_id:
items = items.filter(quotas__in=[voucher.quota_id])
items = items.filter(vouchq).select_related(
items = event.items.filter_available(channel=channel, voucher=voucher).select_related(
'category', 'tax_rule', # for re-grouping
).prefetch_related(
Prefetch('quotas',
@@ -291,12 +275,19 @@ class EventIndex(EventViewMixin, CartMixin, TemplateView):
context['after'] = after
ebd = defaultdict(list)
add_subevents_for_days(self.request.event.subevents.all(), before, after, ebd, set(), self.request.event,
kwargs.get('cart_namespace'))
add_subevents_for_days(
self.request.event.subevents_annotated(self.request.sales_channel),
before, after, ebd, set(), self.request.event,
kwargs.get('cart_namespace')
)
context['weeks'] = weeks_for_template(ebd, self.year, self.month)
context['months'] = [date(self.year, i + 1, 1) for i in range(12)]
context['years'] = range(now().year - 2, now().year + 3)
else:
context['subevent_list'] = self.request.event.subevents_sorted(
self.request.event.subevents_annotated(self.request.sales_channel)
)
context['show_cart'] = (
context['cart']['positions'] and (

View File

@@ -128,7 +128,7 @@ class OrganizerIndex(OrganizerViewMixin, ListView):
).annotate(
order_from=Coalesce('min_from', 'date_from'),
).order_by('order_from')
qs = filter_qs_by_attr(qs, self.request)
qs = Event.annotated(filter_qs_by_attr(qs, self.request))
return qs
def get_context_data(self, **kwargs):
@@ -314,14 +314,14 @@ class CalendarView(OrganizerViewMixin, TemplateView):
def _events_by_day(self, before, after):
ebd = defaultdict(list)
timezones = set()
add_events_for_days(self.request, self.request.organizer.events, before, after, ebd, timezones)
add_subevents_for_days(filter_qs_by_attr(SubEvent.objects.filter(
add_events_for_days(self.request, Event.annotated(self.request.organizer.events, 'web'), before, after, ebd, timezones)
add_subevents_for_days(filter_qs_by_attr(SubEvent.annotated(SubEvent.objects.filter(
event__organizer=self.request.organizer,
event__is_public=True,
event__live=True,
).prefetch_related(
'event___settings_objects', 'event__organizer___settings_objects'
), self.request), before, after, ebd, timezones)
)), self.request), before, after, ebd, timezones)
self._multiple_timezones = len(timezones) > 1
return ebd