Add sub-events and relative date settings (#503)

* Data model

* little crud

* SubEventItemForm etc

* Drop SubEventItem.active, quota editor

* Fix failing tests

* First frontend stuff

* Addons form stuff

* Quota calculation

* net price display on EventIndex

* Add tests, solve some bugs

* Correct quota selection in more places, consolidate pricing logic

* Fix failing quota tests

* Fix TypeError

* Add tests for checkout

* Fixed a bug in QuotaForm

* Prevent immutable cart if a quota was removed from an item

* Add tests for pricing

* Handle waiting list

* Filter in check-in list

* Fixed import lost in rebase

* Fix waiting list widget

* Voucher management

* Voucher redemption

* Fix broken tests

* Add subevents to OrderChangeManager

* Create a subevent during event creation

* Fix bulk voucher creation

* Introduce subevent.active

* Copy from for subevents

* Show active in list

* ICal download for subevents

* Check start and end of presale

* Failing tests / show cart logic

* Test

* Rebase migrations

* REST API integration of sub-events

* Integrate quota calculation into the traditional quota form

* Make subevent argument to add_position optional

* Log-display foo

* pretixdroid and subevents

* Filter by subevent

* Add more tests

* Some mor tests

* Rebase fixes

* More tests

* Relative dates

* Restrict selection in relative datetime widgets

* Filter subevent list

* Re-label has_subevents

* Rebase fixes, subevents in calendar view

* Performance and caching issues

* Refactor calendar templates

* Permission tests

* Calendar fixes and month selection

* subevent selection

* Rename subevents to dates

* Add tests for calendar views
This commit is contained in:
Raphael Michel
2017-07-11 13:56:00 +02:00
committed by GitHub
parent 554800c06f
commit 8123effa65
141 changed files with 5920 additions and 1012 deletions

View File

@@ -5,7 +5,7 @@ from django.core.files import File
from django.core.urlresolvers import resolve, reverse
from django.db import transaction
from django.db.models import Count, F, Q
from django.forms.models import ModelMultipleChoiceField, inlineformset_factory
from django.forms.models import inlineformset_factory
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import redirect
from django.utils.functional import cached_property
@@ -21,6 +21,7 @@ from pretix.base.models import (
CachedTicket, Item, ItemCategory, ItemVariation, Order, Question,
QuestionAnswer, QuestionOption, Quota, Voucher,
)
from pretix.base.models.event import SubEvent
from pretix.base.models.items import ItemAddOn
from pretix.control.forms.item import (
CategoryForm, ItemAddOnForm, ItemAddOnsFormSet, ItemCreateForm,
@@ -549,54 +550,16 @@ class QuotaList(ListView):
template_name = 'pretixcontrol/items/quotas.html'
def get_queryset(self):
return Quota.objects.filter(
qs = Quota.objects.filter(
event=self.request.event
).prefetch_related("items")
if self.request.GET.get("subevent", "") != "":
s = self.request.GET.get("subevent", "")
qs = qs.filter(subevent_id=s)
return qs
class QuotaEditorMixin:
@cached_property
def items(self) -> "List[Item]":
return list(self.request.event.items.all().prefetch_related("variations"))
def get_form(self, form_class=QuotaForm):
if not hasattr(self, '_form'):
kwargs = self.get_form_kwargs()
kwargs['items'] = self.items
self._form = form_class(**kwargs)
return self._form
def get_context_data(self, *args, **kwargs) -> dict:
context = super().get_context_data(*args, **kwargs)
context['items'] = self.items
for item in context['items']:
item.field = self.get_form(QuotaForm)['item_%s' % item.id]
return context
@transaction.atomic
def form_valid(self, form):
res = super().form_valid(form)
items = self.object.items.all()
variations = self.object.variations.all()
selected_variations = []
self.object = form.instance
for item in self.items:
field = form.fields['item_%s' % item.id]
data = form.cleaned_data['item_%s' % item.id]
if isinstance(field, ModelMultipleChoiceField):
for v in data:
selected_variations.append(v)
if data and item not in items:
self.object.items.add(item)
elif not data and item in items:
self.object.items.remove(item)
self.object.variations.add(*[v for v in selected_variations if v not in variations])
self.object.variations.remove(*[v for v in variations if v not in selected_variations])
return res
class QuotaCreate(EventPermissionRequiredMixin, QuotaEditorMixin, CreateView):
class QuotaCreate(EventPermissionRequiredMixin, CreateView):
model = Quota
form_class = QuotaForm
template_name = 'pretixcontrol/items/quota_edit.html'
@@ -691,7 +654,7 @@ class QuotaView(ChartContainingView, DetailView):
raise Http404(_("The requested quota does not exist."))
class QuotaUpdate(EventPermissionRequiredMixin, QuotaEditorMixin, UpdateView):
class QuotaUpdate(EventPermissionRequiredMixin, UpdateView):
model = Quota
form_class = QuotaForm
template_name = 'pretixcontrol/items/quota_edit.html'
@@ -719,6 +682,22 @@ class QuotaUpdate(EventPermissionRequiredMixin, QuotaEditorMixin, UpdateView):
k: form.cleaned_data.get(k) for k in form.changed_data
}
)
if ((form.initial.get('subevent') and not form.instance.subevent)
or (form.instance.subevent and form.initial.get('subevent') != form.instance.subevent.pk)):
if form.initial.get('subevent'):
se = SubEvent.objects.get(event=self.request.event, pk=form.initial.get('subevent'))
se.log_action(
'pretix.subevent.quota.deleted', user=self.request.user, data={
'id': form.instance.pk
}
)
if form.instance.subevent:
form.instance.subevent.log_action(
'pretix.subevent.quota.added', user=self.request.user, data={
'id': form.instance.pk
}
)
return super().form_valid(form)
def get_success_url(self) -> str: