diff --git a/bda/admin.py b/bda/admin.py
index bcbc609c..8af71d00 100644
--- a/bda/admin.py
+++ b/bda/admin.py
@@ -5,7 +5,9 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib import admin
from django.db.models import Sum, Count
-from bda.models import Spectacle, Salle, Participant, ChoixSpectacle, Attribution
+from bda.models import Spectacle, Salle, Participant, ChoixSpectacle, Attribution, Tirage
+
+from datetime import timedelta
class ChoixSpectacleInline(admin.TabularInline):
model = ChoixSpectacle
@@ -37,62 +39,38 @@ class ParticipantAdmin(admin.ModelAdmin):
actions_on_bottom = True
list_per_page = 400
- def send_choices(self, request, queryset):
- for member in queryset.all():
- choices = member.choixspectacle_set.order_by('priority').all()
- if len(choices) == 0:
- continue
- mail = u"""Cher(e) %s,
-Voici tes choix de spectacles tels que notre système les a enregistrés :\n\n""" % member.user.get_full_name()
- next_rank = 1
- member_shows = {}
- for choice in choices:
- if choice.spectacle in member_shows: continue
- else: member_shows[choice.spectacle] = True
- extra = ""
- if choice.double:
- extra += u" ; deux places"
- if choice.autoquit:
- extra += u" ; désistement automatique"
- mail += u"- Choix %d : %s%s\n" % (next_rank, choice.spectacle, extra)
- next_rank += 1
- mail += u"""\nSi cette liste est incorrecte, merci de nous contacter au plus vite (avant samedi 6 octobre 18h).
-
-Artistiquement,
-Le BdA"""
- send_mail ("Choix de spectacles (BdA du COF)", mail,
- "bda@ens.fr", [member.user.email],
- fail_silently = True)
- count = len(queryset.all())
- if count == 1:
- message_bit = u"1 membre a"
- plural = ""
- 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))
- send_choices.short_description = u"Envoyer les choix par mail"
-
def send_attribs(self, request, queryset):
for member in queryset.all():
attribs = member.attributions.all()
if len(attribs) == 0:
- continue
- mail = u"""Cher(e) %s,
+ mail = u"""Cher-e %s,
-Tu t'es inscrit(e) pour le tirage au sort du BdA. Tu as été sélectionné(e)
+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 !
+--
+Le Bureau des Arts
+
+"""
+ name = member.user.get_full_name()
+ mail = mail % name
+ else:
+ mail = u"""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 :
%s
*Paiement*
-L'intégralité de ces places de spectacles est à régler à partir du lundi
-6 octobre et AVANT le vendredi 10 octobre, 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.
+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.
*Mode de retrait des places*
Au moment du paiement, certaines places vous seront remises directement, d'autres
@@ -109,16 +87,16 @@ prochainement disponible, directement sur votre compte GestioCOF.
En vous souhaitant de très beaux spectacles tout au long de l'année,
--
Le Bureau des Arts
-(Jean, Antoine, Élodie, Marion et Louise)
"""
- attribs_text = ""
- name = member.user.get_full_name()
- for attrib in attribs:
- attribs_text += u"- 1 place pour %s\n" % attrib
- mail = mail % (name, attribs_text)
- send_mail ("Résultats du tirage au sort", mail,
- "bda@ens.fr", [member.user.email],
- fail_silently = True)
+ attribs_text = ""
+ name = member.user.get_full_name()
+ 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)
count = len(queryset.all())
if count == 1:
message_bit = u"1 membre a"
@@ -155,3 +133,4 @@ admin.site.register(Salle)
admin.site.register(Participant, ParticipantAdmin)
admin.site.register(Attribution, AttributionAdmin)
admin.site.register(ChoixSpectacle, ChoixSpectacleAdmin)
+admin.site.register(Tirage)
diff --git a/bda/algorithm.py b/bda/algorithm.py
index 623f9756..bce41282 100644
--- a/bda/algorithm.py
+++ b/bda/algorithm.py
@@ -59,12 +59,6 @@ class Algorithm(object):
self.origranks[member][show],
self.choices[member][show].double))
- """
- Pour les 2 Walkyries: c'est Sandefer
-
- Pour les 4 places pour l'Oratorio c'est Maxence Arutkin
- """
-
def __call__(self, seed):
random.seed(seed)
results = []
@@ -102,3 +96,4 @@ class Algorithm(object):
self.IncrementRanks(member, i)
results.append((show,winners,losers))
return results
+
diff --git a/bda/forms.py b/bda/forms.py
index 8a652296..d61623db 100644
--- a/bda/forms.py
+++ b/bda/forms.py
@@ -1,7 +1,7 @@
# coding: utf-8
from django import forms
-from django.forms.models import inlineformset_factory, BaseInlineFormSet
+from django.forms.models import BaseInlineFormSet
from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution
class BaseBdaFormSet(BaseInlineFormSet):
@@ -19,19 +19,21 @@ 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())
+ 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)
+ 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"),))
- spectacle = SpectacleModelChoiceField(queryset = Spectacle.objects.none())
+ spectacle = SpectacleModelChoiceField(queryset=Spectacle.objects.none())
def __init__(self, participant, *args, **kwargs):
super(ResellForm, self).__init__(*args, **kwargs)
diff --git a/bda/migrations/0002_add_tirage.py b/bda/migrations/0002_add_tirage.py
new file mode 100644
index 00000000..1956a4a4
--- /dev/null
+++ b/bda/migrations/0002_add_tirage.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+from django.conf import settings
+from django.utils import timezone
+
+def forwards_func(apps, schema_editor):
+ Tirage = apps.get_model("bda", "Tirage")
+ db_alias = schema_editor.connection.alias
+ Tirage.objects.using(db_alias).bulk_create([
+ Tirage(
+ id=1,
+ title="Tirage de test (migration)",
+ active=False,
+ ouverture=timezone.now(),
+ fermeture=timezone.now()),
+ ])
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('bda', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Tirage',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=300, verbose_name=b'Titre')),
+ ('ouverture', models.DateTimeField(verbose_name=b"Date et heure d'ouverture du tirage")),
+ ('fermeture', models.DateTimeField(verbose_name=b'Date et heure de fermerture du tirage')),
+ ('token', models.TextField(verbose_name=b'Graine du tirage', blank=True)),
+ ('active', models.BooleanField(default=True, verbose_name=b'Tirage actif')),
+ ],
+ ),
+ migrations.RunPython(forwards_func, migrations.RunPython.noop),
+ migrations.AlterField(
+ model_name='participant',
+ name='user',
+ field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AddField(
+ model_name='participant',
+ name='tirage',
+ field=models.ForeignKey(default=1, to='bda.Tirage'),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name='spectacle',
+ name='tirage',
+ field=models.ForeignKey(default=1, to='bda.Tirage'),
+ preserve_default=False,
+ ),
+ ]
diff --git a/bda/models.py b/bda/models.py
index 11c9dd3b..cab8ce41 100644
--- a/bda/models.py
+++ b/bda/models.py
@@ -7,22 +7,36 @@ from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from django.db.models.signals import post_save
-class Salle (models.Model):
- name = models.CharField ("Nom", max_length = 300)
- address = models.TextField ("Adresse")
+class Tirage(models.Model):
+ title = models.CharField("Titre", max_length=300)
+ ouverture = models.DateTimeField("Date et heure d'ouverture du tirage")
+ fermeture = models.DateTimeField("Date et heure de fermerture du tirage")
+ token = models.TextField("Graine du tirage", blank=True)
+ active = models.BooleanField("Tirage actif", default=False)
+
+ 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())
+
+class Salle(models.Model):
+ name = models.CharField("Nom", max_length = 300)
+ address = models.TextField("Adresse")
def __unicode__ (self):
return self.name
-class Spectacle (models.Model):
- title = models.CharField ("Titre", max_length = 300)
- date = models.DateTimeField ("Date & heure")
+class Spectacle(models.Model):
+ title = models.CharField("Titre", max_length=300)
+ date = models.DateTimeField("Date & heure")
location = models.ForeignKey(Salle)
- description = models.TextField ("Description", blank = True)
- slots_description = models.TextField ("Description des places", blank = True)
- price = models.FloatField("Prix d'une place", blank = True)
- slots = models.IntegerField ("Places")
- priority = models.IntegerField ("Priorité", default = 1000)
+ description = models.TextField("Description", blank=True)
+ slots_description = models.TextField("Description des places", blank=True)
+ price = models.FloatField("Prix d'une place")
+ slots = models.IntegerField("Places")
+ priority = models.IntegerField("Priorité", default=1000)
+ tirage = models.ForeignKey(Tirage)
class Meta:
verbose_name = "Spectacle"
@@ -38,7 +52,8 @@ class Spectacle (models.Model):
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)
+ return u"%s - %s, %s, %.02f€" % (self.title, self.date_no_seconds(),
+ self.location, self.price)
PAYMENT_TYPES = (
("cash",u"Cash"),
@@ -47,12 +62,18 @@ PAYMENT_TYPES = (
("autre",u"Autre"),
)
-class Participant (models.Model):
- user = models.OneToOneField(User)
- choices = models.ManyToManyField(Spectacle, through = "ChoixSpectacle", related_name = "chosen_by")
- 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", max_length = 6, choices = PAYMENT_TYPES, blank = True)
+class Participant(models.Model):
+ user = models.ForeignKey(User)
+ choices = models.ManyToManyField(Spectacle,
+ through="ChoixSpectacle",
+ related_name="chosen_by")
+ 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",
+ max_length=6, choices=PAYMENT_TYPES, blank=True)
+ tirage = models.ForeignKey(Tirage)
def __unicode__ (self):
return u"%s" % (self.user)
@@ -63,11 +84,12 @@ DOUBLE_CHOICES = (
("double", "2 places sinon rien"),
)
-class ChoixSpectacle (models.Model):
+class ChoixSpectacle(models.Model):
participant = models.ForeignKey(Participant)
- spectacle = models.ForeignKey(Spectacle, related_name = "participants")
+ 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)
+ double_choice = models.CharField("Nombre de places",
+ default="1", choices=DOUBLE_CHOICES, max_length=10)
def get_double(self):
return self.double_choice != "1"
@@ -83,10 +105,11 @@ class ChoixSpectacle (models.Model):
verbose_name = "voeu"
verbose_name_plural = "voeux"
-class Attribution (models.Model):
+class Attribution(models.Model):
participant = models.ForeignKey(Participant)
- spectacle = models.ForeignKey(Spectacle, related_name = "attribues")
- given = models.BooleanField(u"Donnée", default = False)
+ spectacle = models.ForeignKey(Spectacle, related_name="attribues")
+ given = models.BooleanField(u"Donnée", default=False)
def __unicode__ (self):
return u"%s -- %s" % (self.participant, self.spectacle)
+
diff --git a/bda/templates/bda-attrib-extra.html b/bda/templates/bda-attrib-extra.html
index c2c266d2..8ffccf34 100644
--- a/bda/templates/bda-attrib-extra.html
+++ b/bda/templates/bda-attrib-extra.html
@@ -3,7 +3,8 @@
{% block extracontent %}
Attribution (détails)
-Token : {{ token }}
+Token :
+{{ token }}
Placés : {{ total_slots }} ; Déçus : {{ total_losers }}
diff --git a/bda/templates/bda-attrib.html b/bda/templates/bda-attrib.html
index 22f5786a..f0bfd955 100644
--- a/bda/templates/bda-attrib.html
+++ b/bda/templates/bda-attrib.html
@@ -8,7 +8,8 @@
{% block realcontent %}
Attribution
-Token : {{ token }}
+Token :
+{{ token }}
Placés : {{ total_slots }} ; Déçus : {{ total_losers }}
{% if user.profile.is_buro %}Déficit total: {{ total_deficit }} €, Opéra: {{ opera_deficit }} €, Attribué: {{ total_sold }} € {% endif %}
Temps de calcul : {{ duration|floatformat }}s
diff --git a/bda/templates/inscription-bda.html b/bda/templates/inscription-bda.html
index 8ee08dc9..5f529eef 100644
--- a/bda/templates/inscription-bda.html
+++ b/bda/templates/inscription-bda.html
@@ -98,7 +98,7 @@ var django = {
{% if stateerror %}
Impossible d'enregistrer vos modifications: vous avez apporté d'autres modifications entre temps
{% endif %}
-
-{% endblock %}
diff --git a/bda/templates/inscription-bda2.html b/bda/templates/inscription-bda2.html
deleted file mode 100644
index 91b08b93..00000000
--- a/bda/templates/inscription-bda2.html
+++ /dev/null
@@ -1,120 +0,0 @@
-{% extends "base_title.html" %}
-
-{% block extra_head %}
-
-
-
-
-
-{% endblock %}
-
-{% block realcontent %}
-
-
- Inscription au tirage au sort du BdA
- {% if success %}
- Votre inscription a été mise à jour avec succès !
- {% endif %}
- {% if stateerror %}
- Impossible d'enregistrer vos modifications: vous avez apporté d'autres modifications entre temps
- {% endif %}
-
-{% endblock %}
diff --git a/bda/templates/inscription-bda3.html b/bda/templates/inscription-bda3.html
deleted file mode 100644
index bf77bac8..00000000
--- a/bda/templates/inscription-bda3.html
+++ /dev/null
@@ -1,120 +0,0 @@
-{% extends "base_title.html" %}
-
-{% block extra_head %}
-
-
-
-
-
-{% endblock %}
-
-{% block realcontent %}
-
-
- Inscription au tirage au sort du BdA
- {% if success %}
- Votre inscription a été mise à jour avec succès !
- {% endif %}
- {% if stateerror %}
- Impossible d'enregistrer vos modifications: vous avez apporté d'autres modifications entre temps
- {% endif %}
-
-{% endblock %}
diff --git a/bda/templates/resume_places.html b/bda/templates/resume_places.html
index 4d9a8294..8954d7c3 100644
--- a/bda/templates/resume_places.html
+++ b/bda/templates/resume_places.html
@@ -12,7 +12,7 @@
{% endfor %}
Total à payer : {{ total|floatformat }}€
-
+
{% else %}
Vous n'avez aucune place :(
{% endif %}
diff --git a/bda/templates/spectacle_list.html b/bda/templates/spectacle_list.html
index 8c44b14e..d707dde4 100644
--- a/bda/templates/spectacle_list.html
+++ b/bda/templates/spectacle_list.html
@@ -3,9 +3,9 @@
{% block realcontent %}
Spectacles
{% endblock %}
diff --git a/bda/views.py b/bda/views.py
index f46f468a..ed653b54 100644
--- a/bda/views.py
+++ b/bda/views.py
@@ -6,25 +6,39 @@ from django.contrib.auth.decorators import login_required
from django.db import models
from django.http import Http404
from django.core import serializers
+from django.forms.models import inlineformset_factory
import hashlib
from django.core.mail import send_mail
+from django.utils import timezone
+from django.views.generic.list import ListView
-from datetime import datetime, timedelta
+from datetime import timedelta
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
+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):
- spectacles1 = ChoixSpectacle.objects.filter(double_choice = "1").all().values('spectacle','spectacle__title').annotate(total = models.Count('spectacle'))
- spectacles2 = ChoixSpectacle.objects.exclude(double_choice = "1").all().values('spectacle','spectacle__title').annotate(total = models.Count('spectacle'))
- spectacles = Spectacle.objects.all()
+def etat_places(request, tirage_id):
+ tirage = get_object_or_404(Tirage, id=tirage_id)
+ spectacles1 = ChoixSpectacle.objects \
+ .filter(spectacle__tirage=tirage) \
+ .filter(double_choice="1") \
+ .all() \
+ .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') \
+ .annotate(total=models.Count('spectacle'))
+ spectacles = tirage.spectacle_set.all()
spectacles_dict = {}
total = 0
for spectacle in spectacles:
@@ -33,13 +47,18 @@ def etat_places(request):
spectacles_dict[spectacle.id] = spectacle
for spectacle in spectacles1:
spectacles_dict[spectacle["spectacle"]].total += spectacle["total"]
- spectacles_dict[spectacle["spectacle"]].ratio = spectacles_dict[spectacle["spectacle"]].total/float(spectacles_dict[spectacle["spectacle"]].slots)
+ spectacles_dict[spectacle["spectacle"]].ratio = \
+ spectacles_dict[spectacle["spectacle"]].total / \
+ float(spectacles_dict[spectacle["spectacle"]].slots)
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/float(spectacles_dict[spectacle["spectacle"]].slots)
+ spectacles_dict[spectacle["spectacle"]].ratio = \
+ spectacles_dict[spectacle["spectacle"]].total / \
+ float(spectacles_dict[spectacle["spectacle"]].slots)
total += spectacle["total"]
- return render(request, "etat-places.html", {"spectacles": spectacles, "total": total})
+ return render(request, "etat-places.html",
+ {"spectacles": spectacles, "total": total, 'tirage': tirage})
def _hash_queryset(queryset):
data = serializers.serialize("json", queryset)
@@ -48,9 +67,12 @@ def _hash_queryset(queryset):
return hasher.hexdigest()
@cof_required
-def places(request):
- participant, created = Participant.objects.get_or_create(user = request.user)
- places = participant.attribution_set.order_by("spectacle__date", "spectacle").all()
+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)
+ places = participant.attribution_set.order_by(
+ "spectacle__date", "spectacle").all()
total = sum([place.spectacle.price for place in places])
filtered_places = []
places_dict = {}
@@ -73,13 +95,17 @@ def places(request):
return render(request, "resume_places.html",
{"participant": participant,
"places": filtered_places,
+ "tirage": tirage,
"total": total,
"warning": warning})
@cof_required
-def places_ics(request):
- participant, created = Participant.objects.get_or_create(user = request.user)
- places = participant.attribution_set.order_by("spectacle__date", "spectacle").all()
+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)
+ places = participant.attribution_set.order_by(
+ "spectacle__date", "spectacle").all()
filtered_places = []
places_dict = {}
spectacles = []
@@ -98,45 +124,75 @@ def places_ics(request):
"places": filtered_places}, content_type="text/calendar")
@cof_required
-def inscription(request):
- if datetime.now() > datetime(2015, 10, 4, 12, 00):
- participant, created = Participant.objects.get_or_create(user = request.user)
+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'))
+ return render(request, 'resume_inscription.html',
+ { "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)
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})
- BdaFormSet = inlineformset_factory(Participant, ChoixSpectacle, fields = ("spectacle","double_choice","priority",), formset = BaseBdaFormSet)
- participant, created = Participant.objects.get_or_create(user = request.user)
+ return render(request, "resume_inscription.html",
+ { "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, created = Participant.objects.get_or_create(
+ user=request.user, tirage=tirage)
success = False
stateerror = False
if request.method == "POST":
dbstate = _hash_queryset(participant.choixspectacle_set.all())
if "dbstate" in request.POST and dbstate != request.POST["dbstate"]:
stateerror = True
- formset = BdaFormSet(instance = participant)
+ formset = BdaFormSet(instance=participant)
else:
- formset = BdaFormSet(request.POST, instance = participant)
+ formset = BdaFormSet(request.POST, instance=participant)
if formset.is_valid():
- #ChoixSpectacle.objects.filter(participant = participant).delete()
formset.save()
success = True
- formset = BdaFormSet(instance = participant)
+ formset = BdaFormSet(instance=participant)
else:
- formset = BdaFormSet(instance = participant)
+ formset = BdaFormSet(instance=participant)
dbstate = _hash_queryset(participant.choixspectacle_set.all())
total_price = 0
for choice in participant.choixspectacle_set.all():
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, "stateerror": stateerror})
+ return render(request, "inscription-bda.html",
+ { "formset": formset,
+ "success": success,
+ "total_price": total_price,
+ "dbstate": dbstate,
+ 'tirage': tirage,
+ "stateerror": stateerror})
-def do_tirage(request):
+def do_tirage(request, tirage_id):
+ tirage_elt = get_object_or_404(Tirage, id=tirage_id)
form = TokenForm(request.POST)
if not form.is_valid():
return tirage(request)
+ tirage_elt.token = form.cleaned_data['token']
+ tirage_elt.save()
start = time.time()
data = {}
- shows = Spectacle.objects.select_related().all()
- members = Participant.objects.all()
- choices = ChoixSpectacle.objects.order_by('participant', 'priority').select_related().all()
+ shows = tirage_elt.spectacle_set.select_related().all()
+ members = tirage_elt.spectacle_set.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
@@ -178,23 +234,26 @@ def do_tirage(request):
members2[member].append(show)
member.total += show.price
members2 = members2.items()
- data["members2"] = sorted(members2, key = lambda m: m[0].user.last_name)
- if False and request.user.username in ["seguin", "harazi","fromherz", "ccadiou"]:
+ data["members2"] = sorted(members2, key=lambda m: m[0].user.last_name)
+ # À partir d'ici, le tirage devient effectif
+ # FIXME: Établir les conditions de validations (formulaire ?)
+ # cf. issue #32
+ if False:
Attribution.objects.all().delete()
for (show, members, _) in results:
for (member, _, _, _) in members:
- attrib = Attribution(spectacle = show, participant = member)
+ attrib = Attribution(spectacle=show, participant=member)
attrib.save()
return render(request, "bda-attrib-extra.html", data)
else:
return render(request, "bda-attrib.html", data)
-@login_required
-def tirage(request):
+@buro_required
+def tirage(request, tirage_id):
if request.POST:
form = TokenForm(request.POST)
if form.is_valid():
- return do_tirage(request)
+ return do_tirage(request, tirage_id)
else:
form = TokenForm()
return render(request, "bda-token.html", {"form": form})
@@ -220,15 +279,19 @@ def do_resell(request, form):
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)
+%s (%s)""" % (places, spectacle.title, spectacle.date_no_seconds(),
+ 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})
@login_required
-def revente(request):
- participant, created = Participant.objects.get_or_create(user = request.user)
+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)
if not participant.paid:
return render(request, "bda-notpaid.html", {})
if request.POST:
@@ -237,21 +300,40 @@ def revente(request):
return do_resell(request, form)
else:
form = ResellForm(participant)
- return render(request, "bda-revente.html", {"form": form})
+ return render(request, "bda-revente.html", {"form": form, 'tirage': tirage})
@buro_required
-def spectacle(request, spectacle_id):
- spectacle = get_object_or_404(Spectacle, id = spectacle_id)
+def spectacle(request, tirage_id, spectacle_id):
+ tirage = get_object_or_404(Tirage, id=tirage_id)
+ spectacle = get_object_or_404(Spectacle, id = spectacle_id, tirage=tirage)
return render(request, "bda-emails.html", {"spectacle": spectacle})
+
+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
+ return categories
+ def get_context_data(self, **kwargs):
+ context = super(SpectacleListView, self).get_context_data(**kwargs)
+ context['tirage_id'] = self.tirage.id
+ return context
+
@buro_required
-def unpaid(request):
- return render(request, "bda-unpaid.html", {"unpaid": Participant.objects.filter(paid = False).all()})
+def unpaid(request, tirage_id):
+ tirage = get_object_or_404(Tirage, id=tirage_id)
+ unpaid = tirage.participant_set.filter(paid=False).all()
+ return render(request, "bda-unpaid.html", {"unpaid": unpaid})
@buro_required
-def liste_spectacles_ics(request):
- spectacles = Spectacle.objects.order_by("date").all()
+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}, content_type="text/calendar")
+ {"spectacles": spectacles, "tirage": tirage},
+ content_type="text/calendar")
+
diff --git a/bda2/__init__.py b/bda2/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/bda2/admin.py b/bda2/admin.py
deleted file mode 100644
index 84eebfa3..00000000
--- a/bda2/admin.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# coding: utf-8
-
-from django.core.mail import send_mail
-from django.contrib.contenttypes.models import ContentType
-
-from django.contrib import admin
-from django.db.models import Sum, Count
-from bda2.models import Spectacle, Salle, Participant, ChoixSpectacle, Attribution
-
-class ChoixSpectacleInline(admin.TabularInline):
- model = ChoixSpectacle
- sortable_field_name = "priority"
-
-class AttributionInline(admin.TabularInline):
- model = Attribution
-
-class ParticipantAdmin(admin.ModelAdmin):
- #inlines = [ChoixSpectacleInline]
- inlines = [AttributionInline]
- def get_queryset(self, request):
- 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 €"
- total.admin_order_field = "total"
- total.short_description = "Total à payer"
- list_display = ("user", "nb_places", "total", "paid", "paymenttype")
- list_filter = ("paid",)
- search_fields = ('user__username', 'user__first_name', 'user__last_name')
- actions = ['send_attribs',]
- actions_on_bottom = True
- list_per_page = 400
-
- def send_choices(self, request, queryset):
- for member in queryset.all():
- choices = member.choixspectacle_set.order_by('priority').all()
- if len(choices) == 0:
- continue
- mail = u"""Cher(e) %s,
-Voici tes choix de spectacles tels que notre système les a enregistrés :\n\n""" % member.user.get_full_name()
- next_rank = 1
- member_shows = {}
- for choice in choices:
- if choice.spectacle in member_shows: continue
- else: member_shows[choice.spectacle] = True
- extra = ""
- if choice.double:
- extra += u" ; deux places"
- if choice.autoquit:
- extra += u" ; désistement automatique"
- mail += u"- Choix %d : %s%s\n" % (next_rank, choice.spectacle, extra)
- next_rank += 1
- mail += u"""\nSi cette liste est incorrecte, merci de nous contacter au plus vite (avant samedi 6 octobre 18h).
-
-Artistiquement,
-Le BdA"""
- send_mail ("Choix de spectacles (BdA du COF)", mail,
- "bda@ens.fr", [member.user.email],
- fail_silently = True)
- count = len(queryset.all())
- if count == 1:
- message_bit = u"1 membre a"
- plural = ""
- 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))
- send_choices.short_description = u"Envoyer les choix par mail"
-
- def send_attribs(self, request, queryset):
- for member in queryset.all():
- attribs = member.attributions.all()
- if len(attribs) == 0:
- mail = u"""Cher-e %s,
-
-Tu t'es inscrit-e pour le tirage au sort du BdA. Malheureusement, tu n'as
-obtenu aucune place.
-
-Nous sommes conscients que le nombre de places proposées lors de ce tirage
-au sort est très restreint, mais nous sommes limités par les quotas que
-nous imposent les théâtres.
-
-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 (nouveau) Bureau des Arts
-(Thomas, Caroline, Antonin, Cécile, Hugo)
-
-"""
- name = member.user.get_full_name()
- mail = mail % name
- else:
- mail = u"""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 :
-
-%s
-
-Nous sommes conscients que le nombre de places proposées lors de ce tirage
-au sort est très restreint, mais nous sommes limités par les quotas que
-nous imposent les théâtres.
-
-*Paiement*
-L'intégralité de ces places de spectacles est à régler à partir du lundi
-18 janvier et AVANT le vendredi 22 janvier, 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. Il est possible de payer par carte, chèque ou en espèces.
-
-*Mode de retrait des places*
-Lors du paiement, nous vous donnerons les places physiques que nous possédons, et vous indiquerons
-quelles places sont sur listing, à retirer le soir même de la représentation. Nous vous enverrons un mail de rappel quelques jours avant les spectacles.
-
-Nous vous rappelons que l'obtention de places du BdA vous engage à
-respecter les règles de fonctionnement :
-http://www.cof.ens.fr/bda/?page_id=1370
-Le système de revente des places via les mails BdA-revente est accessible
-directement sur votre compte GestioCOF.
-
-En vous souhaitant de belles représentations,
---
-Le (nouveau) Bureau des Arts
-(Thomas, Caroline, Antonin, Cécile, Hugo)
-"""
- attribs_text = ""
- name = member.user.get_full_name()
- for attrib in attribs:
- attribs_text += u"- 1 place pour %s\n" % attrib
- mail = mail % (name, attribs_text)
-
- send_mail ("[BdA] 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"
- plural = ""
- 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))
- send_attribs.short_description = u"Envoyer les résultats par mail"
-
-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')
-
-import autocomplete_light
-class ChoixSpectacleAdmin(admin.ModelAdmin):
- form = autocomplete_light.modelform_factory(ChoixSpectacle, exclude=[])
- list_display = ("participant", "spectacle", "priority", "double", "autoquit")
- list_filter = ("double", "autoquit")
- search_fields = ('participant__user__username', 'participant__user__first_name', 'participant__user__last_name')
-
-class SpectacleAdmin(admin.ModelAdmin):
- model = Spectacle
- list_display = ("title", "date", "location", "slots", "price")
- list_filter = ("location",)
- search_fields = ("title", "location__name")
-
-admin.site.register(Spectacle, SpectacleAdmin)
-admin.site.register(Salle)
-admin.site.register(Participant, ParticipantAdmin)
-admin.site.register(Attribution, AttributionAdmin)
-admin.site.register(ChoixSpectacle, ChoixSpectacleAdmin)
diff --git a/bda2/algorithm.py b/bda2/algorithm.py
deleted file mode 100644
index 623f9756..00000000
--- a/bda2/algorithm.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# coding: utf-8
-
-from django.conf import settings
-from django.db.models import Max
-
-import random
-
-class Algorithm(object):
-
- shows = None
- ranks = None
- origranks = None
- double = None
-
- def __init__(self, shows, members, choices):
- """Initialisation :
- - on aggrège toutes les demandes pour chaque spectacle dans
- 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.shows = []
- showdict = {}
- for show in shows:
- show.nrequests = 0
- showdict[show] = show
- show.requests = []
- self.shows.append(show)
- self.ranks = {}
- self.origranks = {}
- self.choices = {}
- next_rank = {}
- member_shows = {}
- for member in members:
- self.ranks[member] = {}
- self.choices[member] = {}
- next_rank[member] = 1
- 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
- showdict[choice.spectacle].requests.append(member)
- showdict[choice.spectacle].nrequests += 2 if choice.double else 1
- self.ranks[member][choice.spectacle] = next_rank[member]
- next_rank[member] += 2 if choice.double else 1
- self.choices[member][choice.spectacle] = choice
- for member in members:
- self.origranks[member] = dict(self.ranks[member])
-
- def IncrementRanks(self, member, currank, increment = 1):
- for show in self.ranks[member]:
- if self.ranks[member][show] > currank:
- self.ranks[member][show] -= increment
-
- def appendResult(self, l, member, show):
- l.append((member,
- self.ranks[member][show],
- self.origranks[member][show],
- self.choices[member][show].double))
-
- """
- Pour les 2 Walkyries: c'est Sandefer
-
- Pour les 4 places pour l'Oratorio c'est Maxence Arutkin
- """
-
- def __call__(self, seed):
- random.seed(seed)
- results = []
- shows = sorted(self.shows, key = lambda x: float(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)
- groups[self.ranks[member][show]].append(member)
- # On passe à l'attribution
- winners = []
- losers = []
- for i in range(1, self.max_group + 1):
- group = list(groups[i])
- random.shuffle(group)
- for member in group:
- 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:
- 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
- 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))
- return results
diff --git a/bda2/autocomplete_light_registry.py b/bda2/autocomplete_light_registry.py
deleted file mode 100644
index 3254b3c8..00000000
--- a/bda2/autocomplete_light_registry.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import autocomplete_light
-
-from bda.models import Participant, Spectacle
-
-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_js_attributes={'placeholder': 'spectacle...'})
diff --git a/bda2/difftobda b/bda2/difftobda
deleted file mode 100644
index 3e6686e5..00000000
--- a/bda2/difftobda
+++ /dev/null
@@ -1,421 +0,0 @@
-Only in .: .admin.py.swp
-Binary files ../bda/__init__.pyc and ./__init__.pyc differ
-diff -p -u -r ../bda/admin.py ./admin.py
---- ../bda/admin.py 2013-12-17 10:19:56.000000000 +0100
-+++ ./admin.py 2012-12-08 22:31:46.000000000 +0100
-@@ -4,8 +4,8 @@ from django.core.mail import send_mail
- from django.contrib.contenttypes.models import ContentType
-
- from django.contrib import admin
--from django.db.models import Sum, Count
--from bda.models import Spectacle, Salle, Participant, ChoixSpectacle, Attribution
-+from django.db.models import Sum
-+from bda2.models import Spectacle, Salle, Participant, ChoixSpectacle, Attribution
-
- class ChoixSpectacleInline(admin.TabularInline):
- model = ChoixSpectacle
-@@ -17,18 +17,13 @@ class AttributionInline(admin.TabularInl
- class ParticipantAdmin(admin.ModelAdmin):
- #inlines = [ChoixSpectacleInline]
- inlines = [AttributionInline]
-- def queryset(self, request):
-- 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"
-+ return len(obj.attribution_set.all())
- nb_places.short_description = "Nombre de places"
- def total(self, obj):
-- tot = obj.total
-+ tot = obj.attributions.aggregate(total = Sum('price'))['total']
- 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")
- list_filter = ("paid",)
-@@ -61,7 +56,7 @@ Voici tes choix de spectacles tels que n
- Artistiquement,
- Le BdA"""
- send_mail ("Choix de spectacles (BdA du COF)", mail,
-- "bda@ens.fr", [member.user.email],
-+ "bda@clipper.ens.fr", [member.user.email],
- fail_silently = True)
- count = len(queryset.all())
- if count == 1:
-@@ -86,48 +81,41 @@ pour les spectacles suivants :
- %s
-
- *Paiement*
--L'intégralité de ces places de spectacles est à régler à partir du jeudi
--10 octobre et AVANT le mercredi 23 octobre, 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.
-+Ces spectacles sont à régler avant le lundi 17 décembre, pendant les
-+heures de permanences du COF (tous les jours de la semaine entre 12h et
-+14h, et entre 18h et 20h). Des facilités de paiement sont bien évidemment
-+possibles (encaissement échelonné des chèques).
-
- *Mode de retrait des places*
--Au moment du paiement, une enveloppe vous sera remise, contenant les
--places pour l'Opéra de Paris, pour les premiers spectacles de la Comédie
--française, certains spectacles du Châtelet et du Théâtre de la Ville.
--
--Pour les concerts Radio France, le Théâtre des Champs-Élysées, le théâtre
--du Rond-Point, le théâtre de la Colline, le théâtre de l'Athénée, l'IRCAM,
--la Cité de la musique et le 104, le Studio-Théâtre de la Comédie
--française, les places seront nominatives et à retirer au théâtre le soir
--de la représentation au moins une demi-heure avant le début du spectacle.
--
--Pour le théâtre de l'Odéon, la salle Richelieu le théâtre du Vieux
--colombier de la Comédie française, certains spectacles du théâtre de la
--Ville et du théâtre de Châtelet ainsi que pour le théâtre de Chaillot, les
--places seront distribuées environ une semaine avant la représentation (un
--mail vous en avertira).
--
--Nous vous rappelons que l'obtention de places du BdA vous engage à
--respecter les règles de fonctionnement :
--http://www.cof.ens.fr/bda/?page_id=1370
--Le système de revente des places via les mails BdA-revente sera très
--prochainement disponible, directement sur votre compte GestioCOF.
-+Pour l'Opéra de Paris, le théâtre de la Colline et le théâtre du Châtelet,
-+les places sont à retirer au COF le jour du paiement.
-+
-+Pour les concerts Radio France, le théâtre des Champs-Élysées, l'IRCAM
-+et le 104, les places seront nominatives et à retirer à la salle le soir de
-+la représentation au moins une demi-heure avant le début du spectacle.
-+
-+Pour le théâtre de l'Odéon, la Comédie Française, le théâtre de la Ville,
-+le théâtre de Chaillot, les places seront distribuées dans vos
-+casiers environ une semaine avant la représentation (un mail vous en
-+avertira).
-+
-+Dans tous les cas, n'hésitez pas à nous contacter si vous avez un doute !
-+
-+Nous profitons aussi de ce message pour vous annoncer qu'un festival de
-+courts métrages aura lieu le 21 décembre dans l'école.
-+Plus d'informations : http://www.cof.ens.fr/bda/courts.
-+
-+Culturellement vôtre,
-
--En vous souhaitant de très beaux spectacles tout au long de l'année,
- --
--Le Bureau des Arts
--(Chloé, Emilie, Jaime, Maxime, Olivier)
--"""
-+Le BdA"""
- attribs_text = ""
- name = member.user.get_full_name()
- for attrib in attribs:
- attribs_text += u"- 1 place pour %s\n" % attrib
- mail = mail % (name, attribs_text)
-- send_mail ("Résultats du tirage au sort", mail,
-- "bda@ens.fr", [member.user.email],
-+ send_mail ("Places de spectacle (BdA du COF)", mail,
-+ "bda@clipper.ens.fr", [member.user.email],
- fail_silently = True)
- count = len(queryset.all())
- if count == 1:
-@@ -154,13 +142,7 @@ class ChoixSpectacleAdmin(admin.ModelAdm
- list_filter = ("double", "autoquit")
- search_fields = ('participant__user__username', 'participant__user__first_name', 'participant__user__last_name')
-
--class SpectacleAdmin(admin.ModelAdmin):
-- model = Spectacle
-- list_display = ("title", "date", "location", "slots", "price")
-- list_filter = ("location",)
-- search_fields = ("title", "location__name")
--
--admin.site.register(Spectacle, SpectacleAdmin)
-+admin.site.register(Spectacle)
- admin.site.register(Salle)
- admin.site.register(Participant, ParticipantAdmin)
- admin.site.register(Attribution, AttributionAdmin)
-diff -p -u -r ../bda/algorithm.py ./algorithm.py
---- ../bda/algorithm.py 2013-10-07 14:08:44.000000000 +0200
-+++ ./algorithm.py 2012-10-31 23:01:48.000000000 +0100
-@@ -29,24 +29,25 @@ class Algorithm(object):
- self.ranks = {}
- self.origranks = {}
- self.choices = {}
-- next_rank = {}
-- member_shows = {}
- for member in members:
-- self.ranks[member] = {}
-- self.choices[member] = {}
-- next_rank[member] = 1
-- 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
-- showdict[choice.spectacle].requests.append(member)
-- showdict[choice.spectacle].nrequests += 2 if choice.double else 1
-- self.ranks[member][choice.spectacle] = next_rank[member]
-- next_rank[member] += 2 if choice.double else 1
-- self.choices[member][choice.spectacle] = choice
-- for member in members:
-- self.origranks[member] = dict(self.ranks[member])
-+ ranks = {}
-+ member_choices = {}
-+ member_shows = {}
-+ #next_priority = 1
-+ next_rank = 1
-+ for choice in member.choixspectacle_set.order_by('priority').all():
-+ if choice.spectacle in member_shows: continue
-+ else: member_shows[choice.spectacle] = True
-+ #assert choice.priority == next_priority
-+ #next_priority += 1
-+ showdict[choice.spectacle].requests.append(member)
-+ showdict[choice.spectacle].nrequests += 2 if choice.double else 1
-+ ranks[choice.spectacle] = next_rank
-+ next_rank += 2 if choice.double else 1
-+ member_choices[choice.spectacle] = choice
-+ self.ranks[member] = ranks
-+ self.choices[member] = member_choices
-+ self.origranks[member] = dict(ranks)
-
- def IncrementRanks(self, member, currank, increment = 1):
- for show in self.ranks[member]:
-Only in ../bda: algorithm.pyc
-Only in .: difftobda
-diff -p -u -r ../bda/models.py ./models.py
---- ../bda/models.py 2013-10-10 10:44:43.000000000 +0200
-+++ ./models.py 2012-10-31 23:12:56.000000000 +0100
-@@ -1,7 +1,5 @@
- # coding: utf-8
-
--import calendar
--
- from django.db import models
- from django.contrib.auth.models import User
- from django.utils.translation import ugettext_lazy as _
-@@ -19,7 +17,7 @@ class Spectacle (models.Model):
- date = models.DateTimeField ("Date & heure")
- location = models.ForeignKey(Salle)
- description = models.TextField ("Description", blank = True)
-- slots_description = models.TextField ("Description des places", blank = True)
-+ #slots_description = models.TextField ("Description des places", blank = True)
- price = models.FloatField("Prix d'une place", blank = True)
- slots = models.IntegerField ("Places")
- priority = models.IntegerField ("Priorité", default = 1000)
-@@ -31,14 +29,11 @@ class Spectacle (models.Model):
- def __repr__ (self):
- return u"[%s]" % self.__unicode__()
-
-- def timestamp(self):
-- return "%d" % calendar.timegm(self.date.utctimetuple())
--
- 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)
-+ return u"%s - %s @ %s, %.02f€" % (self.title, self.date_no_seconds(), self.location, self.price)
-
- PAYMENT_TYPES = (
- ("cash",u"Cash"),
-@@ -48,7 +43,7 @@ PAYMENT_TYPES = (
- )
-
- class Participant (models.Model):
-- user = models.ForeignKey(User, unique = True)
-+ user = models.ForeignKey(User, unique = True, related_name = "participants2")
- choices = models.ManyToManyField(Spectacle, through = "ChoixSpectacle", related_name = "chosen_by")
- attributions = models.ManyToManyField(Spectacle, through = "Attribution", related_name = "attributed_to")
- paid = models.BooleanField (u"A payé", default = False)
-Binary files ../bda/models.pyc and ./models.pyc differ
-diff -p -u -r ../bda/views.py ./views.py
---- ../bda/views.py 2014-01-04 21:37:15.000000000 +0100
-+++ ./views.py 2013-02-12 22:03:38.000000000 +0100
-@@ -1,23 +1,19 @@
- # coding: utf-8
-
--from django.contrib.auth.models import User
- from django.shortcuts import render, get_object_or_404
- from django.contrib.auth.decorators import login_required
- from django.db import models
- from django.http import Http404
- from django import forms
- from django.forms.models import inlineformset_factory, BaseInlineFormSet
--from django.core import serializers
--import hashlib
-
- from django.core.mail import send_mail
-
--from datetime import datetime
- import time
-
- from gestioncof.decorators import cof_required, buro_required
--from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution
--from bda.algorithm import Algorithm
-+from bda2.models import Spectacle, Participant, ChoixSpectacle, Attribution
-+from bda2.algorithm import Algorithm
-
- class BaseBdaFormSet(BaseInlineFormSet):
- def clean(self):
-@@ -37,7 +33,7 @@ class BaseBdaFormSet(BaseInlineFormSet):
- raise forms.ValidationError("Vous ne pouvez pas vous inscrire deux fois pour le même spectacle.")
- spectacles.append(spectacle)
-
--@cof_required
-+@buro_required
- def etat_places(request):
- spectacles1 = ChoixSpectacle.objects.all().values('spectacle','spectacle__title').annotate(total = models.Count('spectacle'))
- spectacles2 = ChoixSpectacle.objects.filter(double = True).all().values('spectacle','spectacle__title').annotate(total = models.Count('spectacle'))
-@@ -46,93 +42,47 @@ def etat_places(request):
- total = 0
- for spectacle in spectacles:
- spectacle.total = 0
-- spectacle.ratio = -1.0
- spectacles_dict[spectacle.id] = spectacle
- for spectacle in spectacles1:
- spectacles_dict[spectacle["spectacle"]].total += spectacle["total"]
-- spectacles_dict[spectacle["spectacle"]].ratio = spectacles_dict[spectacle["spectacle"]].total/float(spectacles_dict[spectacle["spectacle"]].slots)
- total += spectacle["total"]
- for spectacle in spectacles2:
- spectacles_dict[spectacle["spectacle"]].total += spectacle["total"]
-- spectacles_dict[spectacle["spectacle"]].ratio = spectacles_dict[spectacle["spectacle"]].total/float(spectacles_dict[spectacle["spectacle"]].slots)
- total += spectacle["total"]
- return render(request, "etat-places.html", {"spectacles": spectacles, "total": total})
-
--def _hash_queryset(queryset):
-- data = serializers.serialize("json", queryset)
-- hasher = hashlib.sha256()
-- hasher.update(data)
-- return hasher.hexdigest()
--
--@cof_required
--def places(request):
-- participant, created = Participant.objects.get_or_create(user = request.user)
-- places = participant.attribution_set.order_by("spectacle__date", "spectacle").all()
-- total = sum([place.spectacle.price for place in places])
-- filtered_places = []
-- places_dict = {}
-- spectacles = []
-- dates = []
-- warning = False
-- for place in places:
-- if place.spectacle in spectacles:
-- places_dict[place.spectacle].double = True
-- else:
-- place.double = False
-- places_dict[place.spectacle] = place
-- spectacles.append(place.spectacle)
-- filtered_places.append(place)
-- date = place.spectacle.date.date()
-- if date in dates:
-- warning = True
-- else:
-- dates.append(date)
-- return render(request, "resume_places.html",
-- {"participant": participant,
-- "places": filtered_places,
-- "total": total,
-- "warning": warning})
--
- @cof_required
- def inscription(request):
-- if datetime.now() > datetime(2013, 10, 6, 23, 59):
-- participant, created = Participant.objects.get_or_create(user = request.user)
-- 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 le 7 octobre !", "choices": choices})
-+ if time.time() > 1354921200:
-+ return render(request, "error.html", {"error_title": "C'est fini !", "error_description": u"Tirage au sort le 6 octobre dans la soirée "})
- BdaFormSet = inlineformset_factory(Participant, ChoixSpectacle, fields = ("spectacle","double","autoquit","priority",), formset = BaseBdaFormSet)
- participant, created = Participant.objects.get_or_create(user = request.user)
- success = False
-- stateerror = False
- if request.method == "POST":
-- dbstate = _hash_queryset(participant.choixspectacle_set.all())
-- if "dbstate" in request.POST and dbstate != request.POST["dbstate"]:
-- stateerror = True
-+ formset = BdaFormSet(request.POST, instance = participant)
-+ if formset.is_valid():
-+ #ChoixSpectacle.objects.filter(participant = participant).delete()
-+ formset.save()
-+ success = True
- formset = BdaFormSet(instance = participant)
-- else:
-- formset = BdaFormSet(request.POST, instance = participant)
-- if formset.is_valid():
-- #ChoixSpectacle.objects.filter(participant = participant).delete()
-- formset.save()
-- success = True
-- formset = BdaFormSet(instance = participant)
- else:
- formset = BdaFormSet(instance = participant)
-- dbstate = _hash_queryset(participant.choixspectacle_set.all())
- total_price = 0
- for choice in participant.choixspectacle_set.all():
- 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, "stateerror": stateerror})
-+ return render(request, "inscription-bda.html", {"formset": formset, "success": success, "total_price": total_price})
-+
-+Spectacle.deficit = lambda x: (x.slots-x.nrequests)*x.price
-
- def do_tirage(request):
- form = TokenForm(request.POST)
- if not form.is_valid():
- return tirage(request)
-- start = time.time()
- data = {}
-- shows = Spectacle.objects.select_related().all()
-+ shows = Spectacle.objects.all()
- members = Participant.objects.all()
-- choices = ChoixSpectacle.objects.order_by('participant', 'priority').select_related().all()
-+ choices = ChoixSpectacle.objects.all()
- algo = Algorithm(shows, members, choices)
- results = algo(form.cleaned_data["token"])
- total_slots = 0
-@@ -149,8 +99,8 @@ def do_tirage(request):
- total_sold = 0
- total_deficit = 0
- opera_deficit = 0
-- for (show, members, _) in results:
-- deficit = (show.slots - len(members)) * show.price
-+ for show in shows:
-+ deficit = show.deficit()
- total_sold += show.slots * show.price
- if deficit >= 0:
- if u"Opéra" in show.location.name:
-@@ -159,23 +109,18 @@ def do_tirage(request):
- data["total_sold"] = total_sold - total_deficit
- data["total_deficit"] = total_deficit
- data["opera_deficit"] = opera_deficit
-- 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
- for (show, members, _) in results:
- for (member, _, _, _) in members:
-- if member.id not in members_uniq:
-- members_uniq[member.id] = member
-+ if member not in members2:
- members2[member] = []
- member.total = 0
-- member = members_uniq[member.id]
- members2[member].append(show)
- member.total += show.price
- members2 = members2.items()
- data["members2"] = sorted(members2, key = lambda m: m[0].user.last_name)
-- if False and request.user.username in ["seguin", "harazi"]:
-+ if False and request.user.username == "seguin":
- Attribution.objects.all().delete()
- for (show, members, _) in results:
- for (member, _, _, _) in members:
-@@ -220,7 +165,7 @@ Je souhaite revendre %s pour %s le %s (%
- Contactez moi par email si vous êtes intéressés !
-
- %s (%s)""" % (places, spectacle.title, spectacle.date_no_seconds(), spectacle.location, spectacle.price, request.user.get_full_name(), request.user.email)
-- send_mail("%s" % spectacle, mail,
-+ send_mail("Revente de place: %s" % spectacle, mail,
- request.user.email, ["bda-revente@lists.ens.fr"],
- fail_silently = True)
- return render(request, "bda-success.html", {"show": spectacle, "places": places})
-Only in .: views.py~
diff --git a/bda2/forms.py b/bda2/forms.py
deleted file mode 100644
index 930e184a..00000000
--- a/bda2/forms.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# coding: utf-8
-
-from django import forms
-from django.forms.models import inlineformset_factory, BaseInlineFormSet
-from bda2.models import Spectacle, Participant, ChoixSpectacle, Attribution
-
-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
- return
- spectacles = []
- for i in range(0, self.total_form_count()):
- form = self.forms[i]
- if not form.cleaned_data:
- continue
- 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.")
- 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"),))
- 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()
-
diff --git a/bda2/migrations/0001_initial.py b/bda2/migrations/0001_initial.py
deleted file mode 100644
index 450e1607..00000000
--- a/bda2/migrations/0001_initial.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-from django.conf import settings
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ]
-
- operations = [
- migrations.CreateModel(
- name='Attribution',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('given', models.BooleanField(default=False, verbose_name='Donn\xe9e')),
- ],
- ),
- migrations.CreateModel(
- name='ChoixSpectacle',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('priority', models.PositiveIntegerField(verbose_name=b'Priorit\xc3\xa9')),
- ('double', models.BooleanField(default=False, verbose_name=b'Deux places1 ')),
- ('autoquit', models.BooleanField(default=False, verbose_name=b'Abandon2 ')),
- ],
- options={
- 'ordering': ('priority',),
- 'verbose_name': 'voeu',
- 'verbose_name_plural': 'voeux',
- },
- ),
- migrations.CreateModel(
- name='Participant',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('paid', models.BooleanField(default=False, verbose_name='A pay\xe9')),
- ('paymenttype', models.CharField(blank=True, max_length=6, verbose_name='Moyen de paiement', choices=[(b'cash', 'Cash'), (b'cb', b'CB'), (b'cheque', 'Ch\xe8que'), (b'autre', 'Autre')])),
- ],
- ),
- migrations.CreateModel(
- name='Salle',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(max_length=300, verbose_name=b'Nom')),
- ('address', models.TextField(verbose_name=b'Adresse')),
- ],
- ),
- migrations.CreateModel(
- name='Spectacle',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('title', models.CharField(max_length=300, verbose_name=b'Titre')),
- ('date', models.DateTimeField(verbose_name=b'Date & heure')),
- ('description', models.TextField(verbose_name=b'Description', blank=True)),
- ('slots_description', models.TextField(verbose_name=b'Description des places', blank=True)),
- ('price', models.FloatField(verbose_name=b"Prix d'une place", blank=True)),
- ('slots', models.IntegerField(verbose_name=b'Places')),
- ('priority', models.IntegerField(default=1000, verbose_name=b'Priorit\xc3\xa9')),
- ('location', models.ForeignKey(to='bda2.Salle')),
- ],
- options={
- 'ordering': ('priority', 'date', 'title'),
- 'verbose_name': 'Spectacle',
- },
- ),
- migrations.AddField(
- model_name='participant',
- name='attributions',
- field=models.ManyToManyField(related_name='attributed_to', through='bda2.Attribution', to='bda2.Spectacle'),
- ),
- migrations.AddField(
- model_name='participant',
- name='choices',
- field=models.ManyToManyField(related_name='chosen_by', through='bda2.ChoixSpectacle', to='bda2.Spectacle'),
- ),
- migrations.AddField(
- model_name='participant',
- name='user',
- field=models.OneToOneField(related_name='participants2', to=settings.AUTH_USER_MODEL),
- ),
- migrations.AddField(
- model_name='choixspectacle',
- name='participant',
- field=models.ForeignKey(to='bda2.Participant'),
- ),
- migrations.AddField(
- model_name='choixspectacle',
- name='spectacle',
- field=models.ForeignKey(related_name='participants', to='bda2.Spectacle'),
- ),
- migrations.AddField(
- model_name='attribution',
- name='participant',
- field=models.ForeignKey(to='bda2.Participant'),
- ),
- migrations.AddField(
- model_name='attribution',
- name='spectacle',
- field=models.ForeignKey(related_name='attribues', to='bda2.Spectacle'),
- ),
- migrations.AlterUniqueTogether(
- name='choixspectacle',
- unique_together=set([('participant', 'spectacle')]),
- ),
- ]
diff --git a/bda2/migrations/__init__.py b/bda2/migrations/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/bda2/models.py b/bda2/models.py
deleted file mode 100644
index c9fefe6e..00000000
--- a/bda2/models.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# coding: utf-8
-
-import calendar
-
-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
-
-class Salle (models.Model):
- name = models.CharField ("Nom", max_length = 300)
- address = models.TextField ("Adresse")
-
- def __unicode__ (self):
- return self.name
-
-class Spectacle (models.Model):
- title = models.CharField ("Titre", max_length = 300)
- date = models.DateTimeField ("Date & heure")
- location = models.ForeignKey(Salle)
- description = models.TextField ("Description", blank = True)
- slots_description = models.TextField ("Description des places", blank = True)
- price = models.FloatField("Prix d'une place", blank = True)
- slots = models.IntegerField ("Places")
- priority = models.IntegerField ("Priorité", default = 1000)
-
- class Meta:
- verbose_name = "Spectacle"
- ordering = ("priority", "date","title",)
-
- def __repr__ (self):
- return u"[%s]" % self.__unicode__()
-
- def timestamp(self):
- return "%d" % calendar.timegm(self.date.utctimetuple())
-
- 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)
-
-PAYMENT_TYPES = (
-("cash",u"Cash"),
-("cb","CB"),
-("cheque",u"Chèque"),
-("autre",u"Autre"),
-)
-
-class Participant (models.Model):
- user = models.OneToOneField(User, related_name = "participants2")
- choices = models.ManyToManyField(Spectacle, through = "ChoixSpectacle", related_name = "chosen_by")
- 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", max_length = 6, choices = PAYMENT_TYPES, blank = True)
-
- def __unicode__ (self):
- return u"%s" % (self.user)
-
-class ChoixSpectacle (models.Model):
- participant = models.ForeignKey(Participant)
- spectacle = models.ForeignKey(Spectacle, related_name = "participants")
- priority = models.PositiveIntegerField("Priorité")
- double = models.BooleanField("Deux places1 ",default=False)
- autoquit = models.BooleanField("Abandon2 ",default=False)
- class Meta:
- ordering = ("priority",)
- unique_together = (("participant", "spectacle",),)
- 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):
- return u"%s -- %s" % (self.participant, self.spectacle)
diff --git a/bda2/static/css/bda.css b/bda2/static/css/bda.css
deleted file mode 100644
index 8851eeee..00000000
--- a/bda2/static/css/bda.css
+++ /dev/null
@@ -1,10 +0,0 @@
-form#tokenform {text-align: center; font-size: 2em;}
-label {margin-right: 10px; vertical-align: top;}
-form#tokenform textarea {font-size: 2em; width: 350px; height: 200px; font-family: 'Droif Serif', serif;}
-input {width: 400px; font-size: 2em;}
-ul.losers {display: inline; margin: 0; padding: 0;}
-ul.losers li {display: inline;}
-span.details {font-size: 0.7em;}
-table {border: 1px solid black; border-collapse: collapse;}
-td {border: 1px solid black; padding: 2px;}
-.attribresult {margin: 10px 0px;}
diff --git a/bda2/templates/bda-attrib-extra.html b/bda2/templates/bda-attrib-extra.html
deleted file mode 100644
index c2c266d2..00000000
--- a/bda2/templates/bda-attrib-extra.html
+++ /dev/null
@@ -1,27 +0,0 @@
-{% extends "bda-attrib.html" %}
-
-{% block extracontent %}
-
-Attribution (détails)
-Token : {{ token }}
-Placés : {{ total_slots }} ; Déçus : {{ total_losers }}
-
-
-{% for member, shows in members2 %}
-
- {{ member.user.get_full_name }}
- {{ member.user.email }}
- Total: {{ member.total }}€
-
-
-{% for show in shows %}
-
-
-
- {{ show }}
-
-
-{% endfor %}
-{% endfor %}
-
-{% endblock %}
diff --git a/bda2/templates/bda-attrib.html b/bda2/templates/bda-attrib.html
deleted file mode 100644
index 8390bd03..00000000
--- a/bda2/templates/bda-attrib.html
+++ /dev/null
@@ -1,41 +0,0 @@
-{% extends "base_title.html" %}
-{% load staticfiles %}
-
-{% block extra_head %}
-
-{% endblock %}
-
-{% block realcontent %}
-
-Attribution
-Token : {{ token }}
-Placés : {{ total_slots }} ; Déçus : {{ total_losers }}
-{% if user.profile.is_buro %}Déficit total: {{ total_deficit }} €, Opéra: {{ opera_deficit }} €, Attribué: {{ total_sold }} € {% endif %}
-
-{% for show, members, losers in results %}
-
-
{{ show.title }} - {{ show.date_no_seconds }} @ {{ show.location }}
-
-{{ show.nrequests }} demandes pour {{ show.slots }} places
-{{ show.price }}€ par place{% if user.profile.is_buro and show.nrequests < show.slots %}, {{ show.deficit }}€ de déficit{% endif %}
-
-Places :
-
-{% for member, rank, origrank, double in members %}
- {{ member.user.get_full_name }} (souhait {{ origrank }} — rang {{ rank }})
-{% endfor %}
-
-Déçus :
-{% if not losers %}/{% else %}
-
-{% for member, rank, origrank, double in losers %}
-{% if not forloop.first %} ; {% endif %}
- {{ member.user.get_full_name }} (souhait {{ origrank }} — rang {{ rank }})
-{% endfor %}
-
-{% endif %}
-
-{% endfor %}
-{% block extracontent %}
-{% endblock %}
-{% endblock %}
diff --git a/bda2/templates/bda-emails.html b/bda2/templates/bda-emails.html
deleted file mode 100644
index 39744ae1..00000000
--- a/bda2/templates/bda-emails.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends "base_title.html" %}
-
-{% block realcontent %}
- {{ spectacle }}
-
-{% endblock %}
diff --git a/bda2/templates/bda-notpaid.html b/bda2/templates/bda-notpaid.html
deleted file mode 100644
index 10b272d8..00000000
--- a/bda2/templates/bda-notpaid.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{% extends "base_title.html" %}
-
-{% block realcontent %}
- Nope
- Avant de revendre des places, il faut aller les payer !
-{% endblock %}
diff --git a/bda2/templates/bda-revente.html b/bda2/templates/bda-revente.html
deleted file mode 100644
index 82ed80fe..00000000
--- a/bda2/templates/bda-revente.html
+++ /dev/null
@@ -1,26 +0,0 @@
-{% extends "base_title.html" %}
-{% load staticfiles %}
-
-{% block extra_head %}
-
-{% endblock %}
-
-{% block realcontent %}
-
-Revente de place
-
-{% endblock %}
diff --git a/bda2/templates/bda-success.html b/bda2/templates/bda-success.html
deleted file mode 100644
index ebcc87a7..00000000
--- a/bda2/templates/bda-success.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% extends "base_title.html" %}
-{% load staticfiles %}
-
-{% block extra_head %}
-
-{% endblock %}
-
-{% block realcontent %}
-
-Revente de place
-Votre offre de revente de {{ places }} pour {{ show.title }} le {{ show.date_no_seconds }} ({{ show.location }}) à {{ show.price }}€ a bien été envoyée.
-{% endblock %}
diff --git a/bda2/templates/bda-token.html b/bda2/templates/bda-token.html
deleted file mode 100644
index cbe72a76..00000000
--- a/bda2/templates/bda-token.html
+++ /dev/null
@@ -1,13 +0,0 @@
-{% extends "base_title.html" %}
-
-{% block realcontent %}
-Tirage au sort du BdA
-
-{% endblock %}
diff --git a/bda2/templates/bda-unpaid.html b/bda2/templates/bda-unpaid.html
deleted file mode 100644
index 5596dd82..00000000
--- a/bda2/templates/bda-unpaid.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends "base_title.html" %}
-
-{% block realcontent %}
- Impayés
-
-{% endblock %}
diff --git a/bda2/templates/etat-places.html b/bda2/templates/etat-places.html
deleted file mode 100644
index 086ca648..00000000
--- a/bda2/templates/etat-places.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% extends "base_title.html" %}
-
-{% block realcontent %}
- Etat des inscriptions BDA
-
- {% for spectacle in spectacles %}
- {{ spectacle.title }} ({{ spectacle.date_no_seconds }}, {{ spectacle.location }} , {{ spectacle.slots }} places) : {{ spectacle.total }} demandes
- {% endfor %}
-
- Total : {{ total }} demandes
-{% endblock %}
diff --git a/bda2/templates/inscription-bda.html b/bda2/templates/inscription-bda.html
deleted file mode 100644
index 933f087a..00000000
--- a/bda2/templates/inscription-bda.html
+++ /dev/null
@@ -1,116 +0,0 @@
-{% extends "base_title.html" %}
-
-{% block extra_head %}
-
-
-
-
-
-{% endblock %}
-
-{% block realcontent %}
-
-
- Inscription au tirage au sort du BDA
- {% if success %}
- Votre inscription a été mise à jour avec succès !
- {% endif %}
-
-{% endblock %}
diff --git a/bda2/templates/inscription-formset.html b/bda2/templates/inscription-formset.html
deleted file mode 100644
index 04b68a6b..00000000
--- a/bda2/templates/inscription-formset.html
+++ /dev/null
@@ -1,40 +0,0 @@
-{{ formset.non_form_errors.as_ul }}
-
diff --git a/bda2/templates/spectacle_list.html b/bda2/templates/spectacle_list.html
deleted file mode 100644
index 956037f8..00000000
--- a/bda2/templates/spectacle_list.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% extends "base_title.html" %}
-
-{% block realcontent %}
- Spectacles
-
-{% endblock %}
diff --git a/bda2/tests.py b/bda2/tests.py
deleted file mode 100644
index 501deb77..00000000
--- a/bda2/tests.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-This file demonstrates writing tests using the unittest module. These will pass
-when you run "manage.py test".
-
-Replace this with more appropriate tests for your application.
-"""
-
-from django.test import TestCase
-
-
-class SimpleTest(TestCase):
- def test_basic_addition(self):
- """
- Tests that 1 + 1 always equals 2.
- """
- self.assertEqual(1 + 1, 2)
diff --git a/bda2/views.py b/bda2/views.py
deleted file mode 100644
index 6e19c7bb..00000000
--- a/bda2/views.py
+++ /dev/null
@@ -1,214 +0,0 @@
-# coding: utf-8
-
-from django.contrib.auth.models import User
-from django.shortcuts import render, get_object_or_404
-from django.contrib.auth.decorators import login_required
-from django.db import models
-from django.http import Http404
-from django.core import serializers
-import hashlib
-
-from django.core.mail import send_mail
-
-from datetime import datetime
-import time
-
-from gestioncof.decorators import cof_required, buro_required
-from bda2.models import Spectacle, Participant, ChoixSpectacle, Attribution
-from bda2.algorithm import Algorithm
-from bda2.forms import BaseBdaFormSet, TokenForm, ResellForm
-
-@cof_required
-def etat_places(request):
- spectacles1 = ChoixSpectacle.objects.all().values('spectacle','spectacle__title').annotate(total = models.Count('spectacle'))
- spectacles2 = ChoixSpectacle.objects.filter(double = True).all().values('spectacle','spectacle__title').annotate(total = models.Count('spectacle'))
- spectacles = Spectacle.objects.all()
- spectacles_dict = {}
- total = 0
- for spectacle in spectacles:
- spectacle.total = 0
- spectacle.ratio = 0.0
- spectacles_dict[spectacle.id] = spectacle
- for spectacle in spectacles1:
- spectacles_dict[spectacle["spectacle"]].total += spectacle["total"]
- spectacles_dict[spectacle["spectacle"]].ratio = spectacles_dict[spectacle["spectacle"]].total/float(spectacles_dict[spectacle["spectacle"]].slots)
- total += spectacle["total"]
- for spectacle in spectacles2:
- spectacles_dict[spectacle["spectacle"]].total += spectacle["total"]
- spectacles_dict[spectacle["spectacle"]].ratio = spectacles_dict[spectacle["spectacle"]].total/float(spectacles_dict[spectacle["spectacle"]].slots)
- total += spectacle["total"]
- return render(request, "etat-places.html", {"spectacles": spectacles, "total": total})
-
-def _hash_queryset(queryset):
- data = serializers.serialize("json", queryset)
- hasher = hashlib.sha256()
- hasher.update(data)
- return hasher.hexdigest()
-
-@cof_required
-def places(request):
- participant, created = Participant.objects.get_or_create(user = request.user)
- places = participant.attribution_set.order_by("spectacle__date", "spectacle").all()
- total = sum([place.spectacle.price for place in places])
- filtered_places = []
- places_dict = {}
- spectacles = []
- dates = []
- warning = False
- for place in places:
- if place.spectacle in spectacles:
- places_dict[place.spectacle].double = True
- else:
- place.double = False
- places_dict[place.spectacle] = place
- spectacles.append(place.spectacle)
- filtered_places.append(place)
- date = place.spectacle.date.date()
- if date in dates:
- warning = True
- else:
- dates.append(date)
- return render(request, "resume_places.html",
- {"participant": participant,
- "places": filtered_places,
- "total": total,
- "warning": warning})
-
-@cof_required
-def inscription(request):
- if datetime.now() > datetime(2016, 1, 17, 12, 00):
- participant, created = Participant.objects.get_or_create(user = request.user)
- 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 le 17 janvier !", "choices": choices})
- BdaFormSet = inlineformset_factory(Participant, ChoixSpectacle, fields = ("spectacle","double","autoquit","priority",), formset = BaseBdaFormSet)
- participant, created = Participant.objects.get_or_create(user = request.user)
- success = False
- stateerror = False
- if request.method == "POST":
- dbstate = _hash_queryset(participant.choixspectacle_set.all())
- if "dbstate" in request.POST and dbstate != request.POST["dbstate"]:
- stateerror = True
- formset = BdaFormSet(instance = participant)
- else:
- formset = BdaFormSet(request.POST, instance = participant)
- if formset.is_valid():
- #ChoixSpectacle.objects.filter(participant = participant).delete()
- formset.save()
- success = True
- formset = BdaFormSet(instance = participant)
- else:
- formset = BdaFormSet(instance = participant)
- dbstate = _hash_queryset(participant.choixspectacle_set.all())
- total_price = 0
- for choice in participant.choixspectacle_set.all():
- total_price += choice.spectacle.price
- if choice.double: total_price += choice.spectacle.price
- return render(request, "inscription-bda2.html", {"formset": formset, "success": success, "total_price": total_price, "dbstate": dbstate, "stateerror": stateerror})
-
-def do_tirage(request):
- form = TokenForm(request.POST)
- if not form.is_valid():
- return tirage(request)
- start = time.time()
- data = {}
- shows = Spectacle.objects.select_related().all()
- members = Participant.objects.all()
- choices = ChoixSpectacle.objects.order_by('participant', 'priority').select_related().all()
- algo = Algorithm(shows, members, choices)
- results = algo(form.cleaned_data["token"])
- total_slots = 0
- total_losers = 0
- for (_, members, losers) in results:
- total_slots += len(members)
- total_losers += len(losers)
- data["total_slots"] = total_slots
- data["total_losers"] = total_losers
- data["shows"] = shows
- data["token"] = form.cleaned_data["token"]
- data["members"] = members
- data["results"] = results
- total_sold = 0
- total_deficit = 0
- opera_deficit = 0
- for (show, members, _) in results:
- deficit = (show.slots - len(members)) * show.price
- total_sold += show.slots * show.price
- if deficit >= 0:
- if u"Opéra" in show.location.name:
- opera_deficit += deficit
- total_deficit += deficit
- data["total_sold"] = total_sold - total_deficit
- data["total_deficit"] = total_deficit
- data["opera_deficit"] = opera_deficit
- 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
- for (show, members, _) in results:
- for (member, _, _, _) in members:
- if member.id not in members_uniq:
- members_uniq[member.id] = member
- members2[member] = []
- member.total = 0
- member = members_uniq[member.id]
- members2[member].append(show)
- member.total += show.price
- members2 = members2.items()
- data["members2"] = sorted(members2, key = lambda m: m[0].user.last_name)
- if False and request.user.username in ["seguin", "harazi", "fromherz", "mpepin"]:
- Attribution.objects.all().delete()
- for (show, members, _) in results:
- for (member, _, _, _) in members:
- attrib = Attribution(spectacle = show, participant = member)
- attrib.save()
- return render(request, "bda-attrib-extra.html", data)
- else:
- return render(request, "bda-attrib.html", data)
-
-@login_required
-def tirage(request):
- if request.POST:
- form = TokenForm(request.POST)
- if form.is_valid():
- return do_tirage(request)
- else:
- 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"]
- places = "2 places" if count == "2" else "une place"
- mail = u"""Bonjour,
-
-Je souhaite revendre %s pour %s le %s (%s) à %.02f€.
-Contactez moi par email si vous êtes intéressés !
-
-%s (%s)""" % (places, spectacle.title, spectacle.date_no_seconds(), 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 = True)
- return render(request, "bda-success.html", {"show": spectacle, "places": places})
-
-@login_required
-def revente(request):
- participant, created = Participant.objects.get_or_create(user = request.user)
- if not participant.paid:
- return render(request, "bda-notpaid.html", {})
- if request.POST:
- form = ResellForm(participant, request.POST)
- if form.is_valid():
- return do_resell(request, form)
- else:
- form = ResellForm(participant)
- return render(request, "bda-revente.html", {"form": form})
-
-@buro_required
-def spectacle(request, spectacle_id):
- spectacle = get_object_or_404(Spectacle, id = spectacle_id)
- return render(request, "bda-emails.html", {"spectacle": spectacle})
-
-@buro_required
-def unpaid(request):
- return render(request, "bda-unpaid.html", {"unpaid": Participant.objects.filter(paid = False).all()})
diff --git a/bda3/__init__.py b/bda3/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/bda3/admin.py b/bda3/admin.py
deleted file mode 100644
index 26b0beed..00000000
--- a/bda3/admin.py
+++ /dev/null
@@ -1,180 +0,0 @@
-# coding: utf-8
-
-from django.core.mail import send_mail
-from django.contrib.contenttypes.models import ContentType
-
-from django.contrib import admin
-from django.db.models import Sum, Count
-from bda3.models import Spectacle, Salle, Participant, ChoixSpectacle, Attribution
-
-class ChoixSpectacleInline(admin.TabularInline):
- model = ChoixSpectacle
- sortable_field_name = "priority"
-
-class AttributionInline(admin.TabularInline):
- model = Attribution
-
-class ParticipantAdmin(admin.ModelAdmin):
- #inlines = [ChoixSpectacleInline]
- inlines = [AttributionInline]
- def get_queryset(self, request):
- 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 €"
- total.admin_order_field = "total"
- total.short_description = "Total à payer"
- list_display = ("user", "nb_places", "total", "paid", "paymenttype")
- list_filter = ("paid",)
- search_fields = ('user__username', 'user__first_name', 'user__last_name')
- actions = ['send_attribs',]
- actions_on_bottom = True
- list_per_page = 400
-
- def send_choices(self, request, queryset):
- for member in queryset.all():
- choices = member.choixspectacle_set.order_by('priority').all()
- if len(choices) == 0:
- continue
- mail = u"""Cher(e) %s,
-Voici tes choix de spectacles tels que notre système les a enregistrés :\n\n""" % member.user.get_full_name()
- next_rank = 1
- member_shows = {}
- for choice in choices:
- if choice.spectacle in member_shows: continue
- else: member_shows[choice.spectacle] = True
- extra = ""
- if choice.double:
- extra += u" ; deux places"
- if choice.autoquit:
- extra += u" ; désistement automatique"
- mail += u"- Choix %d : %s%s\n" % (next_rank, choice.spectacle, extra)
- next_rank += 1
- mail += u"""\nSi cette liste est incorrecte, merci de nous contacter au plus vite (avant samedi 6 octobre 18h).
-
-Artistiquement,
-Le BdA"""
- send_mail ("Choix de spectacles (BdA du COF)", mail,
- "bda@ens.fr", [member.user.email],
- fail_silently = True)
- count = len(queryset.all())
- if count == 1:
- message_bit = u"1 membre a"
- plural = ""
- 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))
- send_choices.short_description = u"Envoyer les choix par mail"
-
- def send_attribs(self, request, queryset):
- for member in queryset.all():
- attribs = member.attributions.all()
- if len(attribs) == 0:
- mail = u"""Cher-e %s,
-
-Tu t'es inscrit-e pour le troisième tirage au sort du BdA. Nous avons le regret
-de t'annoncer que tu n'as pas obtenu de place.
-
-Nous sommes bien conscients que le nombre de places mises en jeu était
-très restreint, mais les premier et deuxième tirages au sort comprenaient
-déjà un nombre exceptionnel de places, et nous dépendons des limites
-fixées par les théâtres partenaires pour l'obtention de places à tarif réduit.
-
-Le système de revente des places via les mails BdA-revente reste disponible,
-alors surveille tes mails.
-
-En vous souhaitant une bonne fin de journée,
---
-Le Bureau des Arts
-
-"""
- name = member.user.get_full_name()
- mail = mail % name
- else:
- mail = u"""Cher-e %s,
-
-Tu t'es inscrit-e pour le troisième tirage au sort du BdA. Tu as été
-sélectionné-e pour les spectacles suivants :
-
-%s
-
-Nous sommes bien conscients que le nombre de places mises en jeu était
-très restreint, mais les premier et deuxième tirages au sort comprenaient
-déjà un nombre exceptionnel de places, et nous dépendons des limites fixées
-par les théâtres partenaires pour l'obtention de places à tarif réduit.
-
-*Paiement*
-L'intégralité de ces places de spectacles est à régler à partir du lundi
-11 avril et AVANT le 16 avril, au bureau du COF pendant les
-heures de permanences (du lundi au vendredi entre 12h et 14h, et entre 18h
-et 20h). Si vous n'êtes pas disponible cette semaine, prévenez-nous par mail.
-Attention : au-delà de cette date, les places pourront être remises en jeu.
-
-*Mode de retrait des places*
-Au moment du paiement, les places pour les spectacles de la Comédie-Française
-et pour la Philarmonie vous seront remises.
-
-Nous vous rappelons que l'obtention de places du BdA vous engage à
-respecter les règles de fonctionnement :
-http://www.cof.ens.fr/bda/?page_id=1370
-
-Le système de revente des places via les mails BdA-revente reste disponible,
-directement sur votre compte GestioCOF.
-
-En vous souhaitant de très beaux spectacles,
---
-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
- mail = mail % (name, attribs_text)
-
- send_mail ("[BdA] 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"
- plural = ""
- 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))
- send_attribs.short_description = u"Envoyer les résultats par mail"
-
-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')
-
-import autocomplete_light
-class ChoixSpectacleAdmin(admin.ModelAdmin):
- form = autocomplete_light.modelform_factory(ChoixSpectacle, exclude=[])
- list_display = ("participant", "spectacle", "priority", "double", "autoquit")
- list_filter = ("double", "autoquit")
- search_fields = ('participant__user__username', 'participant__user__first_name', 'participant__user__last_name')
-
-class SpectacleAdmin(admin.ModelAdmin):
- model = Spectacle
- list_display = ("title", "date", "location", "slots", "price")
- list_filter = ("location",)
- search_fields = ("title", "location__name")
-
-admin.site.register(Spectacle, SpectacleAdmin)
-admin.site.register(Salle)
-admin.site.register(Participant, ParticipantAdmin)
-admin.site.register(Attribution, AttributionAdmin)
-admin.site.register(ChoixSpectacle, ChoixSpectacleAdmin)
diff --git a/bda3/algorithm.py b/bda3/algorithm.py
deleted file mode 100644
index 623f9756..00000000
--- a/bda3/algorithm.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# coding: utf-8
-
-from django.conf import settings
-from django.db.models import Max
-
-import random
-
-class Algorithm(object):
-
- shows = None
- ranks = None
- origranks = None
- double = None
-
- def __init__(self, shows, members, choices):
- """Initialisation :
- - on aggrège toutes les demandes pour chaque spectacle dans
- 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.shows = []
- showdict = {}
- for show in shows:
- show.nrequests = 0
- showdict[show] = show
- show.requests = []
- self.shows.append(show)
- self.ranks = {}
- self.origranks = {}
- self.choices = {}
- next_rank = {}
- member_shows = {}
- for member in members:
- self.ranks[member] = {}
- self.choices[member] = {}
- next_rank[member] = 1
- 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
- showdict[choice.spectacle].requests.append(member)
- showdict[choice.spectacle].nrequests += 2 if choice.double else 1
- self.ranks[member][choice.spectacle] = next_rank[member]
- next_rank[member] += 2 if choice.double else 1
- self.choices[member][choice.spectacle] = choice
- for member in members:
- self.origranks[member] = dict(self.ranks[member])
-
- def IncrementRanks(self, member, currank, increment = 1):
- for show in self.ranks[member]:
- if self.ranks[member][show] > currank:
- self.ranks[member][show] -= increment
-
- def appendResult(self, l, member, show):
- l.append((member,
- self.ranks[member][show],
- self.origranks[member][show],
- self.choices[member][show].double))
-
- """
- Pour les 2 Walkyries: c'est Sandefer
-
- Pour les 4 places pour l'Oratorio c'est Maxence Arutkin
- """
-
- def __call__(self, seed):
- random.seed(seed)
- results = []
- shows = sorted(self.shows, key = lambda x: float(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)
- groups[self.ranks[member][show]].append(member)
- # On passe à l'attribution
- winners = []
- losers = []
- for i in range(1, self.max_group + 1):
- group = list(groups[i])
- random.shuffle(group)
- for member in group:
- 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:
- 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
- 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))
- return results
diff --git a/bda3/autocomplete_light_registry.py b/bda3/autocomplete_light_registry.py
deleted file mode 100644
index 3254b3c8..00000000
--- a/bda3/autocomplete_light_registry.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import autocomplete_light
-
-from bda.models import Participant, Spectacle
-
-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_js_attributes={'placeholder': 'spectacle...'})
diff --git a/bda3/difftobda b/bda3/difftobda
deleted file mode 100644
index 70c81735..00000000
--- a/bda3/difftobda
+++ /dev/null
@@ -1,421 +0,0 @@
-Only in .: .admin.py.swp
-Binary files ../bda/__init__.pyc and ./__init__.pyc differ
-diff -p -u -r ../bda/admin.py ./admin.py
---- ../bda/admin.py 2013-12-17 10:19:56.000000000 +0100
-+++ ./admin.py 2012-12-08 22:31:46.000000000 +0100
-@@ -4,8 +4,8 @@ from django.core.mail import send_mail
- from django.contrib.contenttypes.models import ContentType
-
- from django.contrib import admin
--from django.db.models import Sum, Count
--from bda.models import Spectacle, Salle, Participant, ChoixSpectacle, Attribution
-+from django.db.models import Sum
-+from bda3.models import Spectacle, Salle, Participant, ChoixSpectacle, Attribution
-
- class ChoixSpectacleInline(admin.TabularInline):
- model = ChoixSpectacle
-@@ -17,18 +17,13 @@ class AttributionInline(admin.TabularInl
- class ParticipantAdmin(admin.ModelAdmin):
- #inlines = [ChoixSpectacleInline]
- inlines = [AttributionInline]
-- def queryset(self, request):
-- 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"
-+ return len(obj.attribution_set.all())
- nb_places.short_description = "Nombre de places"
- def total(self, obj):
-- tot = obj.total
-+ tot = obj.attributions.aggregate(total = Sum('price'))['total']
- 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")
- list_filter = ("paid",)
-@@ -61,7 +56,7 @@ Voici tes choix de spectacles tels que n
- Artistiquement,
- Le BdA"""
- send_mail ("Choix de spectacles (BdA du COF)", mail,
-- "bda@ens.fr", [member.user.email],
-+ "bda@clipper.ens.fr", [member.user.email],
- fail_silently = True)
- count = len(queryset.all())
- if count == 1:
-@@ -86,48 +81,41 @@ pour les spectacles suivants :
- %s
-
- *Paiement*
--L'intégralité de ces places de spectacles est à régler à partir du jeudi
--10 octobre et AVANT le mercredi 23 octobre, 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.
-+Ces spectacles sont à régler avant le lundi 17 décembre, pendant les
-+heures de permanences du COF (tous les jours de la semaine entre 12h et
-+14h, et entre 18h et 20h). Des facilités de paiement sont bien évidemment
-+possibles (encaissement échelonné des chèques).
-
- *Mode de retrait des places*
--Au moment du paiement, une enveloppe vous sera remise, contenant les
--places pour l'Opéra de Paris, pour les premiers spectacles de la Comédie
--française, certains spectacles du Châtelet et du Théâtre de la Ville.
--
--Pour les concerts Radio France, le Théâtre des Champs-Élysées, le théâtre
--du Rond-Point, le théâtre de la Colline, le théâtre de l'Athénée, l'IRCAM,
--la Cité de la musique et le 104, le Studio-Théâtre de la Comédie
--française, les places seront nominatives et à retirer au théâtre le soir
--de la représentation au moins une demi-heure avant le début du spectacle.
--
--Pour le théâtre de l'Odéon, la salle Richelieu le théâtre du Vieux
--colombier de la Comédie française, certains spectacles du théâtre de la
--Ville et du théâtre de Châtelet ainsi que pour le théâtre de Chaillot, les
--places seront distribuées environ une semaine avant la représentation (un
--mail vous en avertira).
--
--Nous vous rappelons que l'obtention de places du BdA vous engage à
--respecter les règles de fonctionnement :
--http://www.cof.ens.fr/bda/?page_id=1370
--Le système de revente des places via les mails BdA-revente sera très
--prochainement disponible, directement sur votre compte GestioCOF.
-+Pour l'Opéra de Paris, le théâtre de la Colline et le théâtre du Châtelet,
-+les places sont à retirer au COF le jour du paiement.
-+
-+Pour les concerts Radio France, le théâtre des Champs-Élysées, l'IRCAM
-+et le 104, les places seront nominatives et à retirer à la salle le soir de
-+la représentation au moins une demi-heure avant le début du spectacle.
-+
-+Pour le théâtre de l'Odéon, la Comédie Française, le théâtre de la Ville,
-+le théâtre de Chaillot, les places seront distribuées dans vos
-+casiers environ une semaine avant la représentation (un mail vous en
-+avertira).
-+
-+Dans tous les cas, n'hésitez pas à nous contacter si vous avez un doute !
-+
-+Nous profitons aussi de ce message pour vous annoncer qu'un festival de
-+courts métrages aura lieu le 21 décembre dans l'école.
-+Plus d'informations : http://www.cof.ens.fr/bda/courts.
-+
-+Culturellement vôtre,
-
--En vous souhaitant de très beaux spectacles tout au long de l'année,
- --
--Le Bureau des Arts
--(Chloé, Emilie, Jaime, Maxime, Olivier)
--"""
-+Le BdA"""
- attribs_text = ""
- name = member.user.get_full_name()
- for attrib in attribs:
- attribs_text += u"- 1 place pour %s\n" % attrib
- mail = mail % (name, attribs_text)
-- send_mail ("Résultats du tirage au sort", mail,
-- "bda@ens.fr", [member.user.email],
-+ send_mail ("Places de spectacle (BdA du COF)", mail,
-+ "bda@clipper.ens.fr", [member.user.email],
- fail_silently = True)
- count = len(queryset.all())
- if count == 1:
-@@ -154,13 +142,7 @@ class ChoixSpectacleAdmin(admin.ModelAdm
- list_filter = ("double", "autoquit")
- search_fields = ('participant__user__username', 'participant__user__first_name', 'participant__user__last_name')
-
--class SpectacleAdmin(admin.ModelAdmin):
-- model = Spectacle
-- list_display = ("title", "date", "location", "slots", "price")
-- list_filter = ("location",)
-- search_fields = ("title", "location__name")
--
--admin.site.register(Spectacle, SpectacleAdmin)
-+admin.site.register(Spectacle)
- admin.site.register(Salle)
- admin.site.register(Participant, ParticipantAdmin)
- admin.site.register(Attribution, AttributionAdmin)
-diff -p -u -r ../bda/algorithm.py ./algorithm.py
---- ../bda/algorithm.py 2013-10-07 14:08:44.000000000 +0200
-+++ ./algorithm.py 2012-10-31 23:01:48.000000000 +0100
-@@ -29,24 +29,25 @@ class Algorithm(object):
- self.ranks = {}
- self.origranks = {}
- self.choices = {}
-- next_rank = {}
-- member_shows = {}
- for member in members:
-- self.ranks[member] = {}
-- self.choices[member] = {}
-- next_rank[member] = 1
-- 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
-- showdict[choice.spectacle].requests.append(member)
-- showdict[choice.spectacle].nrequests += 2 if choice.double else 1
-- self.ranks[member][choice.spectacle] = next_rank[member]
-- next_rank[member] += 2 if choice.double else 1
-- self.choices[member][choice.spectacle] = choice
-- for member in members:
-- self.origranks[member] = dict(self.ranks[member])
-+ ranks = {}
-+ member_choices = {}
-+ member_shows = {}
-+ #next_priority = 1
-+ next_rank = 1
-+ for choice in member.choixspectacle_set.order_by('priority').all():
-+ if choice.spectacle in member_shows: continue
-+ else: member_shows[choice.spectacle] = True
-+ #assert choice.priority == next_priority
-+ #next_priority += 1
-+ showdict[choice.spectacle].requests.append(member)
-+ showdict[choice.spectacle].nrequests += 2 if choice.double else 1
-+ ranks[choice.spectacle] = next_rank
-+ next_rank += 2 if choice.double else 1
-+ member_choices[choice.spectacle] = choice
-+ self.ranks[member] = ranks
-+ self.choices[member] = member_choices
-+ self.origranks[member] = dict(ranks)
-
- def IncrementRanks(self, member, currank, increment = 1):
- for show in self.ranks[member]:
-Only in ../bda: algorithm.pyc
-Only in .: difftobda
-diff -p -u -r ../bda/models.py ./models.py
---- ../bda/models.py 2013-10-10 10:44:43.000000000 +0200
-+++ ./models.py 2012-10-31 23:12:56.000000000 +0100
-@@ -1,7 +1,5 @@
- # coding: utf-8
-
--import calendar
--
- from django.db import models
- from django.contrib.auth.models import User
- from django.utils.translation import ugettext_lazy as _
-@@ -19,7 +17,7 @@ class Spectacle (models.Model):
- date = models.DateTimeField ("Date & heure")
- location = models.ForeignKey(Salle)
- description = models.TextField ("Description", blank = True)
-- slots_description = models.TextField ("Description des places", blank = True)
-+ #slots_description = models.TextField ("Description des places", blank = True)
- price = models.FloatField("Prix d'une place", blank = True)
- slots = models.IntegerField ("Places")
- priority = models.IntegerField ("Priorité", default = 1000)
-@@ -31,14 +29,11 @@ class Spectacle (models.Model):
- def __repr__ (self):
- return u"[%s]" % self.__unicode__()
-
-- def timestamp(self):
-- return "%d" % calendar.timegm(self.date.utctimetuple())
--
- 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)
-+ return u"%s - %s @ %s, %.02f€" % (self.title, self.date_no_seconds(), self.location, self.price)
-
- PAYMENT_TYPES = (
- ("cash",u"Cash"),
-@@ -48,7 +43,7 @@ PAYMENT_TYPES = (
- )
-
- class Participant (models.Model):
-- user = models.ForeignKey(User, unique = True)
-+ user = models.ForeignKey(User, unique = True, related_name = "participants2")
- choices = models.ManyToManyField(Spectacle, through = "ChoixSpectacle", related_name = "chosen_by")
- attributions = models.ManyToManyField(Spectacle, through = "Attribution", related_name = "attributed_to")
- paid = models.BooleanField (u"A payé", default = False)
-Binary files ../bda/models.pyc and ./models.pyc differ
-diff -p -u -r ../bda/views.py ./views.py
---- ../bda/views.py 2014-01-04 21:37:15.000000000 +0100
-+++ ./views.py 2013-02-12 22:03:38.000000000 +0100
-@@ -1,23 +1,19 @@
- # coding: utf-8
-
--from django.contrib.auth.models import User
- from django.shortcuts import render, get_object_or_404
- from django.contrib.auth.decorators import login_required
- from django.db import models
- from django.http import Http404
- from django import forms
- from django.forms.models import inlineformset_factory, BaseInlineFormSet
--from django.core import serializers
--import hashlib
-
- from django.core.mail import send_mail
-
--from datetime import datetime
- import time
-
- from gestioncof.decorators import cof_required, buro_required
--from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution
--from bda.algorithm import Algorithm
-+from bda3.models import Spectacle, Participant, ChoixSpectacle, Attribution
-+from bda3.algorithm import Algorithm
-
- class BaseBdaFormSet(BaseInlineFormSet):
- def clean(self):
-@@ -37,7 +33,7 @@ class BaseBdaFormSet(BaseInlineFormSet):
- raise forms.ValidationError("Vous ne pouvez pas vous inscrire deux fois pour le même spectacle.")
- spectacles.append(spectacle)
-
--@cof_required
-+@buro_required
- def etat_places(request):
- spectacles1 = ChoixSpectacle.objects.all().values('spectacle','spectacle__title').annotate(total = models.Count('spectacle'))
- spectacles2 = ChoixSpectacle.objects.filter(double = True).all().values('spectacle','spectacle__title').annotate(total = models.Count('spectacle'))
-@@ -46,93 +42,47 @@ def etat_places(request):
- total = 0
- for spectacle in spectacles:
- spectacle.total = 0
-- spectacle.ratio = -1.0
- spectacles_dict[spectacle.id] = spectacle
- for spectacle in spectacles1:
- spectacles_dict[spectacle["spectacle"]].total += spectacle["total"]
-- spectacles_dict[spectacle["spectacle"]].ratio = spectacles_dict[spectacle["spectacle"]].total/float(spectacles_dict[spectacle["spectacle"]].slots)
- total += spectacle["total"]
- for spectacle in spectacles2:
- spectacles_dict[spectacle["spectacle"]].total += spectacle["total"]
-- spectacles_dict[spectacle["spectacle"]].ratio = spectacles_dict[spectacle["spectacle"]].total/float(spectacles_dict[spectacle["spectacle"]].slots)
- total += spectacle["total"]
- return render(request, "etat-places.html", {"spectacles": spectacles, "total": total})
-
--def _hash_queryset(queryset):
-- data = serializers.serialize("json", queryset)
-- hasher = hashlib.sha256()
-- hasher.update(data)
-- return hasher.hexdigest()
--
--@cof_required
--def places(request):
-- participant, created = Participant.objects.get_or_create(user = request.user)
-- places = participant.attribution_set.order_by("spectacle__date", "spectacle").all()
-- total = sum([place.spectacle.price for place in places])
-- filtered_places = []
-- places_dict = {}
-- spectacles = []
-- dates = []
-- warning = False
-- for place in places:
-- if place.spectacle in spectacles:
-- places_dict[place.spectacle].double = True
-- else:
-- place.double = False
-- places_dict[place.spectacle] = place
-- spectacles.append(place.spectacle)
-- filtered_places.append(place)
-- date = place.spectacle.date.date()
-- if date in dates:
-- warning = True
-- else:
-- dates.append(date)
-- return render(request, "resume_places.html",
-- {"participant": participant,
-- "places": filtered_places,
-- "total": total,
-- "warning": warning})
--
- @cof_required
- def inscription(request):
-- if datetime.now() > datetime(2013, 10, 6, 23, 59):
-- participant, created = Participant.objects.get_or_create(user = request.user)
-- 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 le 7 octobre !", "choices": choices})
-+ if time.time() > 1354921200:
-+ return render(request, "error.html", {"error_title": "C'est fini !", "error_description": u"Tirage au sort le 6 octobre dans la soirée "})
- BdaFormSet = inlineformset_factory(Participant, ChoixSpectacle, fields = ("spectacle","double","autoquit","priority",), formset = BaseBdaFormSet)
- participant, created = Participant.objects.get_or_create(user = request.user)
- success = False
-- stateerror = False
- if request.method == "POST":
-- dbstate = _hash_queryset(participant.choixspectacle_set.all())
-- if "dbstate" in request.POST and dbstate != request.POST["dbstate"]:
-- stateerror = True
-+ formset = BdaFormSet(request.POST, instance = participant)
-+ if formset.is_valid():
-+ #ChoixSpectacle.objects.filter(participant = participant).delete()
-+ formset.save()
-+ success = True
- formset = BdaFormSet(instance = participant)
-- else:
-- formset = BdaFormSet(request.POST, instance = participant)
-- if formset.is_valid():
-- #ChoixSpectacle.objects.filter(participant = participant).delete()
-- formset.save()
-- success = True
-- formset = BdaFormSet(instance = participant)
- else:
- formset = BdaFormSet(instance = participant)
-- dbstate = _hash_queryset(participant.choixspectacle_set.all())
- total_price = 0
- for choice in participant.choixspectacle_set.all():
- 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, "stateerror": stateerror})
-+ return render(request, "inscription-bda.html", {"formset": formset, "success": success, "total_price": total_price})
-+
-+Spectacle.deficit = lambda x: (x.slots-x.nrequests)*x.price
-
- def do_tirage(request):
- form = TokenForm(request.POST)
- if not form.is_valid():
- return tirage(request)
-- start = time.time()
- data = {}
-- shows = Spectacle.objects.select_related().all()
-+ shows = Spectacle.objects.all()
- members = Participant.objects.all()
-- choices = ChoixSpectacle.objects.order_by('participant', 'priority').select_related().all()
-+ choices = ChoixSpectacle.objects.all()
- algo = Algorithm(shows, members, choices)
- results = algo(form.cleaned_data["token"])
- total_slots = 0
-@@ -149,8 +99,8 @@ def do_tirage(request):
- total_sold = 0
- total_deficit = 0
- opera_deficit = 0
-- for (show, members, _) in results:
-- deficit = (show.slots - len(members)) * show.price
-+ for show in shows:
-+ deficit = show.deficit()
- total_sold += show.slots * show.price
- if deficit >= 0:
- if u"Opéra" in show.location.name:
-@@ -159,23 +109,18 @@ def do_tirage(request):
- data["total_sold"] = total_sold - total_deficit
- data["total_deficit"] = total_deficit
- data["opera_deficit"] = opera_deficit
-- 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
- for (show, members, _) in results:
- for (member, _, _, _) in members:
-- if member.id not in members_uniq:
-- members_uniq[member.id] = member
-+ if member not in members2:
- members2[member] = []
- member.total = 0
-- member = members_uniq[member.id]
- members2[member].append(show)
- member.total += show.price
- members2 = members2.items()
- data["members2"] = sorted(members2, key = lambda m: m[0].user.last_name)
-- if False and request.user.username in ["seguin", "harazi"]:
-+ if False and request.user.username == "seguin":
- Attribution.objects.all().delete()
- for (show, members, _) in results:
- for (member, _, _, _) in members:
-@@ -220,7 +165,7 @@ Je souhaite revendre %s pour %s le %s (%
- Contactez moi par email si vous êtes intéressés !
-
- %s (%s)""" % (places, spectacle.title, spectacle.date_no_seconds(), spectacle.location, spectacle.price, request.user.get_full_name(), request.user.email)
-- send_mail("%s" % spectacle, mail,
-+ send_mail("Revente de place: %s" % spectacle, mail,
- request.user.email, ["bda-revente@lists.ens.fr"],
- fail_silently = True)
- return render(request, "bda-success.html", {"show": spectacle, "places": places})
-Only in .: views.py~
diff --git a/bda3/forms.py b/bda3/forms.py
deleted file mode 100644
index 616c96b1..00000000
--- a/bda3/forms.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# coding: utf-8
-
-from django import forms
-from django.forms.models import inlineformset_factory, BaseInlineFormSet
-from bda3.models import Spectacle, Participant, ChoixSpectacle, Attribution
-
-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
- return
- spectacles = []
- for i in range(0, self.total_form_count()):
- form = self.forms[i]
- if not form.cleaned_data:
- continue
- 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.")
- 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"),))
- 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()
-
diff --git a/bda3/migrations/0001_initial.py b/bda3/migrations/0001_initial.py
deleted file mode 100644
index 7a7e061b..00000000
--- a/bda3/migrations/0001_initial.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-from django.conf import settings
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ]
-
- operations = [
- migrations.CreateModel(
- name='Attribution',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('given', models.BooleanField(default=False, verbose_name='Donn\xe9e')),
- ],
- ),
- migrations.CreateModel(
- name='ChoixSpectacle',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('priority', models.PositiveIntegerField(verbose_name=b'Priorit\xc3\xa9')),
- ('double', models.BooleanField(default=False, verbose_name=b'Deux places1 ')),
- ('autoquit', models.BooleanField(default=False, verbose_name=b'Abandon2 ')),
- ],
- options={
- 'ordering': ('priority',),
- 'verbose_name': 'voeu',
- 'verbose_name_plural': 'voeux',
- },
- ),
- migrations.CreateModel(
- name='Participant',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('paid', models.BooleanField(default=False, verbose_name='A pay\xe9')),
- ('paymenttype', models.CharField(blank=True, max_length=6, verbose_name='Moyen de paiement', choices=[(b'cash', 'Cash'), (b'cb', b'CB'), (b'cheque', 'Ch\xe8que'), (b'autre', 'Autre')])),
- ],
- ),
- migrations.CreateModel(
- name='Salle',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(max_length=300, verbose_name=b'Nom')),
- ('address', models.TextField(verbose_name=b'Adresse')),
- ],
- ),
- migrations.CreateModel(
- name='Spectacle',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('title', models.CharField(max_length=300, verbose_name=b'Titre')),
- ('date', models.DateTimeField(verbose_name=b'Date & heure')),
- ('description', models.TextField(verbose_name=b'Description', blank=True)),
- ('slots_description', models.TextField(verbose_name=b'Description des places', blank=True)),
- ('price', models.FloatField(verbose_name=b"Prix d'une place", blank=True)),
- ('slots', models.IntegerField(verbose_name=b'Places')),
- ('priority', models.IntegerField(default=1000, verbose_name=b'Priorit\xc3\xa9')),
- ('location', models.ForeignKey(to='bda3.Salle')),
- ],
- options={
- 'ordering': ('priority', 'date', 'title'),
- 'verbose_name': 'Spectacle',
- },
- ),
- migrations.AddField(
- model_name='participant',
- name='attributions',
- field=models.ManyToManyField(related_name='attributed_to', through='bda3.Attribution', to='bda3.Spectacle'),
- ),
- migrations.AddField(
- model_name='participant',
- name='choices',
- field=models.ManyToManyField(related_name='chosen_by', through='bda3.ChoixSpectacle', to='bda3.Spectacle'),
- ),
- migrations.AddField(
- model_name='participant',
- name='user',
- field=models.OneToOneField(related_name='participants3', to=settings.AUTH_USER_MODEL),
- ),
- migrations.AddField(
- model_name='choixspectacle',
- name='participant',
- field=models.ForeignKey(to='bda3.Participant'),
- ),
- migrations.AddField(
- model_name='choixspectacle',
- name='spectacle',
- field=models.ForeignKey(related_name='participants', to='bda3.Spectacle'),
- ),
- migrations.AddField(
- model_name='attribution',
- name='participant',
- field=models.ForeignKey(to='bda3.Participant'),
- ),
- migrations.AddField(
- model_name='attribution',
- name='spectacle',
- field=models.ForeignKey(related_name='attribues', to='bda3.Spectacle'),
- ),
- migrations.AlterUniqueTogether(
- name='choixspectacle',
- unique_together=set([('participant', 'spectacle')]),
- ),
- ]
diff --git a/bda3/migrations/__init__.py b/bda3/migrations/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/bda3/models.py b/bda3/models.py
deleted file mode 100644
index 6ada1be3..00000000
--- a/bda3/models.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# coding: utf-8
-
-import calendar
-
-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
-
-class Salle (models.Model):
- name = models.CharField ("Nom", max_length = 300)
- address = models.TextField ("Adresse")
-
- def __unicode__ (self):
- return self.name
-
-class Spectacle (models.Model):
- title = models.CharField ("Titre", max_length = 300)
- date = models.DateTimeField ("Date & heure")
- location = models.ForeignKey(Salle)
- description = models.TextField ("Description", blank = True)
- slots_description = models.TextField ("Description des places", blank = True)
- price = models.FloatField("Prix d'une place", blank = True)
- slots = models.IntegerField ("Places")
- priority = models.IntegerField ("Priorité", default = 1000)
-
- class Meta:
- verbose_name = "Spectacle"
- ordering = ("priority", "date","title",)
-
- def __repr__ (self):
- return u"[%s]" % self.__unicode__()
-
- def timestamp(self):
- return "%d" % calendar.timegm(self.date.utctimetuple())
-
- 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)
-
-PAYMENT_TYPES = (
-("cash",u"Cash"),
-("cb","CB"),
-("cheque",u"Chèque"),
-("autre",u"Autre"),
-)
-
-class Participant (models.Model):
- user = models.OneToOneField(User, related_name = "participants3")
- choices = models.ManyToManyField(Spectacle, through = "ChoixSpectacle", related_name = "chosen_by")
- 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", max_length = 6, choices = PAYMENT_TYPES, blank = True)
-
- def __unicode__ (self):
- return u"%s" % (self.user)
-
-class ChoixSpectacle (models.Model):
- participant = models.ForeignKey(Participant)
- spectacle = models.ForeignKey(Spectacle, related_name = "participants")
- priority = models.PositiveIntegerField("Priorité")
- double = models.BooleanField("Deux places1 ",default=False)
- autoquit = models.BooleanField("Abandon2 ",default=False)
- class Meta:
- ordering = ("priority",)
- unique_together = (("participant", "spectacle",),)
- 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):
- return u"%s -- %s" % (self.participant, self.spectacle)
diff --git a/bda3/static/css/bda.css b/bda3/static/css/bda.css
deleted file mode 100644
index 8851eeee..00000000
--- a/bda3/static/css/bda.css
+++ /dev/null
@@ -1,10 +0,0 @@
-form#tokenform {text-align: center; font-size: 2em;}
-label {margin-right: 10px; vertical-align: top;}
-form#tokenform textarea {font-size: 2em; width: 350px; height: 200px; font-family: 'Droif Serif', serif;}
-input {width: 400px; font-size: 2em;}
-ul.losers {display: inline; margin: 0; padding: 0;}
-ul.losers li {display: inline;}
-span.details {font-size: 0.7em;}
-table {border: 1px solid black; border-collapse: collapse;}
-td {border: 1px solid black; padding: 2px;}
-.attribresult {margin: 10px 0px;}
diff --git a/bda3/templates/spectacle_list.html b/bda3/templates/spectacle_list.html
deleted file mode 100644
index a4a67998..00000000
--- a/bda3/templates/spectacle_list.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% extends "base_title.html" %}
-
-{% block realcontent %}
- Spectacles
-
-{% endblock %}
diff --git a/bda3/tests.py b/bda3/tests.py
deleted file mode 100644
index 501deb77..00000000
--- a/bda3/tests.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-This file demonstrates writing tests using the unittest module. These will pass
-when you run "manage.py test".
-
-Replace this with more appropriate tests for your application.
-"""
-
-from django.test import TestCase
-
-
-class SimpleTest(TestCase):
- def test_basic_addition(self):
- """
- Tests that 1 + 1 always equals 2.
- """
- self.assertEqual(1 + 1, 2)
diff --git a/bda3/views.py b/bda3/views.py
deleted file mode 100644
index 5c237b5d..00000000
--- a/bda3/views.py
+++ /dev/null
@@ -1,215 +0,0 @@
-
-# coding: utf-8
-
-from django.contrib.auth.models import User
-from django.shortcuts import render, get_object_or_404
-from django.contrib.auth.decorators import login_required
-from django.db import models
-from django.http import Http404
-from django.core import serializers
-import hashlib
-
-from django.core.mail import send_mail
-
-from datetime import datetime
-import time
-
-from gestioncof.decorators import cof_required, buro_required
-from bda3.models import Spectacle, Participant, ChoixSpectacle, Attribution
-from bda3.algorithm import Algorithm
-from bda3.forms import BaseBdaFormSet, TokenForm, ResellForm
-
-@cof_required
-def etat_places(request):
- spectacles1 = ChoixSpectacle.objects.all().values('spectacle','spectacle__title').annotate(total = models.Count('spectacle'))
- spectacles2 = ChoixSpectacle.objects.filter(double = True).all().values('spectacle','spectacle__title').annotate(total = models.Count('spectacle'))
- spectacles = Spectacle.objects.all()
- spectacles_dict = {}
- total = 0
- for spectacle in spectacles:
- spectacle.total = 0
- spectacle.ratio = -1.0
- spectacles_dict[spectacle.id] = spectacle
- for spectacle in spectacles1:
- spectacles_dict[spectacle["spectacle"]].total += spectacle["total"]
- spectacles_dict[spectacle["spectacle"]].ratio = spectacles_dict[spectacle["spectacle"]].total/float(spectacles_dict[spectacle["spectacle"]].slots)
- total += spectacle["total"]
- for spectacle in spectacles2:
- spectacles_dict[spectacle["spectacle"]].total += spectacle["total"]
- spectacles_dict[spectacle["spectacle"]].ratio = spectacles_dict[spectacle["spectacle"]].total/float(spectacles_dict[spectacle["spectacle"]].slots)
- total += spectacle["total"]
- return render(request, "etat-places.html", {"spectacles": spectacles, "total": total})
-
-def _hash_queryset(queryset):
- data = serializers.serialize("json", queryset)
- hasher = hashlib.sha256()
- hasher.update(data)
- return hasher.hexdigest()
-
-@cof_required
-def places(request):
- participant, created = Participant.objects.get_or_create(user = request.user)
- places = participant.attribution_set.order_by("spectacle__date", "spectacle").all()
- total = sum([place.spectacle.price for place in places])
- filtered_places = []
- places_dict = {}
- spectacles = []
- dates = []
- warning = False
- for place in places:
- if place.spectacle in spectacles:
- places_dict[place.spectacle].double = True
- else:
- place.double = False
- places_dict[place.spectacle] = place
- spectacles.append(place.spectacle)
- filtered_places.append(place)
- date = place.spectacle.date.date()
- if date in dates:
- warning = True
- else:
- dates.append(date)
- return render(request, "resume_places.html",
- {"participant": participant,
- "places": filtered_places,
- "total": total,
- "warning": warning})
-
-@cof_required
-def inscription(request):
- if datetime.now() > datetime(2016, 4, 10, 11, 59):
- participant, created = Participant.objects.get_or_create(user = request.user)
- 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 très bientôt !", "choices": choices})
- BdaFormSet = inlineformset_factory(Participant, ChoixSpectacle, fields = ("spectacle","double","autoquit","priority",), formset = BaseBdaFormSet)
- participant, created = Participant.objects.get_or_create(user = request.user)
- success = False
- stateerror = False
- if request.method == "POST":
- dbstate = _hash_queryset(participant.choixspectacle_set.all())
- if "dbstate" in request.POST and dbstate != request.POST["dbstate"]:
- stateerror = True
- formset = BdaFormSet(instance = participant)
- else:
- formset = BdaFormSet(request.POST, instance = participant)
- if formset.is_valid():
- #ChoixSpectacle.objects.filter(participant = participant).delete()
- formset.save()
- success = True
- formset = BdaFormSet(instance = participant)
- else:
- formset = BdaFormSet(instance = participant)
- dbstate = _hash_queryset(participant.choixspectacle_set.all())
- total_price = 0
- for choice in participant.choixspectacle_set.all():
- total_price += choice.spectacle.price
- if choice.double: total_price += choice.spectacle.price
- return render(request, "inscription-bda3.html", {"formset": formset, "success": success, "total_price": total_price, "dbstate": dbstate, "stateerror": stateerror})
-
-def do_tirage(request):
- form = TokenForm(request.POST)
- if not form.is_valid():
- return tirage(request)
- start = time.time()
- data = {}
- shows = Spectacle.objects.select_related().all()
- members = Participant.objects.all()
- choices = ChoixSpectacle.objects.order_by('participant', 'priority').select_related().all()
- algo = Algorithm(shows, members, choices)
- results = algo(form.cleaned_data["token"])
- total_slots = 0
- total_losers = 0
- for (_, members, losers) in results:
- total_slots += len(members)
- total_losers += len(losers)
- data["total_slots"] = total_slots
- data["total_losers"] = total_losers
- data["shows"] = shows
- data["token"] = form.cleaned_data["token"]
- data["members"] = members
- data["results"] = results
- total_sold = 0
- total_deficit = 0
- opera_deficit = 0
- for (show, members, _) in results:
- deficit = (show.slots - len(members)) * show.price
- total_sold += show.slots * show.price
- if deficit >= 0:
- if u"Opéra" in show.location.name:
- opera_deficit += deficit
- total_deficit += deficit
- data["total_sold"] = total_sold - total_deficit
- data["total_deficit"] = total_deficit
- data["opera_deficit"] = opera_deficit
- 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
- for (show, members, _) in results:
- for (member, _, _, _) in members:
- if member.id not in members_uniq:
- members_uniq[member.id] = member
- members2[member] = []
- member.total = 0
- member = members_uniq[member.id]
- members2[member].append(show)
- member.total += show.price
- members2 = members2.items()
- data["members2"] = sorted(members2, key = lambda m: m[0].user.last_name)
- if False and request.user.username in ["seguin", "harazi", "fromherz", "mpepin"]:
- Attribution.objects.all().delete()
- for (show, members, _) in results:
- for (member, _, _, _) in members:
- attrib = Attribution(spectacle = show, participant = member)
- attrib.save()
- return render(request, "bda-attrib-extra.html", data)
- else:
- return render(request, "bda-attrib.html", data)
-
-@login_required
-def tirage(request):
- if request.POST:
- form = TokenForm(request.POST)
- if form.is_valid():
- return do_tirage(request)
- else:
- 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"]
- places = "2 places" if count == "2" else "une place"
- mail = u"""Bonjour,
-
-Je souhaite revendre %s pour %s le %s (%s) à %.02f€.
-Contactez moi par email si vous êtes intéressés !
-
-%s (%s)""" % (places, spectacle.title, spectacle.date_no_seconds(), 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 = True)
- return render(request, "bda-success.html", {"show": spectacle, "places": places})
-
-@login_required
-def revente(request):
- participant, created = Participant.objects.get_or_create(user = request.user)
- if not participant.paid:
- return render(request, "bda-notpaid.html", {})
- if request.POST:
- form = ResellForm(participant, request.POST)
- if form.is_valid():
- return do_resell(request, form)
- else:
- form = ResellForm(participant)
- return render(request, "bda-revente.html", {"form": form})
-
-@buro_required
-def spectacle(request, spectacle_id):
- spectacle = get_object_or_404(Spectacle, id = spectacle_id)
- return render(request, "bda-emails.html", {"spectacle": spectacle})
-
-@buro_required
-def unpaid(request):
- return render(request, "bda-unpaid.html", {"unpaid": Participant.objects.filter(paid = False).all()})
diff --git a/cof/settings_dev.py b/cof/settings_dev.py
index 3246b6e5..401127ef 100644
--- a/cof/settings_dev.py
+++ b/cof/settings_dev.py
@@ -41,8 +41,6 @@ INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.admindocs',
'bda',
- 'bda2',
- 'bda3',
'autocomplete_light',
'captcha',
'django_cas_ng',
diff --git a/cof/urls.py b/cof/urls.py
index 3e63ae02..e841ee02 100644
--- a/cof/urls.py
+++ b/cof/urls.py
@@ -6,11 +6,9 @@ autocomplete_light.autodiscover()
from django.contrib import admin
admin.autodiscover()
-from django.views.generic.list import ListView
from django.views.generic.base import TemplateView
from bda.models import Spectacle
-from bda2.models import Spectacle as Spectacle2
-from bda3.models import Spectacle as Spectacle3
+from bda.views import SpectacleListView
from gestioncof.petits_cours_views import DemandeListView
urlpatterns = patterns('',
@@ -42,32 +40,16 @@ urlpatterns = patterns('',
url(r'^petitcours/demandes/(?P\d+)$', 'gestioncof.petits_cours_views.details', name = 'petits-cours-demande-details'),
url(r'^petitcours/demandes/(?P\d+)/traitement$', 'gestioncof.petits_cours_views.traitement', name = 'petits-cours-demande-traitement'),
url(r'^petitcours/demandes/(?P\d+)/retraitement$', 'gestioncof.petits_cours_views.retraitement', name = 'petits-cours-demande-retraitement'),
- url(r'^bda/inscription$', 'bda.views.inscription', name = 'bda-tirage-inscription'),
- url(r'^bda2/inscription$', 'bda2.views.inscription', name = 'bda2-tirage-inscription'),
- url(r'^bda3/inscription$', 'bda3.views.inscription', name = 'bda3-tirage-inscription'),
- url(r'^bda/places$', 'bda.views.places', name = "bda-places-attribuees"),
- url(r'^bda/places/places_bda.ics$', 'bda.views.places_ics', name = "bda-places-attribuees-ics"),
- url(r'^bda2/places$', 'bda2.views.places', name = "bda2-places-attribuees"),
- url(r'^bda3/places$', 'bda3.views.places', name = "bda3-places-attribuees"),
- url(r'^bda/revente$', 'bda.views.revente', name = 'bda-revente'),
- url(r'^bda2/revente$', 'bda2.views.revente', name = 'bda2-revente'),
- url(r'^bda3/revente$', 'bda3.views.revente', name = 'bda3-revente'),
- url(r'^bda/etat-places$', 'bda.views.etat_places', name = 'bda-etat-places'),
- url(r'^bda2/etat-places$', 'bda2.views.etat_places', name = 'bda2-etat-places'),
- url(r'^bda3/etat-places$', 'bda3.views.etat_places', name = 'bda3-etat-places'),
- url(r'^bda/tirage$', 'bda.views.tirage'),
- url(r'^bda2/tirage$', 'bda2.views.tirage'),
- url(r'^bda3/tirage$', 'bda3.views.tirage'),
- url(r'^bda/spectacles/$', ListView.as_view(model = Spectacle), name ="bda-liste-spectacles"),
- url(r'^bda/spectacles/liste_spectacles.ics$', 'bda.views.liste_spectacles_ics', name ="bda-liste-spectacles-ics"),
- url(r'^bda/spectacles/unpaid$', "bda.views.unpaid", name = "bda-unpaid"),
- url(r'^bda/spectacles/(?P\d+)$', "bda.views.spectacle", name = "bda-spectacle"),
- url(r'^bda/spectacles-2/$', ListView.as_view(model = Spectacle2), name ="bda2-liste-spectacles"),
- url(r'^bda/spectacles-2/unpaid$', "bda2.views.unpaid", name = "bda2-unpaid"),
- url(r'^bda/spectacles-2/(?P\d+)$', "bda2.views.spectacle", name = "bda2-spectacle"),
- url(r'^bda/spectacles-3/$', ListView.as_view(model = Spectacle3), name ="bda3-liste-spectacles"),
- url(r'^bda/spectacles-3/unpaid$', "bda3.views.unpaid", name = "bda3-unpaid"),
- url(r'^bda/spectacles-3/(?P\d+)$', "bda3.views.spectacle", name = "bda3-spectacle"),
+ url(r'^bda/inscription/(?P\d+)$', 'bda.views.inscription', name = 'bda-tirage-inscription'),
+ url(r'^bda/places/(?P\d+)$', 'bda.views.places', name = "bda-places-attribuees"),
+ url(r'^bda/places/(?P\d+)/places_bda.ics$', 'bda.views.places_ics', name = "bda-places-attribuees-ics"),
+ url(r'^bda/revente/(?P\d+)$', 'bda.views.revente', name = 'bda-revente'),
+ url(r'^bda/etat-places/(?P\d+)$', 'bda.views.etat_places', name = 'bda-etat-places'),
+ url(r'^bda/tirage/(?P\d+)$', 'bda.views.tirage'),
+ url(r'^bda/spectacles/(?P\d+)$', SpectacleListView.as_view() , name ="bda-liste-spectacles"),
+ 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'^survey/(?P\d+)$', 'gestioncof.views.survey'),
url(r'^event/(?P\d+)$', 'gestioncof.views.event'),
url(r'^survey/(?P\d+)/status$', 'gestioncof.views.survey_status'),
diff --git a/gestioncof/templates/home.html b/gestioncof/templates/home.html
index c47a32e0..f0aecebc 100644
--- a/gestioncof/templates/home.html
+++ b/gestioncof/templates/home.html
@@ -21,62 +21,52 @@
{% endfor %}
{% endif %}
-
-
- {% if user.profile.is_cof %}
- BdA
-
- {% endif %}
-
+
+ {% if user.profile.is_cof %}
+ {% if open_tirages %}
+ Tirages du BdA
+ {% for tirage in open_tirages %}
+
+ {% endfor %}
+ {% endif %}
+ {% endif %}
+
Divers
{% if user.profile.is_buro %}
Administration
{% endif %}
- Pour tout problème : cof@ens.fr.
+ Pour tout problème : cof@ens.fr.
{% endblock %}
diff --git a/gestioncof/templates/utile_bda.html b/gestioncof/templates/utile_bda.html
index d2195fa7..5f4f383a 100644
--- a/gestioncof/templates/utile_bda.html
+++ b/gestioncof/templates/utile_bda.html
@@ -10,23 +10,14 @@
BdA diffusion
BdA revente
- Premier tirage
+ Tirages
+ {% for tirage in tirages %}
+ {{ tirage.title }}
- Deuxième tirage
-
- Troisième tirage
-
+ {% endfor %}
{% endblock %}
diff --git a/gestioncof/views.py b/gestioncof/views.py
index 9a2fdc18..71dab9a3 100644
--- a/gestioncof/views.py
+++ b/gestioncof/views.py
@@ -20,14 +20,17 @@ from gestioncof.forms import UserProfileForm, EventStatusFilterForm, \
SurveyForm, SurveyStatusFilterForm, RegistrationUserForm, \
RegistrationProfileForm, AdminEventForm, EventForm
+from bda.models import Tirage
+
import re
@login_required
def home(request):
- data = {"surveys": Survey.objects.filter(old = False).all(),
- "events": Event.objects.filter(old = False).all(),
- "open_surveys": Survey.objects.filter(survey_open = True, old = False).all(),
- "open_events": Event.objects.filter(registration_open = True, old = False).all()}
+ data = {"surveys": Survey.objects.filter(old=False).all(),
+ "events": Event.objects.filter(old=False).all(),
+ "open_surveys": Survey.objects.filter(survey_open=True, old=False).all(),
+ "open_events": Event.objects.filter(registration_open=True, old=False).all(),
+ "open_tirages": Tirage.objects.filter(active=True).all()}
return render(request, "home.html", data)
def login(request):
@@ -496,7 +499,8 @@ def utile_cof(request):
@buro_required
def utile_bda(request):
- return render(request, "utile_bda.html", {})
+ tirages = Tirage.objects.all()
+ return render(request, "utile_bda.html", {'tirages': tirages})
@buro_required
def liste_bdadiff(request):