PEP8: fixed ' = ' → '=' on parameters

'unexpected spaces around keyword / parameter equals'
This commit is contained in:
Théophile Bastian 2016-07-09 20:19:37 +01:00
parent 7de11f2285
commit c7a3656ded
18 changed files with 496 additions and 379 deletions

View file

@ -19,23 +19,25 @@ class AttributionInline(admin.TabularInline):
class ParticipantAdmin(admin.ModelAdmin): class ParticipantAdmin(admin.ModelAdmin):
inlines = [AttributionInline] inlines = [AttributionInline]
def get_queryset(self, request): def get_queryset(self, request):
return Participant.objects.annotate(nb_places = Count('attributions'), return Participant.objects.annotate(nb_places=Count('attributions'),
total = Sum('attributions__price')) total=Sum('attributions__price'))
def nb_places(self, obj): def nb_places(self, obj):
return obj.nb_places return obj.nb_places
nb_places.admin_order_field = "nb_places" nb_places.admin_order_field = "nb_places"
nb_places.short_description = "Nombre de places" nb_places.short_description = "Nombre de places"
def total(self, obj): def total(self, obj):
tot = obj.total tot = obj.total
if tot: return u"%.02f" % tot if tot:
else: return u"0 €" return u"%.02f" % tot
else:
return u"0 €"
total.admin_order_field = "total" total.admin_order_field = "total"
total.short_description = "Total à payer" total.short_description = "Total à payer"
list_display = ("user", "nb_places", "total", "paid", "paymenttype", list_display = ("user", "nb_places", "total", "paid", "paymenttype",
"tirage") "tirage")
list_filter = ("paid", "tirage") list_filter = ("paid", "tirage")
search_fields = ('user__username', 'user__first_name', 'user__last_name') search_fields = ('user__username', 'user__first_name', 'user__last_name')
actions = ['send_attribs',] actions = ['send_attribs', ]
actions_on_bottom = True actions_on_bottom = True
list_per_page = 400 list_per_page = 400
readonly_fields = ("total",) readonly_fields = ("total",)
@ -97,7 +99,7 @@ Le Bureau des Arts
mail = mail % (name, attribs_text, deadline.strftime('%d %b %Y')) mail = mail % (name, attribs_text, deadline.strftime('%d %b %Y'))
send_mail ("Résultats du tirage au sort", mail, send_mail ("Résultats du tirage au sort", mail,
"bda@ens.fr", [member.user.email], "bda@ens.fr", [member.user.email],
fail_silently = True) fail_silently=True)
count = len(queryset.all()) count = len(queryset.all())
if count == 1: if count == 1:
message_bit = u"1 membre a" message_bit = u"1 membre a"
@ -110,7 +112,7 @@ Le Bureau des Arts
class AttributionAdminForm(forms.ModelForm): class AttributionAdminForm(forms.ModelForm):
def clean(self): def clean(self):
cleaned_data=super(AttributionAdminForm, self).clean() cleaned_data = super(AttributionAdminForm, self).clean()
participant = cleaned_data.get("participant") participant = cleaned_data.get("participant")
spectacle = cleaned_data.get("spectacle") spectacle = cleaned_data.get("spectacle")
if participant and spectacle: if participant and spectacle:

View file

@ -39,8 +39,10 @@ class Algorithm(object):
member_shows[member] = {} member_shows[member] = {}
for choice in choices: for choice in choices:
member = choice.participant member = choice.participant
if choice.spectacle in member_shows[member]: continue if choice.spectacle in member_shows[member]:
else: member_shows[member][choice.spectacle] = True continue
else:
member_shows[member][choice.spectacle] = True
showdict[choice.spectacle].requests.append(member) showdict[choice.spectacle].requests.append(member)
showdict[choice.spectacle].nrequests += 2 if choice.double else 1 showdict[choice.spectacle].nrequests += 2 if choice.double else 1
self.ranks[member][choice.spectacle] = next_rank[member] self.ranks[member][choice.spectacle] = next_rank[member]
@ -49,7 +51,7 @@ class Algorithm(object):
for member in members: for member in members:
self.origranks[member] = dict(self.ranks[member]) self.origranks[member] = dict(self.ranks[member])
def IncrementRanks(self, member, currank, increment = 1): def IncrementRanks(self, member, currank, increment=1):
for show in self.ranks[member]: for show in self.ranks[member]:
if self.ranks[member][show] > currank: if self.ranks[member][show] > currank:
self.ranks[member][show] -= increment self.ranks[member][show] -= increment
@ -63,7 +65,7 @@ class Algorithm(object):
def __call__(self, seed): def __call__(self, seed):
random.seed(seed) random.seed(seed)
results = [] results = []
shows = sorted(self.shows, key = lambda x: x.nrequests / x.slots, reverse = True) shows = sorted(self.shows, key=lambda x: x.nrequests / x.slots, reverse=True)
for show in shows: for show in shows:
# On regroupe tous les gens ayant le même rang # On regroupe tous les gens ayant le même rang
groups = dict([(i, []) for i in range(1, self.max_group + 1)]) groups = dict([(i, []) for i in range(1, self.max_group + 1)])
@ -78,7 +80,7 @@ class Algorithm(object):
group = list(groups[i]) group = list(groups[i])
random.shuffle(group) random.shuffle(group)
for member in group: for member in group:
if self.choices[member][show].double: # double if self.choices[member][show].double: # double
if len(winners) + 1 < show.slots: if len(winners) + 1 < show.slots:
self.appendResult(winners, member, show) self.appendResult(winners, member, show)
self.appendResult(winners, member, show) self.appendResult(winners, member, show)
@ -89,12 +91,11 @@ class Algorithm(object):
self.appendResult(losers, member, show) self.appendResult(losers, member, show)
self.appendResult(losers, member, show) self.appendResult(losers, member, show)
self.IncrementRanks(member, i, 2) self.IncrementRanks(member, i, 2)
else: # simple else: # simple
if len(winners) < show.slots: if len(winners) < show.slots:
self.appendResult(winners, member, show) self.appendResult(winners, member, show)
else: else:
self.appendResult(losers, member, show) self.appendResult(losers, member, show)
self.IncrementRanks(member, i) self.IncrementRanks(member, i)
results.append((show,winners,losers)) results.append((show, winners, losers))
return results return results

View file

@ -9,7 +9,8 @@ class BaseBdaFormSet(BaseInlineFormSet):
"""Checks that no two articles have the same title.""" """Checks that no two articles have the same title."""
super(BaseBdaFormSet, self).clean() super(BaseBdaFormSet, self).clean()
if any(self.errors): if any(self.errors):
# Don't bother validating the formset unless each form is valid on its own # Don't bother validating the formset unless each form is valid on
# its own
return return
spectacles = [] spectacles = []
for i in range(0, self.total_form_count()): for i in range(0, self.total_form_count()):
@ -32,10 +33,9 @@ class SpectacleModelChoiceField(forms.ModelChoiceField):
obj.location, obj.price) obj.location, obj.price)
class ResellForm(forms.Form): class ResellForm(forms.Form):
count = forms.ChoiceField(choices = (("1","1"),("2","2"),)) count = forms.ChoiceField(choices=(("1", "1"), ("2", "2"),))
spectacle = SpectacleModelChoiceField(queryset=Spectacle.objects.none()) spectacle = SpectacleModelChoiceField(queryset=Spectacle.objects.none())
def __init__(self, participant, *args, **kwargs): def __init__(self, participant, *args, **kwargs):
super(ResellForm, self).__init__(*args, **kwargs) super(ResellForm, self).__init__(*args, **kwargs)
self.fields['spectacle'].queryset = participant.attributions.all().distinct() self.fields['spectacle'].queryset = participant.attributions.all().distinct()

View file

@ -18,12 +18,12 @@ class Tirage(models.Model):
def __unicode__(self): def __unicode__(self):
return u"%s - %s" % (self.title, self.date_no_seconds()) return u"%s - %s" % (self.title, self.date_no_seconds())
class Salle(models.Model): class Salle(models.Model):
name = models.CharField("Nom", max_length = 300) name = models.CharField("Nom", max_length=300)
address = models.TextField("Adresse") address = models.TextField("Adresse")
def __unicode__ (self): def __unicode__(self):
return self.name return self.name
class Spectacle(models.Model): class Spectacle(models.Model):
@ -39,9 +39,9 @@ class Spectacle(models.Model):
class Meta: class Meta:
verbose_name = "Spectacle" verbose_name = "Spectacle"
ordering = ("priority", "date","title",) ordering = ("priority", "date", "title",)
def __repr__ (self): def __repr__(self):
return u"[%s]" % self.__unicode__() return u"[%s]" % self.__unicode__()
def timestamp(self): def timestamp(self):
@ -50,15 +50,15 @@ class Spectacle(models.Model):
def date_no_seconds(self): def date_no_seconds(self):
return self.date.strftime('%d %b %Y %H:%M') return self.date.strftime('%d %b %Y %H:%M')
def __unicode__ (self): def __unicode__(self):
return u"%s - %s, %s, %.02f" % (self.title, self.date_no_seconds(), return u"%s - %s, %s, %.02f" % (self.title, self.date_no_seconds(),
self.location, self.price) self.location, self.price)
PAYMENT_TYPES = ( PAYMENT_TYPES = (
("cash",u"Cash"), ("cash", u"Cash"),
("cb","CB"), ("cb", "CB"),
("cheque",u"Chèque"), ("cheque", u"Chèque"),
("autre",u"Autre"), ("autre", u"Autre"),
) )
class Participant(models.Model): class Participant(models.Model):
@ -69,12 +69,12 @@ class Participant(models.Model):
attributions = models.ManyToManyField(Spectacle, attributions = models.ManyToManyField(Spectacle,
through="Attribution", through="Attribution",
related_name="attributed_to") related_name="attributed_to")
paid = models.BooleanField (u"A payé", default=False) paid = models.BooleanField(u"A payé", default=False)
paymenttype = models.CharField(u"Moyen de paiement", paymenttype = models.CharField(u"Moyen de paiement",
max_length=6, choices=PAYMENT_TYPES, blank=True) max_length=6, choices=PAYMENT_TYPES, blank=True)
tirage = models.ForeignKey(Tirage) tirage = models.ForeignKey(Tirage)
def __unicode__ (self): def __unicode__(self):
return u"%s" % (self.user) return u"%s" % (self.user)
DOUBLE_CHOICES = ( DOUBLE_CHOICES = (
@ -109,6 +109,5 @@ class Attribution(models.Model):
spectacle = models.ForeignKey(Spectacle, related_name="attribues") spectacle = models.ForeignKey(Spectacle, related_name="attribues")
given = models.BooleanField(u"Donnée", default=False) given = models.BooleanField(u"Donnée", default=False)
def __unicode__ (self): def __unicode__(self):
return u"%s -- %s" % (self.participant, self.spectacle) return u"%s -- %s" % (self.participant, self.spectacle)

View file

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

View file

@ -10,7 +10,7 @@ from django.core import serializers
from django.forms.models import inlineformset_factory from django.forms.models import inlineformset_factory
import hashlib import hashlib
from django.core.mail import send_mail from django.core.mail import send_mail
from django.utils import timezone from django.utils import timezone
from django.views.generic.list import ListView from django.views.generic.list import ListView
@ -23,6 +23,7 @@ from bda.algorithm import Algorithm
from bda.forms import BaseBdaFormSet, TokenForm, ResellForm from bda.forms import BaseBdaFormSet, TokenForm, ResellForm
@cof_required @cof_required
def etat_places(request, tirage_id): def etat_places(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id) tirage = get_object_or_404(Tirage, id=tirage_id)
@ -30,13 +31,13 @@ def etat_places(request, tirage_id):
.filter(spectacle__tirage=tirage) \ .filter(spectacle__tirage=tirage) \
.filter(double_choice="1") \ .filter(double_choice="1") \
.all() \ .all() \
.values('spectacle','spectacle__title') \ .values('spectacle', 'spectacle__title') \
.annotate(total=models.Count('spectacle')) .annotate(total=models.Count('spectacle'))
spectacles2 = ChoixSpectacle.objects \ spectacles2 = ChoixSpectacle.objects \
.filter(spectacle__tirage=tirage) \ .filter(spectacle__tirage=tirage) \
.exclude(double_choice="1") \ .exclude(double_choice="1") \
.all() \ .all() \
.values('spectacle','spectacle__title') \ .values('spectacle', 'spectacle__title') \
.annotate(total=models.Count('spectacle')) .annotate(total=models.Count('spectacle'))
spectacles = tirage.spectacle_set.all() spectacles = tirage.spectacle_set.all()
spectacles_dict = {} spectacles_dict = {}
@ -50,22 +51,24 @@ def etat_places(request, tirage_id):
spectacles_dict[spectacle["spectacle"]].ratio = \ spectacles_dict[spectacle["spectacle"]].ratio = \
spectacles_dict[spectacle["spectacle"]].total / \ spectacles_dict[spectacle["spectacle"]].total / \
spectacles_dict[spectacle["spectacle"]].slots spectacles_dict[spectacle["spectacle"]].slots
total += spectacle["total"] total += spectacle["total"]
for spectacle in spectacles2: for spectacle in spectacles2:
spectacles_dict[spectacle["spectacle"]].total += 2*spectacle["total"] spectacles_dict[spectacle["spectacle"]].total += 2*spectacle["total"]
spectacles_dict[spectacle["spectacle"]].ratio = \ spectacles_dict[spectacle["spectacle"]].ratio = \
spectacles_dict[spectacle["spectacle"]].total / \ spectacles_dict[spectacle["spectacle"]].total / \
spectacles_dict[spectacle["spectacle"]].slots spectacles_dict[spectacle["spectacle"]].slots
total += spectacle["total"] total += spectacle["total"]
return render(request, "etat-places.html", return render(request, "etat-places.html",
{"spectacles": spectacles, "total": total, 'tirage': tirage}) {"spectacles": spectacles, "total": total, 'tirage': tirage})
def _hash_queryset(queryset): def _hash_queryset(queryset):
data = serializers.serialize("json", queryset) data = serializers.serialize("json", queryset)
hasher = hashlib.sha256() hasher = hashlib.sha256()
hasher.update(data) hasher.update(data)
return hasher.hexdigest() return hasher.hexdigest()
@cof_required @cof_required
def places(request, tirage_id): def places(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id) tirage = get_object_or_404(Tirage, id=tirage_id)
@ -99,7 +102,8 @@ def places(request, tirage_id):
"total": total, "total": total,
"warning": warning}) "warning": warning})
@cof_required
@cof_required
def places_ics(request, tirage_id): def places_ics(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id) tirage = get_object_or_404(Tirage, id=tirage_id)
participant, created = Participant.objects.get_or_create( participant, created = Participant.objects.get_or_create(
@ -114,7 +118,8 @@ def places_ics(request, tirage_id):
places_dict[place.spectacle].double = True places_dict[place.spectacle].double = True
else: else:
place.double = False place.double = False
place.spectacle.dtend = place.spectacle.date + timedelta(seconds=7200) place.spectacle.dtend = place.spectacle.date + \
timedelta(seconds=7200)
places_dict[place.spectacle] = place places_dict[place.spectacle] = place
spectacles.append(place.spectacle) spectacles.append(place.spectacle)
filtered_places.append(place) filtered_places.append(place)
@ -122,6 +127,7 @@ def places_ics(request, tirage_id):
{"participant": participant, {"participant": participant,
"places": filtered_places}, content_type="text/calendar") "places": filtered_places}, content_type="text/calendar")
@cof_required @cof_required
def inscription(request, tirage_id): def inscription(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id) tirage = get_object_or_404(Tirage, id=tirage_id)
@ -130,7 +136,7 @@ def inscription(request, tirage_id):
tirage.ouverture.strftime('%d %b %Y à %H:%M')) tirage.ouverture.strftime('%d %b %Y à %H:%M'))
return render(request, 'resume_inscription.html', return render(request, 'resume_inscription.html',
{ "error_title": "Le tirage n'est pas encore ouvert !", { "error_title": "Le tirage n'est pas encore ouvert !",
"error_description": error_desc }) "error_description": error_desc})
if timezone.now() > tirage.fermeture: if timezone.now() > tirage.fermeture:
participant, created = Participant.objects.get_or_create( participant, created = Participant.objects.get_or_create(
user=request.user, tirage=tirage) user=request.user, tirage=tirage)
@ -146,7 +152,7 @@ def inscription(request, tirage_id):
BdaFormSet = inlineformset_factory( BdaFormSet = inlineformset_factory(
Participant, Participant,
ChoixSpectacle, ChoixSpectacle,
fields=("spectacle","double_choice","priority"), fields=("spectacle", "double_choice", "priority"),
formset=BaseBdaFormSet, formset=BaseBdaFormSet,
formfield_callback=formfield_callback) formfield_callback=formfield_callback)
participant, created = Participant.objects.get_or_create( participant, created = Participant.objects.get_or_create(
@ -170,7 +176,8 @@ def inscription(request, tirage_id):
total_price = 0 total_price = 0
for choice in participant.choixspectacle_set.all(): for choice in participant.choixspectacle_set.all():
total_price += choice.spectacle.price total_price += choice.spectacle.price
if choice.double: total_price += choice.spectacle.price if choice.double:
total_price += choice.spectacle.price
return render(request, "inscription-bda.html", return render(request, "inscription-bda.html",
{ "formset": formset, { "formset": formset,
"success": success, "success": success,
@ -179,6 +186,7 @@ def inscription(request, tirage_id):
'tirage': tirage, 'tirage': tirage,
"stateerror": stateerror}) "stateerror": stateerror})
def do_tirage(request, tirage_id): def do_tirage(request, tirage_id):
tirage_elt = get_object_or_404(Tirage, id=tirage_id) tirage_elt = get_object_or_404(Tirage, id=tirage_id)
form = TokenForm(request.POST) form = TokenForm(request.POST)
@ -221,8 +229,9 @@ def do_tirage(request, tirage_id):
data["duration"] = time.time() - start data["duration"] = time.time() - start
if request.user.is_authenticated(): if request.user.is_authenticated():
members2 = {} members2 = {}
members_uniq = {} # Participant objects are not shared accross spectacle results, # Participant objects are not shared accross spectacle results,
# So assign a single object for each Participant id # so assign a single object for each Participant id
members_uniq = {}
for (show, members, _) in results: for (show, members, _) in results:
for (member, _, _, _) in members: for (member, _, _, _) in members:
if member.id not in members_uniq: if member.id not in members_uniq:
@ -249,6 +258,7 @@ def do_tirage(request, tirage_id):
else: else:
return render(request, "bda-attrib.html", data) return render(request, "bda-attrib.html", data)
@buro_required @buro_required
def tirage(request, tirage_id): def tirage(request, tirage_id):
if request.POST: if request.POST:
@ -259,6 +269,7 @@ def tirage(request, tirage_id):
form = TokenForm() form = TokenForm()
return render(request, "bda-token.html", {"form": form}) return render(request, "bda-token.html", {"form": form})
def do_resell(request, form): def do_resell(request, form):
spectacle = form.cleaned_data["spectacle"] spectacle = form.cleaned_data["spectacle"]
count = form.cleaned_data["count"] count = form.cleaned_data["count"]
@ -273,9 +284,10 @@ Contactez moi par email si vous êtes intéressé·e·s !
request.user.email) request.user.email)
send_mail("%s" % spectacle, mail, send_mail("%s" % spectacle, mail,
request.user.email, ["bda-revente@lists.ens.fr"], request.user.email, ["bda-revente@lists.ens.fr"],
fail_silently = False) fail_silently=False)
return render(request, "bda-success.html", {"show": spectacle, "places": places}) return render(request, "bda-success.html", {"show": spectacle, "places": places})
@login_required @login_required
def revente(request, tirage_id): def revente(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id) tirage = get_object_or_404(Tirage, id=tirage_id)
@ -291,6 +303,7 @@ def revente(request, tirage_id):
form = ResellForm(participant) form = ResellForm(participant)
return render(request, "bda-revente.html", {"form": form, 'tirage': tirage}) return render(request, "bda-revente.html", {"form": form, 'tirage': tirage})
@buro_required @buro_required
def spectacle(request, tirage_id, spectacle_id): def spectacle(request, tirage_id, spectacle_id):
tirage = get_object_or_404(Tirage, id=tirage_id) tirage = get_object_or_404(Tirage, id=tirage_id)
@ -299,37 +312,41 @@ def spectacle(request, tirage_id, spectacle_id):
participants = {} participants = {}
for attrib in attributions: for attrib in attributions:
participant = attrib.participant participant = attrib.participant
participant_info = {'lastname': participant.user.last_name, participant_info = {'lastname': participant.user.last_name,
'name': participant.user.get_full_name, 'name': participant.user.get_full_name,
'username': participant.user.username, 'username': participant.user.username,
'email': participant.user.email, 'email': participant.user.email,
'given': int(attrib.given), 'given': int(attrib.given),
'paid': participant.paid, 'paid': participant.paid,
'nb_places': 1} 'nb_places': 1}
if participant.id in participants: if participant.id in participants:
participants[participant.id]['nb_places'] += 1 participants[participant.id]['nb_places'] += 1
participants[participant.id]['given'] += attrib.given participants[participant.id]['given'] += attrib.given
else: else:
participants[participant.id] = participant_info participants[participant.id] = participant_info
participants_info = sorted(participants.values(), participants_info = sorted(participants.values(),
key=lambda part: part['lastname']) key=lambda part: part['lastname'])
return render(request, "bda-participants.html", return render(request, "bda-participants.html",
{"spectacle": spectacle, "participants": participants_info}) {"spectacle": spectacle, "participants": participants_info})
class SpectacleListView(ListView): class SpectacleListView(ListView):
model = Spectacle model = Spectacle
template_name = 'spectacle_list.html' template_name = 'spectacle_list.html'
def get_queryset(self): def get_queryset(self):
self.tirage = get_object_or_404(Tirage, id=self.kwargs['tirage_id']) self.tirage = get_object_or_404(Tirage, id=self.kwargs['tirage_id'])
categories = self.tirage.spectacle_set.all() categories = self.tirage.spectacle_set.all()
return categories return categories
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(SpectacleListView, self).get_context_data(**kwargs) context = super(SpectacleListView, self).get_context_data(**kwargs)
context['tirage_id'] = self.tirage.id context['tirage_id'] = self.tirage.id
context['tirage_name'] = self.tirage.title context['tirage_name'] = self.tirage.title
return context return context
@buro_required @buro_required
def unpaid(request, tirage_id): def unpaid(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id) tirage = get_object_or_404(Tirage, id=tirage_id)
@ -338,7 +355,8 @@ def unpaid(request, tirage_id):
.filter(paid=False, nb_attributions__gt=0).all() .filter(paid=False, nb_attributions__gt=0).all()
return render(request, "bda-unpaid.html", {"unpaid": unpaid}) return render(request, "bda-unpaid.html", {"unpaid": unpaid})
@buro_required
@buro_required
def liste_spectacles_ics(request, tirage_id): def liste_spectacles_ics(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id) tirage = get_object_or_404(Tirage, id=tirage_id)
spectacles = tirage.spectacle_set.order_by("date").all() spectacles = tirage.spectacle_set.order_by("date").all()
@ -347,4 +365,3 @@ def liste_spectacles_ics(request, tirage_id):
return render(request, "liste_spectacles.ics", return render(request, "liste_spectacles.ics",
{"spectacles": spectacles, "tirage": tirage}, {"spectacles": spectacles, "tirage": tirage},
content_type="text/calendar") content_type="text/calendar")

View file

@ -1,22 +1,23 @@
from django.conf.urls import patterns, include, url from django.conf.urls import patterns, include, url
import autocomplete_light import autocomplete_light
autocomplete_light.autodiscover()
from django.contrib import admin from django.contrib import admin
admin.autodiscover()
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from gestioncof.urls import export_patterns, petitcours_patterns, \ from gestioncof.urls import export_patterns, petitcours_patterns, \
surveys_patterns, events_patterns surveys_patterns, events_patterns
autocomplete_light.autodiscover()
admin.autodiscover()
urlpatterns = patterns('', urlpatterns = patterns('',
# Page d'accueil # Page d'accueil
url(r'^$', 'gestioncof.views.home', name = 'home'), url(r'^$', 'gestioncof.views.home', name='home'),
# Le BdA # Le BdA
url(r'^bda/', include('bda.urls')), url(r'^bda/', include('bda.urls')),
# Les exports # Les exports
url(r'^export/', include(export_patterns)), url(r'^export/', include(export_patterns)),
# Les petits cours # Les petits cours
url(r'^petitcours/', include(petitcours_patterns)), url(r'^petitcours/', include(petitcours_patterns)),
@ -24,7 +25,7 @@ urlpatterns = patterns('',
url(r'^survey/', include(surveys_patterns)), url(r'^survey/', include(surveys_patterns)),
# Evenements # Evenements
url(r'^event/', include(events_patterns)), url(r'^event/', include(events_patterns)),
# Authentification # Authentification
url(r'^cof/denied$', TemplateView.as_view(template_name='cof-denied.html'), url(r'^cof/denied$', TemplateView.as_view(template_name='cof-denied.html'),
name="cof-denied"), name="cof-denied"),
url(r'^cas/login$', 'django_cas_ng.views.login', name="cas_login_view"), url(r'^cas/login$', 'django_cas_ng.views.login', name="cas_login_view"),
@ -34,7 +35,7 @@ urlpatterns = patterns('',
{'next_page': 'home'}), {'next_page': 'home'}),
url(r'^login$', 'gestioncof.views.login'), url(r'^login$', 'gestioncof.views.login'),
url(r'^logout$', 'gestioncof.views.logout'), url(r'^logout$', 'gestioncof.views.logout'),
# Infos persos # Infos persos
url(r'^profile$', 'gestioncof.views.profile'), url(r'^profile$', 'gestioncof.views.profile'),
url(r'^outsider/password-change$', url(r'^outsider/password-change$',
'django.contrib.auth.views.password_change'), 'django.contrib.auth.views.password_change'),
@ -57,7 +58,7 @@ urlpatterns = patterns('',
url(r'^admin/doc/', include('django.contrib.admindocs.urls')), url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/(?P<app_label>[\d\w]+)/(?P<model_name>[\d\w]+)/csv/', url(r'^admin/(?P<app_label>[\d\w]+)/(?P<model_name>[\d\w]+)/csv/',
'gestioncof.csv_views.admin_list_export', 'gestioncof.csv_views.admin_list_export',
{'fields': ['username',]}), {'fields': ['username', ]}),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
url(r'^grappelli/', include('grappelli.urls')), url(r'^grappelli/', include('grappelli.urls')),
# Liens utiles du COF et du BdA # Liens utiles du COF et du BdA
@ -67,4 +68,3 @@ urlpatterns = patterns('',
url(r'^utile_cof/diff_cof$', 'gestioncof.views.liste_diffcof'), url(r'^utile_cof/diff_cof$', 'gestioncof.views.liste_diffcof'),
url(r'^utile_bda/bda_revente$', 'gestioncof.views.liste_bdarevente'), url(r'^utile_bda/bda_revente$', 'gestioncof.views.liste_bdarevente'),
) )

View file

