Format launderette

This commit is contained in:
Pierre Brunet 2017-06-12 09:59:44 +02:00
parent 6a43c2cef6
commit 13ec91e7e5
3 changed files with 40 additions and 31 deletions

View File

@ -27,12 +27,13 @@ from django.utils.translation import ugettext_lazy as _
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from counter.models import Counter, Product from counter.models import Counter
from core.models import User from core.models import User
from club.models import Club from club.models import Club
# Create your models here. # Create your models here.
class Launderette(models.Model): class Launderette(models.Model):
name = models.CharField(_('name'), max_length=30) name = models.CharField(_('name'), max_length=30)
counter = models.OneToOneField(Counter, verbose_name=_('counter'), related_name='launderette') counter = models.OneToOneField(Counter, verbose_name=_('counter'), related_name='launderette')
@ -78,6 +79,7 @@ class Launderette(models.Model):
def token_list(self): def token_list(self):
return [t.id for t in self.get_token_list()] return [t.id for t in self.get_token_list()]
class Machine(models.Model): class Machine(models.Model):
name = models.CharField(_('name'), max_length=30) name = models.CharField(_('name'), max_length=30)
launderette = models.ForeignKey(Launderette, related_name='machines', verbose_name=_('launderette')) launderette = models.ForeignKey(Launderette, related_name='machines', verbose_name=_('launderette'))
@ -103,6 +105,7 @@ class Machine(models.Model):
def get_absolute_url(self): def get_absolute_url(self):
return reverse('launderette:launderette_admin', kwargs={"launderette_id": self.launderette.id}) return reverse('launderette:launderette_admin', kwargs={"launderette_id": self.launderette.id})
class Token(models.Model): class Token(models.Model):
name = models.CharField(_('name'), max_length=5) name = models.CharField(_('name'), max_length=5)
launderette = models.ForeignKey(Launderette, related_name='tokens', verbose_name=_('launderette')) launderette = models.ForeignKey(Launderette, related_name='tokens', verbose_name=_('launderette'))
@ -140,6 +143,7 @@ class Token(models.Model):
else: else:
return False return False
class Slot(models.Model): class Slot(models.Model):
start_date = models.DateTimeField(_('start date')) start_date = models.DateTimeField(_('start date'))
type = models.CharField(_('type'), max_length=10, choices=settings.SITH_LAUNDERETTE_MACHINE_TYPES) type = models.CharField(_('type'), max_length=10, choices=settings.SITH_LAUNDERETTE_MACHINE_TYPES)
@ -156,6 +160,4 @@ class Slot(models.Model):
def __str__(self): def __str__(self):
return "User: %s - Date: %s - Type: %s - Machine: %s - Token: %s" % (self.user, self.start_date, self.get_type_display(), return "User: %s - Date: %s - Type: %s - Machine: %s - Token: %s" % (self.user, self.start_date, self.get_type_display(),
self.machine.name, self.token) self.machine.name, self.token)

View File

@ -22,7 +22,7 @@
# #
# #
from django.conf.urls import url, include from django.conf.urls import url
from launderette.views import * from launderette.views import *

View File

