diff --git a/src/tixlbase/migrations/0018_auto_20141025_0908.py b/src/tixlbase/migrations/0018_auto_20141025_0908.py new file mode 100644 index 000000000..822052920 --- /dev/null +++ b/src/tixlbase/migrations/0018_auto_20141025_0908.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('tixlbase', '0017_auto_20141017_2148'), + ] + + operations = [ + migrations.AddField( + model_name='quota', + name='event', + field=models.ForeignKey(to='tixlbase.Event', default=1, verbose_name='Event', related_name='quotas'), + preserve_default=False, + ), + migrations.AlterField( + model_name='cartposition', + name='datetime', + field=models.DateTimeField(verbose_name='Date'), + ), + ] diff --git a/src/tixlbase/models.py b/src/tixlbase/models.py index bf722867d..111509c1d 100644 --- a/src/tixlbase/models.py +++ b/src/tixlbase/models.py @@ -750,6 +750,12 @@ class Quota(models.Model): implementation specific and are considered private. It is planned that they are being used as a fallback solution if redis is not available. """ + event = models.ForeignKey( + Event, + on_delete=models.CASCADE, + related_name="quotas", + verbose_name=_("Event"), + ) name = models.CharField( max_length=200, verbose_name=_("Name") @@ -780,6 +786,9 @@ class Quota(models.Model): verbose_name = _("Quota") verbose_name_plural = _("Quotas") + def __str__(self): + return self.name + class Order(models.Model): """ diff --git a/src/tixlcontrol/templates/tixlcontrol/items/base.html b/src/tixlcontrol/templates/tixlcontrol/items/base.html index 499d305f6..c636133df 100644 --- a/src/tixlcontrol/templates/tixlcontrol/items/base.html +++ b/src/tixlcontrol/templates/tixlcontrol/items/base.html @@ -7,6 +7,7 @@
  • {% trans "Categories" %}
  • {% trans "Properties" %}
  • {% trans "Questions" %}
  • +
  • {% trans "Quotas" %}
  • {% block inside %} {% endblock %} diff --git a/src/tixlcontrol/templates/tixlcontrol/items/question_delete.html b/src/tixlcontrol/templates/tixlcontrol/items/question_delete.html index 0674c40f2..98763ceac 100644 --- a/src/tixlcontrol/templates/tixlcontrol/items/question_delete.html +++ b/src/tixlcontrol/templates/tixlcontrol/items/question_delete.html @@ -18,7 +18,7 @@ - + {% trans "Cancel" %} diff --git a/src/tixlcontrol/templates/tixlcontrol/items/quota.html b/src/tixlcontrol/templates/tixlcontrol/items/quota.html new file mode 100644 index 000000000..a7d14bd81 --- /dev/null +++ b/src/tixlcontrol/templates/tixlcontrol/items/quota.html @@ -0,0 +1,27 @@ +{% extends "tixlcontrol/items/base.html" %} +{% load i18n %} +{% load bootstrap3 %} +{% block title %}{% trans "Quota" %}{% endblock %} +{% block inside %} +

    {% trans "Quota" %}

    +
    + {% csrf_token %} + {% if "success" in request.GET %} +
    + {% trans "Your changes have been saved." %} +
    + {% endif %} +
    + {% trans "General information" %} + {% bootstrap_field form.name layout="horizontal" %} + {% bootstrap_field form.size layout="horizontal" %} +
    +
    +
    + +
    +
    +
    +{% endblock %} diff --git a/src/tixlcontrol/templates/tixlcontrol/items/quota_delete.html b/src/tixlcontrol/templates/tixlcontrol/items/quota_delete.html new file mode 100644 index 000000000..85e997cda --- /dev/null +++ b/src/tixlcontrol/templates/tixlcontrol/items/quota_delete.html @@ -0,0 +1,27 @@ +{% extends "tixlcontrol/items/base.html" %} +{% load i18n %} +{% load bootstrap3 %} +{% block title %}{% trans "Delete quota" %}{% endblock %} +{% block inside %} +

    {% trans "Delete quota" %}

    +
    + {% csrf_token %} +

    {% blocktrans %}Are you sure you want to delete the quota {{ quota }}?{% endblocktrans %}

    + {% if dependent|length > 0 %} +

    {% blocktrans %}The following items might be no longer available for sale:{% endblocktrans %}

    + {% for item in dependent %} +
  • {{ item.name }}
  • + {% endfor %} + {% endif %} +
    +
    + + + {% trans "Cancel" %} + +
    +
    +
    +{% endblock %} diff --git a/src/tixlcontrol/templates/tixlcontrol/items/quotas.html b/src/tixlcontrol/templates/tixlcontrol/items/quotas.html new file mode 100644 index 000000000..7d3ec2568 --- /dev/null +++ b/src/tixlcontrol/templates/tixlcontrol/items/quotas.html @@ -0,0 +1,44 @@ +{% extends "tixlcontrol/items/base.html" %} +{% load i18n %} +{% block title %}{% trans "Quotas" %}{% endblock %} +{% block inside %} +

    {% trans "Quotas" %}

    + {% if "updated" in request.GET %} +
    + {% trans "Your changes have been saved." %} +
    + {% elif "created" in request.GET %} +
    + {% trans "A new quota has been created." %} +
    + {% elif "deleted" in request.GET %} +
    + {% trans "The quota has been deleted." %} +
    + {% endif %} +

    + {% trans "Create a new quota" %} +

    + + + + + + + + + + + + {% for q in quotas %} + + + + + + + + {% endfor %} + +
    {% trans "Quota name" %}{% trans "Items" %}{% trans "Total capacity" %}{% trans "Capacity left" %}
    {{ q.name }}{{ q.size }}
    +{% endblock %} diff --git a/src/tixlcontrol/urls.py b/src/tixlcontrol/urls.py index a87b82926..ce0f9cdf4 100644 --- a/src/tixlcontrol/urls.py +++ b/src/tixlcontrol/urls.py @@ -38,6 +38,11 @@ urlpatterns += patterns( url(r'^properties/(?P\d+)/$', item.PropertyUpdate.as_view(), name='event.items.properties.edit'), url(r'^properties/(?P\d+)/delete$', item.PropertyDelete.as_view(), name='event.items.properties.delete'), url(r'^properties/add$', item.PropertyCreate.as_view(), name='event.items.properties.add'), + url(r'^quotas/$', item.QuotaList.as_view(), name='event.items.quotas'), + url(r'^quotas/(?P\d+)/$', item.QuotaUpdate.as_view(), name='event.items.quotas.edit'), + url(r'^quotas/(?P\d+)/delete$', item.QuotaDelete.as_view(), + name='event.items.quotas.delete'), + url(r'^quotas/add$', item.QuotaCreate.as_view(), name='event.items.quotas.add'), ) )) ) diff --git a/src/tixlcontrol/views/item.py b/src/tixlcontrol/views/item.py index 1dd6b2fc5..835ccf51b 100644 --- a/src/tixlcontrol/views/item.py +++ b/src/tixlcontrol/views/item.py @@ -10,7 +10,9 @@ from django import forms from django.shortcuts import redirect 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, Quota +) from tixlcontrol.permissions import EventPermissionRequiredMixin, event_permission_required from tixlcontrol.views.forms import TolerantFormsetModelForm from tixlcontrol.signals import restriction_formset @@ -406,6 +408,97 @@ class QuestionCreate(EventPermissionRequiredMixin, CreateView): return super().form_valid(form) +class QuotaList(ListView): + model = Quota + context_object_name = 'quotas' + template_name = 'tixlcontrol/items/quotas.html' + + def get_queryset(self): + return Quota.objects.filter( + event=self.request.event + ) + + +class QuotaForm(forms.ModelForm): + + class Meta: + model = Quota + localized_fields = '__all__' + fields = [ + 'name', + 'size', + ] + + +class QuotaCreate(EventPermissionRequiredMixin, CreateView): + model = Quota + form_class = QuotaForm + template_name = 'tixlcontrol/items/quota.html' + permission = 'can_change_items' + context_object_name = 'quota' + + def get_success_url(self): + return reverse('control:event.items.quotas', kwargs={ + 'organizer': self.request.event.organizer.slug, + 'event': self.request.event.slug, + }) + '?created=true' + + def form_valid(self, form): + form.instance.event = self.request.event + return super().form_valid(form) + + +class QuotaUpdate(EventPermissionRequiredMixin, UpdateView): + model = Quota + form_class = QuotaForm + template_name = 'tixlcontrol/items/quota.html' + permission = 'can_change_items' + context_object_name = 'quota' + + def get_object(self, queryset=None): + url = resolve(self.request.path_info) + return self.request.event.quotas.get( + id=url.kwargs['quota'] + ) + + def get_success_url(self): + return reverse('control:event.items.quotas', kwargs={ + 'organizer': self.request.event.organizer.slug, + 'event': self.request.event.slug, + }) + '?updated=true' + + +class QuotaDelete(EventPermissionRequiredMixin, DeleteView): + model = Quota + template_name = 'tixlcontrol/items/quota_delete.html' + permission = 'can_change_items' + context_object_name = 'quota' + + def get_object(self, queryset=None): + url = resolve(self.request.path_info) + return self.request.event.quotas.get( + id=url.kwargs['quota'] + ) + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + context['dependent'] = list(self.get_object().items.all()) + return context + + def delete(self, request, *args, **kwargs): + self.object = self.get_object() + self.object.items.update(category=None) + success_url = self.get_success_url() + self.object.delete() + return HttpResponseRedirect(success_url) + + def get_success_url(self): + return reverse('control:event.items.quotas', kwargs={ + 'organizer': self.request.event.organizer.slug, + 'event': self.request.event.slug, + }) + '?deleted=true' + + class ItemDetailMixin(SingleObjectMixin): model = Item context_object_name = 'item'