Merge branch 'master' of git.eleves.ens.fr:cof-geek/gestioCOF into qwann/zolicss

This commit is contained in:
Qwann 2016-07-20 18:36:09 +02:00
commit fa4308b91e
34 changed files with 488 additions and 233 deletions

View file

@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-
""" """
WSGI config for myproject project. WSGI config for myproject project.
It exposes the WSGI callable as a module-level variable named ``application``. It exposes the WSGI callable as a module-level variable named ``application``.
@ -5,6 +7,10 @@ For more information on this file, see
https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
""" """
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import os import os
from django.core.wsgi import get_wsgi_application from django.core.wsgi import get_wsgi_application

View file

@ -1,4 +1,8 @@
# coding: utf-8 # -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.core.mail import send_mail from django.core.mail import send_mail
@ -52,9 +56,9 @@ class ParticipantAdmin(admin.ModelAdmin):
def total(self, obj): def total(self, obj):
tot = obj.total tot = obj.total
if tot: if tot:
return u"%.02f" % tot return "%.02f" % tot
else: else:
return u"0 €" return "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",
@ -70,7 +74,7 @@ class ParticipantAdmin(admin.ModelAdmin):
for member in queryset.all(): for member in queryset.all():
attribs = member.attributions.all() attribs = member.attributions.all()
if len(attribs) == 0: if len(attribs) == 0:
mail = u"""Cher-e %s, mail = """Cher-e %s,
Tu t'es inscrit-e pour le tirage au sort du BdA. Malheureusement, tu n'as Tu t'es inscrit-e pour le tirage au sort du BdA. Malheureusement, tu n'as
obtenu aucune place. obtenu aucune place.
@ -85,7 +89,7 @@ Le Bureau des Arts
name = member.user.get_full_name() name = member.user.get_full_name()
mail = mail % name mail = mail % name
else: else:
mail = u"""Cher-e %s, mail = """Cher-e %s,
Tu t'es inscrit-e pour le tirage au sort du BdA. Tu as été sélectionné-e Tu t'es inscrit-e pour le tirage au sort du BdA. Tu as été sélectionné-e
pour les spectacles suivants : pour les spectacles suivants :
@ -120,7 +124,7 @@ Le Bureau des Arts
attribs_text = "" attribs_text = ""
name = member.user.get_full_name() name = member.user.get_full_name()
for attrib in attribs: for attrib in attribs:
attribs_text += u"- 1 place pour %s\n" % attrib attribs_text += "- 1 place pour %s\n" % attrib
deadline = member.tirage.fermeture + timedelta(days=7) deadline = member.tirage.fermeture + timedelta(days=7)
mail = mail % (name, attribs_text, mail = mail % (name, attribs_text,
deadline.strftime('%d %b %Y')) deadline.strftime('%d %b %Y'))
@ -129,14 +133,14 @@ Le Bureau des Arts
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 = "1 membre a"
plural = "" plural = ""
else: else:
message_bit = u"%d membres ont" % count message_bit = "%d membres ont" % count
plural = "s" plural = "s"
self.message_user(request, u"%s été informé%s avec succès." self.message_user(request, "%s été informé%s avec succès."
% (message_bit, plural)) % (message_bit, plural))
send_attribs.short_description = u"Envoyer les résultats par mail" send_attribs.short_description = "Envoyer les résultats par mail"
class AttributionAdminForm(forms.ModelForm): class AttributionAdminForm(forms.ModelForm):
@ -147,8 +151,8 @@ class AttributionAdminForm(forms.ModelForm):
if participant and spectacle: if participant and spectacle:
if participant.tirage != spectacle.tirage: if participant.tirage != spectacle.tirage:
raise forms.ValidationError( raise forms.ValidationError(
u"Erreur : le participant et le spectacle n'appartiennent" "Erreur : le participant et le spectacle n'appartiennent"
u"pas au même tirage") "pas au même tirage")
return cleaned_data return cleaned_data
@ -174,7 +178,8 @@ class ChoixSpectacleAdmin(admin.ModelAdmin):
list_filter = ("double_choice", "participant__tirage") list_filter = ("double_choice", "participant__tirage")
search_fields = ('participant__user__username', search_fields = ('participant__user__username',
'participant__user__first_name', 'participant__user__first_name',
'participant__user__last_name') 'participant__user__last_name',
'spectacle__title')
class SpectacleAdmin(admin.ModelAdmin): class SpectacleAdmin(admin.ModelAdmin):
@ -193,8 +198,14 @@ class TirageAdmin(admin.ModelAdmin):
list_filter = ("active", ) list_filter = ("active", )
search_fields = ("title", ) search_fields = ("title", )
class SalleAdmin(admin.ModelAdmin):
model = Salle
search_fields = ('name', 'address')
admin.site.register(Spectacle, SpectacleAdmin) admin.site.register(Spectacle, SpectacleAdmin)
admin.site.register(Salle) admin.site.register(Salle, SalleAdmin)
admin.site.register(Participant, ParticipantAdmin) admin.site.register(Participant, ParticipantAdmin)
admin.site.register(Attribution, AttributionAdmin) admin.site.register(Attribution, AttributionAdmin)
admin.site.register(ChoixSpectacle, ChoixSpectacleAdmin) admin.site.register(ChoixSpectacle, ChoixSpectacleAdmin)

View file

@ -1,6 +1,8 @@
# coding: utf-8 # -*- coding: utf-8 -*-
from __future__ import division from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.db.models import Max from django.db.models import Max

View file

@ -1,3 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import autocomplete_light import autocomplete_light
from bda.models import Participant, Spectacle from bda.models import Participant, Spectacle

View file

@ -1,4 +1,8 @@
# coding: utf-8 # -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django import forms from django import forms
from django.forms.models import BaseInlineFormSet from django.forms.models import BaseInlineFormSet
@ -33,8 +37,8 @@ class TokenForm(forms.Form):
class SpectacleModelChoiceField(forms.ModelChoiceField): class SpectacleModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj): def label_from_instance(self, obj):
return u"%s le %s (%s) à %.02f" % (obj.title, obj.date_no_seconds(), return "%s le %s (%s) à %.02f" % (obj.title, obj.date_no_seconds(),
obj.location, obj.price) obj.location, obj.price)
class ResellForm(forms.Form): class ResellForm(forms.Form):

View file

View file

View file

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.core.management.base import BaseCommand
from django.utils import timezone
from datetime import timedelta
from bda.models import Spectacle
class Command(BaseCommand):
help = 'Envoie les mails de rappel des spectacles dont la date ' \
'approche.\nNe renvoie pas les mails déjà envoyés.'
def handle(self, *args, **options):
now = timezone.now()
delay = timedelta(days=4)
shows = Spectacle.objects \
.filter(date__range=(now, now+delay)) \
.filter(tirage__active=True) \
.filter(rappel_sent__isnull=True) \
.all()
for show in shows:
show.send_rappel()
self.stdout.write(
'Mails de rappels pour %s envoyés avec succès.' % show)
if not shows:
self.stdout.write('Aucun mail à envoyer.')

View file

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bda', '0004_mails-rappel'),
]
operations = [
migrations.AlterField(
model_name='choixspectacle',
name='priority',
field=models.PositiveIntegerField(verbose_name='Priorit\xe9'),
),
migrations.AlterField(
model_name='spectacle',
name='priority',
field=models.IntegerField(default=1000, verbose_name='Priorit\xe9'),
),
migrations.AlterField(
model_name='spectacle',
name='rappel_sent',
field=models.DateTimeField(null=True, verbose_name='Mail de rappel envoy\xe9', blank=True),
),
]

View file

