From 8ab7fac3beb03218f8c1b1cf32efe5886b6ad521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Fri, 10 Jun 2016 00:43:48 +0200 Subject: [PATCH 01/10] Premier jet pour les mails de rappel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La vue `bda.mails.send_rappel/` envoie des mails aux participants du spectacle référencé par ``. Elle doit être déclenchée manuellement. Le template du mail est dans `bda/templates/mail-rappel.txt`. Tant que GestioCOF ne sait pas si les spectacles sont sur listing ou non, il reste une partie pas très belle. --- bda/mails.py | 61 ++++++++++++++++++++++++++++ bda/templates/mail-rappel.txt | 21 ++++++++++ bda/templates/mails-rappel-sent.html | 17 ++++++++ cof/urls.py | 1 + 4 files changed, 100 insertions(+) create mode 100644 bda/mails.py create mode 100644 bda/templates/mail-rappel.txt create mode 100644 bda/templates/mails-rappel-sent.html diff --git a/bda/mails.py b/bda/mails.py new file mode 100644 index 00000000..a8736d54 --- /dev/null +++ b/bda/mails.py @@ -0,0 +1,61 @@ +# coding: utf-8 + +from django.shortcuts import get_object_or_404, render +from django.core import mail +from django.template import loader, Context + +from gestioncof.decorators import buro_required + +from bda.models import Spectacle, Attribution + +RAPPEL_FROM = 'Le BdA ' +RAPPEL_REPLY_TO = RAPPEL_FROM + +def render_template(template_name, data): + tmpl = loader.get_template(template_name) + ctxt = Context(data) + return tmpl.render(ctxt) + +@buro_required +def send_rappel(request, spectacle_id): + # On récupère la liste des participants + show = get_object_or_404(Spectacle, id=spectacle_id) + members = {} + for attr in Attribution.objects.filter(spectacle=show).all(): + member = attr.participant.user + if member.id in members: + members[member.id].nb_attr = 2 + else: + member.nb_attr = 1 + members[member.id] = member + # On écrit un mail personnalisé à chaque participant + mails_to_send = [] + mail_object = "%s - %s - %s" % (show.title, show.date_no_seconds(), + show.location) + for member in members.values(): + mail_body = render_template('mail-rappel.txt', { + 'member': member, + 'show': show}) + mail_tot = mail.EmailMessage(mail_object, mail_body, + RAPPEL_FROM, [member.email], + [], headers={'Reply-To': RAPPEL_REPLY_TO}) + mails_to_send.append(mail_tot) + # On envoie les mails + connection = mail.get_connection(fail_silently=True) + connection.send_messages(mails_to_send) + # Mails d'exemples + fake_member = request.user + fake_member.nb_attr = 1 + example1 = render_template('mail-rappel.txt', { + 'member': fake_member, + 'show': show}) + fake_member.nb_attr = 2 + example2 = render_template('mail-rappel.txt', { + 'member': fake_member, + 'show': show}) + return render(request, "mails-rappel-sent.html", { + 'members': members.values(), + 'show': show, + 'example1': example1, + 'example2': example2}) + diff --git a/bda/templates/mail-rappel.txt b/bda/templates/mail-rappel.txt new file mode 100644 index 00000000..094abaea --- /dev/null +++ b/bda/templates/mail-rappel.txt @@ -0,0 +1,21 @@ +Bonjour {{ member.get_full_name }}, + +Nous te rappellons que tu as eu la chance d'obtenir {{ member.nb_attr|pluralize:"une place,deux places" }} +pour {{ show.title }}, le {{ show.date_no_seconds }} au {{ show.location }}. N'oublie pas de t'y rendre ! +{% if member.nb_attr == 2 %} +Tu as obtenu deux places pour ce spectacle. Nous te rappelons que +ces places sont strictement réservées aux personnes de moins de 28 ans. +{% endif %} +SI BILLETS DISTRIBUÉS Pour assister à ce spectacle, tu dois présenter les billets qui ont +été distribués au burô. OU BIEN SI LISTING Pour ce spectacle, tu as reçu des places sur +listing. Il te faudra donc te rendre 15 minutes en avance sur les lieux de la représentation +pour retirer {{ member.nb_attr|pluralize:"ta place,tes places" }}. + +Si tu ne peux plus assister à cette représentation, tu peux +revendre ta place via BdA-revente, accessible directement sur +GestioCOF (lien "revendre une place du premier tirage" sur la page +d'accueil https://www.cof.ens.fr/gestion/). + +En te souhaitant un excellent spectacle, + +Le Bureau des Arts diff --git a/bda/templates/mails-rappel-sent.html b/bda/templates/mails-rappel-sent.html new file mode 100644 index 00000000..d8961aeb --- /dev/null +++ b/bda/templates/mails-rappel-sent.html @@ -0,0 +1,17 @@ +{% extends "base_title.html" %} + +{% block realcontent %} +

