mirror of
https://github.com/pretix/pretix.git
synced 2026-08-05 09:57:49 +00:00
API: Add list and case-insensitive filters to order(positions) resource
This commit is contained in:
@@ -254,6 +254,12 @@ Endpoints
|
||||
Order position endpoints
|
||||
------------------------
|
||||
|
||||
.. versionchanged:: 1.15
|
||||
|
||||
The order positions endpoint has been extended by the filter queries ``item__in``, ``variation__in``,
|
||||
``order__status__in``, ``subevent__in``, and ``addon_to__in``. The search for attendee names and order codes is now
|
||||
case-insensitive.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/checkinlists/(list)/positions/
|
||||
|
||||
Returns a list of all order positions within a given event. The result is the same as
|
||||
@@ -326,14 +332,22 @@ Order position endpoints
|
||||
``attendee_name,positionid``
|
||||
:query string order: Only return positions of the order with the given order code
|
||||
:query integer item: Only return positions with the purchased item matching the given ID.
|
||||
:query integer item__in: Only return positions with the purchased item matching one of the given comma-separated IDs.
|
||||
:query integer variation: Only return positions with the purchased item variation matching the given ID.
|
||||
:query integer variation__in: Only return positions with one of the purchased item variation matching the given
|
||||
comma-separated IDs.
|
||||
:query string attendee_name: Only return positions with the given value in the attendee_name field. Also, add-on
|
||||
products positions are shown if they refer to an attendee with the given name.
|
||||
:query string secret: Only return positions with the given ticket secret.
|
||||
:query bollean has_checkin: If set to ``true`` or ``false``, only return positions that have or have not been
|
||||
checked in already on this list.
|
||||
:query string order__status: Only return positions with the given order status.
|
||||
:query string order__status__in: Only return positions with one the given comma-separated order status.
|
||||
:query boolean has_checkin: If set to ``true`` or ``false``, only return positions that have or have not been
|
||||
checked in already.
|
||||
:query integer subevent: Only return positions of the sub-event with the given ID
|
||||
:query integer subevent__in: Only return positions of one of the sub-events with the given comma-separated IDs
|
||||
:query integer addon_to: Only return positions that are add-ons to the position with the given ID.
|
||||
:query integer addon_to__in: Only return positions that are add-ons to one of the positions with the given
|
||||
comma-separated IDs.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param list: The ID of the check-in list to look for
|
||||
|
||||
@@ -150,6 +150,10 @@ answers list of objects Answers to user
|
||||
Order endpoints
|
||||
---------------
|
||||
|
||||
.. versionchanged:: 1.15
|
||||
|
||||
Filtering for emails or order codes is now case-insensitive.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/orders/
|
||||
|
||||
Returns a list of all orders within a given event.
|
||||
@@ -609,6 +613,12 @@ Order endpoints
|
||||
Order position endpoints
|
||||
------------------------
|
||||
|
||||
.. versionchanged:: 1.15
|
||||
|
||||
The order positions endpoint has been extended by the filter queries ``item__in``, ``variation__in``,
|
||||
``order__status__in``, ``subevent__in``, and ``addon_to__in``. The search for attendee names and order codes is now
|
||||
case-insensitive.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/orderpositions/
|
||||
|
||||
Returns a list of all order positions within a given event.
|
||||
@@ -681,15 +691,22 @@ Order position endpoints
|
||||
``order__datetime,positionid``
|
||||
:query string order: Only return positions of the order with the given order code
|
||||
:query integer item: Only return positions with the purchased item matching the given ID.
|
||||
:query integer item__in: Only return positions with the purchased item matching one of the given comma-separated IDs.
|
||||
:query integer variation: Only return positions with the purchased item variation matching the given ID.
|
||||
:query integer variation__in: Only return positions with one of the purchased item variation matching the given
|
||||
comma-separated IDs.
|
||||
:query string attendee_name: Only return positions with the given value in the attendee_name field. Also, add-on
|
||||
products positions are shown if they refer to an attendee with the given name.
|
||||
:query string secret: Only return positions with the given ticket secret.
|
||||
:query string order__status: Only return positions with the given order status.
|
||||
:query bollean has_checkin: If set to ``true`` or ``false``, only return positions that have or have not been
|
||||
:query string order__status__in: Only return positions with one the given comma-separated order status.
|
||||
:query boolean has_checkin: If set to ``true`` or ``false``, only return positions that have or have not been
|
||||
checked in already.
|
||||
:query integer subevent: Only return positions of the sub-event with the given ID
|
||||
:query integer subevent__in: Only return positions of one of the sub-events with the given comma-separated IDs
|
||||
:query integer addon_to: Only return positions that are add-ons to the position with the given ID.
|
||||
:query integer addon_to__in: Only return positions that are add-ons to one of the positions with the given
|
||||
comma-separated IDs.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import django_filters
|
||||
from django.db.models import F, Max, OuterRef, Prefetch, Q, Subquery
|
||||
from django.db.models import F, Max, OuterRef, Prefetch, Subquery
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.functional import cached_property
|
||||
@@ -9,6 +8,7 @@ from rest_framework import viewsets
|
||||
from pretix.api.serializers.checkin import CheckinListSerializer
|
||||
from pretix.api.serializers.order import OrderPositionSerializer
|
||||
from pretix.api.views import RichOrderingFilter
|
||||
from pretix.api.views.order import OrderPositionFilter
|
||||
from pretix.base.models import Checkin, CheckinList, Order, OrderPosition
|
||||
from pretix.base.models.organizer import TeamAPIToken
|
||||
from pretix.helpers.database import FixedOrderBy
|
||||
@@ -67,21 +67,11 @@ class CheckinListViewSet(viewsets.ModelViewSet):
|
||||
super().perform_destroy(instance)
|
||||
|
||||
|
||||
class OrderPositionFilter(FilterSet):
|
||||
order = django_filters.CharFilter(name='order', lookup_expr='code')
|
||||
has_checkin = django_filters.rest_framework.BooleanFilter(method='has_checkin_qs')
|
||||
attendee_name = django_filters.CharFilter(method='attendee_name_qs')
|
||||
class CheckinOrderPositionFilter(OrderPositionFilter):
|
||||
|
||||
def has_checkin_qs(self, queryset, name, value):
|
||||
return queryset.filter(last_checked_in__isnull=not value)
|
||||
|
||||
def attendee_name_qs(self, queryset, name, value):
|
||||
return queryset.filter(Q(attendee_name=value) | Q(addon_to__attendee_name=value))
|
||||
|
||||
class Meta:
|
||||
model = OrderPosition
|
||||
fields = ['item', 'variation', 'attendee_name', 'secret', 'order', 'has_checkin', 'addon_to', 'subevent']
|
||||
|
||||
|
||||
class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
serializer_class = OrderPositionSerializer
|
||||
@@ -109,7 +99,7 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
},
|
||||
}
|
||||
|
||||
filter_class = OrderPositionFilter
|
||||
filter_class = CheckinOrderPositionFilter
|
||||
permission = 'can_view_orders'
|
||||
|
||||
@cached_property
|
||||
|
||||
@@ -31,6 +31,10 @@ from pretix.base.signals import register_ticket_outputs
|
||||
|
||||
|
||||
class OrderFilter(FilterSet):
|
||||
email = django_filters.CharFilter(name='email', lookup_expr='iexact')
|
||||
code = django_filters.CharFilter(name='code', lookup_expr='iexact')
|
||||
status = django_filters.CharFilter(name='status', lookup_expr='iexact')
|
||||
|
||||
class Meta:
|
||||
model = Order
|
||||
fields = ['code', 'status', 'email', 'locale']
|
||||
@@ -207,7 +211,7 @@ class OrderViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
|
||||
|
||||
class OrderPositionFilter(FilterSet):
|
||||
order = django_filters.CharFilter(name='order', lookup_expr='code')
|
||||
order = django_filters.CharFilter(name='order', lookup_expr='code__iexact')
|
||||
has_checkin = django_filters.rest_framework.BooleanFilter(method='has_checkin_qs')
|
||||
attendee_name = django_filters.CharFilter(method='attendee_name_qs')
|
||||
|
||||
@@ -215,12 +219,18 @@ class OrderPositionFilter(FilterSet):
|
||||
return queryset.filter(checkins__isnull=not value)
|
||||
|
||||
def attendee_name_qs(self, queryset, name, value):
|
||||
return queryset.filter(Q(attendee_name=value) | Q(addon_to__attendee_name=value))
|
||||
return queryset.filter(Q(attendee_name__iexact=value) | Q(addon_to__attendee_name__iexact=value))
|
||||
|
||||
class Meta:
|
||||
model = OrderPosition
|
||||
fields = ['item', 'variation', 'attendee_name', 'secret', 'order', 'order__status', 'has_checkin',
|
||||
'addon_to', 'subevent']
|
||||
fields = {
|
||||
'item': ['exact', 'in'],
|
||||
'variation': ['exact', 'in'],
|
||||
'secret': ['exact'],
|
||||
'order__status': ['exact', 'in'],
|
||||
'addon_to': ['exact', 'in'],
|
||||
'subevent': ['exact', 'in']
|
||||
}
|
||||
|
||||
|
||||
class OrderPositionViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import copy
|
||||
import datetime
|
||||
from decimal import Decimal
|
||||
from distutils.version import LooseVersion
|
||||
@@ -203,7 +204,10 @@ def test_order_detail(token_client, organizer, event, order, item, taxrule, ques
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_orderposition_list(token_client, organizer, event, order, item, subevent, question):
|
||||
def test_orderposition_list(token_client, organizer, event, order, item, subevent, subevent2, question):
|
||||
i2 = copy.copy(item)
|
||||
i2.pk = None
|
||||
i2.save()
|
||||
var = item.variations.create(value="Children")
|
||||
res = dict(TEST_ORDERPOSITION_RES)
|
||||
op = order.positions.first()
|
||||
@@ -228,6 +232,11 @@ def test_orderposition_list(token_client, organizer, event, order, item, subeven
|
||||
resp = token_client.get(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/?item={}'.format(organizer.slug, event.slug, item.pk))
|
||||
assert [res] == resp.data['results']
|
||||
resp = token_client.get(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/?item__in={},{}'.format(
|
||||
organizer.slug, event.slug, item.pk, i2.pk
|
||||
))
|
||||
assert [res] == resp.data['results']
|
||||
resp = token_client.get(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/?item={}'.format(organizer.slug, event.slug, item.pk + 1))
|
||||
assert [] == resp.data['results']
|
||||
@@ -242,6 +251,9 @@ def test_orderposition_list(token_client, organizer, event, order, item, subeven
|
||||
resp = token_client.get(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/?attendee_name=Peter'.format(organizer.slug, event.slug))
|
||||
assert [res] == resp.data['results']
|
||||
resp = token_client.get(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/?attendee_name=peter'.format(organizer.slug, event.slug))
|
||||
assert [res] == resp.data['results']
|
||||
resp = token_client.get(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/?attendee_name=Mark'.format(organizer.slug, event.slug))
|
||||
assert [] == resp.data['results']
|
||||
@@ -282,6 +294,10 @@ def test_orderposition_list(token_client, organizer, event, order, item, subeven
|
||||
resp = token_client.get(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/?subevent={}'.format(organizer.slug, event.slug, subevent.pk))
|
||||
assert [res] == resp.data['results']
|
||||
resp = token_client.get(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/?subevent__in={},{}'.format(organizer.slug, event.slug,
|
||||
subevent.pk, subevent2.pk))
|
||||
assert [res] == resp.data['results']
|
||||
resp = token_client.get(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/?subevent={}'.format(organizer.slug, event.slug,
|
||||
subevent.pk + 1))
|
||||
|
||||
Reference in New Issue
Block a user