@ -1,4 +1,8 @@
# coding: utf-8 # -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import calendar import calendar
@ -8,6 +12,7 @@ from django.template import loader, Context
from django.core import mail from django.core import mail
from django.conf import settings from django.conf import settings
from django.utils import timezone from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible
def render_template(template_name, data): def render_template(template_name, data):
@ -16,6 +21,7 @@ def render_template(template_name, data):
return tmpl.render(ctxt) return tmpl.render(ctxt)
@python_2_unicode_compatible
class Tirage(models.Model): class Tirage(models.Model):
title = models.CharField("Titre", max_length=300) title = models.CharField("Titre", max_length=300)
ouverture = models.DateTimeField("Date et heure d'ouverture du tirage") ouverture = models.DateTimeField("Date et heure d'ouverture du tirage")
@ -26,18 +32,20 @@ class Tirage(models.Model):
def date_no_seconds(self): def date_no_seconds(self):
return self.fermeture.strftime('%d %b %Y %H:%M') return self.fermeture.strftime('%d %b %Y %H:%M')
def __unicode__(self): def __str__(self):
return u"%s - %s" % (self.title, self.date_no_seconds()) return "%s - %s" % (self.title, self.date_no_seconds())
@python_2_unicode_compatible
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 __str__(self):
return self.name return self.name
@python_2_unicode_compatible
class Spectacle(models.Model): class Spectacle(models.Model):
title = models.CharField("Titre", max_length=300) title = models.CharField("Titre", max_length=300)
date = models.DateTimeField("Date & heure") date = models.DateTimeField("Date & heure")
@ -57,7 +65,7 @@ class Spectacle(models.Model):
ordering = ("priority", "date", "title",) ordering = ("priority", "date", "title",)
def __repr__(self): def __repr__(self):
return u"[%s]" % self.__unicode__() return "[%s]" % self
def timestamp(self): def timestamp(self):
return "%d" % calendar.timegm(self.date.utctimetuple()) return "%d" % calendar.timegm(self.date.utctimetuple())
@ -65,9 +73,9 @@ 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 __str__(self):
return u"%s - %s, %s, %.02f" % (self.title, self.date_no_seconds(), return "%s - %s, %s, %.02f" % (self.title, self.date_no_seconds(),
self.location, self.price) self.location, self.price)
def send_rappel(self): def send_rappel(self):
# On récupère la liste des participants # On récupère la liste des participants
@ -102,13 +110,14 @@ class Spectacle(models.Model):
return members.values() return members.values()
PAYMENT_TYPES = ( PAYMENT_TYPES = (
("cash", u"Cash"), ("cash", "Cash"),
("cb", "CB"), ("cb", "CB"),
("cheque", u"Chèque"), ("cheque", "Chèque"),
("autre", u"Autre"), ("autre", "Autre"),
) )
@python_2_unicode_compatible
class Participant(models.Model): class Participant(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
choices = models.ManyToManyField(Spectacle, choices = models.ManyToManyField(Spectacle,
@ -117,14 +126,14 @@ 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("A payé", default=False)
paymenttype = models.CharField(u"Moyen de paiement", paymenttype = models.CharField("Moyen de paiement",
max_length=6, choices=PAYMENT_TYPES, max_length=6, choices=PAYMENT_TYPES,
blank=True) blank=True)
tirage = models.ForeignKey(Tirage) tirage = models.ForeignKey(Tirage)
def __unicode__(self): def __str__(self):
return u"%s" % (self.user) return "%s - %s" % (self.user, self.tirage.title)
DOUBLE_CHOICES = ( DOUBLE_CHOICES = (
("1", "1 place"), ("1", "1 place"),
@ -133,6 +142,7 @@ DOUBLE_CHOICES = (
) )
@python_2_unicode_compatible
class ChoixSpectacle(models.Model): class ChoixSpectacle(models.Model):
participant = models.ForeignKey(Participant) participant = models.ForeignKey(Participant)
spectacle = models.ForeignKey(Spectacle, related_name="participants") spectacle = models.ForeignKey(Spectacle, related_name="participants")
@ -149,6 +159,11 @@ class ChoixSpectacle(models.Model):
return self.double_choice == "autoquit" return self.double_choice == "autoquit"
autoquit = property(get_autoquit) autoquit = property(get_autoquit)
def __str__(self):
return "Vœux de %s pour %s" % (
self.participant.user.get_full_name,
self.spectacle.title)
class Meta: class Meta:
ordering = ("priority",) ordering = ("priority",)
unique_together = (("participant", "spectacle",),) unique_together = (("participant", "spectacle",),)
@ -156,10 +171,11 @@ class ChoixSpectacle(models.Model):
verbose_name_plural = "voeux" verbose_name_plural = "voeux"
@python_2_unicode_compatible
class Attribution(models.Model): class Attribution(models.Model):
participant = models.ForeignKey(Participant) participant = models.ForeignKey(Participant)
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("Donnée", default=False)
def __unicode__(self): def __str__(self):
return u"%s -- %s" % (self.participant, self.spectacle) return "%s -- %s" % (self.participant, self.spectacle)

View file

@ -1,4 +1,5 @@
{% extends "base_title.html" %} {% extends "base_title.html" %}
{% load staticfiles %}
{% block realcontent %} {% block realcontent %}
<h2>État des inscriptions BdA</h2> <h2>État des inscriptions BdA</h2>
@ -39,8 +40,10 @@
</tbody> </tbody>
</table> </table>
<strong>Total : <u>{{ total }} demandes</u></strong> <strong>Total : <u>{{ total }} demandes</u></strong>
<script type="text/javascript" src="/gestion/media/js/jquery.min.js"></script> <script type="text/javascript"
<script type="text/javascript" src="/gestion/media/js/joequery-Stupid-Table-Plugin/stupidtable.js"></script> src="{% static "js/jquery.min.js" %}"></script>
<script type="text/javascript"
src="{% static "js/joequery-Stupid-Table-Plugin/stupidtable.js" %}"></script>
<script type="text/javascript"> <script type="text/javascript">
$(function(){ $(function(){
$("table.etat-bda").stupidtable(); $("table.etat-bda").stupidtable();

View file

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
""" """
This file demonstrates writing tests using the unittest module. These will pass This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test". when you run "manage.py test".
@ -5,6 +6,11 @@ when you run "manage.py test".
Replace this with more appropriate tests for your application. Replace this with more appropriate tests for your application.
""" """
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.test import TestCase from django.test import TestCase

View file

@ -1,5 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.conf.urls import url, patterns from django.conf.urls import url, patterns
from bda.views import SpectacleListView from bda.views import SpectacleListView

View file

@ -1,6 +1,8 @@
# coding: utf-8 # -*- coding: utf-8 -*-
from __future__ import division from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.shortcuts import render, get_object_or_404 from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
@ -64,7 +66,7 @@ def etat_places(request, tirage_id):
def _hash_queryset(queryset): def _hash_queryset(queryset):
data = serializers.serialize("json", queryset) data = serializers.serialize("json", queryset).encode()
hasher = hashlib.sha256() hasher = hashlib.sha256()
hasher.update(data) hasher.update(data)
return hasher.hexdigest() return hasher.hexdigest()
@ -145,7 +147,7 @@ def inscription(request, tirage_id):
return render(request, "resume_inscription.html", return render(request, "resume_inscription.html",
{"error_title": "C'est fini !", {"error_title": "C'est fini !",
"error_description": "error_description":
u"Tirage au sort dans la journée !", "Tirage au sort dans la journée !",
"choices": choices}) "choices": choices})
def formfield_callback(f, **kwargs): def formfield_callback(f, **kwargs):
@ -194,7 +196,7 @@ 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)
if not form.is_valid(): if not form.is_valid():
return tirage(request) return tirage(request, tirage_id)
tirage_elt.token = form.cleaned_data['token'] tirage_elt.token = form.cleaned_data['token']
tirage_elt.save() tirage_elt.save()
start = time.time() start = time.time()
@ -223,7 +225,7 @@ def do_tirage(request, tirage_id):
deficit = (show.slots - len(members)) * show.price deficit = (show.slots - len(members)) * show.price
total_sold += show.slots * show.price total_sold += show.slots * show.price
if deficit >= 0: if deficit >= 0:
if u"Opéra" in show.location.name: if "Opéra" in show.location.name:
opera_deficit += deficit opera_deficit += deficit
total_deficit += deficit total_deficit += deficit
data["total_sold"] = total_sold - total_deficit data["total_sold"] = total_sold - total_deficit
@ -277,7 +279,7 @@ 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"]
places = "2 places" if count == "2" else "une place" places = "2 places" if count == "2" else "une place"
mail = u"""Bonjour, mail = """Bonjour,
Je souhaite revendre %s pour %s le %s (%s) à %.02f. Je souhaite revendre %s pour %s le %s (%s) à %.02f.
Contactez moi par email si vous êtes intéressé·e·s ! Contactez moi par email si vous êtes intéressé·e·s !

View file

@ -1,5 +1,4 @@
# -*-coding:utf-8 -* # -*- coding: utf-8 -*-
""" """
Django settings for cof project. Django settings for cof project.
@ -10,6 +9,10 @@ For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/ https://docs.djangoproject.com/en/1.8/ref/settings/
""" """
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os import os

View file

@ -1,15 +1,17 @@
# -*-coding:utf-8 -* # -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
from django.conf.urls import patterns, include, url from django.conf.urls import patterns, include, url
from django.conf.urls.static import static from django.conf.urls.static import static
from django.contrib import admin
from django.views.generic.base import TemplateView
import autocomplete_light import autocomplete_light
from django.contrib import admin
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
@ -75,7 +77,7 @@ urlpatterns = patterns(
url(r'^utile_bda/bda_revente$', 'gestioncof.views.liste_bdarevente'), url(r'^utile_bda/bda_revente$', 'gestioncof.views.liste_bdarevente'),
) + \ ) + \
(static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) (static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
if settings.DEBUG if settings.DEBUG
else []) else [])
# Si on est en production, MEDIA_ROOT est servi par Apache. # Si on est en production, MEDIA_ROOT est servi par Apache.
# Il faut dire à Django de servir MEDIA_ROOT lui-même en développement. # Il faut dire à Django de servir MEDIA_ROOT lui-même en développement.

View file

@ -1,4 +1,8 @@
# coding: utf-8 # -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.contrib import admin from django.contrib import admin
from gestioncof.models import * from gestioncof.models import *
@ -8,12 +12,13 @@ from django.contrib.auth.admin import UserAdmin
from django.core.urlresolvers import reverse 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 _
import django.utils.six as six
import autocomplete_light import autocomplete_light
def add_link_field(target_model='', field='', link_text=unicode, def add_link_field(target_model='', field='', link_text=six.text_type,
desc_text=unicode): desc_text=six.text_type):
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()
@ -46,12 +51,14 @@ class SurveyQuestionInline(admin.TabularInline):
class SurveyQuestionAdmin(admin.ModelAdmin): class SurveyQuestionAdmin(admin.ModelAdmin):
search_fields = ('survey__title', 'answer')
inlines = [ inlines = [
SurveyQuestionAnswerInline, SurveyQuestionAnswerInline,
] ]
class SurveyAdmin(admin.ModelAdmin): class SurveyAdmin(admin.ModelAdmin):
search_fields = ('title', 'details')
inlines = [ inlines = [
SurveyQuestionInline, SurveyQuestionInline,
] ]
@ -72,12 +79,14 @@ class EventCommentFieldInline(admin.TabularInline):
class EventOptionAdmin(admin.ModelAdmin): class EventOptionAdmin(admin.ModelAdmin):
search_fields = ('event__title', 'name')
inlines = [ inlines = [
EventOptionChoiceInline, EventOptionChoiceInline,
] ]
class EventAdmin(admin.ModelAdmin): class EventAdmin(admin.ModelAdmin):
search_fields = ('title', 'location', 'description')
inlines = [ inlines = [
EventOptionInline, EventOptionInline,
EventCommentFieldInline, EventCommentFieldInline,
@ -164,17 +173,21 @@ class UserProfileAdmin(UserAdmin):
] ]
# FIXME: This is absolutely horrible.
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 "%s %s (%s)" % (self.first_name, self.last_name, self.username)
else: else:
return self.username return self.username
User.__unicode__ = user_unicode if six.PY2:
User.__unicode__ = user_unicode
else:
User.__str__ = 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__' if six.PY2 else '__str__', 'event', 'user', 'paid')
list_filter = ('paid',) list_filter = ('paid',)
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')
@ -189,6 +202,7 @@ class PetitCoursAbilityAdmin(admin.ModelAdmin):
class PetitCoursAttributionAdmin(admin.ModelAdmin): class PetitCoursAttributionAdmin(admin.ModelAdmin):
list_display = ('user', 'demande', 'matiere', 'rank', ) list_display = ('user', 'demande', 'matiere', 'rank', )
search_fields = ('user__username', 'matiere__name')
class PetitCoursAttributionCounterAdmin(admin.ModelAdmin): class PetitCoursAttributionCounterAdmin(admin.ModelAdmin):
@ -201,13 +215,18 @@ class PetitCoursAttributionCounterAdmin(admin.ModelAdmin):
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 = "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')
list_filter = ('traitee', 'niveau') list_filter = ('traitee', 'niveau')
search_fields = ('name', 'email', 'phone', 'lieu', 'remarques')
class CustomMailAdmin(admin.ModelAdmin):
search_fields = ('shortname', 'title')
admin.site.register(Survey, SurveyAdmin) admin.site.register(Survey, SurveyAdmin)
admin.site.register(SurveyQuestion, SurveyQuestionAdmin) admin.site.register(SurveyQuestion, SurveyQuestionAdmin)

View file

@ -1,3 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django import shortcuts from django import shortcuts
from django.http import Http404 from django.http import Http404
from django.db.models import Q from django.db.models import Q

View file

@ -1,3 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import autocomplete_light import autocomplete_light
from django.contrib.auth.models import User from django.contrib.auth.models import User

View file

@ -1,3 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import csv import csv
from django.http import HttpResponse, HttpResponseForbidden from django.http import HttpResponse, HttpResponseForbidden
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify

View file

@ -1,3 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django_cas_ng.decorators import user_passes_test from django_cas_ng.decorators import user_passes_test

View file

@ -1,4 +1,8 @@
# coding: utf-8 # -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -169,8 +173,8 @@ class EventStatusFilterForm(forms.Form):
class UserProfileForm(forms.ModelForm): class UserProfileForm(forms.ModelForm):
first_name = forms.CharField(label=_(u'Prénom'), max_length=30) first_name = forms.CharField(label=_('Prénom'), max_length=30)
last_name = forms.CharField(label=_(u'Nom'), max_length=30) last_name = forms.CharField(label=_('Nom'), max_length=30)
def __init__(self, *args, **kw): def __init__(self, *args, **kw):
super(UserProfileForm, self).__init__(*args, **kw) super(UserProfileForm, self).__init__(*args, **kw)

View file

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('gestioncof', '0004_registration_mail'),
]
operations = [
migrations.AlterModelOptions(
name='custommail',
options={'verbose_name': 'Mail personnalisable', 'verbose_name_plural': 'Mails personnalisables'},
),
migrations.AlterModelOptions(
name='eventoptionchoice',
options={'verbose_name': 'Choix', 'verbose_name_plural': 'Choix'},
),
migrations.AlterField(
model_name='cofprofile',
name='is_buro',
field=models.BooleanField(default=False, verbose_name='Membre du Bur\xf4'),
),
migrations.AlterField(
model_name='cofprofile',
name='num',
field=models.IntegerField(default=0, verbose_name="Num\xe9ro d'adh\xe9rent", blank=True),
),
migrations.AlterField(
model_name='cofprofile',
name='phone',
field=models.CharField(max_length=20, verbose_name='T\xe9l\xe9phone', blank=True),
),
migrations.AlterField(
model_name='event',
name='old',
field=models.BooleanField(default=False, verbose_name='Archiver (\xe9v\xe9nement fini)'),
),
migrations.AlterField(
model_name='event',
name='start_date',
field=models.DateField(null=True, verbose_name='Date de d\xe9but', blank=True),
),
migrations.AlterField(
model_name='eventcommentfield',
name='default',
field=models.TextField(verbose_name='Valeur par d\xe9faut', blank=True),
),
migrations.AlterField(
model_name='eventregistration',
name='paid',
field=models.BooleanField(default=False, verbose_name='A pay\xe9'),
),
migrations.AlterField(
model_name='survey',
name='details',
field=models.TextField(verbose_name='D\xe9tails', blank=True),
),
migrations.AlterField(
model_name='surveyquestionanswer',
name='answer',
field=models.CharField(max_length=200, verbose_name='R\xe9ponse'),
),
]

View file

@ -1,53 +1,56 @@
# coding: utf-8 # -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import python_2_unicode_compatible
import django.utils.six as six
from django.db.models.signals import post_save from django.db.models.signals import post_save
from petits_cours_models import * from gestioncof.petits_cours_models import *
OCCUPATION_CHOICES = ( OCCUPATION_CHOICES = (
('exterieur', _(u"Extérieur")), ('exterieur', _("Extérieur")),
('1A', _(u"1A")), ('1A', _("1A")),
('2A', _(u"2A")), ('2A', _("2A")),
('3A', _(u"3A")), ('3A', _("3A")),
('4A', _(u"4A")), ('4A', _("4A")),
('archicube', _(u"Archicube")), ('archicube', _("Archicube")),
('doctorant', _(u"Doctorant")), ('doctorant', _("Doctorant")),
('CST', _(u"CST")), ('CST', _("CST")),
) )
TYPE_COTIZ_CHOICES = ( TYPE_COTIZ_CHOICES = (
('etudiant', _(u"Normalien étudiant")), ('etudiant', _("Normalien étudiant")),
('normalien', _(u"Normalien élève")), ('normalien', _("Normalien élève")),
('exterieur', _(u"Extérieur")), ('exterieur', _("Extérieur")),
) )
TYPE_COMMENT_FIELD = ( TYPE_COMMENT_FIELD = (
('text', _(u"Texte long")), ('text', _("Texte long")),
('char', _(u"Texte court")), ('char', _("Texte court")),
) )
def choices_length(choices): @python_2_unicode_compatible
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(_("Occupation"),
default="1A", default="1A",
choices=OCCUPATION_CHOICES, choices=OCCUPATION_CHOICES,
max_length=choices_length( max_length=choices_length(
OCCUPATION_CHOICES)) OCCUPATION_CHOICES))
departement = models.CharField(_(u"Département"), max_length=50, departement = models.CharField(_("Département"), max_length=50,
blank=True) blank=True)
type_cotiz = models.CharField(_(u"Type de cotisation"), type_cotiz = models.CharField(_("Type de cotisation"),
default="normalien", default="normalien",
choices=TYPE_COTIZ_CHOICES, choices=TYPE_COTIZ_CHOICES,
max_length=choices_length( max_length=choices_length(
@ -62,15 +65,15 @@ class CofProfile(models.Model):
petits_cours_accept = models.BooleanField( petits_cours_accept = models.BooleanField(
"Recevoir des petits cours", default=False) "Recevoir des petits cours", default=False)
petits_cours_remarques = models.TextField( petits_cours_remarques = models.TextField(
_(u"Remarques et précisions pour les petits cours"), _("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"
verbose_name_plural = "Profils COF" verbose_name_plural = "Profils COF"
def __unicode__(self): def __str__(self):
return unicode(self.user.username) return six.text_type(self.user.username)
def create_user_profile(sender, instance, created, **kwargs): def create_user_profile(sender, instance, created, **kwargs):
@ -79,13 +82,18 @@ def create_user_profile(sender, instance, created, **kwargs):
post_save.connect(create_user_profile, sender=User) post_save.connect(create_user_profile, sender=User)
@python_2_unicode_compatible
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")
def __str__(self):
return self.name
@python_2_unicode_compatible
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)
@ -97,10 +105,11 @@ class CustomMail(models.Model):
verbose_name = "Mail personnalisable" verbose_name = "Mail personnalisable"
verbose_name_plural = "Mails personnalisables" verbose_name_plural = "Mails personnalisables"
def __unicode__(self): def __str__(self):
return u"%s: %s" % (self.shortname, self.title) return "%s: %s" % (self.shortname, self.title)
@python_2_unicode_compatible
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)
@ -116,10 +125,11 @@ class Event(models.Model):
class Meta: class Meta:
verbose_name = "Événement" verbose_name = "Événement"
def __unicode__(self): def __str__(self):
return unicode(self.title) return six.text_type(self.title)
@python_2_unicode_compatible
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)
@ -130,17 +140,22 @@ class EventCommentField(models.Model):
class Meta: class Meta:
verbose_name = "Champ" verbose_name = "Champ"
def __unicode__(self): def __str__(self):
return unicode(self.name) return six.text_type(self.name)
@python_2_unicode_compatible
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", registration = models.ForeignKey("EventRegistration",
related_name="comments") related_name="comments")
content = models.TextField("Contenu", blank=True, null=True) content = models.TextField("Contenu", blank=True, null=True)
def __str__(self):
return "Commentaire de %s" % self.commentfield
@python_2_unicode_compatible
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)
@ -149,10 +164,11 @@ class EventOption(models.Model):
class Meta: class Meta:
verbose_name = "Option" verbose_name = "Option"
def __unicode__(self): def __str__(self):
return unicode(self.name) return six.text_type(self.name)
@python_2_unicode_compatible
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)
@ -161,10 +177,11 @@ class EventOptionChoice(models.Model):
verbose_name = "Choix" verbose_name = "Choix"
verbose_name_plural = "Choix" verbose_name_plural = "Choix"
def __unicode__(self): def __str__(self):
return unicode(self.value) return six.text_type(self.value)
@python_2_unicode_compatible
class EventRegistration(models.Model): class EventRegistration(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
event = models.ForeignKey(Event) event = models.ForeignKey(Event)
@ -177,11 +194,12 @@ class EventRegistration(models.Model):
verbose_name = "Inscription" verbose_name = "Inscription"
unique_together = ("user", "event") unique_together = ("user", "event")
def __unicode__(self): def __str__(self):
return u"Inscription de %s à %s" % (unicode(self.user), return "Inscription de %s à %s" % (six.text_type(self.user),
unicode(self.event.title)) six.text_type(self.event.title))
@python_2_unicode_compatible
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)
@ -191,10 +209,11 @@ class Survey(models.Model):
class Meta: class Meta:
verbose_name = "Sondage" verbose_name = "Sondage"
def __unicode__(self): def __str__(self):
return unicode(self.title) return six.text_type(self.title)
@python_2_unicode_compatible
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)
@ -203,10 +222,11 @@ class SurveyQuestion(models.Model):
class Meta: class Meta:
verbose_name = "Question" verbose_name = "Question"
def __unicode__(self): def __str__(self):
return unicode(self.question) return six.text_type(self.question)
@python_2_unicode_compatible
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)
@ -214,10 +234,11 @@ class SurveyQuestionAnswer(models.Model):
class Meta: class Meta:
verbose_name = "Réponse" verbose_name = "Réponse"
def __unicode__(self): def __str__(self):
return unicode(self.answer) return six.text_type(self.answer)
@python_2_unicode_compatible
class SurveyAnswer(models.Model): class SurveyAnswer(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
survey = models.ForeignKey(Survey) survey = models.ForeignKey(Survey)
@ -228,7 +249,16 @@ class SurveyAnswer(models.Model):
verbose_name = "Réponses" verbose_name = "Réponses"
unique_together = ("user", "survey") unique_together = ("user", "survey")
def __str__(self):
return "Réponse de %s sondage %s" % (
self.user.get_full_name(),
self.survey.title)
@python_2_unicode_compatible
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)
def __str__(self):
return "Clipper %s" % self.username

View file

@ -1,25 +1,32 @@
# coding: utf-8 # -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import python_2_unicode_compatible
from django.utils.six.moves import reduce
def choices_length(choices): def choices_length(choices):
return reduce(lambda m, choice: max(m, len(choice[0])), choices, 0) return reduce(lambda m, choice: max(m, len(choice[0])), choices, 0)
LEVELS_CHOICES = ( LEVELS_CHOICES = (
('college', _(u"Collège")), ('college', _("Collège")),
('lycee', _(u"Lycée")), ('lycee', _("Lycée")),
('prepa1styear', _(u"Prépa 1ère année / L1")), ('prepa1styear', _("Prépa 1ère année / L1")),
('prepa2ndyear', _(u"Prépa 2ème année / L2")), ('prepa2ndyear', _("Prépa 2ème année / L2")),
('licence3', _(u"Licence 3")), ('licence3', _("Licence 3")),
('other', _(u"Autre (préciser dans les commentaires)")), ('other', _("Autre (préciser dans les commentaires)")),
) )
@python_2_unicode_compatible
class PetitCoursSubject(models.Model): class PetitCoursSubject(models.Model):
name = models.CharField(_(u"Matière"), max_length=30) name = models.CharField(_("Matière"), max_length=30)
users = models.ManyToManyField(User, related_name="petits_cours_matieres", users = models.ManyToManyField(User, related_name="petits_cours_matieres",
through="PetitCoursAbility") through="PetitCoursAbility")
@ -27,91 +34,95 @@ class PetitCoursSubject(models.Model):
verbose_name = "Matière de petits cours" verbose_name = "Matière de petits cours"
verbose_name_plural = "Matières des petits cours" verbose_name_plural = "Matières des petits cours"
def __unicode__(self): def __str__(self):
return self.name return self.name
@python_2_unicode_compatible
class PetitCoursAbility(models.Model): class PetitCoursAbility(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_(u"Matière")) matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matière"))
niveau = models.CharField(_(u"Niveau"), niveau = models.CharField(_("Niveau"),
choices=LEVELS_CHOICES, choices=LEVELS_CHOICES,
max_length=choices_length(LEVELS_CHOICES)) max_length=choices_length(LEVELS_CHOICES))
agrege = models.BooleanField(_(u"Agrégé"), default=False) agrege = models.BooleanField(_("Agrégé"), default=False)
class Meta: class Meta:
verbose_name = "Compétence petits cours" verbose_name = "Compétence petits cours"
verbose_name_plural = "Compétences des petits cours" verbose_name_plural = "Compétences des petits cours"
def __unicode__(self): def __str__(self):
return u"%s - %s - %s" % (self.user.username, return "%s - %s - %s" % (self.user.username,
self.matiere, self.niveau) self.matiere, self.niveau)
@python_2_unicode_compatible
class PetitCoursDemande(models.Model): class PetitCoursDemande(models.Model):
name = models.CharField(_(u"Nom/prénom"), max_length=200) name = models.CharField(_("Nom/prénom"), max_length=200)
email = models.CharField(_(u"Adresse email"), max_length=300) email = models.CharField(_("Adresse email"), max_length=300)
phone = models.CharField(_(u"Téléphone (facultatif)"), phone = models.CharField(_("Téléphone (facultatif)"),
max_length=20, blank=True) max_length=20, blank=True)
quand = models.CharField( quand = models.CharField(
_(u"Quand ?"), _("Quand ?"),
help_text=_(u"Indiquez ici la période désirée pour les petits" help_text=_("Indiquez ici la période désirée pour les petits"
" cours (vacances scolaires, semaine, week-end)."), " cours (vacances scolaires, semaine, week-end)."),
max_length=300, blank=True) max_length=300, blank=True)
freq = models.CharField( freq = models.CharField(
_(u"Fréquence"), _("Fréquence"),
help_text=_(u"Indiquez ici la fréquence envisagée " help_text=_("Indiquez ici la fréquence envisagée "
+ "(hebdomadaire, 2 fois par semaine, ...)"), + "(hebdomadaire, 2 fois par semaine, ...)"),
max_length=300, blank=True) max_length=300, blank=True)
lieu = models.CharField( lieu = models.CharField(
_(u"Lieu (si préférence)"), _("Lieu (si préférence)"),
help_text=_(u"Si vous avez avez une préférence sur le lieu."), help_text=_("Si vous avez avez une préférence sur le lieu."),
max_length=300, blank=True) max_length=300, blank=True)
matieres = models.ManyToManyField( matieres = models.ManyToManyField(
PetitCoursSubject, verbose_name=_(u"Matières"), PetitCoursSubject, verbose_name=_("Matières"),
related_name="demandes") related_name="demandes")
agrege_requis = models.BooleanField(_(u"Agrégé requis"), default=False) agrege_requis = models.BooleanField(_("Agrégé requis"), default=False)
niveau = models.CharField(_(u"Niveau"), niveau = models.CharField(_("Niveau"),
default="", default="",
choices=LEVELS_CHOICES, choices=LEVELS_CHOICES,
max_length=choices_length(LEVELS_CHOICES)) max_length=choices_length(LEVELS_CHOICES))
remarques = models.TextField(_(u"Remarques et précisions"), blank=True) remarques = models.TextField(_("Remarques et précisions"), blank=True)
traitee = models.BooleanField(_(u"Traitée"), default=False) traitee = models.BooleanField(_("Traitée"), default=False)
traitee_par = models.ForeignKey(User, blank=True, null=True) traitee_par = models.ForeignKey(User, blank=True, null=True)
processed = models.DateTimeField(_(u"Date de traitement"), processed = models.DateTimeField(_("Date de traitement"),
blank=True, null=True) blank=True, null=True)
created = models.DateTimeField(_(u"Date de création"), auto_now_add=True) created = models.DateTimeField(_("Date de création"), auto_now_add=True)
class Meta: class Meta:
verbose_name = "Demande de petits cours" verbose_name = "Demande de petits cours"
verbose_name_plural = "Demandes de petits cours" verbose_name_plural = "Demandes de petits cours"
def __unicode__(self): def __str__(self):
return u"Demande %d du %s" % (self.id, return "Demande %d du %s" % (self.id,
self.created.strftime("%d %b %Y")) self.created.strftime("%d %b %Y"))
@python_2_unicode_compatible
class PetitCoursAttribution(models.Model): class PetitCoursAttribution(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
demande = models.ForeignKey(PetitCoursDemande, verbose_name=_("Demande")) demande = models.ForeignKey(PetitCoursDemande, verbose_name=_("Demande"))
matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_(u"Matière")) matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matière"))
date = models.DateTimeField(_(u"Date d'attribution"), auto_now_add=True) date = models.DateTimeField(_("Date d'attribution"), auto_now_add=True)
rank = models.IntegerField("Rang dans l'email") rank = models.IntegerField("Rang dans l'email")
selected = models.BooleanField(_(u"Sélectionné par le demandeur"), selected = models.BooleanField(_("Sélectionné par le demandeur"),
default=False) default=False)
class Meta: class Meta:
verbose_name = "Attribution de petits cours" verbose_name = "Attribution de petits cours"
verbose_name_plural = "Attributions de petits cours" verbose_name_plural = "Attributions de petits cours"
def __unicode__(self): def __str__(self):
return u"Attribution de la demande %d à %s pour %s" \ return "Attribution de la demande %d à %s pour %s" \
% (self.demande.id, self.user.username, self.matiere) % (self.demande.id, self.user.username, self.matiere)
@python_2_unicode_compatible
class PetitCoursAttributionCounter(models.Model): class PetitCoursAttributionCounter(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matiere")) matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matiere"))
@ -121,6 +132,6 @@ class PetitCoursAttributionCounter(models.Model):
verbose_name = "Compteur d'attribution de petits cours" verbose_name = "Compteur d'attribution de petits cours"
verbose_name_plural = "Compteurs d'attributions de petits cours" verbose_name_plural = "Compteurs d'attributions de petits cours"
def __unicode__(self): def __str__(self):
return u"%d demandes envoyées à %s pour %s" \ return "%d demandes envoyées à %s pour %s" \
% (self.count, self.user.username, self.matiere) % (self.count, self.user.username, self.matiere)