@ -9,16 +9,18 @@ from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
def add_link_field(target_model='', field='', link_text=unicode, desc_text=unicode): def add_link_field(target_model='', field='', link_text=unicode, desc_text=unicode):
def add_link(cls): def add_link(cls):
reverse_name = target_model or cls.model.__name__.lower() reverse_name = target_model or cls.model.__name__.lower()
def link(self, instance): def link(self, instance):
app_name = instance._meta.app_label app_name = instance._meta.app_label
reverse_path = "admin:%s_%s_change" % (app_name, reverse_name) reverse_path = "admin:%s_%s_change" % (app_name, reverse_name)
link_obj = getattr(instance, field, None) or instance link_obj = getattr(instance, field, None) or instance
if not link_obj.id: if not link_obj.id:
return "" return ""
url = reverse(reverse_path, args = (link_obj.id,)) url = reverse(reverse_path, args=(link_obj.id,))
return mark_safe("<a href='%s'>%s</a>" % (url, link_text(link_obj))) return mark_safe("<a href='%s'>%s</a>" % (url, link_text(link_obj)))
link.allow_tags = True link.allow_tags = True
link.short_description = desc_text(reverse_name + ' link') link.short_description = desc_text(reverse_name + ' link')
@ -27,58 +29,69 @@ def add_link_field(target_model='', field='', link_text=unicode, desc_text=unico
return cls return cls
return add_link return add_link
class SurveyQuestionAnswerInline(admin.TabularInline): class SurveyQuestionAnswerInline(admin.TabularInline):
model = SurveyQuestionAnswer model = SurveyQuestionAnswer
@add_link_field(desc_text=lambda x: "Réponses", @add_link_field(desc_text=lambda x: "Réponses",
link_text=lambda x: "Éditer les réponses") link_text=lambda x: "Éditer les réponses")
class SurveyQuestionInline(admin.TabularInline): class SurveyQuestionInline(admin.TabularInline):
model = SurveyQuestion model = SurveyQuestion
class SurveyQuestionAdmin(admin.ModelAdmin): class SurveyQuestionAdmin(admin.ModelAdmin):
inlines = [ inlines = [
SurveyQuestionAnswerInline, SurveyQuestionAnswerInline,
] ]
class SurveyAdmin(admin.ModelAdmin): class SurveyAdmin(admin.ModelAdmin):
inlines = [ inlines = [
SurveyQuestionInline, SurveyQuestionInline,
] ]
class EventOptionChoiceInline(admin.TabularInline): class EventOptionChoiceInline(admin.TabularInline):
model = EventOptionChoice model = EventOptionChoice
@add_link_field(desc_text=lambda x: "Choix", @add_link_field(desc_text=lambda x: "Choix",
link_text=lambda x: "Éditer les choix") link_text=lambda x: "Éditer les choix")
class EventOptionInline(admin.TabularInline): class EventOptionInline(admin.TabularInline):
model = EventOption model = EventOption
class EventCommentFieldInline(admin.TabularInline): class EventCommentFieldInline(admin.TabularInline):
model = EventCommentField model = EventCommentField
class EventOptionAdmin(admin.ModelAdmin): class EventOptionAdmin(admin.ModelAdmin):
inlines = [ inlines = [
EventOptionChoiceInline, EventOptionChoiceInline,
] ]
class EventAdmin(admin.ModelAdmin): class EventAdmin(admin.ModelAdmin):
inlines = [ inlines = [
EventOptionInline, EventOptionInline,
EventCommentFieldInline, EventCommentFieldInline,
] ]
class CofProfileInline(admin.StackedInline): class CofProfileInline(admin.StackedInline):
model = CofProfile model = CofProfile
inline_classes = ("collapse open",) inline_classes = ("collapse open",)
class FkeyLookup(object): class FkeyLookup(object):
def __init__(self, fkeydecl, short_description=None, admin_order_field=None): def __init__(self, fkeydecl, short_description=None, admin_order_field=None):
self.fk, fkattrs = fkeydecl.split('__', 1) self.fk, fkattrs = fkeydecl.split('__', 1)
self.fkattrs = fkattrs.split('__') self.fkattrs = fkattrs.split('__')
self.short_description = short_description or self.fkattrs[-1] self.short_description = short_description or self.fkattrs[-1]
self.admin_order_field = admin_order_field or fkeydecl self.admin_order_field = admin_order_field or fkeydecl
def __get__(self, obj, klass): def __get__(self, obj, klass):
if obj is None: if obj is None:
return self # hack required to make Django validate (if obj is return self # hack required to make Django validate (if obj is
@ -89,6 +102,7 @@ class FkeyLookup(object):
item = getattr(item, attr) item = getattr(item, attr)
return item return item
def ProfileInfo(field, short_description, boolean=False): def ProfileInfo(field, short_description, boolean=False):
def getter(self): def getter(self):
try: try:
@ -108,6 +122,7 @@ User.profile_mailing_cof = ProfileInfo("mailing_cof", "ML COF", True)
User.profile_mailing_bda = ProfileInfo("mailing_bda", "ML BDA", True) User.profile_mailing_bda = ProfileInfo("mailing_bda", "ML BDA", True)
User.profile_mailing_bda_revente = ProfileInfo("mailing_bda_revente", "ML BDA-R", True) User.profile_mailing_bda_revente = ProfileInfo("mailing_bda_revente", "ML BDA-R", True)
class UserProfileAdmin(UserAdmin): class UserProfileAdmin(UserAdmin):
def is_buro(self, obj): def is_buro(self, obj):
try: try:
@ -137,12 +152,15 @@ class UserProfileAdmin(UserAdmin):
] ]
import autocomplete_light import autocomplete_light
def user_unicode(self): def user_unicode(self):
if self.first_name and self.last_name: if self.first_name and self.last_name:
return u"%s %s (%s)" % (self.first_name, self.last_name, self.username) return u"%s %s (%s)" % (self.first_name, self.last_name, self.username)
else: else:
return self.username return self.username
User.__unicode__ = user_unicode User.__unicode__ = user_unicode
class EventRegistrationAdmin(admin.ModelAdmin): class EventRegistrationAdmin(admin.ModelAdmin):
form = autocomplete_light.modelform_factory(EventRegistration, exclude=[]) form = autocomplete_light.modelform_factory(EventRegistration, exclude=[])
list_display = ('__unicode__','event','user','paid') list_display = ('__unicode__','event','user','paid')
@ -150,15 +168,18 @@ class EventRegistrationAdmin(admin.ModelAdmin):
search_fields = ('user__username', 'user__first_name', 'user__last_name', search_fields = ('user__username', 'user__first_name', 'user__last_name',
'user__email', 'event__title') 'user__email', 'event__title')
class PetitCoursAbilityAdmin(admin.ModelAdmin): class PetitCoursAbilityAdmin(admin.ModelAdmin):
list_display = ('user','matiere','niveau','agrege') list_display = ('user','matiere','niveau','agrege')
search_fields = ('user__username', 'user__first_name', 'user__last_name', search_fields = ('user__username', 'user__first_name', 'user__last_name',
'user__email', 'matiere__name', 'niveau') 'user__email', 'matiere__name', 'niveau')
list_filter = ('matiere','niveau','agrege') list_filter = ('matiere','niveau','agrege')
class PetitCoursAttributionAdmin(admin.ModelAdmin): class PetitCoursAttributionAdmin(admin.ModelAdmin):
list_display = ('user','demande','matiere','rank',) list_display = ('user','demande','matiere','rank',)
class PetitCoursAttributionCounterAdmin(admin.ModelAdmin): class PetitCoursAttributionCounterAdmin(admin.ModelAdmin):
list_display = ('user','matiere','count',) list_display = ('user','matiere','count',)
list_filter = ('matiere',) list_filter = ('matiere',)
@ -166,11 +187,12 @@ class PetitCoursAttributionCounterAdmin(admin.ModelAdmin):
'user__email', 'matiere__name') 'user__email', 'matiere__name')
actions = ['reset',] actions = ['reset',]
actions_on_bottom = True actions_on_bottom = True
def reset(self, request, queryset): def reset(self, request, queryset):
queryset.update(count=0) queryset.update(count=0)
reset.short_description = u"Remise à zéro du compteur" reset.short_description = u"Remise à zéro du compteur"
class PetitCoursDemandeAdmin(admin.ModelAdmin): class PetitCoursDemandeAdmin(admin.ModelAdmin):
list_display = ('name','email','agrege_requis','niveau','created', list_display = ('name','email','agrege_requis','niveau','created',
'traitee','processed') 'traitee','processed')

View file

@ -5,6 +5,7 @@ from django.db.models import Q
from django.contrib.auth.models import User from django.contrib.auth.models import User
from gestioncof.models import CofProfile, Clipper from gestioncof.models import CofProfile, Clipper
def autocomplete(request): def autocomplete(request):
if "q" not in request.GET: if "q" not in request.GET:
raise Http404 raise Http404
@ -22,25 +23,25 @@ def autocomplete(request):
for bit in bits: for bit in bits:
queries['members'] = queries['members'].filter( queries['members'] = queries['members'].filter(
Q(user__first_name__icontains=bit) Q(user__first_name__icontains=bit)
|Q(user__last_name__icontains=bit) | Q(user__last_name__icontains=bit)
|Q(user__username__icontains=bit) | Q(user__username__icontains=bit)
|Q(login_clipper__icontains=bit)) | Q(login_clipper__icontains=bit))
queries['users'] = queries['users'].filter( queries['users'] = queries['users'].filter(
Q(first_name__icontains=bit) Q(first_name__icontains=bit)
|Q(last_name__icontains=bit) | Q(last_name__icontains=bit)
|Q(username__icontains=bit)) | Q(username__icontains=bit))
queries['clippers'] = queries['clippers'].filter( queries['clippers'] = queries['clippers'].filter(
Q(fullname__icontains=bit) Q(fullname__icontains=bit)
|Q(username__icontains=bit)) | Q(username__icontains=bit))
queries['members'] = queries['members'].distinct() queries['members'] = queries['members'].distinct()
queries['users'] = queries['users'].distinct() queries['users'] = queries['users'].distinct()
usernames = list(queries['members'].values_list('login_clipper', flat = 'True')) \ usernames = list(queries['members'].values_list('login_clipper', flat='True')) \
+ list(queries['users'].values_list('profile__login_clipper', flat = 'True')) + list(queries['users'].values_list('profile__login_clipper', flat='True'))
queries['clippers'] = queries['clippers'].exclude(username__in = usernames).distinct() queries['clippers'] = queries['clippers'].exclude(username__in=usernames).distinct()
# add clippers # add clippers
data.update(queries) data.update(queries)
options = 0 options = 0
for query in queries.values(): for query in queries.values():
options += len(query) options += len(query)

View file

