Voucher list: Refactor to use filter form

This commit is contained in:
Raphael Michel
2018-02-02 15:20:26 +01:00
parent 8a3eaae29c
commit 4ed3df2b08
3 changed files with 143 additions and 55 deletions

View File

@@ -7,7 +7,7 @@ from django.utils.timezone import now
from django.utils.translation import pgettext_lazy, ugettext_lazy as _ from django.utils.translation import pgettext_lazy, ugettext_lazy as _
from pretix.base.models import ( from pretix.base.models import (
Event, Invoice, Item, Order, OrderPosition, Organizer, SubEvent, Checkin, Event, Invoice, Item, Order, OrderPosition, Organizer, SubEvent,
) )
from pretix.base.signals import register_payment_providers from pretix.base.signals import register_payment_providers
from pretix.control.forms.widgets import Select2 from pretix.control.forms.widgets import Select2
@@ -596,3 +596,95 @@ class UserFilterForm(FilterForm):
qs = qs.order_by(self.get_order_by()) qs = qs.order_by(self.get_order_by())
return qs return qs
class VoucherFilterForm(FilterForm):
orders = {
}
status = forms.ChoiceField(
label=_('Status'),
choices=(
('', _('All')),
('v', _('Valid')),
('r', _('Redeemed')),
('e', _('Expired')),
('c', _('Redeemed and checked in with ticket')),
),
required=False
)
tag = forms.CharField(
label=_('Filter by tag'),
widget=forms.TextInput(attrs={
'placeholder': _('Filter by tag'),
}),
required=False
)
search = forms.CharField(
label=_('Search voucher'),
widget=forms.TextInput(attrs={
'placeholder': _('Search voucher'),
'autofocus': 'autofocus'
}),
required=False
)
subevent = forms.ModelChoiceField(
label=pgettext_lazy('subevent', 'Date'),
queryset=SubEvent.objects.none(),
required=False,
empty_label=pgettext_lazy('subevent', 'All dates')
)
def __init__(self, *args, **kwargs):
self.event = kwargs.pop('event')
super().__init__(*args, **kwargs)
if self.event.has_subevents:
self.fields['subevent'].queryset = self.event.subevents.all()
self.fields['subevent'].widget = Select2(
attrs={
'data-model-select2': 'event',
'data-select2-url': reverse('control:event.subevents.select2', kwargs={
'event': self.event.slug,
'organizer': self.event.organizer.slug,
}),
'data-placeholder': pgettext_lazy('subevent', 'All dates')
}
)
self.fields['subevent'].widget.choices = self.fields['subevent'].choices
elif 'subevent':
del self.fields['subevent']
def filter_qs(self, qs):
fdata = self.cleaned_data
if fdata.get('search'):
s = fdata.get('search').strip()
qs = qs.filter(Q(code__icontains=s) | Q(tag__icontains=s) | Q(comment__icontains=s))
if fdata.get('tag'):
s = fdata.get('tag').strip()
qs = qs.filter(tag__icontains=s)
if fdata.get('status'):
s = fdata.get('status')
if s == 'v':
qs = qs.filter(Q(valid_until__isnull=True) | Q(valid_until__gt=now())).filter(redeemed=0)
elif s == 'r':
qs = qs.filter(redeemed__gt=0)
elif s == 'e':
qs = qs.filter(Q(valid_until__isnull=False) & Q(valid_until__lt=now())).filter(redeemed=0)
elif s == 'c':
checkins = Checkin.objects.filter(
position__voucher=OuterRef('pk')
)
qs = qs.annotate(has_checkin=Exists(checkins)).filter(
redeemed__gt=0, has_checkin=True
)
if fdata.get('subevent'):
qs = qs.filter(subevent_id=fdata.get('subevent').pk)
if fdata.get('ordering'):
qs = qs.order_by(self.get_order_by())
return qs

View File

