Add waiting list

This commit is contained in:
Raphael Michel
2016-03-31 19:00:41 +02:00
parent 8f5849a90c
commit c83f539bba
29 changed files with 1216 additions and 26 deletions

View File

@@ -12,7 +12,9 @@ from django.utils import formats
from django.utils.formats import date_format
from django.utils.translation import ugettext_lazy as _
from pretix.base.models import Event, Item, Order, OrderPosition, Voucher
from pretix.base.models import (
Event, Item, Order, OrderPosition, Voucher, WaitingListEntry,
)
from pretix.control.signals import (
event_dashboard_widgets, user_dashboard_widgets,
)
@@ -85,9 +87,53 @@ def base_widgets(sender, **kwargs):
]
@receiver(signal=event_dashboard_widgets)
def waitinglist_widgets(sender, **kwargs):
widgets = []
wles = WaitingListEntry.objects.filter(event=sender)
if wles.count():
quota_cache = {}
itemvar_cache = {}
happy = 0
for wle in wles:
if (wle.item, wle.variation) not in itemvar_cache:
itemvar_cache[(wle.item, wle.variation)] = (
wle.variation.check_quotas(count_waitinglist=False, _cache=quota_cache)
if wle.variation
else wle.item.check_quotas(count_waitinglist=False, _cache=quota_cache)
)
row = itemvar_cache.get((wle.item, wle.variation))
if row[1] > 0:
itemvar_cache[(wle.item, wle.variation)] = (row[0], row[1] - 1)
happy += 1
widgets.append({
'content': NUM_WIDGET.format(num=str(happy), text=_('available to give to people on waiting list')),
'priority': 50,
'url': reverse('control:event.orders.waitinglist', kwargs={
'event': sender.slug,
'organizer': sender.organizer.slug,
})
})
widgets.append({
'content': NUM_WIDGET.format(num=str(wles.count()), text=_('total waiting list length')),
'display_size': 'small',
'priority': 50,
'url': reverse('control:event.orders.waitinglist', kwargs={
'event': sender.slug,
'organizer': sender.organizer.slug,
})
})
return widgets
@receiver(signal=event_dashboard_widgets)
def quota_widgets(sender, **kwargs):
widgets = []
for q in sender.quotas.all():
status, left = q.availability()
widgets.append({

View File

@@ -607,24 +607,33 @@ class QuotaView(ChartContainingView, DetailView):
data = [
{
'label': ugettext('Paid orders'),
'value': self.object.count_paid_orders()
'value': self.object.count_paid_orders(),
'sum': True,
},
{
'label': ugettext('Pending orders'),
'value': self.object.count_pending_orders()
'value': self.object.count_pending_orders(),
'sum': True,
},
{
'label': ugettext('Vouchers'),
'value': self.object.count_blocking_vouchers()
'value': self.object.count_blocking_vouchers(),
'sum': True,
},
{
'label': ugettext('Current user\'s carts'),
'value': self.object.count_in_cart()
}
'value': self.object.count_in_cart(),
'sum': True,
},
{
'label': ugettext('Waiting list'),
'value': self.object.count_waiting_list_pending(),
'sum': False,
},
]
ctx['quota_table_rows'] = list(data)
sum_values = sum([d['value'] for d in data])
sum_values = sum([d['value'] for d in data if d['sum']])
if self.object.size is not None:
data.append({

View File

@@ -0,0 +1,127 @@
from django.contrib import messages
from django.db.models import Sum
from django.db.models.functions import Coalesce
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from django.views import View
from django.views.generic import ListView
from pretix.base.models import Item, WaitingListEntry
from pretix.base.models.waitinglist import WaitingListException
from pretix.base.services.waitinglist import assign_automatically
from pretix.base.views.async import AsyncAction
from pretix.control.permissions import EventPermissionRequiredMixin
class AutoAssign(EventPermissionRequiredMixin, AsyncAction, View):
task = assign_automatically
known_errortypes = ['WaitingListError']
permission = 'can_change_orders'
def get_success_message(self, value):
return _('{num} vouchers have been created and sent out via email.').format(num=value)
def get_success_url(self, value):
return self.get_error_url()
def get_error_url(self):
return reverse('control:event.orders.waitinglist', kwargs={
'event': self.request.event.slug,
'organizer': self.request.event.organizer.slug
})
def post(self, request, *args, **kwargs):
return self.do(self.request.event.id)
class WaitingListView(EventPermissionRequiredMixin, ListView):
model = WaitingListEntry
context_object_name = 'entries'
paginate_by = 30
template_name = 'pretixcontrol/waitinglist/index.html'
permission = 'can_view_orders'
def post(self, request, *args, **kwargs):
if 'assign' in request.POST:
if not request.eventperm.can_change_orders:
messages.error(request, _('You do not have permission to do this'))
return redirect(reverse('control:event.orders.waitinglist', kwargs={
'event': request.event.slug,
'organizer': request.event.organizer.slug
}))
try:
wle = WaitingListEntry.objects.get(
pk=request.POST.get('assign'), event=self.request.event,
)
try:
wle.send_voucher()
except WaitingListException as e:
messages.error(request, str(e))
else:
messages.success(request, _('An email containing a voucher code has been sent to the '
'specified address.'))
return redirect(reverse('control:event.orders.waitinglist', kwargs={
'event': request.event.slug,
'organizer': request.event.organizer.slug
}))
except WaitingListEntry.DoesNotExist:
messages.error(request, _('Waiting list entry not found.'))
return redirect(reverse('control:event.orders.waitinglist', kwargs={
'event': request.event.slug,
'organizer': request.event.organizer.slug
}))
def get_queryset(self):
qs = WaitingListEntry.objects.filter(
event=self.request.event
).select_related('item', 'variation', 'voucher').prefetch_related('item__quotas', 'variation__quotas')
s = self.request.GET.get("status", "")
if s == 's':
qs = qs.filter(voucher__isnull=False)
elif s == 'a':
pass
else:
qs = qs.filter(voucher__isnull=True)
if self.request.GET.get("item", "") != "":
i = self.request.GET.get("item", "")
qs = qs.filter(item_id__in=(i,))
return qs
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['items'] = Item.objects.filter(event=self.request.event)
ctx['filtered'] = ("status" in self.request.GET or "item" in self.request.GET)
itemvar_cache = {}
quota_cache = {}
any_avail = False
for wle in ctx[self.context_object_name]:
if (wle.item, wle.variation) in itemvar_cache:
wle.availability = itemvar_cache.get((wle.item, wle.variation))
else:
wle.availability = (
wle.variation.check_quotas(count_waitinglist=False, _cache=quota_cache)
if wle.variation
else wle.item.check_quotas(count_waitinglist=False, _cache=quota_cache)
)
itemvar_cache[(wle.item, wle.variation)] = wle.availability
if wle.availability[0] == 100:
any_avail = True
ctx['any_avail'] = any_avail
ctx['estimate'] = self.get_sales_estimate()
return ctx
def get_sales_estimate(self):
qs = WaitingListEntry.objects.filter(
event=self.request.event, voucher__isnull=True
).aggregate(
s=Sum(
Coalesce('variation__default_price', 'item__default_price')
)
)
return qs['s']