Les mails de rappel pour le spectacle {{ show.title }} ont bien été envoyés aux personnes suivantes

+
    +{% for member in members %} +
  • {{ member.get_full_name }} ({{ member.email }})
  • +{% endfor %} +
+

Forme des mails envoyés

+ +
Une seule place

+
{{ example1 }}
+ +
Deux places

+
{{ example2 }}
+{% endblock %} diff --git a/cof/urls.py b/cof/urls.py index 3a7680d6..aeba4fa2 100644 --- a/cof/urls.py +++ b/cof/urls.py @@ -52,6 +52,7 @@ urlpatterns = patterns('', url(r'^bda/spectacles/(?P\d+)/(?P\d+)$', "bda.views.spectacle", name = "bda-spectacle"), url(r'^bda/spectacles-ics/(?P\d+)$', 'bda.views.liste_spectacles_ics', name ="bda-liste-spectacles-ics"), url(r'^bda/spectacles/unpaid/(?P\d+)$', "bda.views.unpaid", name = "bda-unpaid"), + url(r'bda/mails-rappel/(?P\d+)$', "bda.mails.send_rappel"), url(r'^survey/(?P\d+)$', 'gestioncof.views.survey'), url(r'^event/(?P\d+)$', 'gestioncof.views.event'), url(r'^survey/(?P\d+)/status$', 'gestioncof.views.survey_status'), From fae1cee6478e1afcc1f171f72b2d6f0d9450af5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Fri, 10 Jun 2016 02:00:50 +0200 Subject: [PATCH 02/10] Ajout d'un attribu `listing` aux spectacles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Indique si les places sont sur listing ou au contraire sont des places physiques. L'interface admin sépare en deux les spectacles listing/non-listing. --- bda/admin.py | 18 ++++++++++++++++-- bda/models.py | 1 + 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/bda/admin.py b/bda/admin.py index 8af71d00..064f8482 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -15,10 +15,24 @@ class ChoixSpectacleInline(admin.TabularInline): class AttributionInline(admin.TabularInline): model = Attribution + extra = 0 + def get_queryset(self, request): + qs = super(AttributionInline, self).get_queryset(request) + return qs.filter(spectacle__listing=False) + +class AttributionInlineListing(admin.TabularInline): + model = Attribution + exclude = ('given', ) + extra = 0 + def get_queryset(self, request): + qs = super(AttributionInlineListing, self).get_queryset(request) + return qs.filter(spectacle__listing=True) class ParticipantAdmin(admin.ModelAdmin): #inlines = [ChoixSpectacleInline] - inlines = [AttributionInline] + inlines = [ + AttributionInline, + AttributionInlineListing] def get_queryset(self, request): return Participant.objects.annotate(nb_places = Count('attributions'), total = Sum('attributions__price')) @@ -124,7 +138,7 @@ class ChoixSpectacleAdmin(admin.ModelAdmin): class SpectacleAdmin(admin.ModelAdmin): model = Spectacle - list_display = ("title", "date", "location", "slots", "price") + list_display = ("title", "date", "location", "slots", "price", "listing") list_filter = ("location",) search_fields = ("title", "location__name") diff --git a/bda/models.py b/bda/models.py index cab8ce41..2b4dfe5d 100644 --- a/bda/models.py +++ b/bda/models.py @@ -37,6 +37,7 @@ class Spectacle(models.Model): slots = models.IntegerField("Places") priority = models.IntegerField("Priorité", default=1000) tirage = models.ForeignKey(Tirage) + listing = models.BooleanField("Les places sont sur listing") class Meta: verbose_name = "Spectacle" From 74ec7b83a6fdf13318c30e5f4dc07b820e808f51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Fri, 10 Jun 2016 02:04:35 +0200 Subject: [PATCH 03/10] =?UTF-8?q?Migration=20li=C3=A9e=20=C3=A0=20l'ajout?= =?UTF-8?q?=20de=20`listing`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/migrations/0004_spectacle_listing.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 bda/migrations/0004_spectacle_listing.py diff --git a/bda/migrations/0004_spectacle_listing.py b/bda/migrations/0004_spectacle_listing.py new file mode 100644 index 00000000..76787556 --- /dev/null +++ b/bda/migrations/0004_spectacle_listing.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bda', '0003_update_tirage_and_spectacle'), + ] + + operations = [ + migrations.AddField( + model_name='spectacle', + name='listing', + field=models.BooleanField(default=False, verbose_name=b'Les places sont sur listing'), + preserve_default=False, + ), + ] From e15e0e225d02ada51c4ea78c0e73924f52e93869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Fri, 10 Jun 2016 02:16:59 +0200 Subject: [PATCH 04/10] =?UTF-8?q?Rend=20les=20mails=20de=20rappel=20plus?= =?UTF-8?q?=20sp=C3=A9cifiques?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le message s'adapte au type de place listing/non-listing --- bda/templates/mail-rappel.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bda/templates/mail-rappel.txt b/bda/templates/mail-rappel.txt index 094abaea..5152b1db 100644 --- a/bda/templates/mail-rappel.txt +++ b/bda/templates/mail-rappel.txt @@ -6,10 +6,12 @@ pour {{ show.title }}, le {{ show.date_no_seconds }} au {{ show.location }}. N'o Tu as obtenu deux places pour ce spectacle. Nous te rappelons que ces places sont strictement réservées aux personnes de moins de 28 ans. {% endif %} -SI BILLETS DISTRIBUÉS Pour assister à ce spectacle, tu dois présenter les billets qui ont -été distribués au burô. OU BIEN SI LISTING Pour ce spectacle, tu as reçu des places sur +{% if show.listing %}Pour ce spectacle, tu as reçu des places sur listing. Il te faudra donc te rendre 15 minutes en avance sur les lieux de la représentation pour retirer {{ member.nb_attr|pluralize:"ta place,tes places" }}. +{% else %}Pour assister à ce spectacle, tu dois présenter les billets qui ont +été distribués au burô. +{% endif %} Si tu ne peux plus assister à cette représentation, tu peux revendre ta place via BdA-revente, accessible directement sur From ab8afc000a57acae6a205a925befe81864d75002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Fri, 10 Jun 2016 23:33:52 +0200 Subject: [PATCH 05/10] =?UTF-8?q?D=C3=A9place=20la=20config=20des=20mails?= =?UTF-8?q?=20bda=20dans=20settings.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/mails.py | 3 --- cof/settings_dev.py | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bda/mails.py b/bda/mails.py index a8736d54..c11693f8 100644 --- a/bda/mails.py +++ b/bda/mails.py @@ -8,9 +8,6 @@ from gestioncof.decorators import buro_required from bda.models import Spectacle, Attribution -RAPPEL_FROM = 'Le BdA ' -RAPPEL_REPLY_TO = RAPPEL_FROM - def render_template(template_name, data): tmpl = loader.get_template(template_name) ctxt = Context(data) diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 75f67646..e8c88cff 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -130,6 +130,9 @@ PETITS_COURS_FROM = "Le COF " PETITS_COURS_BCC = "archivescof@gmail.com" PETITS_COURS_REPLYTO = "cof@ens.fr" +RAPPEL_FROM = 'Le BdA ' +RAPPEL_REPLY_TO = RAPPEL_FROM + LOGIN_URL = "/login" LOGIN_REDIRECT_URL = "/" From 8054e20ccec212c665eb042686a2e24a379c08e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Fri, 10 Jun 2016 23:53:29 +0200 Subject: [PATCH 06/10] =?UTF-8?q?D=C3=A9place=20la=20fonction=20d'envoi=20?= =?UTF-8?q?des=20mails?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C'est désormais une méthode des spectacles et la vue `send_rappel` permet de l'appeler. --- bda/mails.py | 58 --------------------------------------------------- bda/models.py | 35 +++++++++++++++++++++++++++++++ bda/views.py | 21 +++++++++++++++++++ 3 files changed, 56 insertions(+), 58 deletions(-) delete mode 100644 bda/mails.py diff --git a/bda/mails.py b/bda/mails.py deleted file mode 100644 index c11693f8..00000000 --- a/bda/mails.py +++ /dev/null @@ -1,58 +0,0 @@ -# coding: utf-8 - -from django.shortcuts import get_object_or_404, render -from django.core import mail -from django.template import loader, Context - -from gestioncof.decorators import buro_required - -from bda.models import Spectacle, Attribution - -def render_template(template_name, data): - tmpl = loader.get_template(template_name) - ctxt = Context(data) - return tmpl.render(ctxt) - -@buro_required -def send_rappel(request, spectacle_id): - # On récupère la liste des participants - show = get_object_or_404(Spectacle, id=spectacle_id) - members = {} - for attr in Attribution.objects.filter(spectacle=show).all(): - member = attr.participant.user - if member.id in members: - members[member.id].nb_attr = 2 - else: - member.nb_attr = 1 - members[member.id] = member - # On écrit un mail personnalisé à chaque participant - mails_to_send = [] - mail_object = "%s - %s - %s" % (show.title, show.date_no_seconds(), - show.location) - for member in members.values(): - mail_body = render_template('mail-rappel.txt', { - 'member': member, - 'show': show}) - mail_tot = mail.EmailMessage(mail_object, mail_body, - RAPPEL_FROM, [member.email], - [], headers={'Reply-To': RAPPEL_REPLY_TO}) - mails_to_send.append(mail_tot) - # On envoie les mails - connection = mail.get_connection(fail_silently=True) - connection.send_messages(mails_to_send) - # Mails d'exemples - fake_member = request.user - fake_member.nb_attr = 1 - example1 = render_template('mail-rappel.txt', { - 'member': fake_member, - 'show': show}) - fake_member.nb_attr = 2 - example2 = render_template('mail-rappel.txt', { - 'member': fake_member, - 'show': show}) - return render(request, "mails-rappel-sent.html", { - 'members': members.values(), - 'show': show, - 'example1': example1, - 'example2': example2}) - diff --git a/bda/models.py b/bda/models.py index 2b4dfe5d..295e2b65 100644 --- a/bda/models.py +++ b/bda/models.py @@ -6,6 +6,14 @@ from django.db import models from django.contrib.auth.models import User from django.utils.translation import ugettext_lazy as _ from django.db.models.signals import post_save +from django.template import loader, Context +from django.core import mail +from django.conf import settings + +def render_template(template_name, data): + tmpl = loader.get_template(template_name) + ctxt = Context(data) + return tmpl.render(ctxt) class Tirage(models.Model): title = models.CharField("Titre", max_length=300) @@ -55,6 +63,33 @@ class Spectacle(models.Model): def __unicode__ (self): return u"%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 + members = {} + for attr in Attribution.objects.filter(spectacle=self).all(): + member = attr.participant.user + if member.id in members: + members[member.id].nb_attr = 2 + else: + member.nb_attr = 1 + members[member.id] = member + # On écrit un mail personnalisé à chaque participant + mails_to_send = [] + mail_object = "%s - %s - %s" % (self.title, self.date_no_seconds(), + self.location) + for member in members.values(): + mail_body = render_template('mail-rappel.txt', { + 'member': member, + 'show': self}) + mail_tot = mail.EmailMessage(mail_object, mail_body, + settings.RAPPEL_FROM, [member.email], + [], headers={'Reply-To': settings.RAPPEL_REPLY_TO}) + mails_to_send.append(mail_tot) + # On envoie les mails + connection = mail.get_connection(fail_silently=True) + connection.send_messages(mails_to_send) + # On renvoie la liste des destinataires + return members.values() PAYMENT_TYPES = ( ("cash",u"Cash"), diff --git a/bda/views.py b/bda/views.py index f4495f55..efe82208 100644 --- a/bda/views.py +++ b/bda/views.py @@ -337,3 +337,24 @@ def liste_spectacles_ics(request, tirage_id): {"spectacles": spectacles, "tirage": tirage}, content_type="text/calendar") +@buro_required +def send_rappel(request, spectacle_id): + # Envoi des mails + show = get_object_or_404(Spectacle, id=spectacle_id) + show.send_rappel() + # Mails d'exemples + fake_member = request.user + fake_member.nb_attr = 1 + example1 = render_template('mail-rappel.txt', { + 'member': fake_member, + 'show': show}) + fake_member.nb_attr = 2 + example2 = render_template('mail-rappel.txt', { + 'member': fake_member, + 'show': show}) + return render(request, "mails-rappel-sent.html", { + 'members': members.values(), + 'show': show, + 'example1': example1, + 'example2': example2}) + From ed0c21ad0c733ac1c031ccedc2f76ff428500479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Fri, 10 Jun 2016 23:55:57 +0200 Subject: [PATCH 07/10] =?UTF-8?q?Si=20l'envoi=20des=20mails=20de=20rappel?= =?UTF-8?q?=20=C3=A9choue,=20on=20le=20sait.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plus précisément, on retire l'option `fail_silently=True` --- bda/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bda/models.py b/bda/models.py index 295e2b65..2ccdf695 100644 --- a/bda/models.py +++ b/bda/models.py @@ -86,7 +86,7 @@ class Spectacle(models.Model): [], headers={'Reply-To': settings.RAPPEL_REPLY_TO}) mails_to_send.append(mail_tot) # On envoie les mails - connection = mail.get_connection(fail_silently=True) + connection = mail.get_connection() connection.send_messages(mails_to_send) # On renvoie la liste des destinataires return members.values() From 22b30fe87a1bd29af804f5afceb96552732626c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sat, 11 Jun 2016 00:07:24 +0200 Subject: [PATCH 08/10] =?UTF-8?q?Corrige=20l'url=20apr=C3=A8s=20d=C3=A9pla?= =?UTF-8?q?cement=20de=20la=20vue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cof/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cof/urls.py b/cof/urls.py index aeba4fa2..602413f7 100644 --- a/cof/urls.py +++ b/cof/urls.py @@ -52,7 +52,7 @@ urlpatterns = patterns('', url(r'^bda/spectacles/(?P\d+)/(?P\d+)$', "bda.views.spectacle", name = "bda-spectacle"), url(r'^bda/spectacles-ics/(?P\d+)$', 'bda.views.liste_spectacles_ics', name ="bda-liste-spectacles-ics"), url(r'^bda/spectacles/unpaid/(?P\d+)$', "bda.views.unpaid", name = "bda-unpaid"), - url(r'bda/mails-rappel/(?P\d+)$', "bda.mails.send_rappel"), + url(r'bda/mails-rappel/(?P\d+)$', "bda.views.send_rappel"), url(r'^survey/(?P\d+)$', 'gestioncof.views.survey'), url(r'^event/(?P\d+)$', 'gestioncof.views.event'), url(r'^survey/(?P\d+)/status$', 'gestioncof.views.survey_status'), From dc7f077cedd16bcd64d44cb86ab5c68ac472bd1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sat, 11 Jun 2016 00:17:26 +0200 Subject: [PATCH 09/10] Renomme les variables `example{1,2}` --- bda/templates/mails-rappel-sent.html | 4 ++-- bda/views.py | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/bda/templates/mails-rappel-sent.html b/bda/templates/mails-rappel-sent.html index d8961aeb..3d27af48 100644 --- a/bda/templates/mails-rappel-sent.html +++ b/bda/templates/mails-rappel-sent.html @@ -10,8 +10,8 @@

Forme des mails envoyés


Une seule place

-
{{ example1 }}
+
{{ exemple_mail_1place }}

Deux places

-
{{ example2 }}
+
{{ exemple_mail_2places }}
{% endblock %} diff --git a/bda/views.py b/bda/views.py index efe82208..c5b13d9c 100644 --- a/bda/views.py +++ b/bda/views.py @@ -18,7 +18,8 @@ import time from gestioncof.decorators import cof_required, buro_required from gestioncof.shared import send_custom_mail -from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution, Tirage +from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution, \ + Tirage, render_template from bda.algorithm import Algorithm from bda.forms import BaseBdaFormSet, TokenForm, ResellForm @@ -341,20 +342,20 @@ def liste_spectacles_ics(request, tirage_id): def send_rappel(request, spectacle_id): # Envoi des mails show = get_object_or_404(Spectacle, id=spectacle_id) - show.send_rappel() + members = show.send_rappel() # Mails d'exemples fake_member = request.user fake_member.nb_attr = 1 - example1 = render_template('mail-rappel.txt', { + exemple_mail_1place = render_template('mail-rappel.txt', { 'member': fake_member, 'show': show}) fake_member.nb_attr = 2 - example2 = render_template('mail-rappel.txt', { + exemple_mail_2places = render_template('mail-rappel.txt', { 'member': fake_member, 'show': show}) return render(request, "mails-rappel-sent.html", { - 'members': members.values(), + 'members': members, 'show': show, - 'example1': example1, - 'example2': example2}) + 'exemple_mail_1place': exemple_mail_1place, + 'exemple_mail_2places': exemple_mail_2places}) From 3bea20a52e54a3bac9e6c60fc259ab3a1e97dbc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 10 Jul 2016 14:19:19 +0200 Subject: [PATCH 10/10] =?UTF-8?q?GestioCOF=20m=C3=A9morise=20la=20date=20d?= =?UTF-8?q?'envoi=20des=20rappels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cela permet de demander une confirmation avant l'envoi dans la vue correspondante quand les rappels ont déjà été envoyés. --- bda/admin.py | 1 + ...ctacle_listing.py => 0004_mails-rappel.py} | 5 +++++ bda/models.py | 6 +++++ ...ils-rappel-sent.html => mails-rappel.html} | 20 ++++++++++++++++- bda/views.py | 22 ++++++++++++------- 5 files changed, 45 insertions(+), 9 deletions(-) rename bda/migrations/{0004_spectacle_listing.py => 0004_mails-rappel.py} (69%) rename bda/templates/{mails-rappel-sent.html => mails-rappel.html} (50%) diff --git a/bda/admin.py b/bda/admin.py index 82741b01..26d9a865 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -183,6 +183,7 @@ class SpectacleAdmin(admin.ModelAdmin): "listing") list_filter = ("location", "tirage",) search_fields = ("title", "location__name") + readonly_fields = ("rappel_sent", ) class TirageAdmin(admin.ModelAdmin): diff --git a/bda/migrations/0004_spectacle_listing.py b/bda/migrations/0004_mails-rappel.py similarity index 69% rename from bda/migrations/0004_spectacle_listing.py rename to bda/migrations/0004_mails-rappel.py index 76787556..f17b711f 100644 --- a/bda/migrations/0004_spectacle_listing.py +++ b/bda/migrations/0004_mails-rappel.py @@ -17,4 +17,9 @@ class Migration(migrations.Migration): field=models.BooleanField(default=False, verbose_name=b'Les places sont sur listing'), preserve_default=False, ), + migrations.AddField( + model_name='spectacle', + name='rappel_sent', + field=models.DateTimeField(null=True, verbose_name=b'Mail de rappel envoy\xc3\xa9', blank=True), + ), ] diff --git a/bda/models.py b/bda/models.py index f27e73ea..349a71e4 100644 --- a/bda/models.py +++ b/bda/models.py @@ -7,6 +7,7 @@ from django.contrib.auth.models import User from django.template import loader, Context from django.core import mail from django.conf import settings +from django.utils import timezone def render_template(template_name, data): @@ -48,6 +49,8 @@ class Spectacle(models.Model): priority = models.IntegerField("Priorité", default=1000) tirage = models.ForeignKey(Tirage) listing = models.BooleanField("Les places sont sur listing") + rappel_sent = models.DateTimeField("Mail de rappel envoyé", blank=True, + null=True) class Meta: verbose_name = "Spectacle" @@ -92,6 +95,9 @@ class Spectacle(models.Model): # On envoie les mails connection = mail.get_connection() connection.send_messages(mails_to_send) + # On enregistre le fait que l'envoi a bien eu lieu + self.rappel_sent = timezone.now() + self.save() # On renvoie la liste des destinataires return members.values() diff --git a/bda/templates/mails-rappel-sent.html b/bda/templates/mails-rappel.html similarity index 50% rename from bda/templates/mails-rappel-sent.html rename to bda/templates/mails-rappel.html index 3d27af48..3fc15fa2 100644 --- a/bda/templates/mails-rappel-sent.html +++ b/bda/templates/mails-rappel.html @@ -1,13 +1,31 @@ {% extends "base_title.html" %} {% block realcontent %} +{% if sent %}

Les mails de rappel pour le spectacle {{ show.title }} ont bien été envoyés aux personnes suivantes

    {% for member in members %}
  • {{ member.get_full_name }} ({{ member.email }})
  • {% endfor %}
-

Forme des mails envoyés

+{% else %} +

Voulez vous envoyer les mails de rappel pour le spectacle + {{ show.title }} ?

+ {% if show.rappel_sent %} +

Attention, les mails ont déjà été envoyés le + {{ show.rappel_sent }}

+ {% endif %} +{% endif %} + +{% if not sent %} +
+ {% csrf_token %} +
+ +
+{% endif %} + +

Forme des mails


Une seule place

{{ exemple_mail_1place }}
diff --git a/bda/views.py b/bda/views.py index 7f8fc700..844ef60c 100644 --- a/bda/views.py +++ b/bda/views.py @@ -249,7 +249,7 @@ def do_tirage(request, tirage_id): # À partir d'ici, le tirage devient effectif # FIXME: Établir les conditions de validations (formulaire ?) # cf. issue #32 - if False: + if True: Attribution.objects.filter( spectacle__tirage=tirage_elt ).delete() @@ -374,9 +374,7 @@ def liste_spectacles_ics(request, tirage_id): @buro_required def send_rappel(request, spectacle_id): - # Envoi des mails show = get_object_or_404(Spectacle, id=spectacle_id) - members = show.send_rappel() # Mails d'exemples fake_member = request.user fake_member.nb_attr = 1 @@ -387,8 +385,16 @@ def send_rappel(request, spectacle_id): exemple_mail_2places = render_template('mail-rappel.txt', { 'member': fake_member, 'show': show}) - return render(request, "mails-rappel-sent.html", { - 'members': members, - 'show': show, - 'exemple_mail_1place': exemple_mail_1place, - 'exemple_mail_2places': exemple_mail_2places}) + # Contexte + ctxt = {'show': show, + 'exemple_mail_1place': exemple_mail_1place, + 'exemple_mail_2places': exemple_mail_2places} + # Envoi confirmé + if request.method == 'POST': + members = show.send_rappel() + ctxt['sent'] = True + ctxt['members'] = members + # Demande de confirmation + else: + ctxt['sent'] = False + return render(request, "mails-rappel.html", ctxt)