Added the option of unlimited quotas

This commit is contained in:
Raphael Michel
2015-10-21 16:31:58 +02:00
parent 2fb90efa4d
commit a2af3db771
6 changed files with 55 additions and 10 deletions

View File

@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='quota',
name='size',
field=models.PositiveIntegerField(help_text='Leave empty for an unlimited number of tickets.', verbose_name='Total capacity', blank=True, null=True),
),
]

View File

@@ -1,4 +1,5 @@
from itertools import product
import sys
from django.db import models
from django.db.models import Q, Case, Count, Sum, When
@@ -315,7 +316,8 @@ class Item(Versionable):
if self.properties.count() > 0: # NOQA
raise ValueError('Do not call this directly on items which have properties '
'but call this on their ItemVariation objects')
return min([q.availability() for q in self.quotas.all()])
return min([q.availability() for q in self.quotas.all()],
key=lambda s: (s[0], s[1] if s[1] is not None else sys.maxsize))
def check_restrictions(self):
"""
@@ -513,7 +515,8 @@ class ItemVariation(Versionable):
:returns: any of the return codes of :py:meth:`Quota.availability()`.
"""
return min([q.availability() for q in self.quotas.all()])
return min([q.availability() for q in self.quotas.all()],
key=lambda s: (s[0], s[1] if s[1] is not None else sys.maxsize))
def to_variation_dict(self):
"""
@@ -769,7 +772,9 @@ class Quota(Versionable):
verbose_name=_("Name")
)
size = models.PositiveIntegerField(
verbose_name=_("Total capacity")
verbose_name=_("Total capacity"),
null=True, blank=True,
help_text=_("Leave empty for an unlimited number of tickets.")
)
items = VersionedManyToManyField(
Item,
@@ -810,6 +815,9 @@ class Quota(Versionable):
and the second is the number of available tickets.
"""
size_left = self.size
if size_left is None:
return Quota.AVAILABILITY_OK, None
# TODO: Test for interference with old versions of Item-Quota-relations, etc.
# TODO: Prevent corner-cases like people having ordered an item before it got
# its first variationsadde

View File

@@ -228,10 +228,11 @@ class Order(Versionable):
else:
# Use cached version
quota = quota_cache[quota.identity]
quota.cached_availability -= 1
if quota.cached_availability < 0:
# This quota is sold out/currently unavailable, so do not sell this at all
raise Quota.QuotaExceededException(error_messages['unavailable'])
if quota.cached_availability is not None:
quota.cached_availability -= 1
if quota.cached_availability < 0:
# This quota is sold out/currently unavailable, so do not sell this at all
raise Quota.QuotaExceededException(error_messages['unavailable'])
except Quota.QuotaExceededException as e:
return str(e)
return True

View File

@@ -104,7 +104,7 @@ def _add_items(event, items, session, expiry):
quota_ok = i[2]
for quota in quotas:
avail = quota.availability()
if avail[1] < i[2]:
if avail[1] is not None and avail[1] < i[2]:
# This quota is not available or less than i[2] items are left, so we have to
# reduce the number of bought items
if avail[0] != Quota.AVAILABILITY_OK:

View File

@@ -2,8 +2,12 @@
{% if availability.0 == 10 %}
<span class="label label-warning">{% trans "Sold out (pending orders)" %}</span>
{% elif availability.0 == 100 %}
<span class="label label-success">{% blocktrans trimmed with num=availability.1 %}
{{ num }} available{% endblocktrans %}</span>
{% if availability.1 != None %}
<span class="label label-success">{% blocktrans trimmed with num=availability.1 %}
{{ num }} available{% endblocktrans %}</span>
{% else %}
<span class="label label-success">{% trans "Unlimited" %}</span>
{% endif %}
{% elif availability.0 == 20 %}
<span class="label label-warning">{% trans "Sold out (or reserved)" %}</span>
{% elif availability.0 == 0 %}

View File

@@ -303,6 +303,19 @@ class QuotaTestCase(BaseQuotaTestCase):
quota2.save()
self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_GONE, 0))
def test_unlimited(self):
self.quota.items.add(self.item1)
order = Order.objects.create(event=self.event, status=Order.STATUS_PAID,
expires=now() + timedelta(days=3),
total=2)
OrderPosition.objects.create(order=order, item=self.item1, price=2)
OrderPosition.objects.create(order=order, item=self.item1, price=2)
self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_GONE, 0))
self.quota.size = None
self.quota.save()
self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_OK, None))
class OrderTestCase(BaseQuotaTestCase):
def setUp(self):