@ -3,6 +3,7 @@ from django.http import HttpResponse, HttpResponseForbidden
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
from django.apps import apps from django.apps import apps
def export(qs, fields=None): def export(qs, fields=None):
model = qs.model model = qs.model
response = HttpResponse(content_type='text/csv') response = HttpResponse(content_type='text/csv')
@ -29,6 +30,7 @@ def export(qs, fields=None):
# Return CSV file to browser as download # Return CSV file to browser as download
return response return response
def admin_list_export(request, model_name, app_label, queryset=None, fields=None, list_display=True): def admin_list_export(request, model_name, app_label, queryset=None, fields=None, list_display=True):
""" """
Put the following line in your urls.py BEFORE your admin include Put the following line in your urls.py BEFORE your admin include
@ -39,7 +41,7 @@ def admin_list_export(request, model_name, app_label, queryset=None, fields=None
if not queryset: if not queryset:
model = apps.get_model(app_label, model_name) model = apps.get_model(app_label, model_name)
queryset = model.objects.all() queryset = model.objects.all()
queryset = queryset.filter(profile__is_cof = True) queryset = queryset.filter(profile__is_cof=True)
if not fields: if not fields:
if list_display and len(queryset.model._meta.admin.list_display) > 1: if list_display and len(queryset.model._meta.admin.list_display) > 1:
fields = queryset.model._meta.admin.list_display fields = queryset.model._meta.admin.list_display

View file

@ -1,5 +1,6 @@
from django_cas_ng.decorators import user_passes_test from django_cas_ng.decorators import user_passes_test
def is_cof(user): def is_cof(user):
try: try:
profile = user.profile profile = user.profile
@ -8,7 +9,8 @@ def is_cof(user):
return False return False
cof_required = user_passes_test(lambda u: is_cof(u)) cof_required = user_passes_test(lambda u: is_cof(u))
cof_required_customdenied = user_passes_test(lambda u: is_cof(u), login_url = "cof-denied") cof_required_customdenied = user_passes_test(lambda u: is_cof(u), login_url="cof-denied")
def is_buro(user): def is_buro(user):
try: try:

View file

@ -10,6 +10,7 @@ from gestioncof.models import CofProfile, EventCommentValue
from gestioncof.widgets import TriStateCheckbox from gestioncof.widgets import TriStateCheckbox
from gestioncof.shared import lock_table, unlock_table from gestioncof.shared import lock_table, unlock_table
class EventForm(forms.Form): class EventForm(forms.Form):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
event = kwargs.pop("event") event = kwargs.pop("event")
@ -28,18 +29,18 @@ class EventForm(forms.Form):
choices = [(choice.id, choice.value) for choice in option.choices.all()] choices = [(choice.id, choice.value) for choice in option.choices.all()]
if option.multi_choices: if option.multi_choices:
initial = [] if option.id not in all_choices else all_choices[option.id] initial = [] if option.id not in all_choices else all_choices[option.id]
field = forms.MultipleChoiceField(label = option.name, field = forms.MultipleChoiceField(label=option.name,
choices = choices, choices=choices,
widget = CheckboxSelectMultiple, widget=CheckboxSelectMultiple,
required = False, required=False,
initial = initial) initial=initial)
else: else:
initial = None if option.id not in all_choices else all_choices[option.id][0] initial = None if option.id not in all_choices else all_choices[option.id][0]
field = forms.ChoiceField(label = option.name, field = forms.ChoiceField(label=option.name,
choices = choices, choices=choices,
widget = RadioSelect, widget=RadioSelect,
required = False, required=False,
initial = initial) initial=initial)
field.option_id = option.id field.option_id = option.id
self.fields["option_%d" % option.id] = field self.fields["option_%d" % option.id] = field
@ -48,6 +49,7 @@ class EventForm(forms.Form):
if name.startswith('option_'): if name.startswith('option_'):
yield (self.fields[name].option_id, value) yield (self.fields[name].option_id, value)
class SurveyForm(forms.Form): class SurveyForm(forms.Form):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
survey = kwargs.pop("survey") survey = kwargs.pop("survey")
@ -64,18 +66,18 @@ class SurveyForm(forms.Form):
choices = [(answer.id, answer.answer) for answer in question.answers.all()] choices = [(answer.id, answer.answer) for answer in question.answers.all()]
if question.multi_answers: if question.multi_answers:
initial = [] if question.id not in answers else answers[question.id] initial = [] if question.id not in answers else answers[question.id]
field = forms.MultipleChoiceField(label = question.question, field = forms.MultipleChoiceField(label=question.question,
choices = choices, choices=choices,
widget = CheckboxSelectMultiple, widget=CheckboxSelectMultiple,
required = False, required=False,
initial = initial) initial=initial)
else: else:
initial = None if question.id not in answers else answers[question.id][0] initial = None if question.id not in answers else answers[question.id][0]
field = forms.ChoiceField(label = question.question, field = forms.ChoiceField(label=question.question,
choices = choices, choices=choices,
widget = RadioSelect, widget=RadioSelect,
required = False, required=False,
initial = initial) initial=initial)
field.question_id = question.id field.question_id = question.id
self.fields["question_%d" % question.id] = field self.fields["question_%d" % question.id] = field
@ -83,7 +85,8 @@ class SurveyForm(forms.Form):
for name, value in self.cleaned_data.items(): for name, value in self.cleaned_data.items():
if name.startswith('question_'): if name.startswith('question_'):
yield (self.fields[name].question_id, value) yield (self.fields[name].question_id, value)
class SurveyStatusFilterForm(forms.Form): class SurveyStatusFilterForm(forms.Form):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
survey = kwargs.pop("survey") survey = kwargs.pop("survey")
@ -95,11 +98,11 @@ class SurveyStatusFilterForm(forms.Form):
initial = self.data.get(self.add_prefix(name), None) initial = self.data.get(self.add_prefix(name), None)
else: else:
initial = "none" initial = "none"
field = forms.ChoiceField(label = "%s : %s" % (question.question, answer.answer), field = forms.ChoiceField(label="%s : %s" % (question.question, answer.answer),
choices = [("yes", "yes"),("no","no"),("none","none")], choices=[("yes", "yes"), ("no", "no"), ("none", "none")],
widget = TriStateCheckbox, widget=TriStateCheckbox,
required = False, required=False,
initial = initial) initial=initial)
field.question_id = question.id field.question_id = question.id
field.answer_id = answer.id field.answer_id = answer.id
self.fields[name] = field self.fields[name] = field
@ -109,6 +112,7 @@ class SurveyStatusFilterForm(forms.Form):
if name.startswith('question_'): if name.startswith('question_'):
yield (self.fields[name].question_id, self.fields[name].answer_id, value) yield (self.fields[name].question_id, self.fields[name].answer_id, value)
class EventStatusFilterForm(forms.Form): class EventStatusFilterForm(forms.Form):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
event = kwargs.pop("event") event = kwargs.pop("event")
@ -120,11 +124,11 @@ class EventStatusFilterForm(forms.Form):
initial = self.data.get(self.add_prefix(name), None) initial = self.data.get(self.add_prefix(name), None)
else: else:
initial = "none" initial = "none"
field = forms.ChoiceField(label = "%s : %s" % (option.name, choice.value), field = forms.ChoiceField(label="%s : %s" % (option.name, choice.value),
choices = [("yes", "yes"),("no","no"),("none","none")], choices=[("yes", "yes"), ("no", "no"), ("none", "none")],
widget = TriStateCheckbox, widget=TriStateCheckbox,
required = False, required=False,
initial = initial) initial=initial)
field.option_id = option.id field.option_id = option.id
field.choice_id = choice.id field.choice_id = choice.id
self.fields[name] = field self.fields[name] = field
@ -134,11 +138,11 @@ class EventStatusFilterForm(forms.Form):
initial = self.data.get(self.add_prefix(name), None) initial = self.data.get(self.add_prefix(name), None)
else: else:
initial = "none" initial = "none"
field = forms.ChoiceField(label = "Événement payé", field = forms.ChoiceField(label="Événement payé",
choices = [("yes", "yes"),("no","no"),("none","none")], choices=[("yes", "yes"), ("no", "no"), ("none", "none")],
widget = TriStateCheckbox, widget=TriStateCheckbox,
required = False, required=False,
initial = initial) initial=initial)
self.fields[name] = field self.fields[name] = field
def filters(self): def filters(self):
@ -148,6 +152,7 @@ class EventStatusFilterForm(forms.Form):
elif name == "event_has_paid": elif name == "event_has_paid":
yield ("has_paid", None, value) yield ("has_paid", None, value)
class UserProfileForm(forms.ModelForm): class UserProfileForm(forms.ModelForm):
first_name = forms.CharField(label=_(u'Prénom'), max_length=30) first_name = forms.CharField(label=_(u'Prénom'), max_length=30)
last_name = forms.CharField(label=_(u'Nom'), max_length=30) last_name = forms.CharField(label=_(u'Nom'), max_length=30)
@ -174,7 +179,8 @@ class UserProfileForm(forms.ModelForm):
class Meta: class Meta:
model = CofProfile model = CofProfile
fields = ("phone", "mailing_cof", "mailing_bda", "mailing_bda_revente",) fields = ("phone", "mailing_cof", "mailing_bda", "mailing_bda_revente", )
class RegistrationUserForm(forms.ModelForm): class RegistrationUserForm(forms.ModelForm):
def __init__(self, *args, **kw): def __init__(self, *args, **kw):
@ -185,6 +191,7 @@ class RegistrationUserForm(forms.ModelForm):
model = User model = User
fields = ("username", "first_name", "last_name", "email") fields = ("username", "first_name", "last_name", "email")
class RegistrationProfileForm(forms.ModelForm): class RegistrationProfileForm(forms.ModelForm):
def __init__(self, *args, **kw): def __init__(self, *args, **kw):
super(RegistrationProfileForm, self).__init__(*args, **kw) super(RegistrationProfileForm, self).__init__(*args, **kw)
@ -226,12 +233,13 @@ class RegistrationProfileForm(forms.ModelForm):
model = CofProfile model = CofProfile
fields = ("login_clipper", "num", "phone", "occupation", "departement", "is_cof", "type_cotiz", "mailing_cof", "mailing_bda", "mailing_bda_revente", "comments") fields = ("login_clipper", "num", "phone", "occupation", "departement", "is_cof", "type_cotiz", "mailing_cof", "mailing_bda", "mailing_bda_revente", "comments")
STATUS_CHOICES = (('no','Non'), STATUS_CHOICES = (('no', 'Non'),
('wait','Oui mais attente paiement'), ('wait', 'Oui mais attente paiement'),
('paid','Oui payé'),) ('paid', 'Oui payé'),)
class AdminEventForm(forms.Form): class AdminEventForm(forms.Form):
status = forms.ChoiceField(label = "Inscription", choices = STATUS_CHOICES, widget = RadioSelect) status = forms.ChoiceField(label="Inscription", choices=STATUS_CHOICES, widget=RadioSelect)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
event = kwargs.pop("event") event = kwargs.pop("event")
@ -239,12 +247,12 @@ class AdminEventForm(forms.Form):
registration = kwargs.pop("current_registration", None) registration = kwargs.pop("current_registration", None)
current_choices = registration.options.all() if registration is not None else [] current_choices = registration.options.all() if registration is not None else []
paid = kwargs.pop("paid", None) paid = kwargs.pop("paid", None)
if paid == True: if paid is True:
kwargs["initial"] = {"status":"paid"} kwargs["initial"] = {"status": "paid"}
elif paid == False: elif paid is False:
kwargs["initial"] = {"status":"wait"} kwargs["initial"] = {"status": "wait"}
else: else:
kwargs["initial"] = {"status":"no"} kwargs["initial"] = {"status": "no"}
super(AdminEventForm, self).__init__(*args, **kwargs) super(AdminEventForm, self).__init__(*args, **kwargs)
choices = {} choices = {}
for choice in current_choices: for choice in current_choices:
@ -257,32 +265,32 @@ class AdminEventForm(forms.Form):
choices = [(choice.id, choice.value) for choice in option.choices.all()] choices = [(choice.id, choice.value) for choice in option.choices.all()]
if option.multi_choices: if option.multi_choices:
initial = [] if option.id not in all_choices else all_choices[option.id] initial = [] if option.id not in all_choices else all_choices[option.id]
field = forms.MultipleChoiceField(label = option.name, field = forms.MultipleChoiceField(label=option.name,
choices = choices, choices=choices,
widget = CheckboxSelectMultiple, widget=CheckboxSelectMultiple,
required = False, required=False,
initial = initial) initial=initial)
else: else:
initial = None if option.id not in all_choices else all_choices[option.id][0] initial = None if option.id not in all_choices else all_choices[option.id][0]
field = forms.ChoiceField(label = option.name, field = forms.ChoiceField(label=option.name,
choices = choices, choices=choices,
widget = RadioSelect, widget=RadioSelect,
required = False, required=False,
initial = initial) initial=initial)
field.option_id = option.id field.option_id = option.id
self.fields["option_%d" % option.id] = field self.fields["option_%d" % option.id] = field
for commentfield in event.commentfields.all(): for commentfield in event.commentfields.all():
initial = commentfield.default initial = commentfield.default
if registration is not None: if registration is not None:
try: try:
initial = registration.comments.get(commentfield = commentfield).content initial = registration.comments.get(commentfield=commentfield).content
except EventCommentValue.DoesNotExist: except EventCommentValue.DoesNotExist:
pass pass
widget = forms.Textarea if commentfield.fieldtype == "text" else forms.TextInput widget = forms.Textarea if commentfield.fieldtype == "text" else forms.TextInput
field = forms.CharField(label = commentfield.name, field = forms.CharField(label=commentfield.name,
widget = widget, widget=widget,
required = False, required=False,
initial = initial) initial=initial)
field.comment_id = commentfield.id field.comment_id = commentfield.id
self.fields["comment_%d" % commentfield.id] = field self.fields["comment_%d" % commentfield.id] = field
@ -295,4 +303,3 @@ class AdminEventForm(forms.Form):
for name, value in self.cleaned_data.items(): for name, value in self.cleaned_data.items():
if name.startswith('comment_'): if name.startswith('comment_'):
yield (self.fields[name].comment_id, value) yield (self.fields[name].comment_id, value)

View file

@ -29,32 +29,33 @@ TYPE_COMMENT_FIELD = (
('char', _(u"Texte court")), ('char', _(u"Texte court")),
) )
def choices_length (choices):
return reduce (lambda m, choice: max (m, len (choice[0])), choices, 0) def choices_length(choices):
return reduce(lambda m, choice: max(m, len(choice[0])), choices, 0)
class CofProfile(models.Model): class CofProfile(models.Model):
user = models.OneToOneField(User, related_name = "profile") user = models.OneToOneField(User, related_name="profile")
login_clipper = models.CharField("Login clipper", max_length = 8, blank = True) login_clipper = models.CharField("Login clipper", max_length=8, blank=True)
is_cof = models.BooleanField("Membre du COF", default = False) is_cof = models.BooleanField("Membre du COF", default=False)
num = models.IntegerField ("Numéro d'adhérent", blank = True, default = 0) num = models.IntegerField("Numéro d'adhérent", blank=True, default=0)
phone = models.CharField("Téléphone", max_length = 20, blank = True) phone = models.CharField("Téléphone", max_length=20, blank=True)
occupation = models.CharField (_(u"Occupation"), occupation = models.CharField(_(u"Occupation"),
default = "1A", default="1A",
choices = OCCUPATION_CHOICES, choices=OCCUPATION_CHOICES,
max_length = choices_length (OCCUPATION_CHOICES)) max_length=choices_length(OCCUPATION_CHOICES))
departement = models.CharField (_(u"Département"), max_length = 50, blank = True) departement = models.CharField(_(u"Département"), max_length=50, blank=True)
type_cotiz = models.CharField (_(u"Type de cotisation"), type_cotiz = models.CharField(_(u"Type de cotisation"),
default = "normalien", default="normalien",
choices = TYPE_COTIZ_CHOICES, max_length=choices_length(TYPE_COTIZ_CHOICES))
max_length = choices_length (TYPE_COTIZ_CHOICES)) mailing_cof = models.BooleanField("Recevoir les mails COF", default=False)
mailing_cof = models.BooleanField("Recevoir les mails COF", default = False) mailing_bda = models.BooleanField("Recevoir les mails BdA", default=False)
mailing_bda = models.BooleanField("Recevoir les mails BdA", default = False) mailing_bda_revente = models.BooleanField("Recevoir les mails de revente de places BdA", default=False)
mailing_bda_revente = models.BooleanField("Recevoir les mails de revente de places BdA", default = False) comments = models.TextField("Commentaires visibles uniquement par le Buro", blank=True)
comments = models.TextField("Commentaires visibles uniquement par le Buro", blank = True) is_buro = models.BooleanField("Membre du Burô", default=False)
is_buro = models.BooleanField("Membre du Burô", default = False) petits_cours_accept = models.BooleanField("Recevoir des petits cours", default=False)
petits_cours_accept = models.BooleanField("Recevoir des petits cours", default = False)
petits_cours_remarques = models.TextField(_(u"Remarques et précisions pour les petits cours"), petits_cours_remarques = models.TextField(_(u"Remarques et précisions pour les petits cours"),
blank = True, default = "") blank=True, default="")
class Meta: class Meta:
verbose_name = "Profil COF" verbose_name = "Profil COF"
@ -63,22 +64,25 @@ class CofProfile(models.Model):
def __unicode__(self): def __unicode__(self):
return unicode(self.user.username) return unicode(self.user.username)
def create_user_profile(sender, instance, created, **kwargs): def create_user_profile(sender, instance, created, **kwargs):
if created: if created:
CofProfile.objects.get_or_create(user = instance) CofProfile.objects.get_or_create(user=instance)
post_save.connect(create_user_profile, sender = User) post_save.connect(create_user_profile, sender=User)
class Club(models.Model): class Club(models.Model):
name = models.CharField("Nom", max_length = 200) name = models.CharField("Nom", max_length=200)
description = models.TextField("Description") description = models.TextField("Description")
respos = models.ManyToManyField(User, related_name = "clubs_geres") respos = models.ManyToManyField(User, related_name="clubs_geres")
membres = models.ManyToManyField(User, related_name = "clubs") membres = models.ManyToManyField(User, related_name="clubs")
class CustomMail(models.Model): class CustomMail(models.Model):
shortname = models.SlugField(max_length = 50, blank = False) shortname = models.SlugField(max_length=50, blank=False)
title = models.CharField("Titre", max_length = 200, blank = False) title = models.CharField("Titre", max_length=200, blank=False)
content = models.TextField("Contenu", blank = False) content = models.TextField("Contenu", blank=False)
comments = models.TextField("Informations contextuelles sur le mail", blank = True) comments = models.TextField("Informations contextuelles sur le mail", blank=True)
class Meta: class Meta:
verbose_name = "Mails personnalisables" verbose_name = "Mails personnalisables"
@ -86,14 +90,15 @@ class CustomMail(models.Model):
def __unicode__(self): def __unicode__(self):
return u"%s: %s" % (self.shortname, self.title) return u"%s: %s" % (self.shortname, self.title)
class Event(models.Model): class Event(models.Model):
title = models.CharField("Titre", max_length = 200) title = models.CharField("Titre", max_length=200)
location = models.CharField("Lieu", max_length = 200) location = models.CharField("Lieu", max_length=200)
start_date = models.DateField("Date de début", blank = True, null = True) start_date = models.DateField("Date de début", blank=True, null=True)
end_date = models.DateField("Date de fin", blank = True, null = True) end_date = models.DateField("Date de fin", blank=True, null=True)
description = models.TextField("Description", blank = True) description = models.TextField("Description", blank=True)
registration_open = models.BooleanField("Inscriptions ouvertes", default = True) registration_open = models.BooleanField("Inscriptions ouvertes", default=True)
old = models.BooleanField("Archiver (événement fini)", default = False) old = models.BooleanField("Archiver (événement fini)", default=False)
class Meta: class Meta:
verbose_name = "Événement" verbose_name = "Événement"
@ -101,11 +106,12 @@ class Event(models.Model):
def __unicode__(self): def __unicode__(self):
return unicode(self.title) return unicode(self.title)
class EventCommentField(models.Model): class EventCommentField(models.Model):
event = models.ForeignKey(Event, related_name = "commentfields") event = models.ForeignKey(Event, related_name="commentfields")
name = models.CharField("Champ", max_length = 200) name = models.CharField("Champ", max_length=200)
fieldtype = models.CharField("Type", max_length = 10, choices = TYPE_COMMENT_FIELD, default = "text") fieldtype = models.CharField("Type", max_length=10, choices=TYPE_COMMENT_FIELD, default="text")
default = models.TextField("Valeur par défaut", blank = True) default = models.TextField("Valeur par défaut", blank=True)
class Meta: class Meta:
verbose_name = "Champ" verbose_name = "Champ"
@ -113,15 +119,17 @@ class EventCommentField(models.Model):
def __unicode__(self): def __unicode__(self):
return unicode(self.name) return unicode(self.name)
class EventCommentValue(models.Model): class EventCommentValue(models.Model):
commentfield = models.ForeignKey(EventCommentField, related_name = "values") commentfield = models.ForeignKey(EventCommentField, related_name="values")
registration = models.ForeignKey("EventRegistration", related_name = "comments") registration = models.ForeignKey("EventRegistration", related_name="comments")
content = models.TextField("Contenu", blank = True, null = True) content = models.TextField("Contenu", blank=True, null=True)
class EventOption(models.Model): class EventOption(models.Model):
event = models.ForeignKey(Event, related_name = "options") event = models.ForeignKey(Event, related_name="options")
name = models.CharField("Option", max_length = 200) name = models.CharField("Option", max_length=200)
multi_choices = models.BooleanField("Choix multiples", default = False) multi_choices = models.BooleanField("Choix multiples", default=False)
class Meta: class Meta:
verbose_name = "Option" verbose_name = "Option"
@ -129,9 +137,10 @@ class EventOption(models.Model):
def __unicode__(self): def __unicode__(self):
return unicode(self.name) return unicode(self.name)
class EventOptionChoice(models.Model): class EventOptionChoice(models.Model):
event_option = models.ForeignKey(EventOption, related_name = "choices") event_option = models.ForeignKey(EventOption, related_name="choices")
value = models.CharField("Valeur", max_length = 200) value = models.CharField("Valeur", max_length=200)
class Meta: class Meta:
verbose_name = "Choix" verbose_name = "Choix"
@ -139,12 +148,13 @@ class EventOptionChoice(models.Model):
def __unicode__(self): def __unicode__(self):
return unicode(self.value) return unicode(self.value)
class EventRegistration(models.Model): class EventRegistration(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
event = models.ForeignKey(Event) event = models.ForeignKey(Event)
options = models.ManyToManyField(EventOptionChoice) options = models.ManyToManyField(EventOptionChoice)
filledcomments = models.ManyToManyField(EventCommentField, through = EventCommentValue) filledcomments = models.ManyToManyField(EventCommentField, through=EventCommentValue)
paid = models.BooleanField("A payé", default = False) paid = models.BooleanField("A payé", default=False)
class Meta: class Meta:
verbose_name = "Inscription" verbose_name = "Inscription"
@ -153,11 +163,12 @@ class EventRegistration(models.Model):
def __unicode__(self): def __unicode__(self):
return u"Inscription de %s à %s" % (unicode(self.user), unicode(self.event.title)) return u"Inscription de %s à %s" % (unicode(self.user), unicode(self.event.title))
class Survey(models.Model): class Survey(models.Model):
title = models.CharField("Titre", max_length = 200) title = models.CharField("Titre", max_length=200)
details = models.TextField("Détails", blank = True) details = models.TextField("Détails", blank=True)
survey_open = models.BooleanField("Sondage ouvert", default = True) survey_open = models.BooleanField("Sondage ouvert", default=True)
old = models.BooleanField("Archiver (sondage fini)", default = False) old = models.BooleanField("Archiver (sondage fini)", default=False)
class Meta: class Meta:
verbose_name = "Sondage" verbose_name = "Sondage"
@ -165,10 +176,11 @@ class Survey(models.Model):
def __unicode__(self): def __unicode__(self):
return unicode(self.title) return unicode(self.title)
class SurveyQuestion(models.Model): class SurveyQuestion(models.Model):
survey = models.ForeignKey(Survey, related_name = "questions") survey = models.ForeignKey(Survey, related_name="questions")
question = models.CharField("Question", max_length = 200) question = models.CharField("Question", max_length=200)
multi_answers = models.BooleanField("Choix multiples", default = False) multi_answers = models.BooleanField("Choix multiples", default=False)
class Meta: class Meta:
verbose_name = "Question" verbose_name = "Question"
@ -176,9 +188,10 @@ class SurveyQuestion(models.Model):
def __unicode__(self): def __unicode__(self):
return unicode(self.question) return unicode(self.question)
class SurveyQuestionAnswer(models.Model): class SurveyQuestionAnswer(models.Model):
survey_question = models.ForeignKey(SurveyQuestion, related_name = "answers") survey_question = models.ForeignKey(SurveyQuestion, related_name="answers")
answer = models.CharField("Réponse", max_length = 200) answer = models.CharField("Réponse", max_length=200)
class Meta: class Meta:
verbose_name = "Réponse" verbose_name = "Réponse"
@ -186,15 +199,17 @@ class SurveyQuestionAnswer(models.Model):
def __unicode__(self): def __unicode__(self):
return unicode(self.answer) return unicode(self.answer)
class SurveyAnswer(models.Model): class SurveyAnswer(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
survey = models.ForeignKey(Survey) survey = models.ForeignKey(Survey)
answers = models.ManyToManyField(SurveyQuestionAnswer, related_name = "selected_by") answers = models.ManyToManyField(SurveyQuestionAnswer, related_name="selected_by")
class Meta: class Meta:
verbose_name = "Réponses" verbose_name = "Réponses"
unique_together = ("user", "survey") unique_together = ("user", "survey")
class Clipper(models.Model): class Clipper(models.Model):
username = models.CharField("Identifiant", max_length = 20) username = models.CharField("Identifiant", max_length=20)
fullname = models.CharField("Nom complet", max_length = 200) fullname = models.CharField("Nom complet", max_length=200)

View file

@ -26,58 +26,64 @@ from datetime import datetime
import base64 import base64
import simplejson import simplejson
def render_template(template_path, data): def render_template(template_path, data):
tmpl = loader.get_template(template_path) tmpl = loader.get_template(template_path)
context = Context(data) context = Context(data)
return tmpl.render(context) return tmpl.render(context)
class DemandeListView(ListView): class DemandeListView(ListView):
model = PetitCoursDemande model = PetitCoursDemande
template_name = "petits_cours_demandes_list.html" template_name = "petits_cours_demandes_list.html"
paginate_by = 20 paginate_by = 20
def get_queryset(self): def get_queryset(self):
return PetitCoursDemande.objects.order_by('traitee','-id').all() return PetitCoursDemande.objects.order_by('traitee', '-id').all()
@method_decorator(buro_required) @method_decorator(buro_required)
def dispatch(self, *args, **kwargs): def dispatch(self, *args, **kwargs):
return super(DemandeListView, self).dispatch(*args, **kwargs) return super(DemandeListView, self).dispatch(*args, **kwargs)
@buro_required @buro_required
def details(request, demande_id): def details(request, demande_id):
demande = get_object_or_404(PetitCoursDemande, id = demande_id) demande = get_object_or_404(PetitCoursDemande, id=demande_id)
attributions = PetitCoursAttribution.objects.filter(demande = demande).all() attributions = PetitCoursAttribution.objects.filter(demande=demande).all()
return render(request, "details_demande_petit_cours.html", return render(request, "details_demande_petit_cours.html",
{"demande": demande, {"demande": demande,
"attributions": attributions}) "attributions": attributions})
def _get_attrib_counter(user, matiere): def _get_attrib_counter(user, matiere):
counter, created = PetitCoursAttributionCounter.objects.get_or_create(user = user, counter, created = PetitCoursAttributionCounter.objects.get_or_create(user=user,
matiere = matiere) matiere=matiere)
if created: if created:
mincount = PetitCoursAttributionCounter.objects.filter(matiere = matiere).exclude(user = user).all().aggregate(Min('count')) mincount = PetitCoursAttributionCounter.objects.filter(matiere=matiere).exclude(user=user).all().aggregate(Min('count'))
counter.count = mincount['count__min'] counter.count = mincount['count__min']
counter.save() counter.save()
return counter return counter
def _get_demande_candidates(demande, redo = False):
def _get_demande_candidates(demande, redo=False):
for matiere in demande.matieres.all(): for matiere in demande.matieres.all():
candidates = PetitCoursAbility.objects.filter(matiere = matiere, niveau = demande.niveau) candidates = PetitCoursAbility.objects.filter(matiere=matiere, niveau=demande.niveau)
candidates = candidates.filter(user__profile__is_cof = True, candidates = candidates.filter(user__profile__is_cof=True,
user__profile__petits_cours_accept = True) user__profile__petits_cours_accept=True)
if demande.agrege_requis: if demande.agrege_requis:
candidates = candidates.filter(agrege = True) candidates = candidates.filter(agrege=True)
if redo: if redo:
attributions = PetitCoursAttribution.objects.filter(demande = demande, attributions = PetitCoursAttribution.objects.filter(demande=demande,
matiere = matiere).all() matiere=matiere).all()
for attrib in attributions: for attrib in attributions:
candidates = candidates.exclude(user = attrib.user) candidates = candidates.exclude(user=attrib.user)
candidates = candidates.order_by('?').select_related().all() candidates = candidates.order_by('?').select_related().all()
yield (matiere, candidates) yield (matiere, candidates)
@buro_required @buro_required
def traitement(request, demande_id, redo = False): def traitement(request, demande_id, redo=False):
demande = get_object_or_404(PetitCoursDemande, id = demande_id) demande = get_object_or_404(PetitCoursDemande, id=demande_id)
if demande.niveau == "other": if demande.niveau == "other":
return _traitement_other(request, demande, redo) return _traitement_other(request, demande, redo)
if request.method == "POST": if request.method == "POST":
@ -92,7 +98,7 @@ def traitement(request, demande_id, redo = False):
for candidate in candidates: for candidate in candidates:
user = candidate.user user = candidate.user
tuples.append((candidate, _get_attrib_counter(user, matiere))) tuples.append((candidate, _get_attrib_counter(user, matiere)))
tuples = sorted(tuples, key = lambda c: c[1].count) tuples = sorted(tuples, key=lambda c: c[1].count)
candidates, _ = zip(*tuples) candidates, _ = zip(*tuples)
candidates = candidates[0:min(3, len(candidates))] candidates = candidates[0:min(3, len(candidates))]
attribdata[matiere.id] = [] attribdata[matiere.id] = []
@ -110,12 +116,14 @@ def traitement(request, demande_id, redo = False):
return _finalize_traitement(request, demande, proposals, return _finalize_traitement(request, demande, proposals,
proposed_for, unsatisfied, attribdata, redo) proposed_for, unsatisfied, attribdata, redo)
@buro_required @buro_required
def retraitement(request, demande_id): def retraitement(request, demande_id):
return traitement(request, demande_id, redo = True) return traitement(request, demande_id, redo=True)
def _finalize_traitement(request, demande, proposals, proposed_for, def _finalize_traitement(request, demande, proposals, proposed_for,
unsatisfied, attribdata, redo = False, errors = None): unsatisfied, attribdata, redo=False, errors=None):
proposals = proposals.items() proposals = proposals.items()
proposed_for = proposed_for.items() proposed_for = proposed_for.items()
attribdata = attribdata.items() attribdata = attribdata.items()
@ -136,6 +144,7 @@ def _finalize_traitement(request, demande, proposals, proposed_for,
"errors": errors, "errors": errors,
}) })
def _generate_eleve_email(demande, proposed_for): def _generate_eleve_email(demande, proposed_for):
proposed_mails = [] proposed_mails = []
for user, matieres in proposed_for: for user, matieres in proposed_for:
@ -143,6 +152,7 @@ def _generate_eleve_email(demande, proposed_for):
proposed_mails.append((user, msg)) proposed_mails.append((user, msg))
return proposed_mails return proposed_mails
def _traitement_other_preparing(request, demande): def _traitement_other_preparing(request, demande):
redo = "redo" in request.POST redo = "redo" in request.POST
unsatisfied = [] unsatisfied = []
@ -179,7 +189,8 @@ def _traitement_other_preparing(request, demande):
errors.append(u"Seulement %d proposition%s pour %s" % (len(proposals[matiere]), "s" if len(proposals[matiere]) > 1 else "", matiere)) errors.append(u"Seulement %d proposition%s pour %s" % (len(proposals[matiere]), "s" if len(proposals[matiere]) > 1 else "", matiere))
else: else:
unsatisfied.append(matiere) unsatisfied.append(matiere)
return _finalize_traitement(request, demande, proposals, proposed_for, unsatisfied, attribdata, errors = errors) return _finalize_traitement(request, demande, proposals, proposed_for, unsatisfied, attribdata, errors=errors)
def _traitement_other(request, demande, redo): def _traitement_other(request, demande, redo):
if request.method == "POST": if request.method == "POST":
@ -197,7 +208,7 @@ def _traitement_other(request, demande, redo):
for candidate in candidates: for candidate in candidates:
user = candidate.user user = candidate.user
tuples.append((candidate, _get_attrib_counter(user, matiere))) tuples.append((candidate, _get_attrib_counter(user, matiere)))
tuples = sorted(tuples, key = lambda c: c[1].count) tuples = sorted(tuples, key=lambda c: c[1].count)
candidates, _ = zip(*tuples) candidates, _ = zip(*tuples)
attribdata[matiere.id] = [] attribdata[matiere.id] = []
proposals[matiere] = [] proposals[matiere] = []
@ -220,6 +231,7 @@ def _traitement_other(request, demande, redo):
"proposed_for": proposed_for, "proposed_for": proposed_for,
}) })
def _traitement_post(request, demande): def _traitement_post(request, demande):
proposals = {} proposals = {}
proposed_for = {} proposed_for = {}
@ -234,7 +246,7 @@ def _traitement_post(request, demande):
else: else:
proposals[matiere] = [] proposals[matiere] = []
for user_id in attribdata[matiere.id]: for user_id in attribdata[matiere.id]:
user = User.objects.get(pk = user_id) user = User.objects.get(pk=user_id)
proposals[matiere].append(user) proposals[matiere].append(user)
if user not in proposed_for: if user not in proposed_for:
proposed_for[user] = [matiere] proposed_for[user] = [matiere]
@ -254,21 +266,21 @@ def _traitement_post(request, demande):
for (user, msg) in proposed_mails: for (user, msg) in proposed_mails:
msg = EmailMessage("Petits cours ENS par le COF", msg, msg = EmailMessage("Petits cours ENS par le COF", msg,
frommail, [user.email], frommail, [user.email],
[bccaddress], headers = {'Reply-To': replyto}) [bccaddress], headers={'Reply-To': replyto})
mails_to_send.append(msg) mails_to_send.append(msg)
mails_to_send.append(EmailMessage("Cours particuliers ENS", mainmail, mails_to_send.append(EmailMessage("Cours particuliers ENS", mainmail,
frommail, [demande.email], frommail, [demande.email],
[bccaddress], headers = {'Reply-To': replyto})) [bccaddress], headers={'Reply-To': replyto}))
connection = mail.get_connection(fail_silently = True) connection = mail.get_connection(fail_silently=True)
connection.send_messages(mails_to_send) connection.send_messages(mails_to_send)
lock_table(PetitCoursAttributionCounter, PetitCoursAttribution, User) lock_table(PetitCoursAttributionCounter, PetitCoursAttribution, User)
for matiere in proposals: for matiere in proposals:
for rank, user in enumerate(proposals[matiere]): for rank, user in enumerate(proposals[matiere]):
counter = PetitCoursAttributionCounter.objects.get(user = user, matiere = matiere) counter = PetitCoursAttributionCounter.objects.get(user=user, matiere=matiere)
counter.count += 1 counter.count += 1
counter.save() counter.save()
attrib = PetitCoursAttribution(user = user, matiere = matiere, attrib = PetitCoursAttribution(user=user, matiere=matiere,
demande = demande, rank = rank + 1) demande=demande, rank=rank + 1)
attrib.save() attrib.save()
unlock_tables() unlock_tables()
demande.traitee = True demande.traitee = True
@ -280,6 +292,7 @@ def _traitement_post(request, demande):
"redo": redo, "redo": redo,
}) })
class BaseMatieresFormSet(BaseInlineFormSet): class BaseMatieresFormSet(BaseInlineFormSet):
def clean(self): def clean(self):
super(BaseMatieresFormSet, self).clean() super(BaseMatieresFormSet, self).clean()
@ -298,35 +311,36 @@ class BaseMatieresFormSet(BaseInlineFormSet):
raise forms.ValidationError("Vous ne pouvez pas vous inscrire deux fois pour la même matiere avec le même niveau.") raise forms.ValidationError("Vous ne pouvez pas vous inscrire deux fois pour la même matiere avec le même niveau.")
matieres.append((matiere, niveau)) matieres.append((matiere, niveau))
@login_required @login_required
def inscription(request): def inscription(request):
profile, created = CofProfile.objects.get_or_create(user = request.user) profile, created = CofProfile.objects.get_or_create(user=request.user)
if not profile.is_cof: if not profile.is_cof:
return redirect("cof-denied") return redirect("cof-denied")
MatieresFormSet = inlineformset_factory(User, PetitCoursAbility, MatieresFormSet = inlineformset_factory(User, PetitCoursAbility,
fields = ("matiere", "niveau", "agrege",), fields=("matiere", "niveau", "agrege",),
formset = BaseMatieresFormSet) formset=BaseMatieresFormSet)
success = False success = False
if request.method == "POST": if request.method == "POST":
formset = MatieresFormSet(request.POST, instance = request.user) formset = MatieresFormSet(request.POST, instance=request.user)
if formset.is_valid(): if formset.is_valid():
formset.save() formset.save()
profile.petits_cours_accept = "receive_proposals" in request.POST profile.petits_cours_accept = "receive_proposals" in request.POST
profile.petits_cours_remarques = request.POST["remarques"] profile.petits_cours_remarques = request.POST["remarques"]
profile.save() profile.save()
lock_table(PetitCoursAttributionCounter, PetitCoursAbility, User, PetitCoursSubject) lock_table(PetitCoursAttributionCounter, PetitCoursAbility, User, PetitCoursSubject)
abilities = PetitCoursAbility.objects.filter(user = request.user).all() abilities = PetitCoursAbility.objects.filter(user=request.user).all()
for ability in abilities: for ability in abilities:
counter = _get_attrib_counter(ability.user, ability.matiere) counter = _get_attrib_counter(ability.user, ability.matiere)
unlock_tables() unlock_tables()
success = True success = True
formset = MatieresFormSet(instance = request.user) formset = MatieresFormSet(instance=request.user)
else: else:
formset = MatieresFormSet(instance = request.user) formset = MatieresFormSet(instance=request.user)
return render(request, "inscription-petit-cours.html", {"formset": formset, "success": success, "receive_proposals": profile.petits_cours_accept, "remarques": profile.petits_cours_remarques}) return render(request, "inscription-petit-cours.html", {"formset": formset, "success": success, "receive_proposals": profile.petits_cours_accept, "remarques": profile.petits_cours_remarques})
class DemandeForm(ModelForm): class DemandeForm(ModelForm):
captcha = ReCaptchaField(attrs = {'theme': 'clean', 'lang': 'fr'}) captcha = ReCaptchaField(attrs={'theme': 'clean', 'lang': 'fr'})
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(DemandeForm, self).__init__(*args, **kwargs) super(DemandeForm, self).__init__(*args, **kwargs)
@ -337,6 +351,7 @@ class DemandeForm(ModelForm):
fields = ('name', 'email', 'phone', 'quand', 'freq', 'lieu', 'matieres', 'agrege_requis', 'niveau', 'remarques') fields = ('name', 'email', 'phone', 'quand', 'freq', 'lieu', 'matieres', 'agrege_requis', 'niveau', 'remarques')
widgets = {'matieres': forms.CheckboxSelectMultiple} widgets = {'matieres': forms.CheckboxSelectMultiple}
@csrf_exempt @csrf_exempt
def demande(request): def demande(request):
success = False success = False
@ -349,6 +364,7 @@ def demande(request):
form = DemandeForm() form = DemandeForm()
return render(request, "demande-petit-cours.html", {"form": form, "success": success}) return render(request, "demande-petit-cours.html", {"form": form, "success": success})
@csrf_exempt @csrf_exempt
def demande_raw(request): def demande_raw(request):
success = False success = False

