From e57ab7f03055b7bcdf7a4e81e933886dc9029374 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Wed, 18 Oct 2017 13:53:11 +0200 Subject: [PATCH] Allow filtering by payment provider in order search --- src/pretix/base/payment.py | 11 +++ src/pretix/control/forms/filter.py | 69 +++++++++++++------ .../pretixcontrol/search/orders.html | 7 +- src/pretix/plugins/stripe/payment.py | 1 + 4 files changed, 64 insertions(+), 24 deletions(-) diff --git a/src/pretix/base/payment.py b/src/pretix/base/payment.py index 516ab16e39..a9b6e19a49 100644 --- a/src/pretix/base/payment.py +++ b/src/pretix/base/payment.py @@ -50,6 +50,17 @@ class BasePaymentProvider: def __str__(self): return self.identifier + @property + def is_meta(self) -> bool: + """ + Returns whether or whether not this payment provider is a "meta" payment provider that only + works as a settings holder for other payment providers and should never be used directly. This + is a trick to implement payment gateways with multiple payment methods but unified payment settings. + Take a look at the built-in stripe provider to see how this might be used. + By default, this returns ``False``. + """ + return False + @property def is_enabled(self) -> bool: """ diff --git a/src/pretix/control/forms/filter.py b/src/pretix/control/forms/filter.py index c6660dc2c4..e461d1da61 100644 --- a/src/pretix/control/forms/filter.py +++ b/src/pretix/control/forms/filter.py @@ -1,12 +1,47 @@ from django import forms +from django.apps import apps from django.db.models import Exists, OuterRef, Q from django.db.models.functions import Concat from django.utils.timezone import now from django.utils.translation import pgettext_lazy, ugettext_lazy as _ -from pretix.base.models import Invoice, Item, Order, Organizer, SubEvent +from pretix.base.models import Event, Invoice, Item, Order, Organizer, SubEvent from pretix.base.signals import register_payment_providers from pretix.control.utils.i18n import i18ncomp +from pretix.helpers.database import rolledback_transaction + +PAYMENT_PROVIDERS = [] + + +def get_all_payment_providers(): + global PAYMENT_PROVIDERS + + if PAYMENT_PROVIDERS: + return PAYMENT_PROVIDERS + + with rolledback_transaction(): + event = Event.objects.create( + plugins=",".join([app.name for app in apps.get_app_configs()]), + name="INTERNAL", + date_from=now(), + organizer=Organizer.objects.create(name="INTERNAL") + ) + provs = register_payment_providers.send( + sender=event + ) + choices = [] + for recv, prov in provs: + if isinstance(prov, list): + for p in prov: + p = p(event) + if not p.is_meta: + choices.append((p.identifier, p.verbose_name)) + else: + prov = prov(event) + if not prov.is_meta: + choices.append((prov.identifier, prov.verbose_name)) + PAYMENT_PROVIDERS = choices + return choices class FilterForm(forms.Form): @@ -36,6 +71,13 @@ class OrderFilterForm(FilterForm): }), required=False ) + provider = forms.ChoiceField( + label=_('Payment provider'), + choices=[ + ('', _('All payment providers')), + ], + required=False, + ) status = forms.ChoiceField( label=_('Order status'), choices=( @@ -96,6 +138,9 @@ class OrderFilterForm(FilterForm): if fdata.get('ordering'): qs = qs.order_by(dict(self.fields['ordering'].choices)[fdata.get('ordering')]) + if fdata.get('provider'): + qs = qs.filter(payment_provider=fdata.get('provider')) + return qs @@ -109,13 +154,6 @@ class EventOrderFilterForm(OrderFilterForm): required=False, empty_label=_('All products') ) - provider = forms.ChoiceField( - label=_('Payment provider'), - choices=[ - ('', _('All payment providers')), - ], - required=False, - ) subevent = forms.ModelChoiceField( label=pgettext_lazy('subevent', 'Date'), queryset=SubEvent.objects.none(), @@ -123,17 +161,6 @@ class EventOrderFilterForm(OrderFilterForm): empty_label=pgettext_lazy('subevent', 'All dates') ) - 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) @@ -156,9 +183,6 @@ class EventOrderFilterForm(OrderFilterForm): if fdata.get('subevent'): qs = qs.filter(positions__subevent=fdata.get('subevent')) - if fdata.get('provider'): - qs = qs.filter(payment_provider=fdata.get('provider')) - return qs @@ -183,6 +207,7 @@ class OrderSearchFilterForm(OrderFilterForm): self.fields['organizer'].queryset = Organizer.objects.filter( pk__in=request.user.teams.values_list('organizer', flat=True) ) + self.fields['provider'].choices += get_all_payment_providers() def filter_qs(self, qs): fdata = self.cleaned_data diff --git a/src/pretix/control/templates/pretixcontrol/search/orders.html b/src/pretix/control/templates/pretixcontrol/search/orders.html index fb16361381..289b602630 100644 --- a/src/pretix/control/templates/pretixcontrol/search/orders.html +++ b/src/pretix/control/templates/pretixcontrol/search/orders.html @@ -7,15 +7,18 @@ {% 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' %}
+
+ {% bootstrap_field filter_form.provider layout='inline' %} +