diff --git a/doc/api/resources/quotas.rst b/doc/api/resources/quotas.rst index 8856af2d05..87a985e18e 100644 --- a/doc/api/resources/quotas.rst +++ b/doc/api/resources/quotas.rst @@ -81,7 +81,8 @@ 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 integer subevent__in: Only return quotas of sub-events with one the given IDs (comma-separated). + :query integer subevent__in: Only return quotas of sub-events with one of the given IDs (comma-separated). + :query integer items__in: Only return quotas that include a product with one of the given IDs (comma-separated). :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 diff --git a/src/pretix/api/views/item.py b/src/pretix/api/views/item.py index bbf6e5291d..83e0dc19be 100644 --- a/src/pretix/api/views/item.py +++ b/src/pretix/api/views/item.py @@ -485,8 +485,17 @@ class QuestionOptionViewSet(viewsets.ModelViewSet): super().perform_destroy(instance) +class NumberInFilter(django_filters.BaseInFilter, django_filters.NumberFilter): + pass + + with scopes_disabled(): class QuotaFilter(FilterSet): + items__in = NumberInFilter( + field_name='items__id', + lookup_expr='in', + ) + class Meta: model = Quota fields = { @@ -508,7 +517,7 @@ class QuotaViewSet(ConditionalListView, viewsets.ModelViewSet): return self.request.event.quotas.all() def list(self, request, *args, **kwargs): - queryset = self.filter_queryset(self.get_queryset()) + queryset = self.filter_queryset(self.get_queryset()).distinct() page = self.paginate_queryset(queryset) diff --git a/src/tests/api/test_items.py b/src/tests/api/test_items.py index 58b7b28393..4da007e4a7 100644 --- a/src/tests/api/test_items.py +++ b/src/tests/api/test_items.py @@ -1901,10 +1901,11 @@ TEST_QUOTA_RES = { @pytest.mark.django_db -def test_quota_list(token_client, organizer, event, quota, item, subevent): +def test_quota_list(token_client, organizer, event, quota, item, item3, subevent): + quota.items.add(item3) res = dict(TEST_QUOTA_RES) res["id"] = quota.pk - res["items"] = [item.pk] + res["items"] = [item.pk, item3.pk] resp = token_client.get('/api/v1/organizers/{}/events/{}/quotas/'.format(organizer.slug, event.slug)) assert resp.status_code == 200 @@ -1922,6 +1923,13 @@ def test_quota_list(token_client, organizer, event, quota, item, subevent): '/api/v1/organizers/{}/events/{}/quotas/?subevent={}'.format(organizer.slug, event.slug, se2.pk)) assert [] == resp.data['results'] + resp = token_client.get( + '/api/v1/organizers/{}/events/{}/quotas/?items__in={},{},0'.format(organizer.slug, event.slug, item.pk, item3.pk)) + assert [res] == resp.data['results'] + resp = token_client.get( + '/api/v1/organizers/{}/events/{}/quotas/?items__in=0'.format(organizer.slug, event.slug)) + assert [] == resp.data['results'] + @pytest.mark.django_db def test_quota_detail(token_client, organizer, event, quota, item):