diff --git a/doc/api/resources/quotas.rst b/doc/api/resources/quotas.rst index e845dcacd6..66eafc1013 100644 --- a/doc/api/resources/quotas.rst +++ b/doc/api/resources/quotas.rst @@ -69,7 +69,7 @@ Endpoints .. http:get:: /api/v1/organizers/(organizer)/events/(event)/quotas/(id)/ - Returns information on one question, identified by its ID. + Returns information on one quota, identified by its ID. **Example request**: @@ -95,6 +95,46 @@ Endpoints "variations": [1, 4, 5, 7] } + :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 + :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. + +.. http:get:: /api/v1/organizers/(organizer)/events/(event)/quotas/(id)/availability/ + + Returns availability information on one quota, identified by its ID. + + **Example request**: + + .. sourcecode:: http + + GET /api/v1/organizers/bigevents/events/sampleconf/quotas/1/availability/ HTTP/1.1 + Host: pretix.eu + Accept: application/json, text/javascript + + **Example response**: + + .. sourcecode:: http + + HTTP/1.1 200 OK + Vary: Accept + Content-Type: text/javascript + + { + "available": true, + "available_number": 419, + "total_size": 1000, + "pending_orders": 25, + "paid_orders": 423, + "cart_positions": 7, + "blocking_vouchers": 126, + "waiting_list": 0 + } + + Note that ``total_size`` and ``available_number`` are ``null`` in case of unlimited quotas. + :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 diff --git a/src/pretix/api/views/item.py b/src/pretix/api/views/item.py index f869f70a08..16e6b34b71 100644 --- a/src/pretix/api/views/item.py +++ b/src/pretix/api/views/item.py @@ -1,6 +1,8 @@ from django_filters.rest_framework import DjangoFilterBackend, FilterSet from rest_framework import viewsets +from rest_framework.decorators import detail_route from rest_framework.filters import OrderingFilter +from rest_framework.response import Response from pretix.api.serializers.item import ( ItemCategorySerializer, ItemSerializer, QuestionSerializer, @@ -65,3 +67,21 @@ class QuotaViewSet(viewsets.ReadOnlyModelViewSet): def get_queryset(self): return self.request.event.quotas.all() + + @detail_route(methods=['get']) + def availability(self, request, *args, **kwargs): + quota = self.get_object() + + avail = quota.availability() + + data = { + 'paid_orders': quota.count_paid_orders(), + 'pending_orders': quota.count_pending_orders(), + 'blocking_vouchers': quota.count_blocking_vouchers(), + 'cart_positions': quota.count_in_cart(), + 'waiting_list': quota.count_waiting_list_pending(), + 'available_number': avail[1], + 'available': avail[0] == Quota.AVAILABILITY_OK, + 'total_size': quota.size, + } + return Response(data) diff --git a/src/tests/api/test_items.py b/src/tests/api/test_items.py index 74826cd5f3..dbe320c5b6 100644 --- a/src/tests/api/test_items.py +++ b/src/tests/api/test_items.py @@ -219,6 +219,21 @@ def test_quota_detail(token_client, organizer, event, quota, item): assert res == resp.data +@pytest.mark.django_db +def test_quota_availability(token_client, organizer, event, quota, item): + resp = token_client.get('/api/v1/organizers/{}/events/{}/quotas/{}/availability/'.format( + organizer.slug, event.slug, quota.pk)) + assert resp.status_code == 200 + assert {'blocking_vouchers': 0, + 'available_number': 200, + 'pending_orders': 0, + 'cart_positions': 0, + 'available': True, + 'total_size': 200, + 'paid_orders': 0, + 'waiting_list': 0} == resp.data + + @pytest.fixture def question(event, item): q = event.questions.create(question="T-Shirt size", type="C")