diff --git a/src/pretixbase/models.py b/src/pretixbase/models.py index deb1f36ea4..99481bab30 100644 --- a/src/pretixbase/models.py +++ b/src/pretixbase/models.py @@ -782,7 +782,7 @@ class Item(Versionable): self._get_all_available_variations_cache = variations return variations - def availability(self): + def check_quotas(self): """ This method is used to determine whether this Item is currently available for sale. It may return any of the return codes of Quota.availability() @@ -792,7 +792,7 @@ class Item(Versionable): 'but call this on their ItemVariation objects') return min([q.availability() for q in self.quotas.all()]) - def execute_restrictions(self): + def check_restrictions(self): """ This method is used to determine whether this ItemVariation is restricted in sale by any restriction plugins. @@ -869,7 +869,7 @@ class ItemVariation(Versionable): if self.item: self.item.event.get_cache().clear() - def availability(self): + def check_quotas(self): """ This method is used to determine whether this ItemVariation is currently available for sale in terms of quotas. It may return any of the return codes @@ -884,7 +884,7 @@ class ItemVariation(Versionable): vd['variation'] = self return vd - def execute_restrictions(self): + def check_restrictions(self): """ This method is used to determine whether this ItemVariation is restricted in sale by any restriction plugins. diff --git a/src/pretixbase/tests/test_models.py b/src/pretixbase/tests/test_models.py index 68becc1b00..02da787a36 100644 --- a/src/pretixbase/tests/test_models.py +++ b/src/pretixbase/tests/test_models.py @@ -202,15 +202,15 @@ class QuotaTestCase(TestCase): def test_available(self): self.quota.items.add(self.item1) - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_OK, 2)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_OK, 2)) self.quota.items.add(self.item2) self.quota.variations.add(self.var1) try: - self.item2.availability() + self.item2.check_quotas() self.assertTrue(False) except: pass - self.assertEqual(self.var1.availability(), (Quota.AVAILABILITY_OK, 2)) + self.assertEqual(self.var1.check_quotas(), (Quota.AVAILABILITY_OK, 2)) def test_sold_out(self): self.quota.items.add(self.item1) @@ -219,19 +219,19 @@ class QuotaTestCase(TestCase): total=4) OrderPosition.objects.create(order=order, item=self.item1, price=2) OrderPosition.objects.create(order=order, item=self.item1, price=2) - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_GONE, 0)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_GONE, 0)) self.quota.items.add(self.item2) self.quota.variations.add(self.var1) self.quota.size = 3 self.quota.save() - self.assertEqual(self.var1.availability(), (Quota.AVAILABILITY_OK, 1)) + self.assertEqual(self.var1.check_quotas(), (Quota.AVAILABILITY_OK, 1)) order = Order.objects.create(event=self.event, status=Order.STATUS_PAID, expires=now() + timedelta(days=3), total=4) OrderPosition.objects.create(order=order, item=self.item2, variation=self.var1, price=2) - self.assertEqual(self.var1.availability(), (Quota.AVAILABILITY_GONE, 0)) + self.assertEqual(self.var1.check_quotas(), (Quota.AVAILABILITY_GONE, 0)) def test_ordered(self): self.quota.items.add(self.item1) @@ -239,17 +239,17 @@ class QuotaTestCase(TestCase): expires=now() + timedelta(days=3), total=4) OrderPosition.objects.create(order=order, item=self.item1, price=2) - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_OK, 1)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_OK, 1)) order = Order.objects.create(event=self.event, status=Order.STATUS_PENDING, expires=now() + timedelta(days=3), total=4) OrderPosition.objects.create(order=order, item=self.item1, price=2) - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_ORDERED, 0)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_ORDERED, 0)) order.expires = now() - timedelta(days=3) order.save() - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_OK, 1)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_OK, 1)) def test_reserved(self): self.quota.items.add(self.item1) @@ -259,36 +259,36 @@ class QuotaTestCase(TestCase): expires=now() + timedelta(days=3), total=4) OrderPosition.objects.create(order=order, item=self.item1, price=2) - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_OK, 2)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_OK, 2)) order = Order.objects.create(event=self.event, status=Order.STATUS_PENDING, expires=now() + timedelta(days=3), total=4) OrderPosition.objects.create(order=order, item=self.item1, price=2) - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_OK, 1)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_OK, 1)) cp = CartPosition.objects.create(event=self.event, item=self.item1, price=2, expires=now() + timedelta(days=3)) - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_RESERVED, 0)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_RESERVED, 0)) cp.expires = now() - timedelta(days=3) cp.save() - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_OK, 1)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_OK, 1)) self.quota.items.add(self.item2) self.quota.variations.add(self.var1) cp = CartPosition.objects.create(event=self.event, item=self.item2, variation=self.var1, price=2, expires=now() + timedelta(days=3)) - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_RESERVED, 0)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_RESERVED, 0)) def test_multiple(self): self.quota.items.add(self.item1) - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_OK, 2)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_OK, 2)) quota2 = Quota.objects.create(event=self.event, name="Test 2", size=1) quota2.items.add(self.item1) - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_OK, 1)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_OK, 1)) quota2.size = 0 quota2.save() - self.assertEqual(self.item1.availability(), (Quota.AVAILABILITY_GONE, 0)) + self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_GONE, 0)) diff --git a/src/pretixpresale/views/cart.py b/src/pretixpresale/views/cart.py index bac687a289..7280bb5ebf 100644 --- a/src/pretixpresale/views/cart.py +++ b/src/pretixpresale/views/cart.py @@ -39,8 +39,11 @@ class CartActionMixin: class CartAdd(EventViewMixin, CartActionMixin, View): - def post(self, *args, **kwargs): - # Parse input + def _items_from_post_data(self): + """ + Parses the POST data and returns a list of tuples in the + form (item id, variation id or None, number) + """ items = [] for key, value in self.request.POST.items(): if value.strip() == '': @@ -49,14 +52,23 @@ class CartAdd(EventViewMixin, CartActionMixin, View): try: items.append((key.split("_")[1], None, int(value))) except ValueError: - messages.error(self.request, _('Please only enter numbers.')) - return redirect(self.get_failure_url()) + messages.error(self.request, _('Please enter numbers only.')) + return False elif key.startswith('variation_'): try: items.append((key.split("_")[1], key.split("_")[2], int(value))) except ValueError: - messages.error(self.request, _('Please only enter numbers.')) - return redirect(self.get_failure_url()) + messages.error(self.request, _('Please enter numbers only.')) + return False + if len(items) == 0: + messages.error(self.request, _('You did not select any items.')) + return False + return items + + def post(self, *args, **kwargs): + items = self._items_from_post_data() + if not items: + return redirect(self.get_failure_url()) if sum(i[2] for i in items) > self.request.event.max_items_per_order: # TODO: Plurals @@ -64,9 +76,6 @@ class CartAdd(EventViewMixin, CartActionMixin, View): _("You cannot select more than %d items per order") % self.event.max_items_per_order) return redirect(self.get_failure_url()) - # items is now a list of tuples of the form - # (item id, variation id or None, number) - # Fetch items from the database items_cache = { i.identity: i for i @@ -91,7 +100,7 @@ class CartAdd(EventViewMixin, CartActionMixin, View): return redirect(self.get_failure_url()) item = items_cache[i[0]] variation = variations_cache[i[1]] if i[1] is not None else None - price = item.execute_restrictions() if variation is None else variation.execute_restrictions() + price = item.check_restrictions() if variation is None else variation.check_restrictions() if price is False: if not msg_some_unavailable: diff --git a/src/pretixpresale/views/event.py b/src/pretixpresale/views/event.py index a1e8bcfff0..2c6a932845 100644 --- a/src/pretixpresale/views/event.py +++ b/src/pretixpresale/views/event.py @@ -30,13 +30,13 @@ class EventIndex(EventViewMixin, TemplateView): item.has_variations = (len(item.available_variations) != 1 or not item.available_variations[0].empty()) if not item.has_variations: - item.cached_availability = list(item.availability()) + item.cached_availability = list(item.check_quotas()) item.cached_availability[1] = min(item.cached_availability[1], self.request.event.max_items_per_order) item.price = item.available_variations[0]['price'] else: for var in item.available_variations: - var.cached_availability = list(var['variation'].availability()) + var.cached_availability = list(var['variation'].check_quotas()) var.cached_availability[1] = min(var.cached_availability[1], self.request.event.max_items_per_order)