Very basic quota control

This commit is contained in:
Raphael Michel
2014-10-25 11:16:53 +02:00
parent da24aa3f6e
commit 4d2deca1bb
9 changed files with 233 additions and 2 deletions

View File

@@ -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'),
),
]

View File

@@ -750,6 +750,12 @@ class Quota(models.Model):
implementation specific and are considered private. It is planned that they implementation specific and are considered private. It is planned that they
are being used as a fallback solution if redis is not available. 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( name = models.CharField(
max_length=200, max_length=200,
verbose_name=_("Name") verbose_name=_("Name")
@@ -780,6 +786,9 @@ class Quota(models.Model):
verbose_name = _("Quota") verbose_name = _("Quota")
verbose_name_plural = _("Quotas") verbose_name_plural = _("Quotas")
def __str__(self):
return self.name
class Order(models.Model): class Order(models.Model):
""" """

View File

@@ -7,6 +7,7 @@
<li {% if "event.items.categories" in url_name %}class="active"{% endif %}><a href="{% url 'control:event.items.categories' organizer=request.event.organizer.slug event=request.event.slug %}">{% trans "Categories" %}</a></li> <li {% if "event.items.categories" in url_name %}class="active"{% endif %}><a href="{% url 'control:event.items.categories' organizer=request.event.organizer.slug event=request.event.slug %}">{% trans "Categories" %}</a></li>
<li {% if "event.items.properties" in url_name %}class="active"{% endif %}><a href="{% url 'control:event.items.properties' organizer=request.event.organizer.slug event=request.event.slug %}">{% trans "Properties" %}</a></li> <li {% if "event.items.properties" in url_name %}class="active"{% endif %}><a href="{% url 'control:event.items.properties' organizer=request.event.organizer.slug event=request.event.slug %}">{% trans "Properties" %}</a></li>
<li {% if "event.items.questions" in url_name %}class="active"{% endif %}><a href="{% url 'control:event.items.questions' organizer=request.event.organizer.slug event=request.event.slug %}">{% trans "Questions" %}</a></li> <li {% if "event.items.questions" in url_name %}class="active"{% endif %}><a href="{% url 'control:event.items.questions' organizer=request.event.organizer.slug event=request.event.slug %}">{% trans "Questions" %}</a></li>
<li {% if "event.items.quotas" in url_name %}class="active"{% endif %}><a href="{% url 'control:event.items.quotas' organizer=request.event.organizer.slug event=request.event.slug %}">{% trans "Quotas" %}</a></li>
</ul> </ul>
{% block inside %} {% block inside %}
{% endblock %} {% endblock %}

View File

@@ -18,7 +18,7 @@
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">
{% trans "Confirm" %} {% trans "Confirm" %}
</button> </button>
<a href="{% url "control:event.items.properties" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default"> <a href="{% url "control:event.items.questions" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default">
{% trans "Cancel" %} {% trans "Cancel" %}
</a> </a>
</div> </div>

View File

@@ -0,0 +1,27 @@
{% extends "tixlcontrol/items/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block title %}{% trans "Quota" %}{% endblock %}
{% block inside %}
<h1>{% trans "Quota" %}</h1>
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
{% if "success" in request.GET %}
<div class="alert alert-success">
{% trans "Your changes have been saved." %}
</div>
{% endif %}
<fieldset>
<legend>{% trans "General information" %}</legend>
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.size layout="horizontal" %}
</fieldset>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">
{% trans "Save" %}
</button>
</div>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,27 @@
{% extends "tixlcontrol/items/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block title %}{% trans "Delete quota" %}{% endblock %}
{% block inside %}
<h1>{% trans "Delete quota" %}</h1>
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
<p>{% blocktrans %}Are you sure you want to delete the quota <strong>{{ quota }}</strong>?{% endblocktrans %}</p>
{% if dependent|length > 0 %}
<p>{% blocktrans %}The following items might be no longer available for sale:{% endblocktrans %}</p>
{% for item in dependent %}
<li><a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=item.pk %}">{{ item.name }}</a></li>
{% endfor %}
{% endif %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">
{% trans "Confirm" %}
</button>
<a href="{% url "control:event.items.quotas" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default">
{% trans "Cancel" %}
</a>
</div>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,44 @@
{% extends "tixlcontrol/items/base.html" %}
{% load i18n %}
{% block title %}{% trans "Quotas" %}{% endblock %}
{% block inside %}
<h1>{% trans "Quotas" %}</h1>
{% if "updated" in request.GET %}
<div class="alert alert-success">
{% trans "Your changes have been saved." %}
</div>
{% elif "created" in request.GET %}
<div class="alert alert-success">
{% trans "A new quota has been created." %}
</div>
{% elif "deleted" in request.GET %}
<div class="alert alert-success">
{% trans "The quota has been deleted." %}
</div>
{% endif %}
<p>
<a href="{% url "control:event.items.quotas.add" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new quota" %}</a>
</p>
<table class="table table-hover">
<thead>
<tr>
<th>{% trans "Quota name" %}</th>
<th>{% trans "Items" %}</th>
<th>{% trans "Total capacity" %}</th>
<th>{% trans "Capacity left" %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for q in quotas %}
<tr>
<td><strong><a href="{% url "control:event.items.quotas.edit" organizer=request.event.organizer.slug event=request.event.slug quota=q.pk %}">{{ q.name }}</a></strong></td>
<td></td>
<td>{{ q.size }}</td>
<td></td>
<td class="text-right"><a href="{% url "control:event.items.quotas.delete" organizer=request.event.organizer.slug event=request.event.slug quota=q.pk %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@@ -38,6 +38,11 @@ urlpatterns += patterns(
url(r'^properties/(?P<property>\d+)/$', item.PropertyUpdate.as_view(), name='event.items.properties.edit'), url(r'^properties/(?P<property>\d+)/$', item.PropertyUpdate.as_view(), name='event.items.properties.edit'),
url(r'^properties/(?P<property>\d+)/delete$', item.PropertyDelete.as_view(), name='event.items.properties.delete'), url(r'^properties/(?P<property>\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'^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<quota>\d+)/$', item.QuotaUpdate.as_view(), name='event.items.quotas.edit'),
url(r'^quotas/(?P<quota>\d+)/delete$', item.QuotaDelete.as_view(),
name='event.items.quotas.delete'),
url(r'^quotas/add$', item.QuotaCreate.as_view(), name='event.items.quotas.add'),
) )
)) ))
) )

View File

@@ -10,7 +10,9 @@ from django import forms
from django.shortcuts import redirect from django.shortcuts import redirect
from django.forms.models import inlineformset_factory 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.permissions import EventPermissionRequiredMixin, event_permission_required
from tixlcontrol.views.forms import TolerantFormsetModelForm from tixlcontrol.views.forms import TolerantFormsetModelForm
from tixlcontrol.signals import restriction_formset from tixlcontrol.signals import restriction_formset
@@ -406,6 +408,97 @@ class QuestionCreate(EventPermissionRequiredMixin, CreateView):
return super().form_valid(form) 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): class ItemDetailMixin(SingleObjectMixin):
model = Item model = Item
context_object_name = 'item' context_object_name = 'item'