diff --git a/apache/wsgi.py b/apache/wsgi.py index b7a1eb92..177542a8 100644 --- a/apache/wsgi.py +++ b/apache/wsgi.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + """ WSGI config for myproject project. It exposes the WSGI callable as a module-level variable named ``application``. @@ -5,6 +7,10 @@ For more information on this file, see https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ """ +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + import os from django.core.wsgi import get_wsgi_application diff --git a/bda/admin.py b/bda/admin.py index 26d9a865..8f5915d5 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -1,4 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django.core.mail import send_mail @@ -52,9 +56,9 @@ class ParticipantAdmin(admin.ModelAdmin): def total(self, obj): tot = obj.total if tot: - return u"%.02f €" % tot + return "%.02f €" % tot else: - return u"0 €" + return "0 €" total.admin_order_field = "total" total.short_description = "Total à payer" list_display = ("user", "nb_places", "total", "paid", "paymenttype", @@ -70,7 +74,7 @@ class ParticipantAdmin(admin.ModelAdmin): for member in queryset.all(): attribs = member.attributions.all() if len(attribs) == 0: - mail = u"""Cher-e %s, + mail = """Cher-e %s, Tu t'es inscrit-e pour le tirage au sort du BdA. Malheureusement, tu n'as obtenu aucune place. @@ -85,7 +89,7 @@ Le Bureau des Arts name = member.user.get_full_name() mail = mail % name else: - mail = u"""Cher-e %s, + mail = """Cher-e %s, Tu t'es inscrit-e pour le tirage au sort du BdA. Tu as été sélectionné-e pour les spectacles suivants : @@ -120,7 +124,7 @@ Le Bureau des Arts attribs_text = "" name = member.user.get_full_name() for attrib in attribs: - attribs_text += u"- 1 place pour %s\n" % attrib + attribs_text += "- 1 place pour %s\n" % attrib deadline = member.tirage.fermeture + timedelta(days=7) mail = mail % (name, attribs_text, deadline.strftime('%d %b %Y')) @@ -129,14 +133,14 @@ Le Bureau des Arts fail_silently=True) count = len(queryset.all()) if count == 1: - message_bit = u"1 membre a" + message_bit = "1 membre a" plural = "" else: - message_bit = u"%d membres ont" % count + message_bit = "%d membres ont" % count plural = "s" - self.message_user(request, u"%s été informé%s avec succès." + self.message_user(request, "%s été informé%s avec succès." % (message_bit, plural)) - send_attribs.short_description = u"Envoyer les résultats par mail" + send_attribs.short_description = "Envoyer les résultats par mail" class AttributionAdminForm(forms.ModelForm): @@ -147,8 +151,8 @@ class AttributionAdminForm(forms.ModelForm): if participant and spectacle: if participant.tirage != spectacle.tirage: raise forms.ValidationError( - u"Erreur : le participant et le spectacle n'appartiennent" - u"pas au même tirage") + "Erreur : le participant et le spectacle n'appartiennent" + "pas au même tirage") return cleaned_data @@ -174,7 +178,8 @@ class ChoixSpectacleAdmin(admin.ModelAdmin): list_filter = ("double_choice", "participant__tirage") search_fields = ('participant__user__username', 'participant__user__first_name', - 'participant__user__last_name') + 'participant__user__last_name', + 'spectacle__title') class SpectacleAdmin(admin.ModelAdmin): @@ -193,8 +198,14 @@ class TirageAdmin(admin.ModelAdmin): list_filter = ("active", ) search_fields = ("title", ) + +class SalleAdmin(admin.ModelAdmin): + model = Salle + search_fields = ('name', 'address') + + admin.site.register(Spectacle, SpectacleAdmin) -admin.site.register(Salle) +admin.site.register(Salle, SalleAdmin) admin.site.register(Participant, ParticipantAdmin) admin.site.register(Attribution, AttributionAdmin) admin.site.register(ChoixSpectacle, ChoixSpectacleAdmin) diff --git a/bda/algorithm.py b/bda/algorithm.py index 005e714f..bf9b690f 100644 --- a/bda/algorithm.py +++ b/bda/algorithm.py @@ -1,6 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django.db.models import Max diff --git a/bda/autocomplete_light_registry.py b/bda/autocomplete_light_registry.py index 7aa43b07..6c2f3ea6 100644 --- a/bda/autocomplete_light_registry.py +++ b/bda/autocomplete_light_registry.py @@ -1,3 +1,9 @@ +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + import autocomplete_light from bda.models import Participant, Spectacle diff --git a/bda/forms.py b/bda/forms.py index 213ec17b..9f5e3890 100644 --- a/bda/forms.py +++ b/bda/forms.py @@ -1,4 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django import forms from django.forms.models import BaseInlineFormSet @@ -33,8 +37,8 @@ class TokenForm(forms.Form): class SpectacleModelChoiceField(forms.ModelChoiceField): def label_from_instance(self, obj): - return u"%s le %s (%s) à %.02f€" % (obj.title, obj.date_no_seconds(), - obj.location, obj.price) + return "%s le %s (%s) à %.02f€" % (obj.title, obj.date_no_seconds(), + obj.location, obj.price) class ResellForm(forms.Form): diff --git a/bda/management/__init__.py b/bda/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bda/management/commands/__init__.py b/bda/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bda/management/commands/sendrappels.py b/bda/management/commands/sendrappels.py new file mode 100644 index 00000000..1e8da240 --- /dev/null +++ b/bda/management/commands/sendrappels.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +from __future__ import unicode_literals + +from django.core.management.base import BaseCommand +from django.utils import timezone +from datetime import timedelta +from bda.models import Spectacle + + +class Command(BaseCommand): + help = 'Envoie les mails de rappel des spectacles dont la date ' \ + 'approche.\nNe renvoie pas les mails déjà envoyés.' + + def handle(self, *args, **options): + now = timezone.now() + delay = timedelta(days=4) + shows = Spectacle.objects \ + .filter(date__range=(now, now+delay)) \ + .filter(tirage__active=True) \ + .filter(rappel_sent__isnull=True) \ + .all() + for show in shows: + show.send_rappel() + self.stdout.write( + 'Mails de rappels pour %s envoyés avec succès.' % show) + if not shows: + self.stdout.write('Aucun mail à envoyer.') diff --git a/bda/migrations/0005_encoding.py b/bda/migrations/0005_encoding.py new file mode 100644 index 00000000..b36113c2 --- /dev/null +++ b/bda/migrations/0005_encoding.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bda', '0004_mails-rappel'), + ] + + operations = [ + migrations.AlterField( + model_name='choixspectacle', + name='priority', + field=models.PositiveIntegerField(verbose_name='Priorit\xe9'), + ), + migrations.AlterField( + model_name='spectacle', + name='priority', + field=models.IntegerField(default=1000, verbose_name='Priorit\xe9'), + ), + migrations.AlterField( + model_name='spectacle', + name='rappel_sent', + field=models.DateTimeField(null=True, verbose_name='Mail de rappel envoy\xe9', blank=True), + ), + ] diff --git a/bda/models.py b/bda/models.py index 349a71e4..41037643 100644 --- a/bda/models.py +++ b/bda/models.py @@ -1,4 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals import calendar @@ -8,6 +12,7 @@ from django.template import loader, Context from django.core import mail from django.conf import settings from django.utils import timezone +from django.utils.encoding import python_2_unicode_compatible def render_template(template_name, data): @@ -16,6 +21,7 @@ def render_template(template_name, data): return tmpl.render(ctxt) +@python_2_unicode_compatible class Tirage(models.Model): title = models.CharField("Titre", max_length=300) ouverture = models.DateTimeField("Date et heure d'ouverture du tirage") @@ -26,18 +32,20 @@ class Tirage(models.Model): def date_no_seconds(self): return self.fermeture.strftime('%d %b %Y %H:%M') - def __unicode__(self): - return u"%s - %s" % (self.title, self.date_no_seconds()) + def __str__(self): + return "%s - %s" % (self.title, self.date_no_seconds()) +@python_2_unicode_compatible class Salle(models.Model): name = models.CharField("Nom", max_length=300) address = models.TextField("Adresse") - def __unicode__(self): + def __str__(self): return self.name +@python_2_unicode_compatible class Spectacle(models.Model): title = models.CharField("Titre", max_length=300) date = models.DateTimeField("Date & heure") @@ -57,7 +65,7 @@ class Spectacle(models.Model): ordering = ("priority", "date", "title",) def __repr__(self): - return u"[%s]" % self.__unicode__() + return "[%s]" % self def timestamp(self): return "%d" % calendar.timegm(self.date.utctimetuple()) @@ -65,9 +73,9 @@ class Spectacle(models.Model): def date_no_seconds(self): return self.date.strftime('%d %b %Y %H:%M') - def __unicode__(self): - return u"%s - %s, %s, %.02f€" % (self.title, self.date_no_seconds(), - self.location, self.price) + def __str__(self): + return "%s - %s, %s, %.02f€" % (self.title, self.date_no_seconds(), + self.location, self.price) def send_rappel(self): # On récupère la liste des participants @@ -102,13 +110,14 @@ class Spectacle(models.Model): return members.values() PAYMENT_TYPES = ( - ("cash", u"Cash"), + ("cash", "Cash"), ("cb", "CB"), - ("cheque", u"Chèque"), - ("autre", u"Autre"), + ("cheque", "Chèque"), + ("autre", "Autre"), ) +@python_2_unicode_compatible class Participant(models.Model): user = models.ForeignKey(User) choices = models.ManyToManyField(Spectacle, @@ -117,14 +126,14 @@ class Participant(models.Model): attributions = models.ManyToManyField(Spectacle, through="Attribution", related_name="attributed_to") - paid = models.BooleanField(u"A payé", default=False) - paymenttype = models.CharField(u"Moyen de paiement", + paid = models.BooleanField("A payé", default=False) + paymenttype = models.CharField("Moyen de paiement", max_length=6, choices=PAYMENT_TYPES, blank=True) tirage = models.ForeignKey(Tirage) - def __unicode__(self): - return u"%s" % (self.user) + def __str__(self): + return "%s - %s" % (self.user, self.tirage.title) DOUBLE_CHOICES = ( ("1", "1 place"), @@ -133,6 +142,7 @@ DOUBLE_CHOICES = ( ) +@python_2_unicode_compatible class ChoixSpectacle(models.Model): participant = models.ForeignKey(Participant) spectacle = models.ForeignKey(Spectacle, related_name="participants") @@ -149,6 +159,11 @@ class ChoixSpectacle(models.Model): return self.double_choice == "autoquit" autoquit = property(get_autoquit) + def __str__(self): + return "Vœux de %s pour %s" % ( + self.participant.user.get_full_name, + self.spectacle.title) + class Meta: ordering = ("priority",) unique_together = (("participant", "spectacle",),) @@ -156,10 +171,11 @@ class ChoixSpectacle(models.Model): verbose_name_plural = "voeux" +@python_2_unicode_compatible class Attribution(models.Model): participant = models.ForeignKey(Participant) spectacle = models.ForeignKey(Spectacle, related_name="attribues") - given = models.BooleanField(u"Donnée", default=False) + given = models.BooleanField("Donnée", default=False) - def __unicode__(self): - return u"%s -- %s" % (self.participant, self.spectacle) + def __str__(self): + return "%s -- %s" % (self.participant, self.spectacle) diff --git a/bda/templates/etat-places.html b/bda/templates/etat-places.html index e726cde6..c8192ac9 100644 --- a/bda/templates/etat-places.html +++ b/bda/templates/etat-places.html @@ -1,4 +1,5 @@ {% extends "base_title.html" %} +{% load staticfiles %} {% block realcontent %}

État des inscriptions BdA

@@ -39,8 +40,10 @@ Total : {{ total }} demandes - - + +