diff --git a/doc/user/events/widget.rst b/doc/user/events/widget.rst index 8182db5fc4..a9d84f5142 100644 --- a/doc/user/events/widget.rst +++ b/doc/user/events/widget.rst @@ -135,6 +135,10 @@ Alternatively, you can select one or more categories to be shown:: +Or variation IDs:: + + + Multi-event selection --------------------- diff --git a/src/pretix/presale/views/widget.py b/src/pretix/presale/views/widget.py index b2090c5e2d..bf531749db 100644 --- a/src/pretix/presale/views/widget.py +++ b/src/pretix/presale/views/widget.py @@ -54,7 +54,7 @@ from lxml import html from pretix.base.context import get_powered_by from pretix.base.i18n import language -from pretix.base.models import CartPosition, Event, Quota, SubEvent, Voucher +from pretix.base.models import CartPosition, Event, Quota, SubEvent, Voucher, ItemVariation from pretix.base.services.cart import error_messages from pretix.base.settings import GlobalSettingsObject from pretix.base.templatetags.rich_text import rich_text @@ -222,9 +222,18 @@ class WidgetAPIProductList(EventListMixin, View): def _get_items(self): qs = self.request.event.items if 'items' in self.request.GET: - qs = qs.filter(pk__in=self.request.GET.get('items').split(",")) + qs = qs.filter(pk__in=[pk for pk in self.request.GET.get('items').split(",") if pk.isdigit()]) if 'categories' in self.request.GET: - qs = qs.filter(category__pk__in=self.request.GET.get('categories').split(",")) + qs = qs.filter(category__pk__in=[pk for pk in self.request.GET.get('categories').split(",") if pk.isdigit()]) + variation_filter = None + if 'variations' in self.request.GET: + variation_filter = [int(pk) for pk in self.request.GET.get('variations').split(",") if pk.isdigit()] + qs = qs.filter( + pk__in=ItemVariation.objects.filter( + item__event=self.request.event, + pk__in=variation_filter, + ).values_list('item_id', flat=True) + ) items, display_add_to_cart = get_grouped_items( self.request.event, @@ -295,7 +304,7 @@ class WidgetAPIProductList(EventListMixin, View): var.cached_availability[0], var.cached_availability[1] if item.do_show_quota_left else None ], - } for var in item.available_variations + } for var in item.available_variations if (not variation_filter or var.id in variation_filter) ] } for item in g diff --git a/src/tests/presale/test_widget.py b/src/tests/presale/test_widget.py index 6dc61af5b1..03e331eff0 100644 --- a/src/tests/presale/test_widget.py +++ b/src/tests/presale/test_widget.py @@ -290,6 +290,50 @@ class WidgetCartTest(CartTestMixin, TestCase): data = json.loads(response.content.decode()) assert len(data['items_by_category']) == 0 + def test_product_list_view_variation_filter(self): + response = self.client.get('/%s/%s/widget/product_list?variations=%s' % (self.orga.slug, self.event.slug, + self.shirt_red.pk)) + assert response['Access-Control-Allow-Origin'] == '*' + data = json.loads(response.content.decode()) + assert data['items_by_category'] == [ + { + "items": [ + { + "require_voucher": False, + "order_min": None, + "max_price": "14.00", + "price": None, + "picture": None, + "has_variations": 4, + "allow_waitinglist": True, + "description": None, + "min_price": "12.00", + "avail": None, + "variations": [ + { + "value": "Red", + "id": self.shirt_red.pk, + 'original_price': None, + "price": {"gross": "14.00", "net": "11.76", "tax": "2.24", "name": "", + "rate": "19.00", "includes_mixed_tax_rate": False}, + "description": None, + "avail": [100, None], + "order_max": 2 + } + ], + "id": self.shirt.pk, + "free_price": False, + "original_price": None, + "name": "T-Shirt", + "order_max": None + } + ], + "description": None, + "id": self.category.pk, + "name": "Everything" + } + ] + def test_product_list_view_with_voucher(self): with scopes_disabled(): self.event.vouchers.create(item=self.ticket, code="ABCDE")