@ -26,11 +26,8 @@ from datetime import datetime, timedelta
from collections import OrderedDict from collections import OrderedDict
import pytz import pytz
from django.shortcuts import render from django.views.generic import ListView, DetailView, TemplateView
from django.views.generic import ListView, DetailView, RedirectView, TemplateView
from django.views.generic.edit import UpdateView, CreateView, DeleteView, BaseFormView from django.views.generic.edit import UpdateView, CreateView, DeleteView, BaseFormView
from django.forms.models import modelform_factory
from django.forms import CheckboxSelectMultiple
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.utils import dateparse, timezone from django.utils import dateparse, timezone
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse_lazy
@ -38,7 +35,6 @@ from django.conf import settings
from django.db import transaction, DataError from django.db import transaction, DataError
from django import forms from django import forms
from django.template import defaultfilters from django.template import defaultfilters
from django.utils import formats
from core.models import Page, User from core.models import Page, User
from club.models import Club from club.models import Club
@ -49,6 +45,7 @@ from counter.views import GetUserForm
# For users # For users
class LaunderetteMainView(TemplateView): class LaunderetteMainView(TemplateView):
"""Main presentation view""" """Main presentation view"""
template_name = 'launderette/launderette_main.jinja' template_name = 'launderette/launderette_main.jinja'
@ -59,11 +56,13 @@ class LaunderetteMainView(TemplateView):
kwargs['page'] = Page.objects.filter(name='launderette').first() kwargs['page'] = Page.objects.filter(name='launderette').first()
return kwargs return kwargs
class LaunderetteBookMainView(CanViewMixin, ListView): class LaunderetteBookMainView(CanViewMixin, ListView):
"""Choose which launderette to book""" """Choose which launderette to book"""
model = Launderette model = Launderette
template_name = 'launderette/launderette_book_choose.jinja' template_name = 'launderette/launderette_book_choose.jinja'
class LaunderetteBookView(CanViewMixin, DetailView): class LaunderetteBookView(CanViewMixin, DetailView):
"""Display the launderette schedule""" """Display the launderette schedule"""
model = Launderette model = Launderette
@ -96,11 +95,12 @@ class LaunderetteBookView(CanViewMixin, DetailView):
if self.check_slot("WASHING") and self.check_slot("DRYING", self.date + timedelta(hours=1)): if self.check_slot("WASHING") and self.check_slot("DRYING", self.date + timedelta(hours=1)):
Slot(user=self.subscriber, start_date=self.date, machine=self.machines["WASHING"], type="WASHING").save() Slot(user=self.subscriber, start_date=self.date, machine=self.machines["WASHING"], type="WASHING").save()
Slot(user=self.subscriber, start_date=self.date + timedelta(hours=1), Slot(user=self.subscriber, start_date=self.date + timedelta(hours=1),
machine=self.machines["DRYING"], type="DRYING").save() machine=self.machines["DRYING"], type="DRYING").save()
return super(LaunderetteBookView, self).get(request, *args, **kwargs) return super(LaunderetteBookView, self).get(request, *args, **kwargs)
def check_slot(self, type, date=None): def check_slot(self, type, date=None):
if date is None: date = self.date if date is None:
date = self.date
for m in self.object.machines.filter(is_working=True, type=type).all(): for m in self.object.machines.filter(is_working=True, type=type).all():
slot = Slot.objects.filter(start_date=date, machine=m).first() slot = Slot.objects.filter(start_date=date, machine=m).first()
if slot is None: if slot is None:
@ -121,9 +121,9 @@ class LaunderetteBookView(CanViewMixin, DetailView):
kwargs['planning'] = OrderedDict() kwargs['planning'] = OrderedDict()
kwargs['slot_type'] = self.slot_type kwargs['slot_type'] = self.slot_type
start_date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=pytz.UTC) start_date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=pytz.UTC)
for date in LaunderetteBookView.date_iterator(start_date, start_date+timedelta(days=6), timedelta(days=1)): for date in LaunderetteBookView.date_iterator(start_date, start_date + timedelta(days=6), timedelta(days=1)):
kwargs['planning'][date] = [] kwargs['planning'][date] = []
for h in LaunderetteBookView.date_iterator(date, date+timedelta(days=1), timedelta(hours=1)): for h in LaunderetteBookView.date_iterator(date, date + timedelta(days=1), timedelta(hours=1)):
free = False free = False
if self.slot_type == "BOTH" and self.check_slot("WASHING", h) and self.check_slot("DRYING", h + timedelta(hours=1)): if self.slot_type == "BOTH" and self.check_slot("WASHING", h) and self.check_slot("DRYING", h + timedelta(hours=1)):
free = True free = True
@ -137,6 +137,7 @@ class LaunderetteBookView(CanViewMixin, DetailView):
kwargs['planning'][date].append(None) kwargs['planning'][date].append(None)
return kwargs return kwargs
class SlotDeleteView(CanEditPropMixin, DeleteView): class SlotDeleteView(CanEditPropMixin, DeleteView):
"""Delete a slot""" """Delete a slot"""
model = Slot model = Slot
@ -154,6 +155,7 @@ class LaunderetteListView(CanEditPropMixin, ListView):
model = Launderette model = Launderette
template_name = 'launderette/launderette_list.jinja' template_name = 'launderette/launderette_list.jinja'
class LaunderetteEditView(CanEditPropMixin, UpdateView): class LaunderetteEditView(CanEditPropMixin, UpdateView):
"""Edit a launderette""" """Edit a launderette"""
model = Launderette model = Launderette
@ -161,6 +163,7 @@ class LaunderetteEditView(CanEditPropMixin, UpdateView):
fields = ['name'] fields = ['name']
template_name = 'core/edit.jinja' template_name = 'core/edit.jinja'
class LaunderetteCreateView(CanCreateMixin, CreateView): class LaunderetteCreateView(CanCreateMixin, CreateView):
"""Create a new launderette""" """Create a new launderette"""
model = Launderette model = Launderette
@ -174,11 +177,12 @@ class LaunderetteCreateView(CanCreateMixin, CreateView):
form.instance.counter = c form.instance.counter = c
return super(LaunderetteCreateView, self).form_valid(form) return super(LaunderetteCreateView, self).form_valid(form)
class ManageTokenForm(forms.Form): class ManageTokenForm(forms.Form):
action = forms.ChoiceField(choices=[("BACK", _("Back")), ("ADD", _("Add")), ("DEL", _("Delete"))], initial="BACK", action = forms.ChoiceField(choices=[("BACK", _("Back")), ("ADD", _("Add")), ("DEL", _("Delete"))], initial="BACK",
label=_("Action"), widget=forms.RadioSelect) label=_("Action"), widget=forms.RadioSelect)
token_type = forms.ChoiceField(choices=settings.SITH_LAUNDERETTE_MACHINE_TYPES, label=_("Type"), initial="WASHING", token_type = forms.ChoiceField(choices=settings.SITH_LAUNDERETTE_MACHINE_TYPES, label=_("Type"), initial="WASHING",
widget=forms.RadioSelect) widget=forms.RadioSelect)
tokens = forms.CharField(max_length=512, widget=forms.widgets.Textarea, label=_("Tokens, separated by spaces")) tokens = forms.CharField(max_length=512, widget=forms.widgets.Textarea, label=_("Tokens, separated by spaces"))
def process(self, launderette): def process(self, launderette):
@ -210,6 +214,7 @@ class ManageTokenForm(forms.Form):
except: except:
self.add_error(None, _("Token %(token_name)s does not exists") % {'token_name': t}) self.add_error(None, _("Token %(token_name)s does not exists") % {'token_name': t})
class LaunderetteAdminView(CanEditPropMixin, BaseFormView, DetailView): class LaunderetteAdminView(CanEditPropMixin, BaseFormView, DetailView):
"""The admin page of the launderette""" """The admin page of the launderette"""
model = Launderette model = Launderette
@ -253,6 +258,7 @@ class LaunderetteAdminView(CanEditPropMixin, BaseFormView, DetailView):
def get_success_url(self): def get_success_url(self):
return reverse_lazy('launderette:launderette_admin', args=self.args, kwargs=self.kwargs) return reverse_lazy('launderette:launderette_admin', args=self.args, kwargs=self.kwargs)
class GetLaunderetteUserForm(GetUserForm): class GetLaunderetteUserForm(GetUserForm):
def clean(self): def clean(self):
cleaned_data = super(GetLaunderetteUserForm, self).clean() cleaned_data = super(GetLaunderetteUserForm, self).clean()
@ -261,12 +267,13 @@ class GetLaunderetteUserForm(GetUserForm):
raise forms.ValidationError(_("User has booked no slot")) raise forms.ValidationError(_("User has booked no slot"))
return cleaned_data return cleaned_data
class LaunderetteMainClickView(CanEditMixin, BaseFormView, DetailView): class LaunderetteMainClickView(CanEditMixin, BaseFormView, DetailView):
"""The click page of the launderette""" """The click page of the launderette"""
model = Launderette model = Launderette
pk_url_kwarg = "launderette_id" pk_url_kwarg = "launderette_id"
template_name = 'counter/counter_main.jinja' template_name = 'counter/counter_main.jinja'
form_class = GetLaunderetteUserForm # Form to enter a client code and get the corresponding user id form_class = GetLaunderetteUserForm # Form to enter a client code and get the corresponding user id
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
@ -301,6 +308,7 @@ class LaunderetteMainClickView(CanEditMixin, BaseFormView, DetailView):
def get_success_url(self): def get_success_url(self):
return reverse_lazy('launderette:click', args=self.args, kwargs=self.kwargs) return reverse_lazy('launderette:click', args=self.args, kwargs=self.kwargs)
class ClickTokenForm(forms.BaseForm): class ClickTokenForm(forms.BaseForm):
def clean(self): def clean(self):
with transaction.atomic(): with transaction.atomic():
@ -309,11 +317,11 @@ class ClickTokenForm(forms.BaseForm):
counter = Counter.objects.filter(id=self.counter_id).first() counter = Counter.objects.filter(id=self.counter_id).first()
subscriber = customer.user subscriber = customer.user
self.last_basket = { self.last_basket = {
'last_basket': [], 'last_basket': [],
'last_customer': customer.user.get_display_name(), 'last_customer': customer.user.get_display_name(),
} }
total = 0 total = 0
for k,t in self.cleaned_data.items(): for k, t in self.cleaned_data.items():
if t is not None: if t is not None:
slot_id = int(k[5:]) slot_id = int(k[5:])
slot = Slot.objects.filter(id=slot_id).first() slot = Slot.objects.filter(id=slot_id).first()
@ -323,15 +331,16 @@ class ClickTokenForm(forms.BaseForm):
t.borrow_date = datetime.now().replace(tzinfo=pytz.UTC) t.borrow_date = datetime.now().replace(tzinfo=pytz.UTC)
t.save() t.save()
price = settings.SITH_LAUNDERETTE_PRICES[t.type] price = settings.SITH_LAUNDERETTE_PRICES[t.type]
s = Selling(label="Jeton "+t.get_type_display()+""+t.name, club=counter.club, product=None, counter=counter, unit_price=price, s = Selling(label="Jeton " + t.get_type_display() + "" + t.name, club=counter.club, product=None, counter=counter, unit_price=price,
quantity=1, seller=operator, customer=customer) quantity=1, seller=operator, customer=customer)
s.save() s.save()
total += price total += price
self.last_basket['last_basket'].append("Jeton "+t.get_type_display()+""+t.name) self.last_basket['last_basket'].append("Jeton " + t.get_type_display() + "" + t.name)
self.last_basket['new_customer_amount'] = str(customer.amount) self.last_basket['new_customer_amount'] = str(customer.amount)
self.last_basket['last_total'] = str(total) self.last_basket['last_total'] = str(total)
return self.cleaned_data return self.cleaned_data
class LaunderetteClickView(CanEditMixin, DetailView, BaseFormView): class LaunderetteClickView(CanEditMixin, DetailView, BaseFormView):
"""The click page of the launderette""" """The click page of the launderette"""
model = Launderette model = Launderette
@ -346,7 +355,7 @@ class LaunderetteClickView(CanEditMixin, DetailView, BaseFormView):
t_name = str(self2.data[field_name]) t_name = str(self2.data[field_name])
if t_name != "": if t_name != "":
t = Token.objects.filter(name=str(self2.data[field_name]), type=slot.type, launderette=self.object, t = Token.objects.filter(name=str(self2.data[field_name]), type=slot.type, launderette=self.object,
user=None).first() user=None).first()
if t is None: if t is None:
raise forms.ValidationError(_("Token not found")) raise forms.ValidationError(_("Token not found"))
return t return t
@ -354,9 +363,9 @@ class LaunderetteClickView(CanEditMixin, DetailView, BaseFormView):
for s in self.subscriber.slots.filter(token=None, start_date__gte=timezone.now().replace(tzinfo=None)).all(): for s in self.subscriber.slots.filter(token=None, start_date__gte=timezone.now().replace(tzinfo=None)).all():
field_name = "slot-%s" % (str(s.id)) field_name = "slot-%s" % (str(s.id))
fields[field_name] = forms.CharField(max_length=5, required=False, fields[field_name] = forms.CharField(max_length=5, required=False,
label="%s - %s" % (s.get_type_display(), defaultfilters.date(s.start_date, "j N Y H:i"))) label="%s - %s" % (s.get_type_display(), defaultfilters.date(s.start_date, "j N Y H:i")))
# XXX l10n settings.DATETIME_FORMAT didn't work here :/ # XXX l10n settings.DATETIME_FORMAT didn't work here :/
kwargs["clean_"+field_name] = clean_field_factory(field_name, s) kwargs["clean_" + field_name] = clean_field_factory(field_name, s)
kwargs['subscriber_id'] = self.subscriber.id kwargs['subscriber_id'] = self.subscriber.id
kwargs['counter_id'] = self.object.counter.id kwargs['counter_id'] = self.object.counter.id
kwargs['operator_id'] = self.operator.id kwargs['operator_id'] = self.operator.id
@ -401,7 +410,6 @@ class LaunderetteClickView(CanEditMixin, DetailView, BaseFormView):
return reverse_lazy('launderette:main_click', args=self.args, kwargs=self.kwargs) return reverse_lazy('launderette:main_click', args=self.args, kwargs=self.kwargs)
class MachineEditView(CanEditPropMixin, UpdateView): class MachineEditView(CanEditPropMixin, UpdateView):
"""Edit a machine""" """Edit a machine"""
model = Machine model = Machine
@ -409,6 +417,7 @@ class MachineEditView(CanEditPropMixin, UpdateView):
fields = ['name', 'launderette', 'type', 'is_working'] fields = ['name', 'launderette', 'type', 'is_working']
template_name = 'core/edit.jinja' template_name = 'core/edit.jinja'
class MachineDeleteView(CanEditPropMixin, DeleteView): class MachineDeleteView(CanEditPropMixin, DeleteView):
"""Edit a machine""" """Edit a machine"""
model = Machine model = Machine
@ -416,6 +425,7 @@ class MachineDeleteView(CanEditPropMixin, DeleteView):
template_name = 'core/delete_confirm.jinja' template_name = 'core/delete_confirm.jinja'
success_url = reverse_lazy('launderette:launderette_list') success_url = reverse_lazy('launderette:launderette_list')
class MachineCreateView(CanCreateMixin, CreateView): class MachineCreateView(CanCreateMixin, CreateView):
"""Create a new machine""" """Create a new machine"""
model = Machine model = Machine
@ -429,6 +439,3 @@ class MachineCreateView(CanCreateMixin, CreateView):
if obj is not None: if obj is not None:
ret['launderette'] = obj.id ret['launderette'] = obj.id
return ret return ret