Merge branch 'master' into Kerl/fix_32_do_tirage

This commit is contained in:
Martin Pépin 2016-07-10 14:42:09 +02:00
commit 3aa9667eb9
28 changed files with 1010 additions and 605 deletions

View file

@ -4,38 +4,49 @@ from django.core.mail import send_mail
from django.contrib import admin
from django.db.models import Sum, Count
from bda.models import Spectacle, Salle, Participant, ChoixSpectacle, Attribution, Tirage
from bda.models import Spectacle, Salle, Participant, ChoixSpectacle,\
Attribution, Tirage
from django import forms
from datetime import timedelta
import autocomplete_light
class ChoixSpectacleInline(admin.TabularInline):
model = ChoixSpectacle
sortable_field_name = "priority"
class AttributionInline(admin.TabularInline):
model = Attribution
class ParticipantAdmin(admin.ModelAdmin):
inlines = [AttributionInline]
def get_queryset(self, request):
return Participant.objects.annotate(nb_places = Count('attributions'),
total = Sum('attributions__price'))
return Participant.objects.annotate(nb_places=Count('attributions'),
total=Sum('attributions__price'))
def nb_places(self, obj):
return obj.nb_places
nb_places.admin_order_field = "nb_places"
nb_places.short_description = "Nombre de places"
def total(self, obj):
tot = obj.total
if tot: return u"%.02f" % tot
else: return u"0 €"
if tot:
return u"%.02f" % tot
else:
return u"0 €"
total.admin_order_field = "total"
total.short_description = "Total à payer"
list_display = ("user", "nb_places", "total", "paid", "paymenttype",
"tirage")
list_filter = ("paid", "tirage")
search_fields = ('user__username', 'user__first_name', 'user__last_name')
actions = ['send_attribs',]
actions = ['send_attribs', ]
actions_on_bottom = True
list_per_page = 400
readonly_fields = ("total",)
@ -49,8 +60,9 @@ class ParticipantAdmin(admin.ModelAdmin):
Tu t'es inscrit-e pour le tirage au sort du BdA. Malheureusement, tu n'as
obtenu aucune place.
Nous proposons cependant de nombreuses offres hors-tirage tout au long de
l'année, et nous t'invitons à nous contacter si l'une d'entre elles t'intéresse !
Nous proposons cependant de nombreuses offres hors-tirage tout au long de
l'année, et nous t'invitons à nous contacter si l'une d'entre elles
t'intéresse !
--
Le Bureau des Arts
@ -69,15 +81,16 @@ pour les spectacles suivants :
L'intégralité de ces places de spectacles est à régler dès maintenant et AVANT
le %s, au bureau du COF pendant les heures de permanences (du lundi au vendredi
entre 12h et 14h, et entre 18h et 20h). Des facilités de paiement sont bien
évidemment possibles : nous pouvons ne pas encaisser le chèque immédiatement, ou
bien découper votre paiement en deux fois. Pour ceux qui ne pourraient pas venir
payer au bureau, merci de nous contacter par mail.
évidemment possibles : nous pouvons ne pas encaisser le chèque immédiatement,
ou bien découper votre paiement en deux fois. Pour ceux qui ne pourraient pas
venir payer au bureau, merci de nous contacter par mail.
*Mode de retrait des places*
Au moment du paiement, certaines places vous seront remises directement, d'autres
seront à récupérer au cours de l'année, d'autres encore seront nominatives et à retirer
le soir même dans les theâtres correspondants. Pour chaque spectacle, vous recevrez un mail
quelques jours avant la représentation vous indiquant le mode de retrait.
Au moment du paiement, certaines places vous seront remises directement,
d'autres seront à récupérer au cours de l'année, d'autres encore seront
nominatives et à retirer le soir même dans les theâtres correspondants.
Pour chaque spectacle, vous recevrez un mail quelques jours avant la
représentation vous indiquant le mode de retrait.
Nous vous rappelons que l'obtention de places du BdA vous engage à
respecter les règles de fonctionnement :
@ -94,10 +107,11 @@ Le Bureau des Arts
for attrib in attribs:
attribs_text += u"- 1 place pour %s\n" % attrib
deadline = member.tirage.fermeture + timedelta(days=7)
mail = mail % (name, attribs_text, deadline.strftime('%d %b %Y'))
send_mail ("Résultats du tirage au sort", mail,
"bda@ens.fr", [member.user.email],
fail_silently = True)
mail = mail % (name, attribs_text,
deadline.strftime('%d %b %Y'))
send_mail("Résultats du tirage au sort", mail,
"bda@ens.fr", [member.user.email],
fail_silently=True)
count = len(queryset.all())
if count == 1:
message_bit = u"1 membre a"
@ -105,36 +119,48 @@ Le Bureau des Arts
else:
message_bit = u"%d membres ont" % count
plural = "s"
self.message_user(request, u"%s été informé%s avec succès." % (message_bit, plural))
self.message_user(request, u"%s été informé%s avec succès."
% (message_bit, plural))
send_attribs.short_description = u"Envoyer les résultats par mail"
class AttributionAdminForm(forms.ModelForm):
def clean(self):
cleaned_data=super(AttributionAdminForm, self).clean()
cleaned_data = super(AttributionAdminForm, self).clean()
participant = cleaned_data.get("participant")
spectacle = cleaned_data.get("spectacle")
if participant and spectacle:
if participant.tirage != spectacle.tirage:
raise forms.ValidationError(u"Erreur : le participant et le spectacle n'appartiennent pas au même tirage")
raise forms.ValidationError(
u"Erreur : le participant et le spectacle n'appartiennent"
u"pas au même tirage")
return cleaned_data
class AttributionAdmin(admin.ModelAdmin):
def paid(self, obj):
return obj.participant.paid
paid.short_description = 'A payé'
paid.boolean = True
list_display = ("id", "spectacle", "participant", "given", "paid")
search_fields = ('spectacle__title', 'participant__user__username', 'participant__user__first_name', 'participant__user__last_name')
search_fields = ('spectacle__title', 'participant__user__username',
'participant__user__first_name',
'participant__user__last_name')
form = AttributionAdminForm
import autocomplete_light
class ChoixSpectacleAdmin(admin.ModelAdmin):
form = autocomplete_light.modelform_factory(ChoixSpectacle, exclude=[])
def tirage(self, obj):
return obj.participant.tirage
list_display = ("participant", "tirage", "spectacle", "priority", "double_choice")
list_display = ("participant", "tirage", "spectacle", "priority",
"double_choice")
list_filter = ("double_choice", "participant__tirage")
search_fields = ('participant__user__username', 'participant__user__first_name', 'participant__user__last_name')
search_fields = ('participant__user__username',
'participant__user__first_name',
'participant__user__last_name')
class SpectacleAdmin(admin.ModelAdmin):
model = Spectacle
@ -142,6 +168,7 @@ class SpectacleAdmin(admin.ModelAdmin):
list_filter = ("location", "tirage",)
search_fields = ("title", "location__name")
class TirageAdmin(admin.ModelAdmin):
model = Tirage
list_display = ("title", "ouverture", "fermeture", "active",

View file

@ -6,6 +6,7 @@ from django.db.models import Max
import random
class Algorithm(object):
shows = None
@ -19,7 +20,8 @@ class Algorithm(object):
show.requests
- on crée des tables de demandes pour chaque personne, afin de
pouvoir modifier les rankings"""
self.max_group = 2 * choices.aggregate(Max('priority'))['priority__max']
self.max_group = \
2 * choices.aggregate(Max('priority'))['priority__max']
self.shows = []
showdict = {}
for show in shows:
@ -39,8 +41,10 @@ class Algorithm(object):
member_shows[member] = {}
for choice in choices:
member = choice.participant
if choice.spectacle in member_shows[member]: continue
else: member_shows[member][choice.spectacle] = True
if choice.spectacle in member_shows[member]:
continue
else:
member_shows[member][choice.spectacle] = True
showdict[choice.spectacle].requests.append(member)
showdict[choice.spectacle].nrequests += 2 if choice.double else 1
self.ranks[member][choice.spectacle] = next_rank[member]
@ -49,7 +53,7 @@ class Algorithm(object):
for member in members:
self.origranks[member] = dict(self.ranks[member])
def IncrementRanks(self, member, currank, increment = 1):
def IncrementRanks(self, member, currank, increment=1):
for show in self.ranks[member]:
if self.ranks[member][show] > currank:
self.ranks[member][show] -= increment
@ -63,13 +67,14 @@ class Algorithm(object):
def __call__(self, seed):
random.seed(seed)
results = []
shows = sorted(self.shows, key = lambda x: x.nrequests / x.slots, reverse = True)
shows = sorted(self.shows, key=lambda x: x.nrequests / x.slots,
reverse=True)
for show in shows:
# On regroupe tous les gens ayant le même rang
groups = dict([(i, []) for i in range(1, self.max_group + 1)])
for member in show.requests:
if self.ranks[member][show] == 0:
raise RuntimeError, (member, show.title)
raise RuntimeError(member, show.title)
groups[self.ranks[member][show]].append(member)
# On passe à l'attribution
winners = []
@ -78,23 +83,23 @@ class Algorithm(object):
group = list(groups[i])
random.shuffle(group)
for member in group:
if self.choices[member][show].double: # double
if self.choices[member][show].double: # double
if len(winners) + 1 < show.slots:
self.appendResult(winners, member, show)
self.appendResult(winners, member, show)
elif not self.choices[member][show].autoquit and len(winners) < show.slots:
elif not self.choices[member][show].autoquit \
and len(winners) < show.slots:
self.appendResult(winners, member, show)
self.appendResult(losers, member, show)
else:
self.appendResult(losers, member, show)
self.appendResult(losers, member, show)
self.IncrementRanks(member, i, 2)
else: # simple
else: # simple
if len(winners) < show.slots:
self.appendResult(winners, member, show)
else:
self.appendResult(losers, member, show)
self.IncrementRanks(member, i)
results.append((show,winners,losers))
results.append((show, winners, losers))
return results

View file

@ -2,8 +2,11 @@ import autocomplete_light
from bda.models import Participant, Spectacle
autocomplete_light.register(Participant, search_fields=('user__username','user__first_name','user__last_name'),
autocomplete_light.register(
Participant, search_fields=('user__username', 'user__first_name',
'user__last_name'),
autocomplete_js_attributes={'placeholder': 'participant...'})
autocomplete_light.register(Spectacle, search_fields=('title',),
autocomplete_light.register(
Spectacle, search_fields=('title', ),
autocomplete_js_attributes={'placeholder': 'spectacle...'})

View file

@ -4,12 +4,14 @@ from django import forms
from django.forms.models import BaseInlineFormSet
from bda.models import Spectacle
class BaseBdaFormSet(BaseInlineFormSet):
def clean(self):
"""Checks that no two articles have the same title."""
super(BaseBdaFormSet, self).clean()
if any(self.errors):
# Don't bother validating the formset unless each form is valid on its own
# Don't bother validating the formset unless each form is valid on
# its own
return
spectacles = []
for i in range(0, self.total_form_count()):
@ -19,23 +21,27 @@ class BaseBdaFormSet(BaseInlineFormSet):
spectacle = form.cleaned_data['spectacle']
delete = form.cleaned_data['DELETE']
if not delete and spectacle in spectacles:
raise forms.ValidationError("Vous ne pouvez pas vous " + \
"inscrire deux fois pour le même spectacle.")
raise forms.ValidationError(
"Vous ne pouvez pas vous inscrire deux fois pour le "
"même spectacle.")
spectacles.append(spectacle)
class TokenForm(forms.Form):
token = forms.CharField(widget=forms.widgets.Textarea())
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)
class ResellForm(forms.Form):
count = forms.ChoiceField(choices = (("1","1"),("2","2"),))
count = forms.ChoiceField(choices=(("1", "1"), ("2", "2"),))
spectacle = SpectacleModelChoiceField(queryset=Spectacle.objects.none())
def __init__(self, participant, *args, **kwargs):
super(ResellForm, self).__init__(*args, **kwargs)
self.fields['spectacle'].queryset = participant.attributions.all().distinct()
self.fields['spectacle'].queryset = participant.attributions.all() \
.distinct()

View file

@ -6,6 +6,7 @@ from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
class Tirage(models.Model):
title = models.CharField("Titre", max_length=300)
ouverture = models.DateTimeField("Date et heure d'ouverture du tirage")
@ -20,14 +21,16 @@ class Tirage(models.Model):
def __unicode__(self):
return u"%s - %s" % (self.title, self.date_no_seconds())
class Salle(models.Model):
name = models.CharField("Nom", max_length = 300)
name = models.CharField("Nom", max_length=300)
address = models.TextField("Adresse")
def __unicode__ (self):
def __unicode__(self):
return self.name
class Spectacle(models.Model):
title = models.CharField("Titre", max_length=300)
date = models.DateTimeField("Date & heure")
@ -41,9 +44,9 @@ class Spectacle(models.Model):
class Meta:
verbose_name = "Spectacle"
ordering = ("priority", "date","title",)
ordering = ("priority", "date", "title",)
def __repr__ (self):
def __repr__(self):
return u"[%s]" % self.__unicode__()
def timestamp(self):
@ -52,31 +55,33 @@ class Spectacle(models.Model):
def date_no_seconds(self):
return self.date.strftime('%d %b %Y %H:%M')
def __unicode__ (self):
def __unicode__(self):
return u"%s - %s, %s, %.02f" % (self.title, self.date_no_seconds(),
self.location, self.price)
self.location, self.price)
PAYMENT_TYPES = (
("cash",u"Cash"),
("cb","CB"),
("cheque",u"Chèque"),
("autre",u"Autre"),
("cash", u"Cash"),
("cb", "CB"),
("cheque", u"Chèque"),
("autre", u"Autre"),
)
class Participant(models.Model):
user = models.ForeignKey(User)
choices = models.ManyToManyField(Spectacle,
through="ChoixSpectacle",
related_name="chosen_by")
through="ChoixSpectacle",
related_name="chosen_by")
attributions = models.ManyToManyField(Spectacle,
through="Attribution",
related_name="attributed_to")
paid = models.BooleanField (u"A payé", default=False)
through="Attribution",
related_name="attributed_to")
paid = models.BooleanField(u"A payé", default=False)
paymenttype = models.CharField(u"Moyen de paiement",
max_length=6, choices=PAYMENT_TYPES, blank=True)
max_length=6, choices=PAYMENT_TYPES,
blank=True)
tirage = models.ForeignKey(Tirage)
def __unicode__ (self):
def __unicode__(self):
return u"%s" % (self.user)
DOUBLE_CHOICES = (
@ -85,12 +90,14 @@ DOUBLE_CHOICES = (
("double", "2 places sinon rien"),
)
class ChoixSpectacle(models.Model):
participant = models.ForeignKey(Participant)
spectacle = models.ForeignKey(Spectacle, related_name="participants")
priority = models.PositiveIntegerField("Priorité")
double_choice = models.CharField("Nombre de places",
default="1", choices=DOUBLE_CHOICES, max_length=10)
default="1", choices=DOUBLE_CHOICES,
max_length=10)
def get_double(self):
return self.double_choice != "1"
@ -106,11 +113,11 @@ class ChoixSpectacle(models.Model):
verbose_name = "voeu"
verbose_name_plural = "voeux"
class Attribution(models.Model):
participant = models.ForeignKey(Participant)
spectacle = models.ForeignKey(Spectacle, related_name="attribues")
given = models.BooleanField(u"Donnée", default=False)
def __unicode__ (self):
def __unicode__(self):
return u"%s -- %s" % (self.participant, self.spectacle)

View file

@ -3,7 +3,8 @@
from django.conf.urls import url, patterns
from bda.views import SpectacleListView
urlpatterns = patterns('',
urlpatterns = patterns(
'',
url(r'inscription/(?P<tirage_id>\d+)$',
'bda.views.inscription',
name='bda-tirage-inscription'),
@ -21,14 +22,14 @@ urlpatterns = patterns('',
name='bda-etat-places'),
url(r'tirage/(?P<tirage_id>\d+)$', 'bda.views.tirage'),
url(r'spectacles/(?P<tirage_id>\d+)$',
SpectacleListView.as_view() ,
name ="bda-liste-spectacles"),
SpectacleListView.as_view(),
name="bda-liste-spectacles"),
url(r'spectacles/(?P<tirage_id>\d+)/(?P<spectacle_id>\d+)$',
"bda.views.spectacle",
name="bda-spectacle"),
url(r'spectacles-ics/(?P<tirage_id>\d+)$',
'bda.views.liste_spectacles_ics',
name ="bda-liste-spectacles-ics"),
name="bda-liste-spectacles-ics"),
url(r'spectacles/unpaid/(?P<tirage_id>\d+)$',
"bda.views.unpaid",
name="bda-unpaid"),

View file

@ -10,7 +10,7 @@ from django.core import serializers
from django.forms.models import inlineformset_factory
import hashlib
from django.core.mail import send_mail
from django.core.mail import send_mail
from django.utils import timezone
from django.views.generic.list import ListView
@ -18,11 +18,13 @@ from datetime import timedelta
import time
from gestioncof.decorators import cof_required, buro_required
from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution, Tirage
from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\
Tirage
from bda.algorithm import Algorithm
from bda.forms import BaseBdaFormSet, TokenForm, ResellForm
@cof_required
def etat_places(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id)
@ -30,13 +32,13 @@ def etat_places(request, tirage_id):
.filter(spectacle__tirage=tirage) \
.filter(double_choice="1") \
.all() \
.values('spectacle','spectacle__title') \
.values('spectacle', 'spectacle__title') \
.annotate(total=models.Count('spectacle'))
spectacles2 = ChoixSpectacle.objects \
.filter(spectacle__tirage=tirage) \
.exclude(double_choice="1") \
.all() \
.values('spectacle','spectacle__title') \
.values('spectacle', 'spectacle__title') \
.annotate(total=models.Count('spectacle'))
spectacles = tirage.spectacle_set.all()
spectacles_dict = {}
@ -50,15 +52,16 @@ def etat_places(request, tirage_id):
spectacles_dict[spectacle["spectacle"]].ratio = \
spectacles_dict[spectacle["spectacle"]].total / \
spectacles_dict[spectacle["spectacle"]].slots
total += spectacle["total"]
total += spectacle["total"]
for spectacle in spectacles2:
spectacles_dict[spectacle["spectacle"]].total += 2*spectacle["total"]
spectacles_dict[spectacle["spectacle"]].ratio = \
spectacles_dict[spectacle["spectacle"]].total / \
spectacles_dict[spectacle["spectacle"]].slots
total += spectacle["total"]
total += spectacle["total"]
return render(request, "etat-places.html",
{"spectacles": spectacles, "total": total, 'tirage': tirage})
{"spectacles": spectacles, "total": total, 'tirage': tirage})
def _hash_queryset(queryset):
data = serializers.serialize("json", queryset)
@ -66,13 +69,14 @@ def _hash_queryset(queryset):
hasher.update(data)
return hasher.hexdigest()
@cof_required
def places(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id)
participant, created = Participant.objects.get_or_create(
user=request.user, tirage=tirage)
user=request.user, tirage=tirage)
places = participant.attribution_set.order_by(
"spectacle__date", "spectacle").all()
"spectacle__date", "spectacle").all()
total = sum([place.spectacle.price for place in places])
filtered_places = []
places_dict = {}
@ -99,13 +103,14 @@ def places(request, tirage_id):
"total": total,
"warning": warning})
@cof_required
@cof_required
def places_ics(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id)
participant, created = Participant.objects.get_or_create(
user=request.user, tirage=tirage)
user=request.user, tirage=tirage)
places = participant.attribution_set.order_by(
"spectacle__date", "spectacle").all()
"spectacle__date", "spectacle").all()
filtered_places = []
places_dict = {}
spectacles = []
@ -114,7 +119,8 @@ def places_ics(request, tirage_id):
places_dict[place.spectacle].double = True
else:
place.double = False
place.spectacle.dtend = place.spectacle.date + timedelta(seconds=7200)
place.spectacle.dtend = place.spectacle.date \
+ timedelta(seconds=7200)
places_dict[place.spectacle] = place
spectacles.append(place.spectacle)
filtered_places.append(place)
@ -122,35 +128,38 @@ def places_ics(request, tirage_id):
{"participant": participant,
"places": filtered_places}, content_type="text/calendar")
@cof_required
def inscription(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id)
if timezone.now() < tirage.ouverture:
error_desc = "Ouverture le %s" % (
tirage.ouverture.strftime('%d %b %Y à %H:%M'))
tirage.ouverture.strftime('%d %b %Y à %H:%M'))
return render(request, 'resume_inscription.html',
{ "error_title": "Le tirage n'est pas encore ouvert !",
"error_description": error_desc })
{"error_title": "Le tirage n'est pas encore ouvert !",
"error_description": error_desc})
if timezone.now() > tirage.fermeture:
participant, created = Participant.objects.get_or_create(
user=request.user, tirage=tirage)
user=request.user, tirage=tirage)
choices = participant.choixspectacle_set.order_by("priority").all()
return render(request, "resume_inscription.html",
{ "error_title": "C'est fini !",
"error_description": u"Tirage au sort dans la journée !",
"choices": choices})
{"error_title": "C'est fini !",
"error_description":
u"Tirage au sort dans la journée !",
"choices": choices})
def formfield_callback(f, **kwargs):
if f.name == "spectacle":
kwargs['queryset'] = tirage.spectacle_set
return f.formfield(**kwargs)
BdaFormSet = inlineformset_factory(
Participant,
ChoixSpectacle,
fields=("spectacle","double_choice","priority"),
formset=BaseBdaFormSet,
formfield_callback=formfield_callback)
Participant,
ChoixSpectacle,
fields=("spectacle", "double_choice", "priority"),
formset=BaseBdaFormSet,
formfield_callback=formfield_callback)
participant, created = Participant.objects.get_or_create(
user=request.user, tirage=tirage)
user=request.user, tirage=tirage)
success = False
stateerror = False
if request.method == "POST":
@ -170,14 +179,16 @@ def inscription(request, tirage_id):
total_price = 0
for choice in participant.choixspectacle_set.all():
total_price += choice.spectacle.price
if choice.double: total_price += choice.spectacle.price
if choice.double:
total_price += choice.spectacle.price
return render(request, "inscription-bda.html",
{ "formset": formset,
"success": success,
"total_price": total_price,
"dbstate": dbstate,
'tirage': tirage,
"stateerror": stateerror})
{"formset": formset,
"success": success,
"total_price": total_price,
"dbstate": dbstate,
'tirage': tirage,
"stateerror": stateerror})
def do_tirage(request, tirage_id):
tirage_elt = get_object_or_404(Tirage, id=tirage_id)
@ -188,8 +199,8 @@ def do_tirage(request, tirage_id):
data = {}
shows = tirage_elt.spectacle_set.select_related().all()
members = tirage_elt.participant_set.all()
choices = ChoixSpectacle.objects.filter(spectacle__tirage=tirage_elt).order_by(
'participant', 'priority').select_related().all()
choices = ChoixSpectacle.objects.filter(spectacle__tirage=tirage_elt) \
.order_by('participant', 'priority').select_related().all()
algo = Algorithm(shows, members, choices)
results = algo(form.cleaned_data["token"])
total_slots = 0
@ -219,8 +230,9 @@ def do_tirage(request, tirage_id):
data["duration"] = time.time() - start
if request.user.is_authenticated():
members2 = {}
members_uniq = {} # Participant objects are not shared accross spectacle results,
# So assign a single object for each Participant id
# Participant objects are not shared accross spectacle results,
# so assign a single object for each Participant id
members_uniq = {}
for (show, members, _) in results:
for (member, _, _, _) in members:
if member.id not in members_uniq:
@ -235,7 +247,7 @@ def do_tirage(request, tirage_id):
# À partir d'ici, le tirage devient effectif
Attribution.objects.filter(spectacle__tirage=tirage_elt).delete()
tirage_elt.tokens += "%s\n\"\"\"%s\"\"\"\n" % (
timezone.now().strftime("%y-%m-%d %H:%M:%S"),
timezone.now().strftime("%y-%m-%d %H:%M:%S"),
form.cleaned_data['token'])
tirage_elt.enable_do_tirage = False
tirage_elt.save()
@ -247,6 +259,7 @@ def do_tirage(request, tirage_id):
else:
return render(request, "bda-attrib.html", data)
@buro_required
def tirage(request, tirage_id):
tirage_elt = get_object_or_404(Tirage, id=tirage_id)
@ -260,6 +273,7 @@ def tirage(request, tirage_id):
form = TokenForm()
return render(request, "bda-token.html", {"form": form})
def do_resell(request, form):
spectacle = form.cleaned_data["spectacle"]
count = form.cleaned_data["count"]
@ -270,18 +284,20 @@ Je souhaite revendre %s pour %s le %s (%s) à %.02f€.
Contactez moi par email si vous êtes intéressé·e·s !
%s (%s)""" % (places, spectacle.title, spectacle.date_no_seconds(),
spectacle.location, spectacle.price, request.user.get_full_name(),
request.user.email)
spectacle.location, spectacle.price,
request.user.get_full_name(), request.user.email)
send_mail("%s" % spectacle, mail,
request.user.email, ["bda-revente@lists.ens.fr"],
fail_silently = False)
return render(request, "bda-success.html", {"show": spectacle, "places": places})
fail_silently=False)
return render(request, "bda-success.html",
{"show": spectacle, "places": places})
@login_required
def revente(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id)
participant, created = Participant.objects.get_or_create(
user=request.user, tirage=tirage)
user=request.user, tirage=tirage)
if not participant.paid:
return render(request, "bda-notpaid.html", {})
if request.POST:
@ -290,7 +306,9 @@ def revente(request, tirage_id):
return do_resell(request, form)
else:
form = ResellForm(participant)
return render(request, "bda-revente.html", {"form": form, 'tirage': tirage})
return render(request, "bda-revente.html",
{"form": form, 'tirage': tirage})
@buro_required
def spectacle(request, tirage_id, spectacle_id):
@ -300,52 +318,56 @@ def spectacle(request, tirage_id, spectacle_id):
participants = {}
for attrib in attributions:
participant = attrib.participant
participant_info = {'lastname': participant.user.last_name,
'name': participant.user.get_full_name,
'username': participant.user.username,
'email': participant.user.email,
'given': int(attrib.given),
'paid': participant.paid,
participant_info = {'lastname': participant.user.last_name,
'name': participant.user.get_full_name,
'username': participant.user.username,
'email': participant.user.email,
'given': int(attrib.given),
'paid': participant.paid,
'nb_places': 1}
if participant.id in participants:
participants[participant.id]['nb_places'] += 1
participants[participant.id]['nb_places'] += 1
participants[participant.id]['given'] += attrib.given
else:
participants[participant.id] = participant_info
participants_info = sorted(participants.values(),
key=lambda part: part['lastname'])
return render(request, "bda-participants.html",
{"spectacle": spectacle, "participants": participants_info})
participants_info = sorted(participants.values(),
key=lambda part: part['lastname'])
return render(request, "bda-participants.html",
{"spectacle": spectacle, "participants": participants_info})
class SpectacleListView(ListView):
model = Spectacle
template_name = 'spectacle_list.html'
def get_queryset(self):
self.tirage = get_object_or_404(Tirage, id=self.kwargs['tirage_id'])
categories = self.tirage.spectacle_set.all()
return categories
def get_context_data(self, **kwargs):
context = super(SpectacleListView, self).get_context_data(**kwargs)
context['tirage_id'] = self.tirage.id
context['tirage_name'] = self.tirage.title
return context
@buro_required
def unpaid(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id)
unpaid = tirage.participant_set \
.annotate(nb_attributions=Count('attribution')) \
.filter(paid=False, nb_attributions__gt=0).all()
.annotate(nb_attributions=Count('attribution')) \
.filter(paid=False, nb_attributions__gt=0).all()
return render(request, "bda-unpaid.html", {"unpaid": unpaid})
@buro_required
@buro_required
def liste_spectacles_ics(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id)
spectacles = tirage.spectacle_set.order_by("date").all()
for spectacle in spectacles:
spectacle.dtend = spectacle.date + timedelta(seconds=7200)
return render(request, "liste_spectacles.ics",
{"spectacles": spectacles, "tirage": tirage},
content_type="text/calendar")
{"spectacles": spectacles, "tirage": tirage},
content_type="text/calendar")