View file

@ -1,4 +1,8 @@
# coding: utf-8 # -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.shortcuts import render, get_object_or_404, redirect from django.shortcuts import render, get_object_or_404, redirect
from django.core import mail from django.core import mail
@ -181,12 +185,12 @@ def _traitement_other_preparing(request, demande):
if choice == -1: if choice == -1:
continue continue
if choice not in candidates: if choice not in candidates:
errors.append(u"Choix invalide pour la proposition %d" errors.append("Choix invalide pour la proposition %d"
"en %s" % (choice_id + 1, matiere)) "en %s" % (choice_id + 1, matiere))
continue continue
user = candidates[choice] user = candidates[choice]
if user in proposals[matiere]: if user in proposals[matiere]:
errors.append(u"La proposition %d en %s est un doublon" errors.append("La proposition %d en %s est un doublon"
% (choice_id + 1, matiere)) % (choice_id + 1, matiere))
continue continue
proposals[matiere].append(user) proposals[matiere].append(user)
@ -196,9 +200,9 @@ def _traitement_other_preparing(request, demande):
else: else:
proposed_for[user].append(matiere) proposed_for[user].append(matiere)
if not proposals[matiere]: if not proposals[matiere]:
errors.append(u"Aucune proposition pour %s" % (matiere,)) errors.append("Aucune proposition pour %s" % (matiere,))
elif len(proposals[matiere]) < 3: elif len(proposals[matiere]) < 3:
errors.append(u"Seulement %d proposition%s pour %s" errors.append("Seulement %d proposition%s pour %s"
% (len(proposals[matiere]), % (len(proposals[matiere]),
"s" if len(proposals[matiere]) > 1 else "", "s" if len(proposals[matiere]) > 1 else "",
matiere)) matiere))

