forked from DGNum/gestioCOF
Merge branch 'Kerl/mail2bda' into 'master'
Copie des mails de rappel pour le BdA * Le BdA est en copie des mails de rappel (création d'un utilisateur générique BdA à cette fin) * Un lien vers la page d'envoi manuel des mails de rappel est ajouté à la page qui récapitule les situations des participants au spectacle * Quelques modification mineures de cette page * Un test très simple vérifie que les pages mentionnées plus haut sont accessibles à un utilisateur COF authentifié See merge request !238
This commit is contained in:
commit
398893b904
8 changed files with 131 additions and 67 deletions
|
@ -0,0 +1 @@
|
|||
|
|
@ -7,11 +7,20 @@ from custommail.shortcuts import send_mass_custom_mail
|
|||
|
||||
from django.contrib.sites.models import Site
|
||||
from django.db import models
|
||||
from django.db.models import Count
|
||||
from django.contrib.auth.models import User
|
||||
from django.conf import settings
|
||||
from django.utils import timezone, formats
|
||||
|
||||
|
||||
def get_generic_user():
|
||||
generic, _ = User.objects.get_or_create(
|
||||
username="bda_generic",
|
||||
defaults={"email": "bda@ens.fr", "first_name": "Bureau des arts"}
|
||||
)
|
||||
return generic
|
||||
|
||||
|
||||
class Tirage(models.Model):
|
||||
title = models.CharField("Titre", max_length=300)
|
||||
ouverture = models.DateTimeField("Date et heure d'ouverture du tirage")
|
||||
|
@ -96,32 +105,29 @@ class Spectacle(models.Model):
|
|||
Envoie un mail de rappel à toutes les personnes qui ont une place pour
|
||||
ce spectacle.
|
||||
"""
|
||||
# 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][1] = 2
|
||||
else:
|
||||
members[member.id] = [member, 1]
|
||||
# FIXME : faire quelque chose de ça, un utilisateur bda_generic ?
|
||||
# # Pour le BdA
|
||||
# members[0] = ['BdA', 1, 'bda@ens.fr']
|
||||
# members[-1] = ['BdA', 2, 'bda@ens.fr']
|
||||
# On récupère la liste des participants + le BdA
|
||||
members = list(
|
||||
User.objects
|
||||
.filter(participant__attributions=self)
|
||||
.annotate(nb_attr=Count("id")).order_by()
|
||||
)
|
||||
bda_generic = get_generic_user()
|
||||
bda_generic.nb_attr = 1
|
||||
members.append(bda_generic)
|
||||
# On écrit un mail personnalisé à chaque participant
|
||||
datatuple = [(
|
||||
'bda-rappel',
|
||||
{'member': member[0], 'nb_attr': member[1], 'show': self},
|
||||
{'member': member, "nb_attr": member.nb_attr, 'show': self},
|
||||
settings.MAIL_DATA['rappels']['FROM'],
|
||||
[member[0].email])
|
||||
for member in members.values()
|
||||
[member.email])
|
||||
for member in members
|
||||
]
|
||||
send_mass_custom_mail(datatuple)
|
||||
# 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()
|
||||
return members
|
||||
|
||||
@property
|
||||
def is_past(self):
|
||||
|
|
|
@ -3,41 +3,46 @@
|
|||
{% block realcontent %}
|
||||
<h2>Mails de rappels</h2>
|
||||
{% if sent %}
|
||||
<h3>Les mails de rappel pour le spectacle {{ show.title }} ont bien été envoyés aux personnes suivantes</h3>
|
||||
<ul>
|
||||
{% for member in members %}
|
||||
<li>{{ member.get_full_name }} ({{ member.email }})</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<h3>Les mails de rappel pour le spectacle {{ show.title }} ont bien été envoyés aux personnes suivantes</h3>
|
||||
<ul>
|
||||
{% for member in members %}
|
||||
<li>{{ member.get_full_name }} ({{ member.email }})</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<h3>Voulez vous envoyer les mails de rappel pour le spectacle
|
||||
{{ show.title }} ?</h3>
|
||||
{% if show.rappel_sent %}
|
||||
<p class="error">Attention, les mails ont déjà été envoyés le
|
||||
{{ show.rappel_sent }}</p>
|
||||
{% endif %}
|
||||
<h3>Voulez vous envoyer les mails de rappel pour le spectacle {{ show.title }} ?</h3>
|
||||
{% endif %}
|
||||
|
||||
{% if not sent %}
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="pull-right">
|
||||
<input class="btn btn-primary" type="submit" value="Envoyer" />
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
<div class="empty-form">
|
||||
{% if not sent %}
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="pull-right">
|
||||
<input class="btn btn-primary" type="submit" value="Envoyer" />
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<hr \>
|
||||
|
||||
<p>
|
||||
<em>Note :</em> le template de ce mail peut être modifié à
|
||||
<a href="{% url 'admin:custommail_custommail_change' custommail.pk %}">cette adresse</a>
|
||||
</p>
|
||||
|
||||
<hr \>
|
||||
|
||||
<br/>
|
||||
<hr/>
|
||||
<h3>Forme des mails</h3>
|
||||
|
||||
<h4>Une seule place</h4>
|
||||
{% for part in exemple_mail_1place %}
|
||||
<pre>{{ part }}</pre>
|
||||
{% endfor %}
|
||||
{% for part in exemple_mail_1place %}
|
||||
<pre>{{ part }}</pre>
|
||||
{% endfor %}
|
||||
|
||||
<h4>Deux places</h4>
|
||||
{% for part in exemple_mail_2places %}
|
||||
<pre>{{ part }}</pre>
|
||||
<pre>{{ part }}</pre>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -36,17 +36,26 @@
|
|||
</tbody>
|
||||
</table>
|
||||
<h3><a href="{% url "admin:bda_attribution_add" %}?spectacle={{spectacle.id}}"><span class="glyphicon glyphicon-plus-sign"></span> Ajouter une attribution</a></h3>
|
||||
<br>
|
||||
<button class="btn btn-default" type="button" onclick="toggle('export-mails')">Afficher/Cacher mails participants</button>
|
||||
<pre id="export-mails" style="display:none">
|
||||
{%for participant in participants %}{{participant.email}}, {%endfor%}
|
||||
</pre>
|
||||
<br>
|
||||
<button class="btn btn-default" type="button" onclick="toggle('export-salle')">Afficher/Cacher liste noms</button>
|
||||
<pre id="export-salle" style="display:none">
|
||||
<div>
|
||||
<div>
|
||||
<button class="btn btn-default" type="button" onclick="toggle('export-mails')">Afficher/Cacher mails participants</button>
|
||||
<pre id="export-mails" style="display:none">{% spaceless %}
|
||||
{% for participant in participants %}{{ participant.email }}, {% endfor %}
|
||||
{% endspaceless %}</pre>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button class="btn btn-default" type="button" onclick="toggle('export-salle')">Afficher/Cacher liste noms</button>
|
||||
<pre id="export-salle" style="display:none">{% spaceless %}
|
||||
{% for participant in participants %}{{participant.name}} : {{participant.nb_places}} places
|
||||
{% endfor %}
|
||||
</pre>
|
||||
{% endspaceless %}</pre>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a href="{% url 'bda-rappels' spectacle.id %}">Page d'envoi manuel des mails de rappel</a>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript"
|
||||
src="{% static "js/joequery-Stupid-Table-Plugin/stupidtable.js" %}"></script>
|
||||
<script>
|
28
bda/tests.py
28
bda/tests.py
|
@ -1,5 +1,6 @@
|
|||
import json
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.test import TestCase, Client
|
||||
from django.utils import timezone
|
||||
|
||||
|
@ -34,11 +35,36 @@ class TestBdAViews(TestCase):
|
|||
),
|
||||
])
|
||||
|
||||
self.bda_user = User.objects.create_user(
|
||||
username="bda_user", password="bda4ever"
|
||||
)
|
||||
self.bda_user.profile.is_cof = True
|
||||
self.bda_user.profile.is_buro = True
|
||||
self.bda_user.profile.save()
|
||||
|
||||
def bda_participants(self):
|
||||
"""The BdA participants views can be queried"""
|
||||
client = Client()
|
||||
show = self.tirage.spectacle_set.first()
|
||||
|
||||
client.login(self.bda_user.username, "bda4ever")
|
||||
tirage_resp = client.get("/bda/spectacles/{}".format(self.tirage.id))
|
||||
show_resp = client.get(
|
||||
"/bda/spectacles/{}/{}".format(self.tirage.id, show.id)
|
||||
)
|
||||
reminder_url = "/bda/mails-rappel/{}".format(show.id)
|
||||
reminder_get_resp = client.get(reminder_url)
|
||||
reminder_post_resp = client.post(reminder_url)
|
||||
self.assertEqual(200, tirage_resp.status_code)
|
||||
self.assertEqual(200, show_resp.status_code)
|
||||
self.assertEqual(200, reminder_get_resp.status_code)
|
||||
self.assertEqual(200, reminder_post_resp.status_code)
|
||||
|
||||
def test_catalogue(self):
|
||||
"""Test the catalogue JSON API"""
|
||||
client = Client()
|
||||
|
||||
# The `list` hooh
|
||||
# The `list` hook
|
||||
resp = client.get("/bda/catalogue/list")
|
||||
self.assertJSONEqual(
|
||||
resp.content.decode("utf-8"),
|
||||
|
|
|
@ -44,7 +44,10 @@ urlpatterns = [
|
|||
url(r'^revente-immediat/(?P<tirage_id>\d+)$',
|
||||
views.revente_shotgun,
|
||||
name="bda-shotgun"),
|
||||
url(r'^mails-rappel/(?P<spectacle_id>\d+)$', views.send_rappel),
|
||||
url(r'^mails-rappel/(?P<spectacle_id>\d+)$',
|
||||
views.send_rappel,
|
||||
name="bda-rappels"
|
||||
),
|
||||
url(r'^descriptions/(?P<tirage_id>\d+)$', views.descriptions_spectacles,
|
||||
name='bda-descriptions'),
|
||||
url(r'^catalogue/(?P<request_type>[a-z]+)$', views.catalogue,
|
||||
|
|
35
bda/views.py
35
bda/views.py
|
@ -1,15 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from collections import defaultdict
|
||||
from functools import partial
|
||||
import random
|
||||
import hashlib
|
||||
import time
|
||||
import json
|
||||
from datetime import timedelta
|
||||
from custommail.shortcuts import (
|
||||
send_mass_custom_mail, send_custom_mail, render_custom_mail
|
||||
)
|
||||
from custommail.shortcuts import send_mass_custom_mail, send_custom_mail
|
||||
from custommail.models import CustomMail
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib import messages
|
||||
|
@ -27,7 +25,7 @@ from django.views.generic.list import ListView
|
|||
from gestioncof.decorators import cof_required, buro_required
|
||||
from bda.models import (
|
||||
Spectacle, Participant, ChoixSpectacle, Attribution, Tirage,
|
||||
SpectacleRevente, Salle, Quote, CategorieSpectacle
|
||||
SpectacleRevente, Salle, CategorieSpectacle
|
||||
)
|
||||
from bda.algorithm import Algorithm
|
||||
from bda.forms import (
|
||||
|
@ -305,7 +303,8 @@ def do_tirage(tirage_elt, token):
|
|||
# On inscrit à BdA-Revente ceux qui n'ont pas eu les places voulues
|
||||
ChoixRevente = Participant.choicesrevente.through
|
||||
|
||||
# Suppression des reventes demandées/enregistrées (si le tirage est relancé)
|
||||
# Suppression des reventes demandées/enregistrées
|
||||
# (si le tirage est relancé)
|
||||
(
|
||||
ChoixRevente.objects
|
||||
.filter(spectacle__tirage=tirage_elt)
|
||||
|
@ -612,7 +611,7 @@ def spectacle(request, tirage_id, spectacle_id):
|
|||
|
||||
participants_info = sorted(participants.values(),
|
||||
key=lambda part: part['lastname'])
|
||||
return render(request, "bda-participants.html",
|
||||
return render(request, "bda/participants.html",
|
||||
{"spectacle": spectacle, "participants": participants_info})
|
||||
|
||||
|
||||
|
@ -651,20 +650,24 @@ def unpaid(request, tirage_id):
|
|||
def send_rappel(request, spectacle_id):
|
||||
show = get_object_or_404(Spectacle, id=spectacle_id)
|
||||
# Mails d'exemples
|
||||
exemple_mail_1place = render_custom_mail('bda-rappel', {
|
||||
custommail = CustomMail.objects.get(shortname="bda-rappel")
|
||||
exemple_mail_1place = custommail.render({
|
||||
'member': request.user,
|
||||
'show': show,
|
||||
'nb_attr': 1
|
||||
})
|
||||
exemple_mail_2places = render_custom_mail('bda-rappel', {
|
||||
exemple_mail_2places = custommail.render({
|
||||
'member': request.user,
|
||||
'show': show,
|
||||
'nb_attr': 2
|
||||
})
|
||||
# Contexte
|
||||
ctxt = {'show': show,
|
||||
'exemple_mail_1place': exemple_mail_1place,
|
||||
'exemple_mail_2places': exemple_mail_2places}
|
||||
ctxt = {
|
||||
'show': show,
|
||||
'exemple_mail_1place': exemple_mail_1place,
|
||||
'exemple_mail_2places': exemple_mail_2places,
|
||||
'custommail': custommail,
|
||||
}
|
||||
# Envoi confirmé
|
||||
if request.method == 'POST':
|
||||
members = show.send_rappel()
|
||||
|
@ -673,6 +676,14 @@ def send_rappel(request, spectacle_id):
|
|||
# Demande de confirmation
|
||||
else:
|
||||
ctxt['sent'] = False
|
||||
if show.rappel_sent:
|
||||
messages.warning(
|
||||
request,
|
||||
"Attention, un mail de rappel pour ce spectale a déjà été "
|
||||
"envoyé le {}".format(formats.localize(
|
||||
timezone.template_localtime(show.rappel_sent)
|
||||
))
|
||||
)
|
||||
return render(request, "bda/mails-rappel.html", ctxt)
|
||||
|
||||
|
||||
|
|
|
@ -40,8 +40,9 @@ a {
|
|||
background: transparent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
div.empty-form {
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #444;
|
||||
|
@ -341,10 +342,12 @@ fieldset legend {
|
|||
font-weight: 700;
|
||||
font-size: large;
|
||||
color:#DE826B;
|
||||
padding-bottom: .5em;
|
||||
}
|
||||
|
||||
#main-content h4 {
|
||||
color:#DE826B;
|
||||
padding-bottom: .5em;
|
||||
}
|
||||
|
||||
#main-content h2,
|
||||
|
|
Loading…
Reference in a new issue