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 %}