From effc9723f1efeb9c34090907477f3eb2c814c545 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Thu, 4 Jun 2020 18:39:30 +0200 Subject: [PATCH] Add event meta data fields to order search form --- src/pretix/control/forms/filter.py | 58 ++++++++++++++++++- .../pretixcontrol/search/orders.html | 41 +++++++------ src/pretix/control/views/search.py | 3 + 3 files changed, 81 insertions(+), 21 deletions(-) diff --git a/src/pretix/control/forms/filter.py b/src/pretix/control/forms/filter.py index 51a85fd7c..144409fd3 100644 --- a/src/pretix/control/forms/filter.py +++ b/src/pretix/control/forms/filter.py @@ -349,16 +349,34 @@ class OrderSearchFilterForm(OrderFilterForm): ) def __init__(self, *args, **kwargs): - request = kwargs.pop('request') + self.request = kwargs.pop('request') super().__init__(*args, **kwargs) - if request.user.has_active_staff_session(request.session.session_key): + if self.request.user.has_active_staff_session(self.request.session.session_key): 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) + pk__in=self.request.user.teams.values_list('organizer', flat=True) ) self.fields['provider'].choices += get_all_payment_providers() + seen = set() + for p in self.meta_properties.all(): + if p.name in seen: + continue + seen.add(p.name) + self.fields['meta_{}'.format(p.name)] = forms.CharField( + label=p.name, + required=False, + widget=forms.TextInput( + attrs={ + 'data-typeahead-url': reverse('control:events.meta.typeahead') + '?' + urlencode({ + 'property': p.name, + 'organizer': '' + }) + } + ) + ) + def filter_qs(self, qs): fdata = self.cleaned_data qs = super().filter_qs(qs) @@ -366,8 +384,42 @@ class OrderSearchFilterForm(OrderFilterForm): if fdata.get('organizer'): qs = qs.filter(event__organizer=fdata.get('organizer')) + filters_by_property_name = {} + for i, p in enumerate(self.meta_properties): + d = fdata.get('meta_{}'.format(p.name)) + if d: + emv_with_value = EventMetaValue.objects.filter( + event=OuterRef('event_id'), + property__pk=p.pk, + value=d + ) + emv_with_any_value = EventMetaValue.objects.filter( + event=OuterRef('event_id'), + property__pk=p.pk, + ) + qs = qs.annotate(**{'attr_{}'.format(i): Exists(emv_with_value)}) + if p.name in filters_by_property_name: + filters_by_property_name[p.name] |= Q(**{'attr_{}'.format(i): True}) + else: + filters_by_property_name[p.name] = Q(**{'attr_{}'.format(i): True}) + if p.default == d: + qs = qs.annotate(**{'attr_{}_any'.format(i): Exists(emv_with_any_value)}) + filters_by_property_name[p.name] |= Q(**{ + 'attr_{}_any'.format(i): False, 'event__organizer_id': p.organizer_id + }) + for f in filters_by_property_name.values(): + qs = qs.filter(f) + return qs + @cached_property + def meta_properties(self): + # We ignore superuser permissions here. This is intentional – we do not want to show super + # users a form with all meta properties ever assigned. + return EventMetaProperty.objects.filter( + organizer_id__in=self.request.user.teams.values_list('organizer', flat=True) + ) + class SubEventFilterForm(FilterForm): orders = { diff --git a/src/pretix/control/templates/pretixcontrol/search/orders.html b/src/pretix/control/templates/pretixcontrol/search/orders.html index 52e0a14f1..d83c96138 100644 --- a/src/pretix/control/templates/pretixcontrol/search/orders.html +++ b/src/pretix/control/templates/pretixcontrol/search/orders.html @@ -7,25 +7,30 @@ {% block title %}{% trans "Order search" %}{% endblock %} {% block content %}

{% trans "Order search" %}

-
-
- {% bootstrap_field filter_form.query layout='inline' %} + +
+
+ {% 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' %} +
+ {% for mf in meta_fields %} +
+ {% bootstrap_field mf layout='inline' %} +
+ {% endfor %}
-
- {% bootstrap_field filter_form.status layout='inline' %} -
-
- {% bootstrap_field filter_form.organizer layout='inline' %} -
-
- {% bootstrap_field filter_form.provider layout='inline' %} -
-
-
@@ -84,7 +89,7 @@ {% endif %} {% if o.is_overpaid %} {% trans "OVERPAID" %} - {% elif o.is_underpaid %} + {% elif o.is_underpaid %} {% trans "UNDERPAID" %} {% elif o.is_pending_with_full_payment %} {% trans "FULLY PAID" %} diff --git a/src/pretix/control/views/search.py b/src/pretix/control/views/search.py index 8e89ce5c3..b0a5c7568 100644 --- a/src/pretix/control/views/search.py +++ b/src/pretix/control/views/search.py @@ -22,6 +22,9 @@ class OrderSearch(PaginationMixin, ListView): def get_context_data(self, **kwargs): ctx = super().get_context_data() ctx['filter_form'] = self.filter_form + ctx['meta_fields'] = [ + self.filter_form[k] for k in self.filter_form.fields if k.startswith('meta_') + ] # Only compute this annotations for this page (query optimization) s = OrderPosition.objects.filter(