View file

@ -1,3 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.conf import settings from django.conf import settings
from django_cas_ng.backends import CASBackend from django_cas_ng.backends import CASBackend

View file

@ -1,3 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django import template from django import template
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
@ -22,7 +28,7 @@ def highlight_text(text, q):
@register.filter @register.filter
def highlight_user(user, q): def highlight_user(user, q):
if user.first_name and user.last_name: if user.first_name and user.last_name:
text = u"%s %s (<tt>%s</tt>)" % (user.first_name, user.last_name, user.username) text = "%s %s (<tt>%s</tt>)" % (user.first_name, user.last_name, user.username)
else: else:
text = user.username text = user.username
return highlight_text(text, q) return highlight_text(text, q)
@ -30,7 +36,7 @@ def highlight_user(user, q):
@register.filter @register.filter
def highlight_clipper(clipper, q): def highlight_clipper(clipper, q):
if clipper.fullname: if clipper.fullname:
text = u"%s (<tt>%s</tt>)" % (clipper.fullname, clipper.username) text = "%s (<tt>%s</tt>)" % (clipper.fullname, clipper.username)
else: else:
text = clipper.username text = clipper.username
return highlight_text(text, q) return highlight_text(text, q)

View file

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
""" """
This file demonstrates writing tests using the unittest module. These will pass This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test". when you run "manage.py test".
@ -5,6 +6,10 @@ when you run "manage.py test".
Replace this with more appropriate tests for your application. Replace this with more appropriate tests for your application.
""" """
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.test import TestCase from django.test import TestCase

