From 9c3fc69176a43f936e731680d48d47a8cab0bdb5 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Fri, 4 Jun 2021 17:15:55 +0200 Subject: [PATCH] Quotas API: Allow to bulk-query availability --- doc/api/resources/quotas.rst | 12 ++++++++++++ src/pretix/api/serializers/item.py | 11 ++++++++++- src/pretix/api/views/item.py | 18 ++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/doc/api/resources/quotas.rst b/doc/api/resources/quotas.rst index b7939c3589..35057645dc 100644 --- a/doc/api/resources/quotas.rst +++ b/doc/api/resources/quotas.rst @@ -28,12 +28,22 @@ closed boolean Whether the quo field). release_after_exit boolean Whether the quota regains capacity as soon as some tickets have been scanned at an exit. +available boolean Whether this quota is available. Only returned if ``with_availability=true`` + is set on the request. Do not rely on this value for critical operations, it may be + slightly out of date. +available_number integer Number of available tickets. Only returned if ``with_availability=true`` + is set on the request. Do not rely on this value for critical operations, it may be + slightly out of date. ``null`` means unlimited. ===================================== ========================== ======================================================= .. versionchanged:: 3.10 The attribute ``release_after_exit`` has been added. +.. versionchanged:: 4.1 + + The ``with_availability`` query parameter has been added. + Endpoints --------- @@ -80,6 +90,7 @@ Endpoints :query string ordering: Manually set the ordering of results. Valid fields to be used are ``id`` and ``position``. Default: ``position`` :query integer subevent: Only return quotas of the sub-event with the given ID + :query string with_availability: Set to ``true`` to get availability information. Can lead to increased answer times. :param organizer: The ``slug`` field of the organizer to fetch :param event: The ``slug`` field of the event to fetch :statuscode 200: no error @@ -120,6 +131,7 @@ Endpoints :param organizer: The ``slug`` field of the organizer to fetch :param event: The ``slug`` field of the event to fetch :param id: The ``id`` field of the quota to fetch + :query string with_availability: Set to ``true`` to get availability information. Can lead to increased answer times. :statuscode 200: no error :statuscode 401: Authentication failure :statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource. diff --git a/src/pretix/api/serializers/item.py b/src/pretix/api/serializers/item.py index 70f68d2531..57ea732748 100644 --- a/src/pretix/api/serializers/item.py +++ b/src/pretix/api/serializers/item.py @@ -408,10 +408,19 @@ class QuestionSerializer(I18nAwareModelSerializer): class QuotaSerializer(I18nAwareModelSerializer): + available = serializers.BooleanField(read_only=True) + available_number = serializers.IntegerField(read_only=True) class Meta: model = Quota - fields = ('id', 'name', 'size', 'items', 'variations', 'subevent', 'closed', 'close_when_sold_out', 'release_after_exit') + fields = ('id', 'name', 'size', 'items', 'variations', 'subevent', 'closed', 'close_when_sold_out', + 'release_after_exit', 'available', 'available_number') + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if 'request' not in self.context or self.context['request'].GET.get('with_availability') != 'true': + del self.fields['available'] + del self.fields['available_number'] def validate(self, data): data = super().validate(data) diff --git a/src/pretix/api/views/item.py b/src/pretix/api/views/item.py index 2036d70765..e21c8a2e2e 100644 --- a/src/pretix/api/views/item.py +++ b/src/pretix/api/views/item.py @@ -477,6 +477,23 @@ class QuotaViewSet(ConditionalListView, viewsets.ModelViewSet): def get_queryset(self): return self.request.event.quotas.all() + def list(self, request, *args, **kwargs): + queryset = self.filter_queryset(self.get_queryset()) + + page = self.paginate_queryset(queryset) + + if self.request.GET.get('with_availability') == 'true': + if page: + qa = QuotaAvailability() + qa.queue(*page) + qa.compute(allow_cache=False) + for q in page: + q.available = qa.results[q][0] == Quota.AVAILABILITY_OK + q.available_number = qa.results[q][1] + + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + def perform_create(self, serializer): serializer.save(event=self.request.event) serializer.instance.log_action( @@ -496,6 +513,7 @@ class QuotaViewSet(ConditionalListView, viewsets.ModelViewSet): def get_serializer_context(self): ctx = super().get_serializer_context() ctx['event'] = self.request.event + ctx['request'] = self.request return ctx def perform_update(self, serializer):