# coding: utf-8 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.mail import send_mail import time from gestioncof.decorators import cof_required, buro_required from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution from bda.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) @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')) spectacles = Spectacle.objects.all() spectacles_dict = {} total = 0 for spectacle in spectacles: spectacle.total = 0 spectacles_dict[spectacle.id] = spectacle for spectacle in spectacles1: spectacles_dict[spectacle["spectacle"]].total += spectacle["total"] total += spectacle["total"] for spectacle in spectacles2: spectacles_dict[spectacle["spectacle"]].total += spectacle["total"] total += spectacle["total"] return render(request, "etat-places.html", {"spectacles": spectacles, "total": total}) @cof_required def inscription(request): if time.time() > 1349474400: 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 if request.method == "POST": 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) 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}) 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) data = {} shows = Spectacle.objects.all() members = Participant.objects.all() choices = ChoixSpectacle.objects.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 in shows: deficit = show.deficit() 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 if request.user.is_authenticated(): members2 = {} for (show, members, _) in results: for (member, _, _, _) in members: if member not in members2: members2[member] = [] member.total = 0 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 == "seguin": 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("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}) @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()})