View file

@ -1,3 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.conf.urls import url from django.conf.urls import url
from gestioncof.petits_cours_views import DemandeListView from gestioncof.petits_cours_views import DemandeListView

View file

@ -1,4 +1,8 @@
# coding: utf-8 # -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import unicodecsv import unicodecsv
@ -7,6 +11,7 @@ from django.http import Http404, HttpResponse
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import login as django_login_view from django.contrib.auth.views import login as django_login_view
from django.contrib.auth.models import User from django.contrib.auth.models import User
import django.utils.six as six
from gestioncof.models import Survey, SurveyAnswer, SurveyQuestion, \ from gestioncof.models import Survey, SurveyAnswer, SurveyQuestion, \
SurveyQuestionAnswer SurveyQuestionAnswer
@ -453,13 +458,13 @@ def registration(request):
(current_registration, created_reg) = \ (current_registration, created_reg) = \
EventRegistration.objects.get_or_create(user=member, EventRegistration.objects.get_or_create(user=member,
event=form.event) event=form.event)
update_event_form_comments(event, form, current_registration) update_event_form_comments(form.event, form, current_registration)
current_registration.options = all_choices current_registration.options = all_choices
current_registration.paid = \ current_registration.paid = \
(form.cleaned_data['status'] == 'paid') (form.cleaned_data['status'] == 'paid')
current_registration.save() current_registration.save()
if event.title == "Mega 15" and created_reg: if form.event.title == "Mega 15" and created_reg:
field = EventCommentField.objects.get(event=event, field = EventCommentField.objects.get(event=form.event,
name="Commentaires") name="Commentaires")
try: try:
comments = EventCommentValue.objects.get( comments = EventCommentValue.objects.get(
@ -491,7 +496,7 @@ def export_members(request):
bits = [profile.num, user.username, user.first_name, user.last_name, bits = [profile.num, user.username, user.first_name, user.last_name,
user.email, profile.phone, profile.occupation, user.email, profile.phone, profile.occupation,
profile.departement, profile.type_cotiz] profile.departement, profile.type_cotiz]
writer.writerow([unicode(bit) for bit in bits]) writer.writerow([six.text_type(bit) for bit in bits])
return response return response
@ -511,7 +516,7 @@ def csv_export_mega(filename, qs):
profile.phone, profile.num, profile.phone, profile.num,
profile.comments if profile.comments else "", comments] profile.comments if profile.comments else "", comments]
writer.writerow([unicode(bit) for bit in bits]) writer.writerow([six.text_type(bit) for bit in bits])
return response return response
@ -531,7 +536,7 @@ def export_mega_remarksonly(request):
profile = user.profile profile = user.profile
bits = [user.username, user.first_name, user.last_name, user.email, bits = [user.username, user.first_name, user.last_name, user.email,
profile.phone, profile.num, profile.comments, val.content] profile.phone, profile.num, profile.comments, val.content]
writer.writerow([unicode(bit) for bit in bits]) writer.writerow([six.text_type(bit) for bit in bits])
return response return response

