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.db.models import Q
from django.utils.timezone import now
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(
label=_('Search for…'),
widget=forms.TextInput(attrs={
@@ -27,6 +30,88 @@ class OrderSearchFilterForm(forms.Form):
),
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(
label=_('Organizer'),
queryset=Organizer.objects.none(),
@@ -43,3 +128,12 @@ class OrderSearchFilterForm(forms.Form):
self.fields['organizer'].queryset = Organizer.objects.filter(
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 eventurl %}
{% load urlreplace %}
{% load bootstrap3 %}
{% block title %}{% trans "Orders" %}{% endblock %}
{% block content %}
<h1>{% trans "Orders" %}</h1>
@@ -25,64 +26,60 @@
{% endif %}
</div>
{% else %}
<p>
<form class="form-inline helper-display-inline"
action="{% url "control:event.orders.go" event=request.event.slug organizer=request.event.organizer.slug %}">
<div class="input-group">
<input type="text" name="code" class="form-control" placeholder="{% trans "Order code" %}" autofocus>
<span class="input-group-btn">
<div class="row filter-form">
<form class="col-md-2 col-xs-12"
action="{% url "control:event.orders.go" event=request.event.slug organizer=request.event.organizer.slug %}">
<div class="input-group">
<input type="text" name="code" class="form-control" placeholder="{% trans "Order code" %}" autofocus>
<span class="input-group-btn">
<button class="btn btn-primary" type="submit">{% trans "Go!" %}</button>
</span>
</div>
</form>
<form class="form-inline helper-display-inline" action="" method="get">
<select name="status" class="form-control">
<option value="">{% trans "All orders" %}</option>
<option value="p" {% if request.GET.status == "p" %}selected="selected"{% endif %}>{% trans "Paid" %}</option>
<option value="n" {% if request.GET.status == "n" %}selected="selected"{% endif %}>{% trans "Pending" %}</option>
<option value="o" {% if request.GET.status == "o" %}selected="selected"{% endif %}>{% trans "Pending (overdue)" %}</option>
<option value="e" {% if request.GET.status == "e" %}selected="selected"{% endif %}>{% trans "Expired" %}</option>
<option value="ne" {% if request.GET.status == "ne" %}selected="selected"{% endif %}>{% trans "Pending or expired" %}</option>
<option value="c" {% if request.GET.status == "c" %}selected="selected"{% endif %}>{% trans "Canceled" %}</option>
<option value="r" {% if request.GET.status == "r" %}selected="selected"{% endif %}>{% trans "Refunded" %}</option>
</select>
<select name="item" class="form-control">
<option value="">{% trans "All products" %}</option>
{% for item in items %}
<option value="{{ item.id }}"
{% if request.GET.item|add:0 == item.id %}selected="selected"{% endif %}>
{{ item.name }}
</option>
{% endfor %}
</select>
<select name="provider" class="form-control">
<option value="">{% trans "All payment providers" %}</option>
{% for p in providers %}
<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>
</div>
</form>
<form class="" action="" method="get">
<div class="col-md-2 col-xs-6">
{% bootstrap_field filter_form.status layout='inline' %}
</div>
<div class="col-md-2 col-xs-6">
{% bootstrap_field filter_form.item layout='inline' %}
</div>
<div class="col-md-2 col-xs-6">
{% bootstrap_field filter_form.provider layout='inline' %}
</div>
<div class="col-md-2 col-xs-6">
{% bootstrap_field filter_form.query layout='inline' %}
</div>
<div class="col-md-2 col-xs-6">
<button class="btn btn-primary btn-block" type="submit">
<span class="fa fa-filter"></span>
<span class="hidden-md">
{% trans "Filter" %}
</span>
</button>
</div>
</form>
</div>
{% include "pretixcontrol/pagination.html" %}
<div class="table-responsive">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>{% trans "Order code" %} <a href="?{% url_replace request 'ordering' '-code'%}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'code'%}"><i class="fa fa-caret-up"></i></a></th>
<th>{% trans "User" %} <a href="?{% url_replace request 'ordering' '-email'%}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'email'%}"><i class="fa fa-caret-up"></i></a></th>
<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' 'total'%}"><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>
<th>{% trans "Order code" %}
<a href="?{% url_replace request 'ordering' '-code' %}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'code' %}"><i class="fa fa-caret-up"></i></a></th>
<th>{% trans "User" %}
<a href="?{% url_replace request 'ordering' '-email' %}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'email' %}"><i class="fa fa-caret-up"></i></a></th>
<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' 'total' %}"><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>
</thead>
<tbody>

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
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
@@ -33,34 +32,7 @@ class OrderSearch(ListView):
)
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'))
qs = self.filter_form.filter_qs(qs)
if self.request.GET.get("ordering", "") != "":
p = self.request.GET.get("ordering", "")