diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index 6eac15a964..a9074f7c1c 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -80,6 +80,9 @@ def check_positions(event, dt, positions, quotas_locked): err = None for i, cp in enumerate(positions): + if not cp.item.active: + err = err or error_messages['unavailable'] + continue quotas = list(cp.item.quotas.all()) if cp.variation is None else list(cp.variation.quotas.all()) if cp.expires >= dt: # Other checks are not necessary diff --git a/src/pretix/presale/views/cart.py b/src/pretix/presale/views/cart.py index ff22af4a64..4c0b0977f8 100644 --- a/src/pretix/presale/views/cart.py +++ b/src/pretix/presale/views/cart.py @@ -208,7 +208,7 @@ class CartAdd(EventViewMixin, CartActionMixin, View): # Fetch all quotas. If there are no quotas, this item is not allowed to be sold. quotas = list(item.quotas.all()) if variation is None else list(variation.quotas.all()) - if price is False or len(quotas) == 0: + if price is False or len(quotas) == 0 or not item.active: self.error_message(self.error_messages['unavailable']) continue diff --git a/src/pretix/presale/views/event.py b/src/pretix/presale/views/event.py index 9847184ea9..5f24a86cb6 100644 --- a/src/pretix/presale/views/event.py +++ b/src/pretix/presale/views/event.py @@ -34,7 +34,9 @@ class EventIndex(EventViewMixin, CartDisplayMixin, TemplateView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Fetch all items - items = self.request.event.items.all().select_related( + items = self.request.event.items.all().filter( + active=True + ).select_related( 'category', # for re-grouping ).prefetch_related( 'properties', # for .get_all_available_variations() diff --git a/src/tests/presale/test_event.py b/src/tests/presale/test_event.py index 91f850afb2..a3db225562 100644 --- a/src/tests/presale/test_event.py +++ b/src/tests/presale/test_event.py @@ -43,9 +43,16 @@ class ItemDisplayTest(EventTestMixin, BrowserTest): super().setUp() self.driver.implicitly_wait(10) + def test_not_active(self): + q = Quota.objects.create(event=self.event, name='Quota', size=2) + item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=0, active=False) + q.items.add(item) + self.driver.get('%s/%s/%s/' % (self.live_server_url, self.orga.slug, self.event.slug)) + self.assertNotIn("Early-bird", self.driver.find_element_by_css_selector("body").text) + def test_without_category(self): q = Quota.objects.create(event=self.event, name='Quota', size=2) - item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=0) + item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=0, active=True) q.items.add(item) self.driver.get('%s/%s/%s/' % (self.live_server_url, self.orga.slug, self.event.slug)) self.assertIn("Early-bird", self.driver.find_element_by_css_selector("section .product-row:first-child").text)