View file

@ -1,3 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.forms.widgets import Widget from django.forms.widgets import Widget
from django.forms.utils import flatatt from django.forms.utils import flatatt
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
@ -15,5 +21,5 @@ class TriStateCheckbox(Widget):
if value is None: if value is None:
value = 'none' value = 'none'
final_attrs = self.build_attrs(attrs, value=value) final_attrs = self.build_attrs(attrs, value=value)
output = [u"<span class=\"tristate\"%s></span>" % flatatt(final_attrs)] output = ["<span class=\"tristate\"%s></span>" % flatatt(final_attrs)]
return mark_safe('\n'.join(output)) return mark_safe('\n'.join(output))

View file

@ -1,4 +1,10 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import os import os
import sys import sys
@ -7,10 +13,10 @@ if __name__ == "__main__":
from gestioncof.models import Clipper from gestioncof.models import Clipper
current = {} current = {}
print "[ FETCHING ]" print("[ FETCHING ]")
for clipper in Clipper.objects.all(): for clipper in Clipper.objects.all():
current[clipper.username] = clipper current[clipper.username] = clipper
print "[ SYNCING ]" print("[ SYNCING ]")
for line in sys.stdin: for line in sys.stdin:
bits = line.split(":") bits = line.split(":")
username = bits[0] username = bits[0]
@ -20,9 +26,9 @@ if __name__ == "__main__":
if clipper.fullname != fullname: if clipper.fullname != fullname:
clipper.fullname = fullname clipper.fullname = fullname
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

