diff --git a/src/pretix/base/migrations/0081_quota_cached_availability_paid_orders.py b/src/pretix/base/migrations/0081_quota_cached_availability_paid_orders.py
new file mode 100644
index 0000000000..2f6c031274
--- /dev/null
+++ b/src/pretix/base/migrations/0081_quota_cached_availability_paid_orders.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2017-10-18 09:06
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+def clear_quota_caches(app, schema_editor):
+ Quota = app.get_model('pretixbase', 'Quota')
+ Quota.objects.all().update(cached_availability_time=None)
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('pretixbase', '0080_auto_20171016_1553'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='quota',
+ name='cached_availability_paid_orders',
+ field=models.PositiveIntegerField(blank=True, null=True),
+ ),
+ migrations.RunPython(
+ clear_quota_caches, migrations.RunPython.noop
+ )
+ ]
diff --git a/src/pretix/base/models/items.py b/src/pretix/base/models/items.py
index 345dfa82ec..3ec1d1d4d5 100644
--- a/src/pretix/base/models/items.py
+++ b/src/pretix/base/models/items.py
@@ -727,6 +727,7 @@ class Quota(LoggedModel):
)
cached_availability_state = models.PositiveIntegerField(null=True, blank=True)
cached_availability_number = models.PositiveIntegerField(null=True, blank=True)
+ cached_availability_paid_orders = models.PositiveIntegerField(null=True, blank=True)
cached_availability_time = models.DateTimeField(null=True, blank=True)
class Meta:
@@ -783,8 +784,13 @@ class Quota(LoggedModel):
self.cached_availability_state = res[0]
self.cached_availability_number = res[1]
self.cached_availability_time = now_dt
+ if self.size is None:
+ self.cached_availability_paid_orders = self.count_pending_orders()
self.save(
- update_fields=['cached_availability_state', 'cached_availability_number', 'cached_availability_time'],
+ update_fields=[
+ 'cached_availability_state', 'cached_availability_number', 'cached_availability_time',
+ 'cached_availability_paid_orders'
+ ],
clear_cache=False
)
@@ -799,8 +805,9 @@ class Quota(LoggedModel):
if size_left is None:
return Quota.AVAILABILITY_OK, None
- # TODO: Test for interference with old versions of Item-Quota-relations, etc.
- size_left -= self.count_paid_orders()
+ paid_orders = self.count_paid_orders()
+ self.cached_availability_paid_orders = paid_orders
+ size_left -= paid_orders
if size_left <= 0:
return Quota.AVAILABILITY_GONE, 0
diff --git a/src/pretix/base/services/quotas.py b/src/pretix/base/services/quotas.py
index eda775fc6f..6c90058ecb 100644
--- a/src/pretix/base/services/quotas.py
+++ b/src/pretix/base/services/quotas.py
@@ -10,11 +10,11 @@ from ..signals import periodic_task
@receiver(signal=periodic_task)
def build_all_quota_caches(sender, **kwargs):
- refresh_quota_cashes.apply_async()
+ refresh_quota_caches.apply_async()
@app.task
-def refresh_quota_cashes():
+def refresh_quota_caches():
last_activity = LogEntry.objects.filter(
event=OuterRef('event_id'),
).order_by().values('event').annotate(
diff --git a/src/pretix/control/forms/filter.py b/src/pretix/control/forms/filter.py
index a997ba8a19..c6660dc2c4 100644
--- a/src/pretix/control/forms/filter.py
+++ b/src/pretix/control/forms/filter.py
@@ -260,7 +260,7 @@ class EventFilterForm(FilterForm):
'date_from': 'order_from',
'date_to': 'order_to',
'live': 'live',
- 'sum_quota_available': 'sum_quota_available'
+ 'sum_tickets_paid': 'sum_tickets_paid'
}
status = forms.ChoiceField(
label=_('Status'),
diff --git a/src/pretix/control/templates/pretixcontrol/events/index.html b/src/pretix/control/templates/pretixcontrol/events/index.html
index 0b1923c3e1..1ce4a8c91f 100644
--- a/src/pretix/control/templates/pretixcontrol/events/index.html
+++ b/src/pretix/control/templates/pretixcontrol/events/index.html
@@ -68,9 +68,9 @@
- {% trans "Quota available" %}
-
-
+ {% trans "Paid tickets per quota" %}
+
+
|
{% trans "Status" %}
@@ -97,7 +97,7 @@
{% trans "Series" %}
{% endif %}
{% if e.settings.show_date_to and e.date_to %}
- –
+ –
{% if e.has_subevents %}
{{ e.max_fromto|default_if_none:e.max_from|default_if_none:e.max_to|default_if_none:""|date:"SHORT_DATETIME_FORMAT" }}
{% else %}
@@ -107,7 +107,7 @@
|
{% for q in e.first_quotas|slice:":3" %}
- {% include "pretixcontrol/fragment_quota_box.html" with quota=q %}
+ {% include "pretixcontrol/fragment_quota_box_paid.html" with quota=q %}
{% endfor %}
{% if e.first_quotas|length > 3 %}
{% blocktrans with date=q.cached_availability_time|date:"SHORT_DATETIME_FORMAT" %}Numbers as of {{ date }}{% endblocktrans %}">
{% if q.size|default_if_none:"NONE" == "NONE" %}
diff --git a/src/pretix/control/templates/pretixcontrol/fragment_quota_box_paid.html b/src/pretix/control/templates/pretixcontrol/fragment_quota_box_paid.html
new file mode 100644
index 0000000000..03809d6561
--- /dev/null
+++ b/src/pretix/control/templates/pretixcontrol/fragment_quota_box_paid.html
@@ -0,0 +1,16 @@
+{% load i18n %}
+ {% blocktrans with date=q.cached_availability_time|date:"SHORT_DATETIME_FORMAT" %}Numbers as of {{ date }}{% endblocktrans %}{% if q.cached_avail.1 is not None %} {% blocktrans with num=q.cached_avail.1 %}Currently available: {{ num }}{% endblocktrans %}{% endif %}">
+ {% if q.size|default_if_none:"NONE" == "NONE" %}
+
+
+ {% else %}
+
+ {% endif %}
+
+ {{ q.cached_availability_paid_orders|default_if_none:"?" }} / {{ q.size|default_if_none:"∞" }}
+
+
diff --git a/src/pretix/control/templates/pretixcontrol/subevents/index.html b/src/pretix/control/templates/pretixcontrol/subevents/index.html
index f99b1f1c0c..18b6cc1c2a 100644
--- a/src/pretix/control/templates/pretixcontrol/subevents/index.html
+++ b/src/pretix/control/templates/pretixcontrol/subevents/index.html
@@ -52,9 +52,9 @@
- {% trans "Quota available" %}
-
-
+ {% trans "Paid tickets per quota" %}
+
+
|
{% trans "Status" %}
@@ -74,7 +74,7 @@
| {{ s.get_date_from_display }} |
{% for q in s.first_quotas|slice:":3" %}
- {% include "pretixcontrol/fragment_quota_box.html" with quota=q %}
+ {% include "pretixcontrol/fragment_quota_box_paid.html" with quota=q %}
{% endfor %}
{% if s.first_quotas|length > 3 %}
0 else 0
- q.inv_percent = 100 - q.percent
+ if q.size is not None:
+ q.percent_paid = min(
+ 100,
+ round(q.cached_availability_paid_orders / q.size * 100) if q.size > 0 else 100
+ )
return ctx
@cached_property
diff --git a/src/pretix/control/views/subevents.py b/src/pretix/control/views/subevents.py
index 60652240f6..a4a2265ae2 100644
--- a/src/pretix/control/views/subevents.py
+++ b/src/pretix/control/views/subevents.py
@@ -31,16 +31,16 @@ class SubEventList(EventPermissionRequiredMixin, ListView):
permission = 'can_change_settings'
def get_queryset(self):
- sum_quota_available = Quota.objects.filter(
+ sum_tickets_paid = Quota.objects.filter(
subevent=OuterRef('pk')
).order_by().values('subevent').annotate(
- s=Sum('cached_availability_number')
+ s=Sum('cached_availability_paid_orders')
).values(
's'
)
qs = self.request.event.subevents.annotate(
- sum_quota_available=Subquery(sum_quota_available, output_field=IntegerField())
+ sum_tickets_paid=Subquery(sum_tickets_paid, output_field=IntegerField())
).prefetch_related(
Prefetch('quotas',
queryset=Quota.objects.annotate(s=Coalesce(F('size'), 0)).order_by('-s'),
@@ -61,9 +61,11 @@ class SubEventList(EventPermissionRequiredMixin, ListView):
if q.cached_availability_time is not None
else q.availability(allow_cache=True)
)
- if q.cached_avail[1] is not None:
- q.percent = round(q.cached_avail[1] / q.size * 100) if q.size > 0 else 0
- q.inv_percent = 100 - q.percent
+ if q.size is not None:
+ q.percent_paid = min(
+ 100,
+ round(q.cached_availability_paid_orders / q.size * 100) if q.size > 0 else 100
+ )
return ctx
@cached_property
diff --git a/src/pretix/static/pretixcontrol/scss/main.scss b/src/pretix/static/pretixcontrol/scss/main.scss
index b120f4b300..d84446cc7c 100644
--- a/src/pretix/static/pretixcontrol/scss/main.scss
+++ b/src/pretix/static/pretixcontrol/scss/main.scss
@@ -418,7 +418,7 @@ body.loading #wrapper {
display: block;
text-align: center;
}
- .progress-bar-success {
+ &.availability .progress-bar-success {
background: lighten($brand-success, 20%);
}
}
| |