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~