Use FilterForm for list of orders

This commit is contained in:
Raphael Michel
2017-06-28 17:28:30 +02:00
parent c2bd2f0672
commit 8ea9d5685d
5 changed files with 157 additions and 120 deletions

View File

@@ -1,10 +1,13 @@
from django import forms from django import forms
from django.db.models import Q
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from pretix.base.models import Organizer from pretix.base.models import Item, Order, Organizer
from pretix.base.signals import register_payment_providers
class OrderSearchFilterForm(forms.Form): class OrderFilterForm(forms.Form):
query = forms.CharField( query = forms.CharField(
label=_('Search for…'), label=_('Search for…'),
widget=forms.TextInput(attrs={ widget=forms.TextInput(attrs={
@@ -27,6 +30,88 @@ class OrderSearchFilterForm(forms.Form):
), ),
required=False, required=False,
) )
def filter_qs(self, qs):
fdata = self.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)
return qs
@property
def filtered(self):
return self.is_valid() and any(self.cleaned_data.values())
class EventOrderFilterForm(OrderFilterForm):
item = forms.ModelChoiceField(
label=_('Products'),
queryset=Item.objects.none(),
required=False,
empty_label=_('All products')
)
provider = forms.ChoiceField(
label=_('Payment provider'),
choices=[
('', _('All payment providers')),
],
required=False,
)
def get_payment_providers(self):
providers = []
responses = register_payment_providers.send(self.event)
for receiver, response in responses:
provider = response(self.event)
providers.append({
'name': provider.identifier,
'verbose_name': provider.verbose_name
})
return providers
def __init__(self, *args, **kwargs):
self.event = kwargs.pop('event')
super().__init__(*args, **kwargs)
self.fields['item'].queryset = self.event.items.all()
self.fields['provider'].choices += [(p['name'], p['verbose_name']) for p in self.get_payment_providers()]
def filter_qs(self, qs):
fdata = self.cleaned_data
qs = super().filter_qs(qs)
if fdata.get('item'):
qs = qs.filter(positions__item_id__in=(fdata.get('item'),))
if fdata.get('provider'):
qs = qs.filter(payment_provider=fdata.get('provider'))
return qs
class OrderSearchFilterForm(OrderFilterForm):
organizer = forms.ModelChoiceField( organizer = forms.ModelChoiceField(
label=_('Organizer'), label=_('Organizer'),
queryset=Organizer.objects.none(), queryset=Organizer.objects.none(),
@@ -43,3 +128,12 @@ class OrderSearchFilterForm(forms.Form):
self.fields['organizer'].queryset = Organizer.objects.filter( self.fields['organizer'].queryset = Organizer.objects.filter(
pk__in=request.user.teams.values_list('organizer', flat=True) pk__in=request.user.teams.values_list('organizer', flat=True)
) )
def filter_qs(self, qs):
fdata = self.cleaned_data
qs = super().filter_qs(qs)
if fdata.get('organizer'):
qs = qs.filter(event__organizer=fdata.get('organizer'))
return qs

View File

@@ -2,6 +2,7 @@
{% load i18n %} {% load i18n %}
{% load eventurl %} {% load eventurl %}
{% load urlreplace %} {% load urlreplace %}
{% load bootstrap3 %}
{% block title %}{% trans "Orders" %}{% endblock %} {% block title %}{% trans "Orders" %}{% endblock %}
{% block content %} {% block content %}
<h1>{% trans "Orders" %}</h1> <h1>{% trans "Orders" %}</h1>
@@ -25,64 +26,60 @@
{% endif %} {% endif %}
</div> </div>
{% else %} {% else %}
<p> <div class="row filter-form">
<form class="form-inline helper-display-inline" <form class="col-md-2 col-xs-12"
action="{% url "control:event.orders.go" event=request.event.slug organizer=request.event.organizer.slug %}"> action="{% url "control:event.orders.go" event=request.event.slug organizer=request.event.organizer.slug %}">
<div class="input-group"> <div class="input-group">
<input type="text" name="code" class="form-control" placeholder="{% trans "Order code" %}" autofocus> <input type="text" name="code" class="form-control" placeholder="{% trans "Order code" %}" autofocus>
<span class="input-group-btn"> <span class="input-group-btn">
<button class="btn btn-primary" type="submit">{% trans "Go!" %}</button> <button class="btn btn-primary" type="submit">{% trans "Go!" %}</button>
</span> </span>
</div> </div>
</form> </form>
<form class="form-inline helper-display-inline" action="" method="get"> <form class="" action="" method="get">
<select name="status" class="form-control"> <div class="col-md-2 col-xs-6">
<option value="">{% trans "All orders" %}</option> {% bootstrap_field filter_form.status layout='inline' %}
<option value="p" {% if request.GET.status == "p" %}selected="selected"{% endif %}>{% trans "Paid" %}</option> </div>
<option value="n" {% if request.GET.status == "n" %}selected="selected"{% endif %}>{% trans "Pending" %}</option> <div class="col-md-2 col-xs-6">
<option value="o" {% if request.GET.status == "o" %}selected="selected"{% endif %}>{% trans "Pending (overdue)" %}</option> {% bootstrap_field filter_form.item layout='inline' %}
<option value="e" {% if request.GET.status == "e" %}selected="selected"{% endif %}>{% trans "Expired" %}</option> </div>
<option value="ne" {% if request.GET.status == "ne" %}selected="selected"{% endif %}>{% trans "Pending or expired" %}</option> <div class="col-md-2 col-xs-6">
<option value="c" {% if request.GET.status == "c" %}selected="selected"{% endif %}>{% trans "Canceled" %}</option> {% bootstrap_field filter_form.provider layout='inline' %}
<option value="r" {% if request.GET.status == "r" %}selected="selected"{% endif %}>{% trans "Refunded" %}</option> </div>
</select> <div class="col-md-2 col-xs-6">
<select name="item" class="form-control"> {% bootstrap_field filter_form.query layout='inline' %}
<option value="">{% trans "All products" %}</option> </div>
{% for item in items %} <div class="col-md-2 col-xs-6">
<option value="{{ item.id }}" <button class="btn btn-primary btn-block" type="submit">
{% if request.GET.item|add:0 == item.id %}selected="selected"{% endif %}> <span class="fa fa-filter"></span>
{{ item.name }} <span class="hidden-md">
</option> {% trans "Filter" %}
{% endfor %} </span>
</select> </button>
<select name="provider" class="form-control"> </div>
<option value="">{% trans "All payment providers" %}</option> </form>
{% for p in providers %} </div>
<option value="{{ p.name }}"
{% if request.GET.provider == p.name %}selected="selected"{% endif %}>
{{ p.verbose_name }}
</option>
{% endfor %}
</select>
<input type="text" name="user" class="form-control" placeholder="{% trans "Search user" %}" value="{{ request.GET.user }}">
<button class="btn btn-primary" type="submit">{% trans "Filter" %}</button>
</form>
</p>
{% include "pretixcontrol/pagination.html" %} {% include "pretixcontrol/pagination.html" %}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-condensed table-hover"> <table class="table table-condensed table-hover">
<thead> <thead>
<tr> <tr>
<th>{% trans "Order code" %} <a href="?{% url_replace request 'ordering' '-code'%}"><i class="fa fa-caret-down"></i></a> <th>{% trans "Order code" %}
<a href="?{% url_replace request 'ordering' 'code'%}"><i class="fa fa-caret-up"></i></a></th> <a href="?{% url_replace request 'ordering' '-code' %}"><i class="fa fa-caret-down"></i></a>
<th>{% trans "User" %} <a href="?{% url_replace request 'ordering' '-email'%}"><i class="fa fa-caret-down"></i></a> <a href="?{% url_replace request 'ordering' 'code' %}"><i class="fa fa-caret-up"></i></a></th>
<a href="?{% url_replace request 'ordering' 'email'%}"><i class="fa fa-caret-up"></i></a></th> <th>{% trans "User" %}
<th>{% trans "Order total" %} <a href="?{% url_replace request 'ordering' '-total'%}"><i class="fa fa-caret-down"></i></a> <a href="?{% url_replace request 'ordering' '-email' %}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'total'%}"><i class="fa fa-caret-up"></i></a></th> <a href="?{% url_replace request 'ordering' 'email' %}"><i class="fa fa-caret-up"></i></a></th>
<th>{% trans "Order date" %} <a href="?{% url_replace request 'ordering' '-datetime'%}"><i class="fa fa-caret-down"></i></a> <th>{% trans "Order total" %}
<a href="?{% url_replace request 'ordering' 'datetime'%}"><i class="fa fa-caret-up"></i></a></th> <a href="?{% url_replace request 'ordering' '-total' %}"><i class="fa fa-caret-down"></i></a>
<th>{% trans "Status" %} <a href="?{% url_replace request 'ordering' '-status'%}"><i class="fa fa-caret-down"></i></a> <a href="?{% url_replace request 'ordering' 'total' %}"><i class="fa fa-caret-up"></i></a></th>
<a href="?{% url_replace request 'ordering' 'status'%}"><i class="fa fa-caret-up"></i></a></th> <th>{% trans "Order date" %}
<a href="?{% url_replace request 'ordering' '-datetime' %}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'datetime' %}"><i class="fa fa-caret-up"></i></a>
</th>
<th>{% trans "Status" %}
<a href="?{% url_replace request 'ordering' '-status' %}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'status' %}"><i class="fa fa-caret-up"></i></a></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>

View File

@@ -19,7 +19,9 @@
<div class="col-md-2 col-sm-6 col-xs-12"> <div class="col-md-2 col-sm-6 col-xs-12">
<button class="btn btn-primary btn-block" type="submit"> <button class="btn btn-primary btn-block" type="submit">
<span class="fa fa-filter"></span> <span class="fa fa-filter"></span>
{% trans "Filter" %} <span class="hidden-md">
{% trans "Filter" %}
</span>
</button> </button>
</div> </div>
</form> </form>

View File

@@ -3,7 +3,6 @@ from datetime import timedelta
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db.models import Q
from django.http import FileResponse, Http404, HttpResponseNotAllowed from django.http import FileResponse, Http404, HttpResponseNotAllowed
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from django.utils.functional import cached_property from django.utils.functional import cached_property
@@ -31,6 +30,7 @@ from pretix.base.signals import (
register_data_exporters, register_payment_providers, register_data_exporters, register_payment_providers,
) )
from pretix.base.views.async import AsyncAction from pretix.base.views.async import AsyncAction
from pretix.control.forms.filter import EventOrderFilterForm
from pretix.control.forms.orders import ( from pretix.control.forms.orders import (
CommentForm, ExporterForm, ExtendForm, OrderContactForm, OrderLocaleForm, CommentForm, ExporterForm, ExtendForm, OrderContactForm, OrderLocaleForm,
OrderPositionAddForm, OrderPositionChangeForm, OrderPositionAddForm, OrderPositionChangeForm,
@@ -50,28 +50,9 @@ class OrderList(EventPermissionRequiredMixin, ListView):
qs = Order.objects.filter( qs = Order.objects.filter(
event=self.request.event event=self.request.event
) )
if self.request.GET.get("user", "") != "": if self.filter_form.is_valid():
u = self.request.GET.get("user", "") qs = self.filter_form.filter_qs(qs)
qs = qs.filter(
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 self.request.GET.get("status", "") != "":
s = self.request.GET.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 self.request.GET.get("item", "") != "":
i = self.request.GET.get("item", "")
qs = qs.filter(positions__item_id__in=(i,))
if self.request.GET.get("provider", "") != "":
p = self.request.GET.get("provider", "")
qs = qs.filter(payment_provider=p)
if self.request.GET.get("ordering", "") != "": if self.request.GET.get("ordering", "") != "":
p = self.request.GET.get("ordering", "") p = self.request.GET.get("ordering", "")
p_admissable = ('-code', 'code', '-email', 'email', '-total', 'total', '-datetime', 'datetime', '-status', 'status') p_admissable = ('-code', 'code', '-email', 'email', '-total', 'total', '-datetime', 'datetime', '-status', 'status')
@@ -80,24 +61,15 @@ class OrderList(EventPermissionRequiredMixin, ListView):
return qs.distinct() return qs.distinct()
def get_payment_providers(self):
providers = []
responses = register_payment_providers.send(self.request.event)
for receiver, response in responses:
provider = response(self.request.event)
providers.append({
'name': provider.identifier,
'verbose_name': provider.verbose_name
})
return providers
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs) ctx = super().get_context_data(**kwargs)
ctx['items'] = Item.objects.filter(event=self.request.event) ctx['filter_form'] = self.filter_form
ctx['filtered'] = ("status" in self.request.GET or "item" in self.request.GET or "user" in self.request.GET or "provider" in self.request.GET)
ctx['providers'] = self.get_payment_providers()
return ctx return ctx
@cached_property
def filter_form(self):
return EventOrderFilterForm(data=self.request.GET, event=self.request.event)
class OrderView(EventPermissionRequiredMixin, DetailView): class OrderView(EventPermissionRequiredMixin, DetailView):
context_object_name = 'order' context_object_name = 'order'

View File

@@ -1,6 +1,5 @@
from django.db.models import Q from django.db.models import Q
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.timezone import now
from django.views.generic import ListView from django.views.generic import ListView
from pretix.base.models import Order from pretix.base.models import Order
@@ -33,34 +32,7 @@ class OrderSearch(ListView):
) )
if self.filter_form.is_valid(): if self.filter_form.is_valid():
fdata = self.filter_form.cleaned_data qs = self.filter_form.filter_qs(qs)
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", "") != "": if self.request.GET.get("ordering", "") != "":
p = self.request.GET.get("ordering", "") p = self.request.GET.get("ordering", "")