forked from CGM_Public/pretix_original
Basic restriction control
This commit is contained in:
6
src/tixlcontrol/signals.py
Normal file
6
src/tixlcontrol/signals.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from tixlbase.signals import EventPluginSignal
|
||||||
|
|
||||||
|
|
||||||
|
restriction_formset = EventPluginSignal(
|
||||||
|
providing_args=["item"]
|
||||||
|
)
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills">
|
||||||
<li {% if "event.item" == url_name %}class="active"{% endif %}><a href="{% url 'control:event.item' organizer=request.event.organizer.slug event=request.event.slug item=item.pk %}">{% trans "General information" %}</a></li>
|
<li {% if "event.item" == url_name %}class="active"{% endif %}><a href="{% url 'control:event.item' organizer=request.event.organizer.slug event=request.event.slug item=item.pk %}">{% trans "General information" %}</a></li>
|
||||||
<li {% if "event.item.variations" == url_name %}class="active"{% endif %}><a href="{% url 'control:event.item.variations' organizer=request.event.organizer.slug event=request.event.slug item=item.pk %}">{% trans "Variations" %}</a></li>
|
<li {% if "event.item.variations" == url_name %}class="active"{% endif %}><a href="{% url 'control:event.item.variations' organizer=request.event.organizer.slug event=request.event.slug item=item.pk %}">{% trans "Variations" %}</a></li>
|
||||||
|
<li {% if "event.item.restrictions" == url_name %}class="active"{% endif %}><a href="{% url 'control:event.item.restrictions' organizer=request.event.organizer.slug event=request.event.slug item=item.pk %}">{% trans "Restrictions" %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
{% block inside %}
|
{% block inside %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
41
src/tixlcontrol/templates/tixlcontrol/item/restrictions.html
Normal file
41
src/tixlcontrol/templates/tixlcontrol/item/restrictions.html
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{% extends "tixlcontrol/item/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load formset_tags %}
|
||||||
|
{% block inside %}
|
||||||
|
<h2>{% trans "Restrictions" %}</h2>
|
||||||
|
<form action="" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% for set in formsets %}
|
||||||
|
<fieldset>
|
||||||
|
<legend>{{ set.title }}</legend>
|
||||||
|
<div data-formset class="restriction-formset" data-formset-prefix="{{ set.formset.prefix }}">
|
||||||
|
<div data-formset-body>
|
||||||
|
{{ set.formset.management_form }}
|
||||||
|
{% for f in set.formset %}
|
||||||
|
<div class="form-horizontal" data-formset-form>
|
||||||
|
{% bootstrap_form f layout="horizontal" %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<script type="form-template" data-formset-empty-form>
|
||||||
|
{% escapescript %}
|
||||||
|
<div class="form-horizontal" data-formset-form>
|
||||||
|
{% bootstrap_form set.formset.empty_form layout="horizontal" %}
|
||||||
|
</div>
|
||||||
|
{% endescapescript %}
|
||||||
|
</script>
|
||||||
|
<button type="button" class="btn btn-default" data-formset-add><i class="fa fa-plus"></i> {% trans "Add a new restriction" %}</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
{% trans "Save" %}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -23,6 +23,7 @@ urlpatterns += patterns(
|
|||||||
url(r'^items/$', item.ItemList.as_view(), name='event.items'),
|
url(r'^items/$', item.ItemList.as_view(), name='event.items'),
|
||||||
url(r'^items/(?P<item>\d+)/$', item.ItemUpdateGeneral.as_view(), name='event.item'),
|
url(r'^items/(?P<item>\d+)/$', item.ItemUpdateGeneral.as_view(), name='event.item'),
|
||||||
url(r'^items/(?P<item>\d+)/variations$', item.ItemVariations.as_view(), name='event.item.variations'),
|
url(r'^items/(?P<item>\d+)/variations$', item.ItemVariations.as_view(), name='event.item.variations'),
|
||||||
|
url(r'^items/(?P<item>\d+)/restrictions$', item.ItemRestrictions.as_view(), name='event.item.restrictions'),
|
||||||
url(r'^categories/$', item.CategoryList.as_view(), name='event.items.categories'),
|
url(r'^categories/$', item.CategoryList.as_view(), name='event.items.categories'),
|
||||||
url(r'^categories/(?P<category>\d+)/delete$', item.CategoryDelete.as_view(), name='event.items.categories.delete'),
|
url(r'^categories/(?P<category>\d+)/delete$', item.CategoryDelete.as_view(), name='event.items.categories.delete'),
|
||||||
url(r'^categories/(?P<category>\d+)/up$', item.category_move_up, name='event.items.categories.up'),
|
url(r'^categories/(?P<category>\d+)/up$', item.category_move_up, name='event.items.categories.up'),
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from django.forms.models import inlineformset_factory
|
|||||||
from tixlbase.models import Item, ItemCategory, Property, ItemVariation, PropertyValue, Question
|
from tixlbase.models import Item, ItemCategory, Property, ItemVariation, PropertyValue, Question
|
||||||
from tixlcontrol.permissions import EventPermissionRequiredMixin, event_permission_required
|
from tixlcontrol.permissions import EventPermissionRequiredMixin, event_permission_required
|
||||||
from tixlcontrol.views.forms import TolerantFormsetModelForm
|
from tixlcontrol.views.forms import TolerantFormsetModelForm
|
||||||
|
from tixlcontrol.signals import restriction_formset
|
||||||
|
|
||||||
|
|
||||||
class ItemList(ListView):
|
class ItemList(ListView):
|
||||||
@@ -405,6 +406,20 @@ class QuestionCreate(EventPermissionRequiredMixin, CreateView):
|
|||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
class ItemDetailMixin(SingleObjectMixin):
|
||||||
|
model = Item
|
||||||
|
context_object_name = 'item'
|
||||||
|
|
||||||
|
def get_object(self, queryset=None):
|
||||||
|
if not hasattr(self, 'object') or not self.object:
|
||||||
|
url = resolve(self.request.path_info)
|
||||||
|
self.item = self.request.event.items.get(
|
||||||
|
id=url.kwargs['item']
|
||||||
|
)
|
||||||
|
self.object = self.item
|
||||||
|
return self.object
|
||||||
|
|
||||||
|
|
||||||
class ItemUpdateFormGeneral(forms.ModelForm):
|
class ItemUpdateFormGeneral(forms.ModelForm):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@@ -429,18 +444,10 @@ class ItemUpdateFormGeneral(forms.ModelForm):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class ItemUpdateGeneral(EventPermissionRequiredMixin, UpdateView):
|
class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateView):
|
||||||
model = Item
|
|
||||||
form_class = ItemUpdateFormGeneral
|
form_class = ItemUpdateFormGeneral
|
||||||
template_name = 'tixlcontrol/item/index.html'
|
template_name = 'tixlcontrol/item/index.html'
|
||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'item'
|
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
|
||||||
url = resolve(self.request.path_info)
|
|
||||||
return self.request.event.items.get(
|
|
||||||
id=url.kwargs['item']
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse('control:event.item', kwargs={
|
return reverse('control:event.item', kwargs={
|
||||||
@@ -461,10 +468,8 @@ class ItemVariationForm(forms.ModelForm):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class ItemVariations(EventPermissionRequiredMixin, TemplateView, SingleObjectMixin):
|
class ItemVariations(ItemDetailMixin, EventPermissionRequiredMixin, TemplateView):
|
||||||
|
|
||||||
model = Item
|
|
||||||
context_object_name = 'item'
|
|
||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@@ -618,14 +623,6 @@ class ItemVariations(EventPermissionRequiredMixin, TemplateView, SingleObjectMix
|
|||||||
form.save()
|
form.save()
|
||||||
return self.render_to_response(context)
|
return self.render_to_response(context)
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
|
||||||
if not self.item:
|
|
||||||
url = resolve(self.request.path_info)
|
|
||||||
self.item = self.request.event.items.get(
|
|
||||||
id=url.kwargs['item']
|
|
||||||
)
|
|
||||||
return self.item
|
|
||||||
|
|
||||||
def get_template_names(self):
|
def get_template_names(self):
|
||||||
if self.dimension == 1:
|
if self.dimension == 1:
|
||||||
return ['tixlcontrol/item/variations_1d.html']
|
return ['tixlcontrol/item/variations_1d.html']
|
||||||
@@ -639,3 +636,64 @@ class ItemVariations(EventPermissionRequiredMixin, TemplateView, SingleObjectMix
|
|||||||
context['forms'] = self.forms
|
context['forms'] = self.forms
|
||||||
context['properties'] = self.properties
|
context['properties'] = self.properties
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class ItemRestrictions(ItemDetailMixin, EventPermissionRequiredMixin, TemplateView):
|
||||||
|
|
||||||
|
permission = 'can_change_items'
|
||||||
|
template_name = 'tixlcontrol/item/restrictions.html'
|
||||||
|
|
||||||
|
def get_formsets(self):
|
||||||
|
responses = restriction_formset.send(self.object.event, item=self.object)
|
||||||
|
formsets = []
|
||||||
|
for receiver, response in responses:
|
||||||
|
response['formset'] = response['formsetclass'](
|
||||||
|
self.request.POST if self.request.method == 'POST' else None,
|
||||||
|
queryset=response['queryset'],
|
||||||
|
prefix=response['prefix'],
|
||||||
|
)
|
||||||
|
formsets.append(response)
|
||||||
|
return formsets
|
||||||
|
|
||||||
|
def main(self, request, *args, **kwargs):
|
||||||
|
self.object = self.get_object()
|
||||||
|
self.request = request
|
||||||
|
self.formsets = self.get_formsets()
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
self.main(request, *args, **kwargs)
|
||||||
|
context = self.get_context_data(object=self.object)
|
||||||
|
return self.render_to_response(context)
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
self.main(request, *args, **kwargs)
|
||||||
|
valid = True
|
||||||
|
for f in self.formsets:
|
||||||
|
valid &= f['formset'].is_valid()
|
||||||
|
if valid:
|
||||||
|
for f in self.formsets:
|
||||||
|
for form in f['formset']:
|
||||||
|
if 'DELETE' in form.cleaned_data and form.cleaned_data['DELETE'] is True:
|
||||||
|
if form.instance.pk is None:
|
||||||
|
continue
|
||||||
|
form.instance.delete()
|
||||||
|
else:
|
||||||
|
form.instance.event = request.event
|
||||||
|
form.instance.item = self.object
|
||||||
|
form.instance.save()
|
||||||
|
return redirect(self.get_success_url())
|
||||||
|
else:
|
||||||
|
context = self.get_context_data(object=self.object)
|
||||||
|
return self.render_to_response(context)
|
||||||
|
|
||||||
|
def get_context_data(self, *args, **kwargs):
|
||||||
|
context = super().get_context_data(*args, **kwargs)
|
||||||
|
context['formsets'] = self.formsets
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse('control:event.item.restrictions', kwargs={
|
||||||
|
'organizer': self.request.event.organizer.slug,
|
||||||
|
'event': self.request.event.slug,
|
||||||
|
'item': self.object.pk
|
||||||
|
}) + '?success=true'
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django import forms
|
||||||
|
from django.forms.models import modelformset_factory
|
||||||
|
|
||||||
from tixlbase.signals import determine_availability
|
from tixlbase.signals import determine_availability
|
||||||
|
from tixlcontrol.signals import restriction_formset
|
||||||
|
|
||||||
from .models import TimeRestriction
|
from .models import TimeRestriction
|
||||||
|
|
||||||
@@ -105,3 +109,36 @@ def availability_handler(sender, **kwargs):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return variations
|
return variations
|
||||||
|
|
||||||
|
|
||||||
|
class TimeRestrictionForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = TimeRestriction
|
||||||
|
localized_fields = '__all__'
|
||||||
|
fields = [
|
||||||
|
'timeframe_from',
|
||||||
|
'timeframe_to',
|
||||||
|
'price',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(restriction_formset)
|
||||||
|
def formset_handler(sender, **kwargs):
|
||||||
|
# Handle the signal's input arguments
|
||||||
|
item = kwargs['item']
|
||||||
|
|
||||||
|
formset = modelformset_factory(
|
||||||
|
TimeRestriction,
|
||||||
|
form=TimeRestrictionForm,
|
||||||
|
can_order=False,
|
||||||
|
can_delete=True,
|
||||||
|
extra=0,
|
||||||
|
)
|
||||||
|
queryset = TimeRestriction.objects.filter(item=item)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'title': _('Restriction by time'),
|
||||||
|
'formsetclass': formset,
|
||||||
|
'queryset': queryset,
|
||||||
|
'prefix': 'timerestriction',
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user