diff --git a/src/pretix/control/forms/filter.py b/src/pretix/control/forms/filter.py new file mode 100644 index 0000000000..f6cc4a3a3b --- /dev/null +++ b/src/pretix/control/forms/filter.py @@ -0,0 +1,45 @@ +from django import forms +from django.utils.translation import ugettext_lazy as _ + +from pretix.base.models import Organizer + + +class OrderSearchFilterForm(forms.Form): + query = forms.CharField( + label=_('Search for…'), + widget=forms.TextInput(attrs={ + 'placeholder': _('Search for…'), + 'autofocus': 'autofocus' + }), + required=False + ) + status = forms.ChoiceField( + label=_('Order status'), + choices=( + ('', _('All orders')), + ('p', _('Paid')), + ('n', _('Pending')), + ('o', _('Pending (overdue)')), + ('e', _('Expired')), + ('ne', _('Pending or expired')), + ('c', _('Canceled')), + ('r', _('Refunded')), + ), + required=False, + ) + organizer = forms.ModelChoiceField( + label=_('Organizer'), + queryset=Organizer.objects.none(), + required=False, + empty_label=_('All organizers') + ) + + def __init__(self, *args, **kwargs): + request = kwargs.pop('request') + super().__init__(*args, **kwargs) + if request.user.is_superuser: + self.fields['organizer'].queryset = Organizer.objects.all() + else: + self.fields['organizer'].queryset = Organizer.objects.filter( + pk__in=request.user.teams.values_list('organizer', flat=True) + ) diff --git a/src/pretix/control/templates/pretixcontrol/search/orders.html b/src/pretix/control/templates/pretixcontrol/search/orders.html index 210fe333f6..8516a0fba1 100644 --- a/src/pretix/control/templates/pretixcontrol/search/orders.html +++ b/src/pretix/control/templates/pretixcontrol/search/orders.html @@ -2,16 +2,25 @@ {% load i18n %} {% load eventurl %} {% load urlreplace %} +{% load bootstrap3 %} {% block title %}{% trans "Order search" %}{% endblock %} {% block content %}

{% trans "Order search" %}

-
-
- - - - + +
+ {% bootstrap_field filter_form.query layout='inline' %} +
+
+ {% bootstrap_field filter_form.status layout='inline' %} +
+
+ {% bootstrap_field filter_form.organizer layout='inline' %} +
+
+
diff --git a/src/pretix/control/views/search.py b/src/pretix/control/views/search.py index a3dafb64b2..8cb50bda82 100644 --- a/src/pretix/control/views/search.py +++ b/src/pretix/control/views/search.py @@ -1,7 +1,10 @@ from django.db.models import Q +from django.utils.functional import cached_property +from django.utils.timezone import now from django.views.generic import ListView from pretix.base.models import Order +from pretix.control.forms.filter import OrderSearchFilterForm class OrderSearch(ListView): @@ -10,6 +13,15 @@ class OrderSearch(ListView): paginate_by = 30 template_name = 'pretixcontrol/search/orders.html' + @cached_property + def filter_form(self): + return OrderSearchFilterForm(data=self.request.GET, request=self.request) + + def get_context_data(self, **kwargs): + ctx = super().get_context_data() + ctx['filter_form'] = self.filter_form + return ctx + def get_queryset(self): qs = Order.objects.all() if not self.request.user.is_superuser: @@ -20,22 +32,35 @@ class OrderSearch(ListView): can_view_orders=True).values_list('limit_events__id', flat=True)) ) - if self.request.GET.get("query", "") != "": - u = self.request.GET.get("query", "") - if "-" in u: - code = (Q(event__slug__icontains=u.split("-")[0]) - & Q(code__icontains=Order.normalize_code(u.split("-")[1]))) - else: - code = Q(code__icontains=Order.normalize_code(u)) - qs = qs.filter( - code - | Q(email__icontains=u) - | Q(positions__attendee_name__icontains=u) - | Q(positions__attendee_email__icontains=u) - | Q(invoice_address__name__icontains=u) - | Q(invoice_address__company__icontains=u) - ) - print(qs.query) + if self.filter_form.is_valid(): + fdata = self.filter_form.cleaned_data + if fdata.get('query'): + u = fdata.get('query') + if "-" in u: + code = (Q(event__slug__icontains=u.split("-")[0]) + & Q(code__icontains=Order.normalize_code(u.split("-")[1]))) + else: + code = Q(code__icontains=Order.normalize_code(u)) + qs = qs.filter( + code + | Q(email__icontains=u) + | Q(positions__attendee_name__icontains=u) + | Q(positions__attendee_email__icontains=u) + | Q(invoice_address__name__icontains=u) + | Q(invoice_address__company__icontains=u) + ) + + if fdata.get('status'): + s = fdata.get('status') + if s == 'o': + qs = qs.filter(status=Order.STATUS_PENDING, expires__lt=now().replace(hour=0, minute=0, second=0)) + elif s == 'ne': + qs = qs.filter(status__in=[Order.STATUS_PENDING, Order.STATUS_EXPIRED]) + else: + qs = qs.filter(status=s) + + if fdata.get('organizer'): + qs = qs.filter(event__organizer=fdata.get('organizer')) if self.request.GET.get("ordering", "") != "": p = self.request.GET.get("ordering", "")