mirror of
https://github.com/pretix/pretix.git
synced 2026-05-06 15:24:02 +00:00
* [WIP] manual check-in of attendees This enables manual check-in of attendees. The post-code was heavily copied from the APIRedeemView of the pretixdroid, thus so far this seems to be working, but I have a few questions: The checkin-Objects generated by the pretixdroid-app have a nonce. Should the checkin object generated here have a nonce, too? Should the result of the check-in be noted in any other way than by the change of the status? * addressed review comments * implement unit test for manual checkin * fix style-issues * Slight layout change * Log who did the manual check-in * Improve unit test to check the result of the action
123 lines
5.2 KiB
Python
123 lines
5.2 KiB
Python
from django.contrib import messages
|
|
from django.core.urlresolvers import reverse
|
|
from django.db.models import F, Prefetch, Q
|
|
from django.db.models.functions import Coalesce
|
|
from django.shortcuts import redirect
|
|
from django.utils.timezone import now
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.views.generic import ListView
|
|
|
|
from pretix.base.models import Checkin, Item, Order, OrderPosition
|
|
from pretix.control.permissions import EventPermissionRequiredMixin
|
|
|
|
|
|
class CheckInView(EventPermissionRequiredMixin, ListView):
|
|
model = Checkin
|
|
context_object_name = 'entries'
|
|
paginate_by = 30
|
|
template_name = 'pretixcontrol/checkin/index.html'
|
|
permission = 'can_view_orders'
|
|
|
|
def get_queryset(self):
|
|
|
|
qs = OrderPosition.objects.filter(order__event=self.request.event, order__status='p')
|
|
|
|
# if this setting is False, we check only items for admission
|
|
if not self.request.event.settings.ticket_download_nonadm:
|
|
qs = qs.filter(item__admission=True)
|
|
|
|
if self.request.GET.get("status", "") != "":
|
|
p = self.request.GET.get("status", "")
|
|
if p == '1':
|
|
# records with check-in record
|
|
qs = qs.filter(checkins__isnull=False)
|
|
elif p == '0':
|
|
qs = qs.filter(checkins__isnull=True)
|
|
|
|
if self.request.GET.get("user", "") != "":
|
|
u = self.request.GET.get("user", "")
|
|
qs = qs.filter(
|
|
Q(order__email__icontains=u) | Q(attendee_name__icontains=u) | Q(attendee_email__icontains=u)
|
|
)
|
|
|
|
if self.request.GET.get("item", "") != "":
|
|
u = self.request.GET.get("item", "")
|
|
qs = qs.filter(item_id=u)
|
|
|
|
if self.request.GET.get("subevent", "") != "":
|
|
s = self.request.GET.get("subevent", "")
|
|
qs = qs.filter(subevent_id=s)
|
|
|
|
qs = qs.prefetch_related(
|
|
Prefetch('checkins', queryset=Checkin.objects.filter(position__order__event=self.request.event))
|
|
).select_related('order', 'item', 'addon_to')
|
|
|
|
if self.request.GET.get("ordering", "") != "":
|
|
p = self.request.GET.get("ordering", "")
|
|
keys_allowed = self.get_ordering_keys_mappings()
|
|
if p in keys_allowed:
|
|
mapped_field = keys_allowed[p]
|
|
if isinstance(mapped_field, dict):
|
|
order = mapped_field.pop('_order')
|
|
qs = qs.annotate(**mapped_field).order_by(order)
|
|
elif isinstance(mapped_field, (list, tuple)):
|
|
qs = qs.order_by(*mapped_field)
|
|
else:
|
|
qs = qs.order_by(mapped_field)
|
|
|
|
return qs.distinct()
|
|
|
|
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 "user" in self.request.GET or "item" in self.request.GET
|
|
or "subevent" in self.request.GET)
|
|
return ctx
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
positions = OrderPosition.objects.select_related('item', 'variation', 'order', 'addon_to').filter(
|
|
order__event=self.request.event,
|
|
pk__in=request.POST.getlist('checkin')
|
|
)
|
|
|
|
for op in positions:
|
|
created = False
|
|
if op.order.status == Order.STATUS_PAID:
|
|
ci, created = Checkin.objects.get_or_create(position=op, defaults={
|
|
'datetime': now(),
|
|
})
|
|
op.order.log_action('pretix.control.views.checkin', data={
|
|
'position': op.id,
|
|
'positionid': op.positionid,
|
|
'first': created,
|
|
'datetime': now()
|
|
}, user=request.user)
|
|
|
|
messages.success(request, _('The selected tickets have been marked as checked in.'))
|
|
return redirect(reverse('control:event.orders.checkins', kwargs={
|
|
'event': self.request.event.slug,
|
|
'organizer': self.request.event.organizer.slug
|
|
}) + '?' + request.GET.urlencode())
|
|
|
|
@staticmethod
|
|
def get_ordering_keys_mappings():
|
|
return {
|
|
'code': 'order__code',
|
|
'-code': '-order__code',
|
|
'email': 'order__email',
|
|
'-email': '-order__email',
|
|
# Set nulls_first to be consistent over databases
|
|
'status': F('checkins__id').asc(nulls_first=True),
|
|
'-status': F('checkins__id').desc(nulls_last=True),
|
|
'timestamp': F('checkins__datetime').asc(nulls_first=True),
|
|
'-timestamp': F('checkins__datetime').desc(nulls_last=True),
|
|
'item': ('item__name', 'variation__value'),
|
|
'-item': ('-item__name', 'variation__value'),
|
|
'subevent': ('subevent__date_from', 'subevent__name'),
|
|
'-subevent': ('-subevent__date_from', '-subevent__name'),
|
|
'name': {'_order': F('display_name').asc(nulls_first=True),
|
|
'display_name': Coalesce('attendee_name', 'addon_to__attendee_name')},
|
|
'-name': {'_order': F('display_name').desc(nulls_last=True),
|
|
'display_name': Coalesce('attendee_name', 'addon_to__attendee_name')},
|
|
}
|