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/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 %} - - - - - - -{% for show in shows %} - - - - - - -{% endfor %} -{% endfor %} -
{{ member.user.get_full_name }}{{ member.user.email }}Total: {{ member.total }}€
{{ show }}
-{% 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 : - -Déçus : -{% if not losers %}/{% else %} - -{% 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

-
- {% csrf_token %} -{% if form.spectacle.errors %}{% endif %} -

- -Bonjour,
-
-Je souhaite revendre {{ form.count }} place(s) pour {{ form.spectacle }}.
-Contactez-moi par email si vous êtes intéressé !
-
-{{ user.get_full_name }} ({{ user.email }}) -
-

- -
-{% 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

-
- {% csrf_token %} - La graine : -
- {{ form.token }} -
- -
-{% 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

- - 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 %} -
- {% csrf_token %} - {% include "inscription-formset.html" %} - - - - Prix total actuel : {{ total_price }}€ -
-

- 1: demander deux places pour ce spectable
- 2: abandonner une place si impossible d'en obtenir une seconde pour ce spectacle (si vous avez coché l'option Deux places pour ce spectacle)
- 3: cette liste de vœu est ordonnée (du plus important au moins important), pour ajuster la priorité vous pouvez déplacer chaque vœu
-

-
-{% 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 }} - -{{ formset.management_form }} -{% for form in formset.forms %} - {% if forloop.first %} - - {% for field in form.visible_fields %} - {% if field.name != "DELETE" and field.name != "priority" %} - - {% endif %} - {% endfor %} - - - - {% endif %} - - {% for field in form.visible_fields %} - {% if field.name != "DELETE" and field.name != "priority" %} - - {% endif %} - {% endfor %} - - -{% endfor %} - -
{{ field.label|safe|capfirst }}3
- {% if forloop.first %} - {{ form.non_field_errors }} - {% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %} - {% endif %} - {{ field.errors.as_ul }} - {{ field }} -
- - - - -
-
-
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 93d54f62..00000000 --- a/bda2/views.py +++ /dev/null @@ -1,248 +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 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 bda2.models import Spectacle, Participant, ChoixSpectacle, Attribution -from bda2.algorithm import Algorithm - -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) - -@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) - -class TokenForm(forms.Form): - token = forms.CharField(widget = forms.widgets.Textarea()) - -@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}) - -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() - -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/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 620f1824..00000000 --- a/bda3/views.py +++ /dev/null @@ -1,249 +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 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 bda3.models import Spectacle, Participant, ChoixSpectacle, Attribution -from bda3.algorithm import Algorithm - -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) - -@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) - -class TokenForm(forms.Form): - token = forms.CharField(widget = forms.widgets.Textarea()) - -@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}) - -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() - -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()})