@@ -1,5 +1,7 @@
{% extends "pretixcontrol/vouchers/base.html" %} {% extends "pretixcontrol/vouchers/base.html" %}
{% load i18n %} {% load i18n %}
{% load bootstrap3 %}
{% load urlreplace %}
{% block title %}{% trans "Vouchers" %}{% endblock %} {% block title %}{% trans "Vouchers" %}{% endblock %}
{% block inside %} {% block inside %}
<p> <p>
@@ -8,34 +10,36 @@
reserve some quota for your very special guests. reserve some quota for your very special guests.
{% endblocktrans %} {% endblocktrans %}
</p> </p>
<form class="form-inline helper-display-inline" action="" method="get"> <div class="row filter-form">
<p> <form class="" action="" method="get">
<input type="text" name="search" class="form-control" placeholder="{% trans "Search voucher" %}" <div class="col-md-3 col-xs-6">
value="{{ request.GET.search }}" autofocus> {% bootstrap_field filter_form.search layout='inline' %}
<input type="text" name="tag" class="form-control" placeholder="{% trans "Filter by tag" %}" </div>
value="{{ request.GET.tag }}"> <div class="col-md-3 col-xs-6">
<select name="status" class="form-control"> {% bootstrap_field filter_form.tag layout='inline' %}
<option value="">{% trans "All vouchers" %}</option> </div>
<option value="v" {% if request.GET.status == "v" %}selected="selected"{% endif %}>{% trans "Valid" %}</option>
<option value="r" {% if request.GET.status == "r" %}selected="selected"{% endif %}>{% trans "Redeemed" %}</option>
<option value="e" {% if request.GET.status == "e" %}selected="selected"{% endif %}>{% trans "Expired" %}</option>
<option value="c" {% if request.GET.status == "c" %}selected="selected"{% endif %}>{% trans "Redeemed and checked in with ticket" %}</option>
</select>
{% if request.event.has_subevents %} {% if request.event.has_subevents %}
<select name="subevent" class="form-control"> <div class="col-md-2 col-xs-6">
<option value="">{% trans "All dates" context "subevent" %}</option> {% bootstrap_field filter_form.status layout='inline' %}
{% for se in request.event.subevents.all %} </div>
<option value="{{ se.id }}" <div class="col-md-2 col-xs-6">
{% if request.GET.subevent|add:0 == se.id %}selected="selected"{% endif %}> {% bootstrap_field filter_form.subevent layout='inline' %}
{{ se.name }} {{ se.get_date_range_display }} </div>
</option> {% else %}
{% endfor %} <div class="col-md-4 col-xs-6">
</select> {% bootstrap_field filter_form.status layout='inline' %}
</div>
{% endif %} {% endif %}
<button class="btn btn-primary" type="submit">{% trans "Filter" %}</button> <div class="col-md-2 col-xs-6">
<button class="btn btn-default" type="submit" name="download" value="yes">{% trans "Download list" %}</button> <button class="btn btn-primary btn-block" type="submit">
</p> <span class="fa fa-filter"></span>
<span class="hidden-md">
{% trans "Filter" %}
</span>
</button>
</div>
</form> </form>
</div>
{% if vouchers|length == 0 %} {% if vouchers|length == 0 %}
<div class="empty-collection"> <div class="empty-collection">
<p> <p>
@@ -60,6 +64,9 @@
<a href="{% url "control:event.vouchers.bulk" organizer=request.event.organizer.slug event=request.event.slug %}" <a href="{% url "control:event.vouchers.bulk" organizer=request.event.organizer.slug event=request.event.slug %}"
class="btn btn-default"><i class="fa fa-plus"></i> class="btn btn-default"><i class="fa fa-plus"></i>
{% trans "Create multiple new vouchers" %}</a> {% trans "Create multiple new vouchers" %}</a>
<a href="?{% url_replace request "download" "yes" %}"
class="btn btn-default"><i class="fa fa-download"></i>
{% trans "Download list" %}</a>
</p> </p>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover table-quotas"> <table class="table table-hover table-quotas">

View File

@@ -5,19 +5,20 @@ from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.core.urlresolvers import resolve, reverse from django.core.urlresolvers import resolve, reverse
from django.db import transaction from django.db import transaction
from django.db.models import Exists, OuterRef, Q, Sum from django.db.models import Sum
from django.http import ( from django.http import (
Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect, Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect,
JsonResponse, JsonResponse,
) )
from django.utils.timezone import now from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.views.generic import ( from django.views.generic import (
CreateView, DeleteView, ListView, TemplateView, UpdateView, View, CreateView, DeleteView, ListView, TemplateView, UpdateView, View,
) )
from pretix.base.models import Checkin, Voucher from pretix.base.models import Voucher
from pretix.base.models.vouchers import _generate_random_code from pretix.base.models.vouchers import _generate_random_code
from pretix.control.forms.filter import VoucherFilterForm
from pretix.control.forms.vouchers import VoucherBulkForm, VoucherForm from pretix.control.forms.vouchers import VoucherBulkForm, VoucherForm
from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.permissions import EventPermissionRequiredMixin
from pretix.control.signals import voucher_form_class from pretix.control.signals import voucher_form_class
@@ -32,31 +33,19 @@ class VoucherList(PaginationMixin, EventPermissionRequiredMixin, ListView):
def get_queryset(self): def get_queryset(self):
qs = self.request.event.vouchers.all().select_related('item', 'variation') qs = self.request.event.vouchers.all().select_related('item', 'variation')
if self.request.GET.get("search", "") != "": if self.filter_form.is_valid():
s = self.request.GET.get("search", "").strip() qs = self.filter_form.filter_qs(qs)
qs = qs.filter(Q(code__icontains=s) | Q(tag__icontains=s) | Q(comment__icontains=s))
if self.request.GET.get("tag", "") != "": return qs.distinct()
s = self.request.GET.get("tag", "")
qs = qs.filter(tag__icontains=s) def get_context_data(self, **kwargs):
if self.request.GET.get("status", "") != "": ctx = super().get_context_data(**kwargs)
s = self.request.GET.get("status", "") ctx['filter_form'] = self.filter_form
if s == 'v': return ctx
qs = qs.filter(Q(valid_until__isnull=True) | Q(valid_until__gt=now())).filter(redeemed=0)
elif s == 'r': @cached_property
qs = qs.filter(redeemed__gt=0) def filter_form(self):
elif s == 'e': return VoucherFilterForm(data=self.request.GET, event=self.request.event)
qs = qs.filter(Q(valid_until__isnull=False) & Q(valid_until__lt=now())).filter(redeemed=0)
elif s == 'c':
checkins = Checkin.objects.filter(
position__voucher=OuterRef('pk')
)
qs = qs.annotate(has_checkin=Exists(checkins)).filter(
redeemed__gt=0, has_checkin=True
)
if self.request.GET.get("subevent", "") != "":
s = self.request.GET.get("subevent", "")
qs = qs.filter(subevent_id=s)
return qs
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
if request.GET.get("download", "") == "yes": if request.GET.get("download", "") == "yes":