View file

@ -12,17 +12,18 @@ from gestioncof.models import CofProfile, CustomMail
User = get_user_model() User = get_user_model()
class COFCASBackend(CASBackend): class COFCASBackend(CASBackend):
def authenticate_cas(self, ticket, service, request): def authenticate_cas(self, ticket, service, request):
"""Verifies CAS ticket and gets or creates User object""" """Verifies CAS ticket and gets or creates User object"""
client = get_cas_client(service_url=service) client = get_cas_client(service_url=service)
username, attributes, _= client.verify_ticket(ticket) username, attributes, _ = client.verify_ticket(ticket)
if attributes: if attributes:
request.session['attributes'] = attributes request.session['attributes'] = attributes
if not username: if not username:
return None return None
profiles = CofProfile.objects.filter(login_clipper = username) profiles = CofProfile.objects.filter(login_clipper=username)
if len(profiles) > 0: if len(profiles) > 0:
profile = profiles.order_by('-is_cof')[0] profile = profiles.order_by('-is_cof')[0]
user = profile.user user = profile.user
@ -43,7 +44,7 @@ class COFCASBackend(CASBackend):
try: try:
profile = user.profile profile = user.profile
except CofProfile.DoesNotExist: except CofProfile.DoesNotExist:
profile, created = CofProfile.objects.get_or_create(user = user) profile, created = CofProfile.objects.get_or_create(user=user)
profile.save() profile.save()
if not profile.login_clipper: if not profile.login_clipper:
profile.login_clipper = user.username profile.login_clipper = user.username
@ -57,7 +58,8 @@ class COFCASBackend(CASBackend):
user.save() user.save()
return user return user
def context_processor (request):
def context_processor(request):
'''Append extra data to the context of the given request''' '''Append extra data to the context of the given request'''
data = { data = {
"user": request.user, "user": request.user,
@ -65,17 +67,20 @@ def context_processor (request):
} }
return data return data
def lock_table(*models): def lock_table(*models):
query = "LOCK TABLES " query = "LOCK TABLES "
for i, model in enumerate(models): for i, model in enumerate(models):
table = model._meta.db_table table = model._meta.db_table
if i > 0: query += ", " if i > 0:
query += ", "
query += "%s WRITE" % table query += "%s WRITE" % table
cursor = connection.cursor() cursor = connection.cursor()
cursor.execute(query) cursor.execute(query)
row = cursor.fetchone() row = cursor.fetchone()
return row return row
def unlock_tables(*models): def unlock_tables(*models):
cursor = connection.cursor() cursor = connection.cursor()
cursor.execute("UNLOCK TABLES") cursor.execute("UNLOCK TABLES")
@ -84,15 +89,17 @@ def unlock_tables(*models):
unlock_table = unlock_tables unlock_table = unlock_tables
def send_custom_mail(to, shortname, context = None, from_email = "cof@ens.fr"):
if context is None: context = {} def send_custom_mail(to, shortname, context=None, from_email="cof@ens.fr"):
if context is None:
context = {}
if isinstance(to, DjangoUser): if isinstance(to, DjangoUser):
context["nom"] = to.get_full_name() context["nom"] = to.get_full_name()
context["prenom"] = to.first_name context["prenom"] = to.first_name
to = to.email to = to.email
mail = CustomMail.objects.get(shortname = shortname) mail = CustomMail.objects.get(shortname=shortname)
template = Template(mail.content) template = Template(mail.content)
message = template.render(Context(context)) message = template.render(Context(context))
send_mail (mail.title, message, send_mail(mail.title, message,
from_email, [to], from_email, [to],
fail_silently = True) fail_silently=True)