@ -1,66 +0,0 @@
#!/usr/bin/env python
# coding: utf-8
import os
import sys
import time
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cof.settings")
from django.conf import settings
settings.DEBUG = True
from bda.models import Spectacle, Participant, ChoixSpectacle
from bda.algorithm import Algorithm
from django.db.models import Sum
from django.db import connection
start = time.time()
shows = Spectacle.objects.all()
members = Participant.objects.all()
choices = ChoixSpectacle.objects.order_by('participant', 'priority') \
.select_related().all()
available_slots = Spectacle.objects.aggregate(Sum('slots'))['slots__sum']
cursor = connection.cursor()
cursor.execute(
"SELECT SUM(`slots` * `price`) AS `total` FROM `bda_spectacle`;")
total_price = cursor.fetchone()[0]
print "%d spectacles" % len(shows)
print "%d places" % available_slots
print "%d participants" % len(members)
print "%d demandes" % len(choices)
print "%d places demandées" % (len(choices)
+ len(choices.filter(double=True).all()))
print "%.02f€ à brasser" % total_price
print "Récupération: %.2fs" % (time.time() - start)
start_init = time.time()
algo = Algorithm(shows, members, choices)
print "Initialisation: %.2fs" % (time.time() - start_init)
start_algo = time.time()
results = algo(sys.argv[1])
print "Traitement: %.2fs" % (time.time() - start_algo)
print len(connection.queries), "requêtes SQL effectuées"
queries = list(connection.queries)
total_slots = 0
total_losers = 0
for (_, members, losers) in results:
total_slots += len(members)
total_losers += len(losers)
print "Placés %d\nDécus %d" % (total_slots, total_losers)
print "Total %d" % (total_slots + total_losers)
members2 = {}
members_uniq = {}
for (show, members, _) in results:
for (member, _, _, _) in members:
if member.id not in members_uniq:
members_uniq[member.id] = member
members2[member] = []
member.total = 0
member = members_uniq[member.id]
members2[member].append(show)
member.total += show.price
if len(members) < show.slots:
print "%d place(s) invendue(s) pour %s" \
% (show.slots - len(members), show)
members2 = members2.items()
print "Temps total: %.2fs" % (time.time() - start)
print "Requêtes SQL:"
for query in queries:
print query['sql']