View file

@ -20,6 +20,7 @@ from gestioncof.forms import UserProfileForm, EventStatusFilterForm, \
from bda.models import Tirage from bda.models import Tirage
@login_required @login_required
def home(request): def home(request):
data = {"surveys": Survey.objects.filter(old=False).all(), data = {"surveys": Survey.objects.filter(old=False).all(),
@ -29,61 +30,65 @@ def home(request):
"open_tirages": Tirage.objects.filter(active=True).all()} "open_tirages": Tirage.objects.filter(active=True).all()}
return render(request, "home.html", data) return render(request, "home.html", data)
def login(request): def login(request):
if request.user.is_authenticated(): if request.user.is_authenticated():
return redirect("gestioncof.views.home") return redirect("gestioncof.views.home")
return render(request, "login_switch.html", {}) return render(request, "login_switch.html", {})
def login_ext(request): def login_ext(request):
if request.method == "POST" and "username" in request.POST: if request.method == "POST" and "username" in request.POST:
try: try:
user = User.objects.get(username = request.POST["username"]) user = User.objects.get(username=request.POST["username"])
if not user.has_usable_password() or user.password in ("","!"): if not user.has_usable_password() or user.password in ("", "!"):
profile, created = CofProfile.objects.get_or_create(user = user) profile, created = CofProfile.objects.get_or_create(user=user)
if profile.login_clipper: if profile.login_clipper:
return render(request, "error.html", {"error_type": "use_clipper_login"}) return render(request, "error.html", {"error_type": "use_clipper_login"})
else: else:
return render(request, "error.html", {"error_type": "no_password"}) return render(request, "error.html", {"error_type": "no_password"})
except User.DoesNotExist: except User.DoesNotExist:
pass pass
return django_login_view(request, template_name = 'login.html') return django_login_view(request, template_name='login.html')
@login_required @login_required
def logout(request): def logout(request):
try: try:
profile = request.user.profile profile = request.user.profile
except CofProfile.DoesNotExist: except CofProfile.DoesNotExist:
profile, created = CofProfile.objects.get_or_create(user = request.user) profile, created = CofProfile.objects.get_or_create(user=request.user)
if profile.login_clipper: if profile.login_clipper:
return redirect("django_cas_ng.views.logout") return redirect("django_cas_ng.views.logout")
else: else:
return redirect("django.contrib.auth.views.logout") return redirect("django.contrib.auth.views.logout")
@login_required @login_required
def survey(request, survey_id): def survey(request, survey_id):
survey = get_object_or_404(Survey, id = survey_id) survey = get_object_or_404(Survey, id=survey_id)
if not survey.survey_open: if not survey.survey_open:
raise Http404 raise Http404
success = False success = False
deleted = False deleted = False
if request.method == "POST": if request.method == "POST":
form = SurveyForm(request.POST, survey = survey) form = SurveyForm(request.POST, survey=survey)
if request.POST.get('delete'): if request.POST.get('delete'):
try: try:
current_answer = SurveyAnswer.objects.get(user = request.user, survey = survey) current_answer = SurveyAnswer.objects.get(user=request.user, survey=survey)
current_answer.delete() current_answer.delete()
current_answer = None current_answer = None
except SurveyAnswer.DoesNotExist: except SurveyAnswer.DoesNotExist:
current_answer = None current_answer = None
form = SurveyForm(survey = survey) form = SurveyForm(survey=survey)
success = True success = True
deleted = True deleted = True
else: else:
if form.is_valid(): if form.is_valid():
all_answers = [] all_answers = []
for question_id, answers_ids in form.answers(): for question_id, answers_ids in form.answers():
question = get_object_or_404(SurveyQuestion, id = question_id, question = get_object_or_404(SurveyQuestion, id=question_id,
survey = survey) survey=survey)
if type(answers_ids) != list: if type(answers_ids) != list:
answers_ids = [answers_ids] answers_ids = [answers_ids]
if not question.multi_answers and len(answers_ids) > 1: if not question.multi_answers and len(answers_ids) > 1:
@ -93,31 +98,32 @@ def survey(request, survey_id):
continue continue
answer_id = int(answer_id) answer_id = int(answer_id)
answer = SurveyQuestionAnswer.objects.get( answer = SurveyQuestionAnswer.objects.get(
id = answer_id, id=answer_id,
survey_question = question) survey_question=question)
all_answers.append(answer) all_answers.append(answer)
try: try:
current_answer = SurveyAnswer.objects.get(user = request.user, survey = survey) current_answer = SurveyAnswer.objects.get(user=request.user, survey=survey)
except SurveyAnswer.DoesNotExist: except SurveyAnswer.DoesNotExist:
current_answer = SurveyAnswer(user = request.user, survey = survey) current_answer = SurveyAnswer(user=request.user, survey=survey)
current_answer.save() current_answer.save()
current_answer.answers = all_answers current_answer.answers = all_answers
current_answer.save() current_answer.save()
success = True success = True
else: else:
try: try:
current_answer = SurveyAnswer.objects.get(user = request.user, survey = survey) current_answer = SurveyAnswer.objects.get(user=request.user, survey=survey)
form = SurveyForm(survey = survey, current_answers = current_answer.answers) form = SurveyForm(survey=survey, current_answers=current_answer.answers)
except SurveyAnswer.DoesNotExist: except SurveyAnswer.DoesNotExist:
current_answer = None current_answer = None
form = SurveyForm(survey = survey) form = SurveyForm(survey=survey)
return render(request, "survey.html", {"survey": survey, "form": form, "success": success, "deleted": deleted, "current_answer": current_answer}) return render(request, "survey.html", {"survey": survey, "form": form, "success": success, "deleted": deleted, "current_answer": current_answer})
def get_event_form_choices(event, form): def get_event_form_choices(event, form):
all_choices = [] all_choices = []
for option_id, choices_ids in form.choices(): for option_id, choices_ids in form.choices():
option = get_object_or_404(EventOption, id = option_id, option = get_object_or_404(EventOption, id=option_id,
event = event) event=event)
if type(choices_ids) != list: if type(choices_ids) != list:
choices_ids = [choices_ids] choices_ids = [choices_ids]
if not option.multi_choices and len(choices_ids) > 1: if not option.multi_choices and len(choices_ids) > 1:
@ -127,42 +133,43 @@ def get_event_form_choices(event, form):
continue continue
choice_id = int(choice_id) choice_id = int(choice_id)
choice = EventOptionChoice.objects.get( choice = EventOptionChoice.objects.get(
id = choice_id, id=choice_id,
event_option = option) event_option=option)
all_choices.append(choice) all_choices.append(choice)
return all_choices return all_choices
def update_event_form_comments(event, form, registration): def update_event_form_comments(event, form, registration):
for commentfield_id, value in form.comments(): for commentfield_id, value in form.comments():
field = get_object_or_404(EventCommentField, id = commentfield_id, field = get_object_or_404(EventCommentField, id=commentfield_id,
event = event) event=event)
if value == field.default: if value == field.default:
continue continue
(storage, _) = EventCommentValue.objects.get_or_create(commentfield = field, (storage, _) = EventCommentValue.objects.get_or_create(commentfield=field,
registration = registration) registration=registration)
storage.content = value storage.content = value
storage.save() storage.save()
@login_required @login_required
def event(request, event_id): def event(request, event_id):
event = get_object_or_404(Event, id = event_id) event = get_object_or_404(Event, id=event_id)
if not event.registration_open: if not event.registration_open:
raise Http404 raise Http404
success = False success = False
if request.method == "POST": if request.method == "POST":
form = EventForm(request.POST, event = event) form = EventForm(request.POST, event=event)
if form.is_valid(): if form.is_valid():
all_choices = get_event_form_choices(event, form) all_choices = get_event_form_choices(event, form)
(current_registration, _) = EventRegistration.objects.get_or_create(user = request.user, event = event) (current_registration, _) = EventRegistration.objects.get_or_create(user=request.user, event=event)
current_registration.options = all_choices current_registration.options = all_choices
current_registration.save() current_registration.save()
success = True success = True
else: else:
try: try:
current_registration = EventRegistration.objects.get(user = request.user, event = event) current_registration = EventRegistration.objects.get(user=request.user, event=event)
form = EventForm(event = event, current_choices = current_registration.options) form = EventForm(event=event, current_choices=current_registration.options)
except EventRegistration.DoesNotExist: except EventRegistration.DoesNotExist:
form = EventForm(event = event) form = EventForm(event=event)
return render(request, "event.html", {"event": event, "form": form, "success": success}) return render(request, "event.html", {"event": event, "form": form, "success": success})
def clean_post_for_status(initial): def clean_post_for_status(initial):
@ -175,27 +182,27 @@ def clean_post_for_status(initial):
@buro_required @buro_required
def event_status(request, event_id): def event_status(request, event_id):
event = get_object_or_404(Event, id = event_id) event = get_object_or_404(Event, id=event_id)
registrations_query = EventRegistration.objects.filter(event = event) registrations_query = EventRegistration.objects.filter(event=event)
post_data = clean_post_for_status(request.POST) post_data = clean_post_for_status(request.POST)
form = EventStatusFilterForm(post_data or None, event = event) form = EventStatusFilterForm(post_data or None, event=event)
if form.is_valid(): if form.is_valid():
for option_id, choice_id, value in form.filters(): for option_id, choice_id, value in form.filters():
if option_id == "has_paid": if option_id == "has_paid":
if value == "yes": if value == "yes":
registrations_query = registrations_query.filter(paid = True) registrations_query = registrations_query.filter(paid=True)
elif value == "no": elif value == "no":
registrations_query = registrations_query.filter(paid = False) registrations_query = registrations_query.filter(paid=False)
continue continue
choice = get_object_or_404(EventOptionChoice, id = choice_id, event_option__id = option_id) choice = get_object_or_404(EventOptionChoice, id=choice_id, event_option__id=option_id)
if value == "none": if value == "none":
continue continue
if value == "yes": if value == "yes":
registrations_query = registrations_query.filter(options__id__exact = choice.id) registrations_query = registrations_query.filter(options__id__exact=choice.id)
elif value == "no": elif value == "no":
registrations_query = registrations_query.exclude(options__id__exact = choice.id) registrations_query = registrations_query.exclude(options__id__exact=choice.id)
user_choices = registrations_query.prefetch_related("user").all() user_choices = registrations_query.prefetch_related("user").all()
options = EventOption.objects.filter(event = event).all() options = EventOption.objects.filter(event=event).all()
choices_count = {} choices_count = {}
for option in options: for option in options:
for choice in option.choices.all(): for choice in option.choices.all():
@ -205,23 +212,24 @@ def event_status(request, event_id):
choices_count[choice.id] += 1 choices_count[choice.id] += 1
return render(request, "event_status.html", {"event": event, "user_choices": user_choices, "options": options, "choices_count": choices_count, "form": form}) return render(request, "event_status.html", {"event": event, "user_choices": user_choices, "options": options, "choices_count": choices_count, "form": form})
@buro_required @buro_required
def survey_status(request, survey_id): def survey_status(request, survey_id):
survey = get_object_or_404(Survey, id = survey_id) survey = get_object_or_404(Survey, id=survey_id)
answers_query = SurveyAnswer.objects.filter(survey = survey) answers_query = SurveyAnswer.objects.filter(survey=survey)
post_data = clean_post_for_status(request.POST) post_data = clean_post_for_status(request.POST)
form = SurveyStatusFilterForm(post_data or None, survey = survey) form = SurveyStatusFilterForm(post_data or None, survey=survey)
if form.is_valid(): if form.is_valid():
for question_id, answer_id, value in form.filters(): for question_id, answer_id, value in form.filters():
answer = get_object_or_404(SurveyQuestionAnswer, id = answer_id, survey_question__id = question_id) answer = get_object_or_404(SurveyQuestionAnswer, id=answer_id, survey_question__id=question_id)
if value == "none": if value == "none":
continue continue
if value == "yes": if value == "yes":
answers_query = answers_query.filter(answers__id__exact = answer.id) answers_query = answers_query.filter(answers__id__exact=answer.id)
elif value == "no": elif value == "no":
answers_query = answers_query.exclude(answers__id__exact = answer.id) answers_query = answers_query.exclude(answers__id__exact=answer.id)
user_answers = answers_query.prefetch_related("user").all() user_answers = answers_query.prefetch_related("user").all()
questions = SurveyQuestion.objects.filter(survey = survey).all() questions = SurveyQuestion.objects.filter(survey=survey).all()
answers_count = {} answers_count = {}
for question in questions: for question in questions:
for answer in question.answers.all(): for answer in question.answers.all():
@ -231,29 +239,32 @@ def survey_status(request, survey_id):
answers_count[answer.id] += 1 answers_count[answer.id] += 1
return render(request, "survey_status.html", {"survey": survey, "user_answers": user_answers, "questions": questions, "answers_count": answers_count, "form": form}) return render(request, "survey_status.html", {"survey": survey, "user_answers": user_answers, "questions": questions, "answers_count": answers_count, "form": form})
@login_required @login_required
def profile(request): def profile(request):
success = False success = False
if request.method == "POST": if request.method == "POST":
form = UserProfileForm(request.POST, instance = request.user.profile) form = UserProfileForm(request.POST, instance=request.user.profile)
if form.is_valid(): if form.is_valid():
form.save() form.save()
success = True success = True
else: else:
form = UserProfileForm(instance = request.user.profile) form = UserProfileForm(instance=request.user.profile)
return render(request, "profile.html", {"form": form, "success": success}) return render(request, "profile.html", {"form": form, "success": success})
def registration_set_ro_fields(user_form, profile_form): def registration_set_ro_fields(user_form, profile_form):
user_form.fields['username'].widget.attrs['readonly'] = True user_form.fields['username'].widget.attrs['readonly'] = True
profile_form.fields['login_clipper'].widget.attrs['readonly'] = True profile_form.fields['login_clipper'].widget.attrs['readonly'] = True
@buro_required @buro_required
def registration_form(request, login_clipper = None, username = None): def registration_form(request, login_clipper=None, username=None):
member = None member = None
if login_clipper: if login_clipper:
clipper = get_object_or_404(Clipper, username = login_clipper) clipper = get_object_or_404(Clipper, username=login_clipper)
try: # check if the given user is already registered try: # check if the given user is already registered
member = User.objects.filter(username = login_clipper).get() member = User.objects.filter(username=login_clipper).get()
username = member.username username = member.username
login_clipper = None login_clipper = None
except User.DoesNotExist: except User.DoesNotExist:
@ -270,11 +281,11 @@ def registration_form(request, login_clipper = None, username = None):
user_form.fields['last_name'].initial = " ".join(bits[1:]) user_form.fields['last_name'].initial = " ".join(bits[1:])
registration_set_ro_fields(user_form, profile_form) registration_set_ro_fields(user_form, profile_form)
if username: if username:
member = get_object_or_404(User, username = username) member = get_object_or_404(User, username=username)
(profile, _) = CofProfile.objects.get_or_create(user = member) (profile, _) = CofProfile.objects.get_or_create(user=member)
# already existing, prefill # already existing, prefill
user_form = RegistrationUserForm(instance = member) user_form = RegistrationUserForm(instance=member)
profile_form = RegistrationProfileForm(instance = profile) profile_form = RegistrationProfileForm(instance=profile)
registration_set_ro_fields(user_form, profile_form) registration_set_ro_fields(user_form, profile_form)
elif not login_clipper: elif not login_clipper:
# new user # new user
@ -283,20 +294,20 @@ def registration_form(request, login_clipper = None, username = None):
return render(request, "registration_form.html", {"user_form": user_form, "profile_form": profile_form, "member": member, "login_clipper": login_clipper}) return render(request, "registration_form.html", {"user_form": user_form, "profile_form": profile_form, "member": member, "login_clipper": login_clipper})
@buro_required @buro_required
def registration_form2(request, login_clipper = None, username = None): def registration_form2(request, login_clipper=None, username=None):
events = Event.objects.filter(old = False).all() events = Event.objects.filter(old=False).all()
member = None member = None
if login_clipper: if login_clipper:
clipper = get_object_or_404(Clipper, username = login_clipper) clipper = get_object_or_404(Clipper, username=login_clipper)
try: # check if the given user is already registered try: # check if the given user is already registered
member = User.objects.filter(username = login_clipper).get() member = User.objects.filter(username=login_clipper).get()
username = member.username username = member.username
login_clipper = None login_clipper = None
except User.DoesNotExist: except User.DoesNotExist:
# new user, but prefill # new user, but prefill
user_form = RegistrationUserForm() user_form = RegistrationUserForm()
profile_form = RegistrationProfileForm() profile_form = RegistrationProfileForm()
event_forms = [AdminEventForm(event = event) for event in events] event_forms = [AdminEventForm(event=event) for event in events]
user_form.fields['username'].initial = login_clipper user_form.fields['username'].initial = login_clipper
user_form.fields['email'].initial = login_clipper + "@clipper.ens.fr" user_form.fields['email'].initial = login_clipper + "@clipper.ens.fr"
profile_form.fields['login_clipper'].initial = login_clipper profile_form.fields['login_clipper'].initial = login_clipper
@ -307,27 +318,28 @@ def registration_form2(request, login_clipper = None, username = None):
user_form.fields['last_name'].initial = " ".join(bits[1:]) user_form.fields['last_name'].initial = " ".join(bits[1:])
registration_set_ro_fields(user_form, profile_form) registration_set_ro_fields(user_form, profile_form)
if username: if username:
member = get_object_or_404(User, username = username) member = get_object_or_404(User, username=username)
(profile, _) = CofProfile.objects.get_or_create(user = member) (profile, _) = CofProfile.objects.get_or_create(user=member)
# already existing, prefill # already existing, prefill
user_form = RegistrationUserForm(instance = member) user_form = RegistrationUserForm(instance=member)
profile_form = RegistrationProfileForm(instance = profile) profile_form = RegistrationProfileForm(instance=profile)
registration_set_ro_fields(user_form, profile_form) registration_set_ro_fields(user_form, profile_form)
event_forms = [] event_forms = []
for event in events: for event in events:
try: try:
current_registration = EventRegistration.objects.get(user = member, event = event) current_registration = EventRegistration.objects.get(user=member, event=event)
form = AdminEventForm(event = event, current_registration = current_registration, paid = current_registration.paid) form = AdminEventForm(event=event, current_registration=current_registration, paid=current_registration.paid)
except EventRegistration.DoesNotExist: except EventRegistration.DoesNotExist:
form = AdminEventForm(event = event) form = AdminEventForm(event=event)
event_forms.append(form) event_forms.append(form)
elif not login_clipper: elif not login_clipper:
# new user # new user
user_form = RegistrationUserForm() user_form = RegistrationUserForm()
profile_form = RegistrationProfileForm() profile_form = RegistrationProfileForm()
event_forms = [AdminEventForm(event = event) for event in events] event_forms = [AdminEventForm(event=event) for event in events]
return render(request, "registration_form.html", {"user_form": user_form, "profile_form": profile_form, "member": member, "login_clipper": login_clipper, "event_forms": event_forms}) return render(request, "registration_form.html", {"user_form": user_form, "profile_form": profile_form, "member": member, "login_clipper": login_clipper, "event_forms": event_forms})
@buro_required @buro_required
def registration(request): def registration(request):
if request.POST: if request.POST:
@ -337,59 +349,62 @@ def registration(request):
success = False success = False
user_form = RegistrationUserForm(request_dict) user_form = RegistrationUserForm(request_dict)
profile_form = RegistrationProfileForm(request_dict) profile_form = RegistrationProfileForm(request_dict)
events = Event.objects.filter(old = False).all() events = Event.objects.filter(old=False).all()
event_forms = [AdminEventForm(request_dict, event = event) for event in events] event_forms = [AdminEventForm(request_dict, event=event) for event in events]
user_form.is_valid() user_form.is_valid()
profile_form.is_valid() profile_form.is_valid()
for event_form in event_forms: event_form.is_valid() for event_form in event_forms:
event_form.is_valid()
member = None member = None
login_clipper = None login_clipper = None
if "user_exists" in request_dict and request_dict["user_exists"]: if "user_exists" in request_dict and request_dict["user_exists"]:
username = request_dict["username"] username = request_dict["username"]
try: try:
member = User.objects.filter(username = username).get() member = User.objects.filter(username=username).get()
(profile, _) = CofProfile.objects.get_or_create(user = member) (profile, _) = CofProfile.objects.get_or_create(user=member)
user_form = RegistrationUserForm(request_dict, instance = member) user_form = RegistrationUserForm(request_dict, instance=member)
profile_form = RegistrationProfileForm(request_dict, instance = profile) profile_form = RegistrationProfileForm(request_dict, instance=profile)
except User.DoesNotExist: except User.DoesNotExist:
try: try:
clipper = Clipper.objects.filter(username = username).get() clipper = Clipper.objects.filter(username=username).get()
login_clipper = clipper.username login_clipper = clipper.username
except Clipper.DoesNotExist: except Clipper.DoesNotExist:
pass pass
for form in event_forms: for form in event_forms:
if not form.is_valid(): break if not form.is_valid():
if form.cleaned_data['status'] == 'no': continue break
if form.cleaned_data['status'] == 'no':
continue
all_choices = get_event_form_choices(form.event, form) all_choices = get_event_form_choices(form.event, form)
if user_form.is_valid() and profile_form.is_valid() and not any([not form.is_valid() for form in event_forms]): if user_form.is_valid() and profile_form.is_valid() and not any([not form.is_valid() for form in event_forms]):
member = user_form.save() member = user_form.save()
(profile, _) = CofProfile.objects.get_or_create(user = member) (profile, _) = CofProfile.objects.get_or_create(user=member)
was_cof = profile.is_cof was_cof = profile.is_cof
request_dict["num"] = profile.num request_dict["num"] = profile.num
profile_form = RegistrationProfileForm(request_dict, instance = profile) profile_form = RegistrationProfileForm(request_dict, instance=profile)
profile_form.is_valid() profile_form.is_valid()
profile_form.save() profile_form.save()
(profile, _) = CofProfile.objects.get_or_create(user = member) (profile, _) = CofProfile.objects.get_or_create(user=member)
if profile.is_cof and not was_cof: if profile.is_cof and not was_cof:
send_custom_mail(member, "bienvenue") send_custom_mail(member, "bienvenue")
for form in event_forms: for form in event_forms:
if form.cleaned_data['status'] == 'no': if form.cleaned_data['status'] == 'no':
try: try:
current_registration = EventRegistration.objects.get(user = member, event = form.event) current_registration = EventRegistration.objects.get(user=member, event=form.event)
current_registration.delete() current_registration.delete()
except EventRegistration.DoesNotExist: except EventRegistration.DoesNotExist:
pass pass
continue continue
all_choices = get_event_form_choices(form.event, form) all_choices = get_event_form_choices(form.event, form)
(current_registration, created_reg) = EventRegistration.objects.get_or_create(user = member, event = form.event) (current_registration, created_reg) = EventRegistration.objects.get_or_create(user=member, event=form.event)
update_event_form_comments(event, form, current_registration) update_event_form_comments(event, form, current_registration)
current_registration.options = all_choices current_registration.options = all_choices
current_registration.paid = (form.cleaned_data['status'] == 'paid') current_registration.paid = (form.cleaned_data['status'] == 'paid')
current_registration.save() current_registration.save()
if event.title == "Mega 15" and created_reg: if event.title == "Mega 15" and created_reg:
field = EventCommentField.objects.get(event = event, name = "Commentaires") field = EventCommentField.objects.get(event=event, name="Commentaires")
try: try:
comments = EventCommentValue.objects.get(commentfield = field, registration = current_registration).content comments = EventCommentValue.objects.get(commentfield=field, registration=current_registration).content
except EventCommentValue.DoesNotExist: except EventCommentValue.DoesNotExist:
comments = field.default comments = field.default
send_custom_mail(member, "mega", {"remarques": comments}) send_custom_mail(member, "mega", {"remarques": comments})
@ -398,22 +413,24 @@ def registration(request):
else: else:
return render(request, "registration.html") return render(request, "registration.html")
@buro_required @buro_required
def export_members(request): def export_members(request):
response = HttpResponse(content_type = 'text/csv') response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=membres_cof.csv' response['Content-Disposition'] = 'attachment; filename=membres_cof.csv'
writer = unicodecsv.writer(response) writer = unicodecsv.writer(response)
for profile in CofProfile.objects.filter(is_cof = True).all(): for profile in CofProfile.objects.filter(is_cof=True).all():
user = profile.user user = profile.user
bits = [profile.num, user.username, user.first_name, user.last_name, user.email, profile.phone, profile.occupation, profile.departement, profile.type_cotiz] bits = [profile.num, user.username, user.first_name, user.last_name, user.email, profile.phone, profile.occupation, profile.departement, profile.type_cotiz]
writer.writerow([unicode(bit) for bit in bits]) writer.writerow([unicode(bit) for bit in bits])
return response return response
@buro_required @buro_required
def csv_export_mega(filename, qs): def csv_export_mega(filename, qs):
response = HttpResponse(content_type = 'text/csv') response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=' + filename response['Content-Disposition'] = 'attachment; filename=' + filename
writer = unicodecsv.writer(response) writer = unicodecsv.writer(response)
@ -426,15 +443,16 @@ def csv_export_mega(filename, qs):
return response return response
@buro_required @buro_required
def export_mega_remarksonly(request): def export_mega_remarksonly(request):
filename = 'remarques_mega_2015.csv' filename = 'remarques_mega_2015.csv'
response = HttpResponse(content_type = 'text/csv') response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=' + filename response['Content-Disposition'] = 'attachment; filename=' + filename
writer = unicodecsv.writer(response) writer = unicodecsv.writer(response)
event = Event.objects.get(title = "Mega 15") event = Event.objects.get(title="Mega 15")
commentfield = event.commentfields.get(name = "Commentaires") commentfield = event.commentfields.get(name="Commentaires")
for val in commentfield.values.all(): for val in commentfield.values.all():
reg = val.registration reg = val.registration
user = reg.user user = reg.user
@ -444,6 +462,7 @@ def export_mega_remarksonly(request):
return response return response
@buro_required @buro_required
def export_mega_bytype(request, type): def export_mega_bytype(request, type):
types = {"orga-actif": "Orga élève", types = {"orga-actif": "Orga élève",
@ -454,60 +473,67 @@ def export_mega_bytype(request, type):
if type not in types: if type not in types:
raise Http404 raise Http404
event = Event.objects.get(title = "Mega 15") event = Event.objects.get(title="Mega 15")
type_option = event.options.get(name = "Type") type_option = event.options.get(name="Type")
participant_type = type_option.choices.get(value = types[type]).id participant_type = type_option.choices.get(value=types[type]).id
qs = EventRegistration.objects.filter(event = event).filter(options__id__exact = participant_type) qs = EventRegistration.objects.filter(event=event).filter(options__id__exact=participant_type)
return csv_export_mega(type + '_mega_2015.csv', qs) return csv_export_mega(type + '_mega_2015.csv', qs)
@buro_required @buro_required
def export_mega_orgas(request): def export_mega_orgas(request):
event = Event.objects.get(title = "Mega 15") event = Event.objects.get(title="Mega 15")
type_option = event.options.get(name = "Type") type_option = event.options.get(name="Type")
participant_type_a = type_option.choices.get(value = "Conscrit étudiant").id participant_type_a = type_option.choices.get(value="Conscrit étudiant").id
participant_type_b = type_option.choices.get(value = "Conscrit élève").id participant_type_b = type_option.choices.get(value="Conscrit élève").id
qs = EventRegistration.objects.filter(event = event).exclude(options__id__in = (participant_type_a, participant_type_b)) qs = EventRegistration.objects.filter(event=event).exclude(options__id__in=(participant_type_a, participant_type_b))
return csv_export_mega('orgas_mega_15.csv', qs) return csv_export_mega('orgas_mega_15.csv', qs)
@buro_required @buro_required
def export_mega_participants(request): def export_mega_participants(request):
event = Event.objects.get(title = "Mega 15") event = Event.objects.get(title="Mega 15")
type_option = event.options.get(name = "Type") type_option = event.options.get(name="Type")
participant_type_a = type_option.choices.get(value = "Conscrit étudiant").id participant_type_a = type_option.choices.get(value="Conscrit étudiant").id
participant_type_b = type_option.choices.get(value = "Conscrit élève").id participant_type_b = type_option.choices.get(value="Conscrit élève").id
qs = EventRegistration.objects.filter(event = event).filter(options__id__in = (participant_type_a, participant_type_b)) qs = EventRegistration.objects.filter(event=event).filter(options__id__in=(participant_type_a, participant_type_b))
return csv_export_mega('participants_mega_15.csv', qs) return csv_export_mega('participants_mega_15.csv', qs)
@buro_required @buro_required
def export_mega(request): def export_mega(request):
event = Event.objects.filter(title = "Mega 15") event = Event.objects.filter(title="Mega 15")
qs = EventRegistration.objects.filter(event = event).order_by("user__username") qs = EventRegistration.objects.filter(event=event).order_by("user__username")
return csv_export_mega('all_mega_2015.csv', qs) return csv_export_mega('all_mega_2015.csv', qs)
@buro_required @buro_required
def utile_cof(request): def utile_cof(request):
return render(request, "utile_cof.html", {}) return render(request, "utile_cof.html", {})
@buro_required @buro_required
def utile_bda(request): def utile_bda(request):
tirages = Tirage.objects.all() tirages = Tirage.objects.all()
return render(request, "utile_bda.html", {'tirages': tirages}) return render(request, "utile_bda.html", {'tirages': tirages})
@buro_required @buro_required
def liste_bdadiff(request): def liste_bdadiff(request):
titre = "BdA diffusion" titre = "BdA diffusion"
personnes = CofProfile.objects.filter(mailing_bda = True, is_cof = True).all() personnes = CofProfile.objects.filter(mailing_bda=True, is_cof=True).all()
return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes}) return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes})
@buro_required @buro_required
def liste_bdarevente(request): def liste_bdarevente(request):
titre = "BdA revente" titre = "BdA revente"
personnes = CofProfile.objects.filter(mailing_bda_revente = True, is_cof = True).all() personnes = CofProfile.objects.filter(mailing_bda_revente=True, is_cof=True).all()
return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes}) return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes})
@buro_required @buro_required
def liste_diffcof(request): def liste_diffcof(request):
titre = "Diffusion COF" titre = "Diffusion COF"
personnes = CofProfile.objects.filter(mailing_cof = True, is_cof = True).all() personnes = CofProfile.objects.filter(mailing_cof=True, is_cof=True).all()
return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes}) return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes})

View file

@ -22,7 +22,7 @@ if __name__ == "__main__":
clipper.save() clipper.save()
print "Updated", username print "Updated", username
else: else:
clipper = Clipper(username = username, fullname = fullname) clipper = Clipper(username=username, fullname=fullname)
clipper.save() clipper.save()
print "Created", username print "Created", username
print "[ DONE ]" print "[ DONE ]"

View file

@ -24,7 +24,7 @@ if __name__ == "__main__":
print "%d places" % available_slots print "%d places" % available_slots
print "%d participants" % len(members) print "%d participants" % len(members)
print "%d demandes" % len(choices) print "%d demandes" % len(choices)
print "%d places demandées" % (len(choices) + len(choices.filter(double = True).all())) print "%d places demandées" % (len(choices) + len(choices.filter(double=True).all()))
print "%.02f€ à brasser" % total_price print "%.02f€ à brasser" % total_price
print "Récupération: %.2fs" % (time.time() - start) print "Récupération: %.2fs" % (time.time() - start)
start_init = time.time() start_init = time.time()