Merge branch 'master' into Kerl/fix_32_do_tirage

This commit is contained in:
Martin Pépin 2016-07-10 14:42:09 +02:00
commit 3aa9667eb9
28 changed files with 1010 additions and 605 deletions

View file

@ -9,86 +9,109 @@ from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
def add_link_field(target_model='', field='', link_text=unicode, desc_text=unicode):
import autocomplete_light
def add_link_field(target_model='', field='', link_text=unicode,
desc_text=unicode):
def add_link(cls):
reverse_name = target_model or cls.model.__name__.lower()
def link(self, instance):
app_name = instance._meta.app_label
reverse_path = "admin:%s_%s_change" % (app_name, reverse_name)
link_obj = getattr(instance, field, None) or instance
if not link_obj.id:
return ""
url = reverse(reverse_path, args = (link_obj.id,))
return mark_safe("<a href='%s'>%s</a>" % (url, link_text(link_obj)))
url = reverse(reverse_path, args=(link_obj.id,))
return mark_safe("<a href='%s'>%s</a>"
% (url, link_text(link_obj)))
link.allow_tags = True
link.short_description = desc_text(reverse_name + ' link')
cls.link = link
cls.readonly_fields = list(getattr(cls, 'readonly_fields', [])) + ['link']
cls.readonly_fields =\
list(getattr(cls, 'readonly_fields', [])) + ['link']
return cls
return add_link
class SurveyQuestionAnswerInline(admin.TabularInline):
model = SurveyQuestionAnswer
@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):
model = SurveyQuestion
class SurveyQuestionAdmin(admin.ModelAdmin):
inlines = [
SurveyQuestionAnswerInline,
]
SurveyQuestionAnswerInline,
]
class SurveyAdmin(admin.ModelAdmin):
inlines = [
SurveyQuestionInline,
]
SurveyQuestionInline,
]
class EventOptionChoiceInline(admin.TabularInline):
model = EventOptionChoice
@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):
model = EventOption
class EventCommentFieldInline(admin.TabularInline):
model = EventCommentField
class EventOptionAdmin(admin.ModelAdmin):
inlines = [
EventOptionChoiceInline,
]
EventOptionChoiceInline,
]
class EventAdmin(admin.ModelAdmin):
inlines = [
EventOptionInline,
EventCommentFieldInline,
]
EventOptionInline,
EventCommentFieldInline,
]
class CofProfileInline(admin.StackedInline):
model = CofProfile
inline_classes = ("collapse open",)
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.fkattrs = fkattrs.split('__')
self.short_description = short_description or self.fkattrs[-1]
self.admin_order_field = admin_order_field or fkeydecl
def __get__(self, obj, klass):
if obj is None:
return self # hack required to make Django validate (if obj is
# None, then we're a class, and classes are callable
# <wink>)
"""
hack required to make Django validate (if obj is
None, then we're a class, and classes are callable
<wink>)
"""
return self
item = getattr(obj, self.fk)
for attr in self.fkattrs:
item = getattr(item, attr)
return item
def ProfileInfo(field, short_description, boolean=False):
def getter(self):
try:
@ -99,14 +122,17 @@ def ProfileInfo(field, short_description, boolean=False):
getter.boolean = boolean
return getter
User.profile_login_clipper = FkeyLookup("profile__login_clipper", "Login clipper")
User.profile_login_clipper = FkeyLookup("profile__login_clipper",
"Login clipper")
User.profile_num = FkeyLookup("profile__num", "Numéro")
User.profile_phone = ProfileInfo("phone", "Téléphone")
User.profile_occupation = ProfileInfo("occupation", "Occupation")
User.profile_departement = ProfileInfo("departement", "Departement")
User.profile_mailing_cof = ProfileInfo("mailing_cof", "ML COF", 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):
def is_buro(self, obj):
@ -116,6 +142,7 @@ class UserProfileAdmin(UserAdmin):
return False
is_buro.short_description = 'Membre du Buro'
is_buro.boolean = True
def is_cof(self, obj):
try:
return obj.profile.is_cof
@ -124,57 +151,63 @@ class UserProfileAdmin(UserAdmin):
is_cof.short_description = 'Membre du COF'
is_cof.boolean = True
list_display = ('profile_num',) + UserAdmin.list_display \
+ ( 'profile_login_clipper','profile_phone','profile_occupation',
'profile_mailing_cof','profile_mailing_bda',
'profile_mailing_bda_revente','is_cof','is_buro',)
list_display_links = ('username','email','first_name','last_name')
+ ('profile_login_clipper', 'profile_phone', 'profile_occupation',
'profile_mailing_cof', 'profile_mailing_bda',
'profile_mailing_bda_revente', 'is_cof', 'is_buro', )
list_display_links = ('username', 'email', 'first_name', 'last_name')
list_filter = UserAdmin.list_filter \
+ ( 'profile__is_cof', 'profile__is_buro', 'profile__mailing_cof',
'profile__mailing_bda')
+ ('profile__is_cof', 'profile__is_buro', 'profile__mailing_cof',
'profile__mailing_bda')
search_fields = UserAdmin.search_fields + ('profile__phone',)
inlines = [
CofProfileInline,
]
CofProfileInline,
]
import autocomplete_light
def user_unicode(self):
if self.first_name and self.last_name:
return u"%s %s (%s)" % (self.first_name, self.last_name, self.username)
else:
return self.username
User.__unicode__ = user_unicode
class EventRegistrationAdmin(admin.ModelAdmin):
form = autocomplete_light.modelform_factory(EventRegistration, exclude=[])
list_display = ('__unicode__','event','user','paid')
list_display = ('__unicode__', 'event', 'user', 'paid')
list_filter = ('paid',)
search_fields = ('user__username', 'user__first_name', 'user__last_name',
'user__email', 'event__title')
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',
'user__email', 'matiere__name', 'niveau')
list_filter = ('matiere','niveau','agrege')
list_filter = ('matiere', 'niveau', 'agrege')
class PetitCoursAttributionAdmin(admin.ModelAdmin):
list_display = ('user','demande','matiere','rank',)
list_display = ('user', 'demande', 'matiere', 'rank', )
class PetitCoursAttributionCounterAdmin(admin.ModelAdmin):
list_display = ('user','matiere','count',)
list_display = ('user', 'matiere', 'count', )
list_filter = ('matiere',)
search_fields = ('user__username', 'user__first_name', 'user__last_name',
'user__email', 'matiere__name')
actions = ['reset',]
actions = ['reset', ]
actions_on_bottom = True
def reset(self, request, queryset):
queryset.update(count=0)
reset.short_description = u"Remise à zéro du compteur"
class PetitCoursDemandeAdmin(admin.ModelAdmin):
list_display = ('name','email','agrege_requis','niveau','created',
'traitee','processed')
list_filter = ('traitee','niveau')
list_display = ('name', 'email', 'agrege_requis', 'niveau', 'created',
'traitee', 'processed')
list_filter = ('traitee', 'niveau')
admin.site.register(Survey, SurveyAdmin)
admin.site.register(SurveyQuestion, SurveyQuestionAdmin)
@ -188,6 +221,7 @@ admin.site.register(CustomMail)
admin.site.register(PetitCoursSubject)
admin.site.register(PetitCoursAbility, PetitCoursAbilityAdmin)
admin.site.register(PetitCoursAttribution, PetitCoursAttributionAdmin)
admin.site.register(PetitCoursAttributionCounter, PetitCoursAttributionCounterAdmin)
admin.site.register(PetitCoursAttributionCounter,
PetitCoursAttributionCounterAdmin)
admin.site.register(PetitCoursDemande, PetitCoursDemandeAdmin)
admin.site.register(EventRegistration, EventRegistrationAdmin)

View file

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

View file

@ -2,5 +2,6 @@ import autocomplete_light
from django.contrib.auth.models import User
autocomplete_light.register(User, search_fields=('username','first_name','last_name'),
autocomplete_light.register(
User, search_fields=('username', 'first_name', 'last_name'),
autocomplete_js_attributes={'placeholder': 'membre...'})

View file

@ -3,10 +3,12 @@ from django.http import HttpResponse, HttpResponseForbidden
from django.template.defaultfilters import slugify
from django.apps import apps
def export(qs, fields=None):
model = qs.model
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=%s.csv' % slugify(model.__name__)
response['Content-Disposition'] = 'attachment; filename=%s.csv' \
% slugify(model.__name__)
writer = csv.writer(response)
# Write headers to CSV file
if fields:
@ -29,17 +31,20 @@ def export(qs, fields=None):
# Return CSV file to browser as download
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
(r'^admin/(?P<app_label>[\d\w]+)/(?P<model_name>[\d\w]+)/csv/', 'util.csv_view.admin_list_export'),
(r'^admin/(?P<app_label>[\d\w]+)/(?P<model_name>[\d\w]+)/csv/',
'util.csv_view.admin_list_export'),
"""
if not request.user.is_staff:
return HttpResponseForbidden()
if not queryset:
model = apps.get_model(app_label, model_name)
queryset = model.objects.all()
queryset = queryset.filter(profile__is_cof = True)
queryset = queryset.filter(profile__is_cof=True)
if not fields:
if list_display and len(queryset.model._meta.admin.list_display) > 1:
fields = queryset.model._meta.admin.list_display
@ -47,12 +52,17 @@ def admin_list_export(request, model_name, app_label, queryset=None, fields=None
fields = None
return export(queryset, fields)
"""
Create your own change_list.html for your admin view and put something like this in it:
Create your own change_list.html for your admin view and put something
like this in it:
{% block object-tools %}
<ul class="object-tools">
<li><a href="csv/{%if request.GET%}?{{request.GET.urlencode}}{%endif%}" class="addlink">Export to CSV</a></li>
<li><a href="csv/{%if request.GET%}?{{request.GET.urlencode}}
{%endif%}" class="addlink">Export to CSV</a></li>
{% if has_add_permission %}
<li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name|escape as name %}Add {{ name }}{% endblocktrans %}</a></li>
<li><a href="add/{% if is_popup %}?_popup=1{% endif %}"
class="addlink">
{% blocktrans with cl.opts.verbose_name|escape as name %}
Add {{ name }}{% endblocktrans %}</a></li>
{% endif %}
</ul>
{% endblock %}

View file

@ -1,5 +1,6 @@
from django_cas_ng.decorators import user_passes_test
def is_cof(user):
try:
profile = user.profile
@ -8,7 +9,9 @@ def is_cof(user):
return False
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):
try:

View file

@ -10,6 +10,7 @@ from gestioncof.models import CofProfile, EventCommentValue
from gestioncof.widgets import TriStateCheckbox
from gestioncof.shared import lock_table, unlock_table
class EventForm(forms.Form):
def __init__(self, *args, **kwargs):
event = kwargs.pop("event")
@ -25,21 +26,25 @@ class EventForm(forms.Form):
choices[choice.event_option.id].append(choice.id)
all_choices = choices
for option in event.options.all():
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:
initial = [] if option.id not in all_choices else all_choices[option.id]
field = forms.MultipleChoiceField(label = option.name,
choices = choices,
widget = CheckboxSelectMultiple,
required = False,
initial = initial)
initial = [] if option.id not in all_choices \
else all_choices[option.id]
field = forms.MultipleChoiceField(
label=option.name,
choices=choices,
widget=CheckboxSelectMultiple,
required=False,
initial=initial)
else:
initial = None if option.id not in all_choices else all_choices[option.id][0]
field = forms.ChoiceField(label = option.name,
choices = choices,
widget = RadioSelect,
required = False,
initial = initial)
initial = None if option.id not in all_choices \
else all_choices[option.id][0]
field = forms.ChoiceField(label=option.name,
choices=choices,
widget=RadioSelect,
required=False,
initial=initial)
field.option_id = option.id
self.fields["option_%d" % option.id] = field
@ -48,6 +53,7 @@ class EventForm(forms.Form):
if name.startswith('option_'):
yield (self.fields[name].option_id, value)
class SurveyForm(forms.Form):
def __init__(self, *args, **kwargs):
survey = kwargs.pop("survey")
@ -61,21 +67,25 @@ class SurveyForm(forms.Form):
else:
answers[answer.survey_question.id].append(answer.id)
for question in survey.questions.all():
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:
initial = [] if question.id not in answers else answers[question.id]
field = forms.MultipleChoiceField(label = question.question,
choices = choices,
widget = CheckboxSelectMultiple,
required = False,
initial = initial)
initial = [] if question.id not in answers\
else answers[question.id]
field = forms.MultipleChoiceField(
label=question.question,
choices=choices,
widget=CheckboxSelectMultiple,
required=False,
initial=initial)
else:
initial = None if question.id not in answers else answers[question.id][0]
field = forms.ChoiceField(label = question.question,
choices = choices,
widget = RadioSelect,
required = False,
initial = initial)
initial = None if question.id not in answers\
else answers[question.id][0]
field = forms.ChoiceField(label=question.question,
choices=choices,
widget=RadioSelect,
required=False,
initial=initial)
field.question_id = question.id
self.fields["question_%d" % question.id] = field
@ -83,7 +93,8 @@ class SurveyForm(forms.Form):
for name, value in self.cleaned_data.items():
if name.startswith('question_'):
yield (self.fields[name].question_id, value)
class SurveyStatusFilterForm(forms.Form):
def __init__(self, *args, **kwargs):
survey = kwargs.pop("survey")
@ -91,15 +102,17 @@ class SurveyStatusFilterForm(forms.Form):
for question in survey.questions.all():
for answer in question.answers.all():
name = "question_%d_answer_%d" % (question.id, answer.id)
if self.is_bound and self.data.get(self.add_prefix(name), None):
if self.is_bound \
and self.data.get(self.add_prefix(name), None):
initial = self.data.get(self.add_prefix(name), None)
else:
initial = "none"
field = forms.ChoiceField(label = "%s : %s" % (question.question, answer.answer),
choices = [("yes", "yes"),("no","no"),("none","none")],
widget = TriStateCheckbox,
required = False,
initial = initial)
field = forms.ChoiceField(
label="%s : %s" % (question.question, answer.answer),
choices=[("yes", "yes"), ("no", "no"), ("none", "none")],
widget=TriStateCheckbox,
required=False,
initial=initial)
field.question_id = question.id
field.answer_id = answer.id
self.fields[name] = field
@ -107,7 +120,9 @@ class SurveyStatusFilterForm(forms.Form):
def filters(self):
for name, value in self.cleaned_data.items():
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):
def __init__(self, *args, **kwargs):
@ -116,15 +131,17 @@ class EventStatusFilterForm(forms.Form):
for option in event.options.all():
for choice in option.choices.all():
name = "option_%d_choice_%d" % (option.id, choice.id)
if self.is_bound and self.data.get(self.add_prefix(name), None):
if self.is_bound \
and self.data.get(self.add_prefix(name), None):
initial = self.data.get(self.add_prefix(name), None)
else:
initial = "none"
field = forms.ChoiceField(label = "%s : %s" % (option.name, choice.value),
choices = [("yes", "yes"),("no","no"),("none","none")],
widget = TriStateCheckbox,
required = False,
initial = initial)
field = forms.ChoiceField(
label="%s : %s" % (option.name, choice.value),
choices=[("yes", "yes"), ("no", "no"), ("none", "none")],
widget=TriStateCheckbox,
required=False,
initial=initial)
field.option_id = option.id
field.choice_id = choice.id
self.fields[name] = field
@ -134,20 +151,23 @@ class EventStatusFilterForm(forms.Form):
initial = self.data.get(self.add_prefix(name), None)
else:
initial = "none"
field = forms.ChoiceField(label = "Événement payé",
choices = [("yes", "yes"),("no","no"),("none","none")],
widget = TriStateCheckbox,
required = False,
initial = initial)
field = forms.ChoiceField(label="Événement payé",
choices=[("yes", "yes"), ("no", "no"),
("none", "none")],
widget=TriStateCheckbox,
required=False,
initial=initial)
self.fields[name] = field
def filters(self):
for name, value in self.cleaned_data.items():
if name.startswith('option_'):
yield (self.fields[name].option_id, self.fields[name].choice_id, value)
yield (self.fields[name].option_id,
self.fields[name].choice_id, value)
elif name == "event_has_paid":
yield ("has_paid", None, value)
class UserProfileForm(forms.ModelForm):
first_name = forms.CharField(label=_(u'Prénom'), max_length=30)
last_name = forms.CharField(label=_(u'Nom'), max_length=30)
@ -174,7 +194,9 @@ class UserProfileForm(forms.ModelForm):
class Meta:
model = CofProfile
fields = ("phone", "mailing_cof", "mailing_bda", "mailing_bda_revente",)
fields = ("phone", "mailing_cof", "mailing_bda",
"mailing_bda_revente", )
class RegistrationUserForm(forms.ModelForm):
def __init__(self, *args, **kw):
@ -185,6 +207,7 @@ class RegistrationUserForm(forms.ModelForm):
model = User
fields = ("username", "first_name", "last_name", "email")
class RegistrationProfileForm(forms.ModelForm):
def __init__(self, *args, **kw):
super(RegistrationProfileForm, self).__init__(*args, **kw)
@ -224,27 +247,33 @@ class RegistrationProfileForm(forms.ModelForm):
class Meta:
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'),
('wait', 'Oui mais attente paiement'),
('paid', 'Oui payé'),)
STATUS_CHOICES = (('no','Non'),
('wait','Oui mais attente paiement'),
('paid','Oui payé'),)
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):
event = kwargs.pop("event")
self.event = event
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)
if paid == True:
kwargs["initial"] = {"status":"paid"}
elif paid == False:
kwargs["initial"] = {"status":"wait"}
if paid is True:
kwargs["initial"] = {"status": "paid"}
elif paid is False:
kwargs["initial"] = {"status": "wait"}
else:
kwargs["initial"] = {"status":"no"}
kwargs["initial"] = {"status": "no"}
super(AdminEventForm, self).__init__(*args, **kwargs)
choices = {}
for choice in current_choices:
@ -254,35 +283,41 @@ class AdminEventForm(forms.Form):
choices[choice.event_option.id].append(choice.id)
all_choices = choices
for option in event.options.all():
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:
initial = [] if option.id not in all_choices else all_choices[option.id]
field = forms.MultipleChoiceField(label = option.name,
choices = choices,
widget = CheckboxSelectMultiple,
required = False,
initial = initial)
initial = [] if option.id not in all_choices\
else all_choices[option.id]
field = forms.MultipleChoiceField(
label=option.name,
choices=choices,
widget=CheckboxSelectMultiple,
required=False,
initial=initial)
else:
initial = None if option.id not in all_choices else all_choices[option.id][0]
field = forms.ChoiceField(label = option.name,
choices = choices,
widget = RadioSelect,
required = False,
initial = initial)
initial = None if option.id not in all_choices\
else all_choices[option.id][0]
field = forms.ChoiceField(label=option.name,
choices=choices,
widget=RadioSelect,
required=False,
initial=initial)
field.option_id = option.id
self.fields["option_%d" % option.id] = field
for commentfield in event.commentfields.all():
initial = commentfield.default
if registration is not None:
try:
initial = registration.comments.get(commentfield = commentfield).content
initial = registration.comments \
.get(commentfield=commentfield).content
except EventCommentValue.DoesNotExist:
pass
widget = forms.Textarea if commentfield.fieldtype == "text" else forms.TextInput
field = forms.CharField(label = commentfield.name,
widget = widget,
required = False,
initial = initial)
widget = forms.Textarea if commentfield.fieldtype == "text" \
else forms.TextInput
field = forms.CharField(label=commentfield.name,
widget=widget,
required=False,
initial=initial)
field.comment_id = commentfield.id
self.fields["comment_%d" % commentfield.id] = field
@ -295,4 +330,3 @@ class AdminEventForm(forms.Form):
for name, value in self.cleaned_data.items():
if name.startswith('comment_'):
yield (self.fields[name].comment_id, value)

View file

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('gestioncof', '0002_enable_unprocessed_demandes'),
]
operations = [
migrations.AddField(
model_name='event',
name='image',
field=models.ImageField(upload_to=b'imgs/events/', null=True, verbose_name=b'Image', blank=True),
),
]

View file

@ -29,32 +29,41 @@ TYPE_COMMENT_FIELD = (
('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):
user = models.OneToOneField(User, related_name = "profile")
login_clipper = models.CharField("Login clipper", max_length = 8, blank = True)
is_cof = models.BooleanField("Membre du COF", default = False)
num = models.IntegerField ("Numéro d'adhérent", blank = True, default = 0)
phone = models.CharField("Téléphone", max_length = 20, blank = True)
occupation = models.CharField (_(u"Occupation"),
default = "1A",
choices = OCCUPATION_CHOICES,
max_length = choices_length (OCCUPATION_CHOICES))
departement = models.CharField (_(u"Département"), max_length = 50, blank = True)
type_cotiz = models.CharField (_(u"Type de cotisation"),
default = "normalien",
choices = TYPE_COTIZ_CHOICES,
max_length = choices_length (TYPE_COTIZ_CHOICES))
mailing_cof = models.BooleanField("Recevoir les mails COF", 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)
comments = models.TextField("Commentaires visibles uniquement par le Buro", blank = True)
is_buro = models.BooleanField("Membre du Burô", 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"),
blank = True, default = "")
user = models.OneToOneField(User, related_name="profile")
login_clipper = models.CharField("Login clipper", max_length=8, blank=True)
is_cof = models.BooleanField("Membre du COF", default=False)
num = models.IntegerField("Numéro d'adhérent", blank=True, default=0)
phone = models.CharField("Téléphone", max_length=20, blank=True)
occupation = models.CharField(_(u"Occupation"),
default="1A",
choices=OCCUPATION_CHOICES,
max_length=choices_length(
OCCUPATION_CHOICES))
departement = models.CharField(_(u"Département"), max_length=50,
blank=True)
type_cotiz = models.CharField(_(u"Type de cotisation"),
default="normalien",
choices=TYPE_COTIZ_CHOICES,
max_length=choices_length(
TYPE_COTIZ_CHOICES))
mailing_cof = models.BooleanField("Recevoir les mails COF", 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)
comments = models.TextField(
"Commentaires visibles uniquement par le Buro", blank=True)
is_buro = models.BooleanField("Membre du Burô", 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"),
blank=True, default="")
class Meta:
verbose_name = "Profil COF"
@ -63,22 +72,26 @@ class CofProfile(models.Model):
def __unicode__(self):
return unicode(self.user.username)
def create_user_profile(sender, instance, created, **kwargs):
if created:
CofProfile.objects.get_or_create(user = instance)
post_save.connect(create_user_profile, sender = User)
CofProfile.objects.get_or_create(user=instance)
post_save.connect(create_user_profile, sender=User)
class Club(models.Model):
name = models.CharField("Nom", max_length = 200)
name = models.CharField("Nom", max_length=200)
description = models.TextField("Description")
respos = models.ManyToManyField(User, related_name = "clubs_geres")
membres = models.ManyToManyField(User, related_name = "clubs")
respos = models.ManyToManyField(User, related_name="clubs_geres")
membres = models.ManyToManyField(User, related_name="clubs")
class CustomMail(models.Model):
shortname = models.SlugField(max_length = 50, blank = False)
title = models.CharField("Titre", max_length = 200, blank = False)
content = models.TextField("Contenu", blank = False)
comments = models.TextField("Informations contextuelles sur le mail", blank = True)
shortname = models.SlugField(max_length=50, blank=False)
title = models.CharField("Titre", max_length=200, blank=False)
content = models.TextField("Contenu", blank=False)
comments = models.TextField("Informations contextuelles sur le mail",
blank=True)
class Meta:
verbose_name = "Mails personnalisables"
@ -86,14 +99,18 @@ class CustomMail(models.Model):
def __unicode__(self):
return u"%s: %s" % (self.shortname, self.title)
class Event(models.Model):
title = models.CharField("Titre", max_length = 200)
location = models.CharField("Lieu", max_length = 200)
start_date = models.DateField("Date de début", blank = True, null = True)
end_date = models.DateField("Date de fin", blank = True, null = True)
description = models.TextField("Description", blank = True)
registration_open = models.BooleanField("Inscriptions ouvertes", default = True)
old = models.BooleanField("Archiver (événement fini)", default = False)
title = models.CharField("Titre", max_length=200)
location = models.CharField("Lieu", max_length=200)
start_date = models.DateField("Date de début", blank=True, null=True)
end_date = models.DateField("Date de fin", blank=True, null=True)
description = models.TextField("Description", blank=True)
image = models.ImageField("Image", blank=True, null=True,
upload_to="imgs/events/")
registration_open = models.BooleanField("Inscriptions ouvertes",
default=True)
old = models.BooleanField("Archiver (événement fini)", default=False)
class Meta:
verbose_name = "Événement"
@ -101,11 +118,13 @@ class Event(models.Model):
def __unicode__(self):
return unicode(self.title)
class EventCommentField(models.Model):
event = models.ForeignKey(Event, related_name = "commentfields")
name = models.CharField("Champ", max_length = 200)
fieldtype = models.CharField("Type", max_length = 10, choices = TYPE_COMMENT_FIELD, default = "text")
default = models.TextField("Valeur par défaut", blank = True)
event = models.ForeignKey(Event, related_name="commentfields")
name = models.CharField("Champ", max_length=200)
fieldtype = models.CharField("Type", max_length=10,
choices=TYPE_COMMENT_FIELD, default="text")
default = models.TextField("Valeur par défaut", blank=True)
class Meta:
verbose_name = "Champ"
@ -113,15 +132,18 @@ class EventCommentField(models.Model):
def __unicode__(self):
return unicode(self.name)
class EventCommentValue(models.Model):
commentfield = models.ForeignKey(EventCommentField, related_name = "values")
registration = models.ForeignKey("EventRegistration", related_name = "comments")
content = models.TextField("Contenu", blank = True, null = True)
commentfield = models.ForeignKey(EventCommentField, related_name="values")
registration = models.ForeignKey("EventRegistration",
related_name="comments")
content = models.TextField("Contenu", blank=True, null=True)
class EventOption(models.Model):
event = models.ForeignKey(Event, related_name = "options")
name = models.CharField("Option", max_length = 200)
multi_choices = models.BooleanField("Choix multiples", default = False)
event = models.ForeignKey(Event, related_name="options")
name = models.CharField("Option", max_length=200)
multi_choices = models.BooleanField("Choix multiples", default=False)
class Meta:
verbose_name = "Option"
@ -129,9 +151,10 @@ class EventOption(models.Model):
def __unicode__(self):
return unicode(self.name)
class EventOptionChoice(models.Model):
event_option = models.ForeignKey(EventOption, related_name = "choices")
value = models.CharField("Valeur", max_length = 200)
event_option = models.ForeignKey(EventOption, related_name="choices")
value = models.CharField("Valeur", max_length=200)
class Meta:
verbose_name = "Choix"
@ -139,25 +162,29 @@ class EventOptionChoice(models.Model):
def __unicode__(self):
return unicode(self.value)
class EventRegistration(models.Model):
user = models.ForeignKey(User)
event = models.ForeignKey(Event)
options = models.ManyToManyField(EventOptionChoice)
filledcomments = models.ManyToManyField(EventCommentField, through = EventCommentValue)
paid = models.BooleanField("A payé", default = False)
filledcomments = models.ManyToManyField(EventCommentField,
through=EventCommentValue)
paid = models.BooleanField("A payé", default=False)
class Meta:
verbose_name = "Inscription"
unique_together = ("user", "event")
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):
title = models.CharField("Titre", max_length = 200)
details = models.TextField("Détails", blank = True)
survey_open = models.BooleanField("Sondage ouvert", default = True)
old = models.BooleanField("Archiver (sondage fini)", default = False)
title = models.CharField("Titre", max_length=200)
details = models.TextField("Détails", blank=True)
survey_open = models.BooleanField("Sondage ouvert", default=True)
old = models.BooleanField("Archiver (sondage fini)", default=False)
class Meta:
verbose_name = "Sondage"
@ -165,10 +192,11 @@ class Survey(models.Model):
def __unicode__(self):
return unicode(self.title)
class SurveyQuestion(models.Model):
survey = models.ForeignKey(Survey, related_name = "questions")
question = models.CharField("Question", max_length = 200)
multi_answers = models.BooleanField("Choix multiples", default = False)
survey = models.ForeignKey(Survey, related_name="questions")
question = models.CharField("Question", max_length=200)
multi_answers = models.BooleanField("Choix multiples", default=False)
class Meta:
verbose_name = "Question"
@ -176,9 +204,10 @@ class SurveyQuestion(models.Model):
def __unicode__(self):
return unicode(self.question)
class SurveyQuestionAnswer(models.Model):
survey_question = models.ForeignKey(SurveyQuestion, related_name = "answers")
answer = models.CharField("Réponse", max_length = 200)
survey_question = models.ForeignKey(SurveyQuestion, related_name="answers")
answer = models.CharField("Réponse", max_length=200)
class Meta:
verbose_name = "Réponse"
@ -186,15 +215,18 @@ class SurveyQuestionAnswer(models.Model):
def __unicode__(self):
return unicode(self.answer)
class SurveyAnswer(models.Model):
user = models.ForeignKey(User)
survey = models.ForeignKey(Survey)
answers = models.ManyToManyField(SurveyQuestionAnswer, related_name = "selected_by")
answers = models.ManyToManyField(SurveyQuestionAnswer,
related_name="selected_by")
class Meta:
verbose_name = "Réponses"
unique_together = ("user", "survey")
class Clipper(models.Model):
username = models.CharField("Identifiant", max_length = 20)
fullname = models.CharField("Nom complet", max_length = 200)
username = models.CharField("Identifiant", max_length=20)
fullname = models.CharField("Nom complet", max_length=200)

View file

@ -4,8 +4,9 @@ from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
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)
LEVELS_CHOICES = (
('college', _(u"Collège")),
@ -16,6 +17,7 @@ LEVELS_CHOICES = (
('other', _(u"Autre (préciser dans les commentaires)")),
)
class PetitCoursSubject(models.Model):
name = models.CharField(_(u"Matière"), max_length=30)
users = models.ManyToManyField(User, related_name="petits_cours_matieres",
@ -28,12 +30,13 @@ class PetitCoursSubject(models.Model):
def __unicode__(self):
return self.name
class PetitCoursAbility(models.Model):
user = models.ForeignKey(User)
matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_(u"Matière"))
niveau = models.CharField (_(u"Niveau"),
choices=LEVELS_CHOICES,
max_length=choices_length (LEVELS_CHOICES))
niveau = models.CharField(_(u"Niveau"),
choices=LEVELS_CHOICES,
max_length=choices_length(LEVELS_CHOICES))
agrege = models.BooleanField(_(u"Agrégé"), default=False)
class Meta:
@ -41,7 +44,9 @@ class PetitCoursAbility(models.Model):
verbose_name_plural = "Compétences des petits cours"
def __unicode__(self):
return u"%s - %s - %s" % (self.user.username, self.matiere, self.niveau)
return u"%s - %s - %s" % (self.user.username,
self.matiere, self.niveau)
class PetitCoursDemande(models.Model):
name = models.CharField(_(u"Nom/prénom"), max_length=200)
@ -49,28 +54,28 @@ class PetitCoursDemande(models.Model):
phone = models.CharField(_(u"Téléphone (facultatif)"),
max_length=20, blank=True)
quand = models.CharField(
_(u"Quand ?"),
help_text=_(u"Indiquez ici la période désirée pour les petits" \
+ " cours (vacances scolaires, semaine, week-end)."),
max_length=300, blank=True)
_(u"Quand ?"),
help_text=_(u"Indiquez ici la période désirée pour les petits"
" cours (vacances scolaires, semaine, week-end)."),
max_length=300, blank=True)
freq = models.CharField(
_(u"Fréquence"),
help_text=_(u"Indiquez ici la fréquence envisagée " \
_(u"Fréquence"),
help_text=_(u"Indiquez ici la fréquence envisagée "
+ "(hebdomadaire, 2 fois par semaine, ...)"),
max_length=300, blank=True)
max_length=300, blank=True)
lieu = models.CharField(
_(u"Lieu (si préférence)"),
help_text=_(u"Si vous avez avez une préférence sur le lieu."),
max_length=300, blank=True)
_(u"Lieu (si préférence)"),
help_text=_(u"Si vous avez avez une préférence sur le lieu."),
max_length=300, blank=True)
matieres = models.ManyToManyField(
PetitCoursSubject, verbose_name=_(u"Matières"),
related_name="demandes")
PetitCoursSubject, verbose_name=_(u"Matières"),
related_name="demandes")
agrege_requis = models.BooleanField(_(u"Agrégé requis"), default=False)
niveau = models.CharField (_(u"Niveau"),
default="",
choices=LEVELS_CHOICES,
max_length=choices_length (LEVELS_CHOICES))
niveau = models.CharField(_(u"Niveau"),
default="",
choices=LEVELS_CHOICES,
max_length=choices_length(LEVELS_CHOICES))
remarques = models.TextField(_(u"Remarques et précisions"), blank=True)
@ -85,7 +90,9 @@ class PetitCoursDemande(models.Model):
verbose_name_plural = "Demandes de petits cours"
def __unicode__(self):
return u"Demande %d du %s" % (self.id, self.created.strftime("%d %b %Y"))
return u"Demande %d du %s" % (self.id,
self.created.strftime("%d %b %Y"))
class PetitCoursAttribution(models.Model):
user = models.ForeignKey(User)
@ -94,7 +101,7 @@ class PetitCoursAttribution(models.Model):
date = models.DateTimeField(_(u"Date d'attribution"), auto_now_add=True)
rank = models.IntegerField("Rang dans l'email")
selected = models.BooleanField(_(u"Sélectionné par le demandeur"),
default=False)
default=False)
class Meta:
verbose_name = "Attribution de petits cours"
@ -102,7 +109,8 @@ class PetitCoursAttribution(models.Model):
def __unicode__(self):
return u"Attribution de la demande %d à %s pour %s" \
% (self.demande.id, self.user.username, self.matiere)
% (self.demande.id, self.user.username, self.matiere)
class PetitCoursAttributionCounter(models.Model):
user = models.ForeignKey(User)
@ -115,5 +123,4 @@ class PetitCoursAttributionCounter(models.Model):
def __unicode__(self):
return u"%d demandes envoyées à %s pour %s" \
% (self.count, self.user.username, self.matiere)
% (self.count, self.user.username, self.matiere)

View file

@ -26,58 +26,67 @@ from datetime import datetime
import base64
import simplejson
def render_template(template_path, data):
tmpl = loader.get_template(template_path)
context = Context(data)
return tmpl.render(context)
class DemandeListView(ListView):
model = PetitCoursDemande
template_name = "petits_cours_demandes_list.html"
paginate_by = 20
def get_queryset(self):
return PetitCoursDemande.objects.order_by('traitee','-id').all()
return PetitCoursDemande.objects.order_by('traitee', '-id').all()
@method_decorator(buro_required)
def dispatch(self, *args, **kwargs):
return super(DemandeListView, self).dispatch(*args, **kwargs)
@buro_required
def details(request, demande_id):
demande = get_object_or_404(PetitCoursDemande, id = demande_id)
attributions = PetitCoursAttribution.objects.filter(demande = demande).all()
demande = get_object_or_404(PetitCoursDemande, id=demande_id)
attributions = PetitCoursAttribution.objects.filter(demande=demande).all()
return render(request, "details_demande_petit_cours.html",
{"demande": demande,
"attributions": attributions})
def _get_attrib_counter(user, matiere):
counter, created = PetitCoursAttributionCounter.objects.get_or_create(user = user,
matiere = matiere)
counter, created = PetitCoursAttributionCounter \
.objects.get_or_create(user=user, matiere=matiere)
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.save()
return counter
def _get_demande_candidates(demande, redo = False):
def _get_demande_candidates(demande, redo=False):
for matiere in demande.matieres.all():
candidates = PetitCoursAbility.objects.filter(matiere = matiere, niveau = demande.niveau)
candidates = candidates.filter(user__profile__is_cof = True,
user__profile__petits_cours_accept = True)
candidates = PetitCoursAbility.objects.filter(matiere=matiere,
niveau=demande.niveau)
candidates = candidates.filter(user__profile__is_cof=True,
user__profile__petits_cours_accept=True)
if demande.agrege_requis:
candidates = candidates.filter(agrege = True)
candidates = candidates.filter(agrege=True)
if redo:
attributions = PetitCoursAttribution.objects.filter(demande = demande,
matiere = matiere).all()
attributions = PetitCoursAttribution.objects \
.filter(demande=demande, matiere=matiere).all()
for attrib in attributions:
candidates = candidates.exclude(user = attrib.user)
candidates = candidates.exclude(user=attrib.user)
candidates = candidates.order_by('?').select_related().all()
yield (matiere, candidates)
@buro_required
def traitement(request, demande_id, redo = False):
demande = get_object_or_404(PetitCoursDemande, id = demande_id)
def traitement(request, demande_id, redo=False):
demande = get_object_or_404(PetitCoursDemande, id=demande_id)
if demande.niveau == "other":
return _traitement_other(request, demande, redo)
if request.method == "POST":
@ -92,7 +101,7 @@ def traitement(request, demande_id, redo = False):
for candidate in candidates:
user = candidate.user
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 = candidates[0:min(3, len(candidates))]
attribdata[matiere.id] = []
@ -110,12 +119,14 @@ def traitement(request, demande_id, redo = False):
return _finalize_traitement(request, demande, proposals,
proposed_for, unsatisfied, attribdata, redo)
@buro_required
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,
unsatisfied, attribdata, redo = False, errors = None):
unsatisfied, attribdata, redo=False, errors=None):
proposals = proposals.items()
proposed_for = proposed_for.items()
attribdata = attribdata.items()
@ -123,7 +134,11 @@ def _finalize_traitement(request, demande, proposals, proposed_for,
mainmail = render_template("petits-cours-mail-demandeur.txt",
{"proposals": proposals,
"unsatisfied": unsatisfied,
"extra": "<textarea name=\"extra\" style=\"width:99%; height: 90px;\"></textarea>"})
"extra":
'<textarea name="extra" '
'style="width:99%; height: 90px;">'
'</textarea>'
})
return render(request, "traitement_demande_petit_cours.html",
{"demande": demande,
"unsatisfied": unsatisfied,
@ -131,18 +146,22 @@ def _finalize_traitement(request, demande, proposals, proposed_for,
"proposed_for": proposed_for,
"proposed_mails": proposed_mails,
"mainmail": mainmail,
"attribdata": base64.b64encode(simplejson.dumps(attribdata)),
"attribdata":
base64.b64encode(simplejson.dumps(attribdata)),
"redo": redo,
"errors": errors,
})
})
def _generate_eleve_email(demande, proposed_for):
proposed_mails = []
for user, matieres in proposed_for:
msg = render_template("petits-cours-mail-eleve.txt", {"demande": demande, "matieres": matieres})
msg = render_template("petits-cours-mail-eleve.txt",
{"demande": demande, "matieres": matieres})
proposed_mails.append((user, msg))
return proposed_mails
def _traitement_other_preparing(request, demande):
redo = "redo" in request.POST
unsatisfied = []
@ -157,15 +176,18 @@ def _traitement_other_preparing(request, demande):
attribdata[matiere.id] = []
proposals[matiere] = []
for choice_id in range(min(3, len(candidates))):
choice = int(request.POST["proposal-%d-%d" % (matiere.id, choice_id)])
choice = int(
request.POST["proposal-%d-%d" % (matiere.id, choice_id)])
if choice == -1:
continue
if choice not in candidates:
errors.append(u"Choix invalide pour la proposition %d en %s" % (choice_id + 1, matiere))
errors.append(u"Choix invalide pour la proposition %d"
"en %s" % (choice_id + 1, matiere))
continue
user = candidates[choice]
if user in proposals[matiere]:
errors.append(u"La proposition %d en %s est un doublon" % (choice_id + 1, matiere))
errors.append(u"La proposition %d en %s est un doublon"
% (choice_id + 1, matiere))
continue
proposals[matiere].append(user)
attribdata[matiere.id].append(user.id)
@ -176,10 +198,15 @@ def _traitement_other_preparing(request, demande):
if not proposals[matiere]:
errors.append(u"Aucune proposition pour %s" % (matiere,))
elif len(proposals[matiere]) < 3:
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:
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):
if request.method == "POST":
@ -197,7 +224,7 @@ def _traitement_other(request, demande, redo):
for candidate in candidates:
user = candidate.user
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)
attribdata[matiere.id] = []
proposals[matiere] = []
@ -218,7 +245,8 @@ def _traitement_other(request, demande, redo):
"unsatisfied": unsatisfied,
"proposals": proposals,
"proposed_for": proposed_for,
})
})
def _traitement_post(request, demande):
proposals = {}
@ -234,7 +262,7 @@ def _traitement_post(request, demande):
else:
proposals[matiere] = []
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)
if user not in proposed_for:
proposed_for[user] = [matiere]
@ -254,21 +282,23 @@ def _traitement_post(request, demande):
for (user, msg) in proposed_mails:
msg = EmailMessage("Petits cours ENS par le COF", msg,
frommail, [user.email],
[bccaddress], headers = {'Reply-To': replyto})
[bccaddress], headers={'Reply-To': replyto})
mails_to_send.append(msg)
mails_to_send.append(EmailMessage("Cours particuliers ENS", mainmail,
frommail, [demande.email],
[bccaddress], headers = {'Reply-To': replyto}))
connection = mail.get_connection(fail_silently = True)
[bccaddress],
headers={'Reply-To': replyto}))
connection = mail.get_connection(fail_silently=True)
connection.send_messages(mails_to_send)
lock_table(PetitCoursAttributionCounter, PetitCoursAttribution, User)
for matiere in proposals:
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.save()
attrib = PetitCoursAttribution(user = user, matiere = matiere,
demande = demande, rank = rank + 1)
attrib = PetitCoursAttribution(user=user, matiere=matiere,
demande=demande, rank=rank + 1)
attrib.save()
unlock_tables()
demande.traitee = True
@ -278,13 +308,15 @@ def _traitement_post(request, demande):
return render(request, "traitement_demande_petit_cours_success.html",
{"demande": demande,
"redo": redo,
})
})
class BaseMatieresFormSet(BaseInlineFormSet):
def clean(self):
super(BaseMatieresFormSet, self).clean()
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
matieres = []
for i in range(0, self.total_form_count()):
@ -295,38 +327,48 @@ class BaseMatieresFormSet(BaseInlineFormSet):
niveau = form.cleaned_data['niveau']
delete = form.cleaned_data['DELETE']
if not delete and (matiere, niveau) in matieres:
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))
@login_required
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:
return redirect("cof-denied")
MatieresFormSet = inlineformset_factory(User, PetitCoursAbility,
fields = ("matiere", "niveau", "agrege",),
formset = BaseMatieresFormSet)
fields=("matiere", "niveau",
"agrege",),
formset=BaseMatieresFormSet)
success = False
if request.method == "POST":
formset = MatieresFormSet(request.POST, instance = request.user)
formset = MatieresFormSet(request.POST, instance=request.user)
if formset.is_valid():
formset.save()
profile.petits_cours_accept = "receive_proposals" in request.POST
profile.petits_cours_remarques = request.POST["remarques"]
profile.save()
lock_table(PetitCoursAttributionCounter, PetitCoursAbility, User, PetitCoursSubject)
abilities = PetitCoursAbility.objects.filter(user = request.user).all()
lock_table(PetitCoursAttributionCounter, PetitCoursAbility, User,
PetitCoursSubject)
abilities = PetitCoursAbility.objects \
.filter(user=request.user).all()
for ability in abilities:
counter = _get_attrib_counter(ability.user, ability.matiere)
unlock_tables()
success = True
formset = MatieresFormSet(instance = request.user)
formset = MatieresFormSet(instance=request.user)
else:
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})
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})
class DemandeForm(ModelForm):
captcha = ReCaptchaField(attrs = {'theme': 'clean', 'lang': 'fr'})
captcha = ReCaptchaField(attrs={'theme': 'clean', 'lang': 'fr'})
def __init__(self, *args, **kwargs):
super(DemandeForm, self).__init__(*args, **kwargs)
@ -334,9 +376,11 @@ class DemandeForm(ModelForm):
class Meta:
model = PetitCoursDemande
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}
@csrf_exempt
def demande(request):
success = False
@ -347,7 +391,9 @@ def demande(request):
success = True
else:
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
def demande_raw(request):
@ -359,4 +405,5 @@ def demande_raw(request):
success = True
else:
form = DemandeForm()
return render(request, "demande-petit-cours-raw.html", {"form": form, "success": success})
return render(request, "demande-petit-cours-raw.html",
{"form": form, "success": success})

View file

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

View file

@ -10,6 +10,7 @@
<h2>Inscription d'un nouveau membre</h2>
<input type="text" name="q" id="search_autocomplete" spellcheck="false" />
<div id="form-placeholder"></div>
<span class="yourlabs-autocomplete"></span>
<script type="text/javascript">
$(document).ready(function() {
$('input#search_autocomplete').yourlabsAutocomplete({
@ -18,6 +19,9 @@
id: 'search_autocomplete',
choiceSelector: 'li:has(a)',
placeholder: "Chercher un utilisateur par nom, prénom ou identifiant clipper",
container: $("#main-content"),
box: $(".yourlabs-autocomplete"),
fixPosition: function() {},
});
$('input#search_autocomplete').bind(
'selectChoice',

View file

@ -19,7 +19,8 @@ petitcours_patterns = [
name='petits-cours-demande-raw'),
url(r'^demandes$', DemandeListView.as_view(),
name='petits-cours-demandes-list'),
url(r'^demandes/(?P<demande_id>\d+)$', 'gestioncof.petits_cours_views.details',
url(r'^demandes/(?P<demande_id>\d+)$',
'gestioncof.petits_cours_views.details',
name='petits-cours-demande-details'),
url(r'^demandes/(?P<demande_id>\d+)/traitement$',
'gestioncof.petits_cours_views.traitement',
@ -38,5 +39,3 @@ events_patterns = [
url(r'^(?P<event_id>\d+)$', 'gestioncof.views.event'),
url(r'^(?P<event_id>\d+)/status$', 'gestioncof.views.event_status'),
]

View file

@ -8,8 +8,10 @@ from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import login as django_login_view
from django.contrib.auth.models import User
from gestioncof.models import Survey, SurveyAnswer, SurveyQuestion, SurveyQuestionAnswer
from gestioncof.models import Event, EventRegistration, EventOption, EventOptionChoice
from gestioncof.models import Survey, SurveyAnswer, SurveyQuestion, \
SurveyQuestionAnswer
from gestioncof.models import Event, EventRegistration, EventOption, \
EventOptionChoice
from gestioncof.models import EventCommentField, EventCommentValue
from gestioncof.shared import send_custom_mail
from gestioncof.models import CofProfile, Clipper
@ -20,70 +22,81 @@ from gestioncof.forms import UserProfileForm, EventStatusFilterForm, \
from bda.models import Tirage
@login_required
def home(request):
data = {"surveys": Survey.objects.filter(old=False).all(),
"events": Event.objects.filter(old=False).all(),
"open_surveys": Survey.objects.filter(survey_open=True, old=False).all(),
"open_events": Event.objects.filter(registration_open=True, old=False).all(),
"open_surveys":
Survey.objects.filter(survey_open=True, old=False).all(),
"open_events":
Event.objects.filter(registration_open=True, old=False).all(),
"open_tirages": Tirage.objects.filter(active=True).all()}
return render(request, "home.html", data)
def login(request):
if request.user.is_authenticated():
return redirect("gestioncof.views.home")
return render(request, "login_switch.html", {})
def login_ext(request):
if request.method == "POST" and "username" in request.POST:
try:
user = User.objects.get(username = request.POST["username"])
if not user.has_usable_password() or user.password in ("","!"):
profile, created = CofProfile.objects.get_or_create(user = user)
user = User.objects.get(username=request.POST["username"])
if not user.has_usable_password() or user.password in ("", "!"):
profile, created = CofProfile.objects.get_or_create(user=user)
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:
return render(request, "error.html", {"error_type": "no_password"})
return render(request, "error.html",
{"error_type": "no_password"})
except User.DoesNotExist:
pass
return django_login_view(request, template_name = 'login.html')
return django_login_view(request, template_name='login.html')
@login_required
def logout(request):
try:
profile = request.user.profile
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:
return redirect("django_cas_ng.views.logout")
else:
return redirect("django.contrib.auth.views.logout")
@login_required
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:
raise Http404
success = False
deleted = False
if request.method == "POST":
form = SurveyForm(request.POST, survey = survey)
form = SurveyForm(request.POST, survey=survey)
if request.POST.get('delete'):
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 = None
except SurveyAnswer.DoesNotExist:
current_answer = None
form = SurveyForm(survey = survey)
form = SurveyForm(survey=survey)
success = True
deleted = True
else:
if form.is_valid():
all_answers = []
for question_id, answers_ids in form.answers():
question = get_object_or_404(SurveyQuestion, id = question_id,
survey = survey)
question = get_object_or_404(SurveyQuestion,
id=question_id,
survey=survey)
if type(answers_ids) != list:
answers_ids = [answers_ids]
if not question.multi_answers and len(answers_ids) > 1:
@ -93,31 +106,39 @@ def survey(request, survey_id):
continue
answer_id = int(answer_id)
answer = SurveyQuestionAnswer.objects.get(
id = answer_id,
survey_question = question)
id=answer_id,
survey_question=question)
all_answers.append(answer)
try:
current_answer = SurveyAnswer.objects.get(user = request.user, survey = survey)
current_answer = SurveyAnswer.objects.get(
user=request.user, survey=survey)
except SurveyAnswer.DoesNotExist:
current_answer = SurveyAnswer(user = request.user, survey = survey)
current_answer = SurveyAnswer(user=request.user,
survey=survey)
current_answer.save()
current_answer.answers = all_answers
current_answer.save()
success = True
else:
try:
current_answer = SurveyAnswer.objects.get(user = request.user, survey = survey)
form = SurveyForm(survey = survey, current_answers = current_answer.answers)
current_answer = SurveyAnswer.objects.get(user=request.user,
survey=survey)
form = SurveyForm(survey=survey,
current_answers=current_answer.answers)
except SurveyAnswer.DoesNotExist:
current_answer = None
form = SurveyForm(survey = survey)
return render(request, "survey.html", {"survey": survey, "form": form, "success": success, "deleted": deleted, "current_answer": current_answer})
form = SurveyForm(survey=survey)
return render(request, "survey.html", {"survey": survey, "form": form,
"success": success,
"deleted": deleted,
"current_answer": current_answer})
def get_event_form_choices(event, form):
all_choices = []
for option_id, choices_ids in form.choices():
option = get_object_or_404(EventOption, id = option_id,
event = event)
option = get_object_or_404(EventOption, id=option_id,
event=event)
if type(choices_ids) != list:
choices_ids = [choices_ids]
if not option.multi_choices and len(choices_ids) > 1:
@ -127,43 +148,52 @@ def get_event_form_choices(event, form):
continue
choice_id = int(choice_id)
choice = EventOptionChoice.objects.get(
id = choice_id,
event_option = option)
id=choice_id,
event_option=option)
all_choices.append(choice)
return all_choices
def update_event_form_comments(event, form, registration):
for commentfield_id, value in form.comments():
field = get_object_or_404(EventCommentField, id = commentfield_id,
event = event)
field = get_object_or_404(EventCommentField, id=commentfield_id,
event=event)
if value == field.default:
continue
(storage, _) = EventCommentValue.objects.get_or_create(commentfield = field,
registration = registration)
(storage, _) = EventCommentValue.objects.get_or_create(
commentfield=field,
registration=registration)
storage.content = value
storage.save()
@login_required
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:
raise Http404
success = False
if request.method == "POST":
form = EventForm(request.POST, event = event)
form = EventForm(request.POST, event=event)
if form.is_valid():
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.save()
success = True
else:
try:
current_registration = EventRegistration.objects.get(user = request.user, event = event)
form = EventForm(event = event, current_choices = current_registration.options)
current_registration = \
EventRegistration.objects.get(user=request.user, event=event)
form = EventForm(event=event,
current_choices=current_registration.options)
except EventRegistration.DoesNotExist:
form = EventForm(event = event)
return render(request, "event.html", {"event": event, "form": form, "success": success})
form = EventForm(event=event)
return render(request, "event.html",
{"event": event, "form": form, "success": success})
def clean_post_for_status(initial):
d = initial.copy()
@ -173,29 +203,34 @@ def clean_post_for_status(initial):
d[k[3:]] = v
return d
@buro_required
def event_status(request, event_id):
event = get_object_or_404(Event, id = event_id)
registrations_query = EventRegistration.objects.filter(event = event)
event = get_object_or_404(Event, id=event_id)
registrations_query = EventRegistration.objects.filter(event=event)
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():
for option_id, choice_id, value in form.filters():
if option_id == "has_paid":
if value == "yes":
registrations_query = registrations_query.filter(paid = True)
registrations_query = registrations_query.filter(paid=True)
elif value == "no":
registrations_query = registrations_query.filter(paid = False)
registrations_query = registrations_query.filter(
paid=False)
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":
continue
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":
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()
options = EventOption.objects.filter(event = event).all()
options = EventOption.objects.filter(event=event).all()
choices_count = {}
for option in options:
for choice in option.choices.all():
@ -203,25 +238,32 @@ def event_status(request, event_id):
for user_choice in user_choices:
for choice in user_choice.options.all():
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
def survey_status(request, survey_id):
survey = get_object_or_404(Survey, id = survey_id)
answers_query = SurveyAnswer.objects.filter(survey = survey)
survey = get_object_or_404(Survey, id=survey_id)
answers_query = SurveyAnswer.objects.filter(survey=survey)
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():
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":
continue
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":
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()
questions = SurveyQuestion.objects.filter(survey = survey).all()
questions = SurveyQuestion.objects.filter(survey=survey).all()
answers_count = {}
for question in questions:
for answer in question.answers.all():
@ -229,31 +271,37 @@ def survey_status(request, survey_id):
for user_answer in user_answers:
for answer in user_answer.answers.all():
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
def profile(request):
success = False
if request.method == "POST":
form = UserProfileForm(request.POST, instance = request.user.profile)
form = UserProfileForm(request.POST, instance=request.user.profile)
if form.is_valid():
form.save()
success = True
else:
form = UserProfileForm(instance = request.user.profile)
form = UserProfileForm(instance=request.user.profile)
return render(request, "profile.html", {"form": form, "success": success})
def registration_set_ro_fields(user_form, profile_form):
user_form.fields['username'].widget.attrs['readonly'] = True
profile_form.fields['login_clipper'].widget.attrs['readonly'] = True
@buro_required
def registration_form(request, login_clipper = None, username = None):
def registration_form(request, login_clipper=None, username=None):
member = None
if login_clipper:
clipper = get_object_or_404(Clipper, username = login_clipper)
try: # check if the given user is already registered
member = User.objects.filter(username = login_clipper).get()
clipper = get_object_or_404(Clipper, username=login_clipper)
try: # check if the given user is already registered
member = User.objects.filter(username=login_clipper).get()
username = member.username
login_clipper = None
except User.DoesNotExist:
@ -261,7 +309,8 @@ def registration_form(request, login_clipper = None, username = None):
user_form = RegistrationUserForm()
profile_form = RegistrationProfileForm()
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
if clipper.fullname:
bits = clipper.fullname.split(" ")
@ -270,35 +319,39 @@ def registration_form(request, login_clipper = None, username = None):
user_form.fields['last_name'].initial = " ".join(bits[1:])
registration_set_ro_fields(user_form, profile_form)
if username:
member = get_object_or_404(User, username = username)
(profile, _) = CofProfile.objects.get_or_create(user = member)
member = get_object_or_404(User, username=username)
(profile, _) = CofProfile.objects.get_or_create(user=member)
# already existing, prefill
user_form = RegistrationUserForm(instance = member)
profile_form = RegistrationProfileForm(instance = profile)
user_form = RegistrationUserForm(instance=member)
profile_form = RegistrationProfileForm(instance=profile)
registration_set_ro_fields(user_form, profile_form)
elif not login_clipper:
# new user
user_form = RegistrationUserForm()
profile_form = RegistrationProfileForm()
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
def registration_form2(request, login_clipper = None, username = None):
events = Event.objects.filter(old = False).all()
def registration_form2(request, login_clipper=None, username=None):
events = Event.objects.filter(old=False).all()
member = None
if login_clipper:
clipper = get_object_or_404(Clipper, username = login_clipper)
try: # check if the given user is already registered
member = User.objects.filter(username = login_clipper).get()
clipper = get_object_or_404(Clipper, username=login_clipper)
try: # check if the given user is already registered
member = User.objects.filter(username=login_clipper).get()
username = member.username
login_clipper = None
except User.DoesNotExist:
# new user, but prefill
user_form = RegistrationUserForm()
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['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
if clipper.fullname:
bits = clipper.fullname.split(" ")
@ -307,26 +360,34 @@ def registration_form2(request, login_clipper = None, username = None):
user_form.fields['last_name'].initial = " ".join(bits[1:])
registration_set_ro_fields(user_form, profile_form)
if username:
member = get_object_or_404(User, username = username)
(profile, _) = CofProfile.objects.get_or_create(user = member)
member = get_object_or_404(User, username=username)
(profile, _) = CofProfile.objects.get_or_create(user=member)
# already existing, prefill
user_form = RegistrationUserForm(instance = member)
profile_form = RegistrationProfileForm(instance = profile)
user_form = RegistrationUserForm(instance=member)
profile_form = RegistrationProfileForm(instance=profile)
registration_set_ro_fields(user_form, profile_form)
event_forms = []
for event in events:
try:
current_registration = EventRegistration.objects.get(user = member, event = event)
form = AdminEventForm(event = event, current_registration = current_registration, paid = current_registration.paid)
current_registration = EventRegistration.objects.get(
user=member, event=event)
form = AdminEventForm(
event=event,
current_registration=current_registration,
paid=current_registration.paid)
except EventRegistration.DoesNotExist:
form = AdminEventForm(event = event)
form = AdminEventForm(event=event)
event_forms.append(form)
elif not login_clipper:
# new user
user_form = RegistrationUserForm()
profile_form = RegistrationProfileForm()
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})
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})
@buro_required
def registration(request):
@ -337,113 +398,144 @@ def registration(request):
success = False
user_form = RegistrationUserForm(request_dict)
profile_form = RegistrationProfileForm(request_dict)
events = Event.objects.filter(old = False).all()
event_forms = [AdminEventForm(request_dict, event = event) for event in events]
events = Event.objects.filter(old=False).all()
event_forms = \
[AdminEventForm(request_dict, event=event) for event in events]
user_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
login_clipper = None
if "user_exists" in request_dict and request_dict["user_exists"]:
username = request_dict["username"]
try:
member = User.objects.filter(username = username).get()
(profile, _) = CofProfile.objects.get_or_create(user = member)
user_form = RegistrationUserForm(request_dict, instance = member)
profile_form = RegistrationProfileForm(request_dict, instance = profile)
member = User.objects.filter(username=username).get()
(profile, _) = CofProfile.objects.get_or_create(user=member)
user_form = RegistrationUserForm(request_dict, instance=member)
profile_form = RegistrationProfileForm(request_dict,
instance=profile)
except User.DoesNotExist:
try:
clipper = Clipper.objects.filter(username = username).get()
clipper = Clipper.objects.filter(username=username).get()
login_clipper = clipper.username
except Clipper.DoesNotExist:
pass
for form in event_forms:
if not form.is_valid(): break
if form.cleaned_data['status'] == 'no': continue
if not form.is_valid():
break
if form.cleaned_data['status'] == 'no':
continue
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()
(profile, _) = CofProfile.objects.get_or_create(user = member)
(profile, _) = CofProfile.objects.get_or_create(user=member)
was_cof = profile.is_cof
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.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:
send_custom_mail(member, "bienvenue")
for form in event_forms:
if form.cleaned_data['status'] == 'no':
try:
current_registration = EventRegistration.objects.get(user = member, event = form.event)
current_registration = EventRegistration.objects.get(
user=member, event=form.event)
current_registration.delete()
except EventRegistration.DoesNotExist:
pass
continue
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)
current_registration.options = all_choices
current_registration.paid = (form.cleaned_data['status'] == 'paid')
current_registration.paid = \
(form.cleaned_data['status'] == 'paid')
current_registration.save()
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:
comments = EventCommentValue.objects.get(commentfield = field, registration = current_registration).content
comments = EventCommentValue.objects.get(
commentfield=field,
registration=current_registration).content
except EventCommentValue.DoesNotExist:
comments = field.default
send_custom_mail(member, "mega", {"remarques": comments})
success = True
return render(request, "registration_post.html", {"success": success, "user_form": user_form, "profile_form": profile_form, "member": member, "login_clipper": login_clipper, "event_forms": event_forms})
return render(request, "registration_post.html",
{"success": success,
"user_form": user_form,
"profile_form": profile_form,
"member": member,
"login_clipper": login_clipper,
"event_forms": event_forms})
else:
return render(request, "registration.html")
@buro_required
def export_members(request):
response = HttpResponse(content_type = 'text/csv')
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=membres_cof.csv'
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
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])
return response
@buro_required
def csv_export_mega(filename, qs):
response = HttpResponse(content_type = 'text/csv')
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=' + filename
writer = unicodecsv.writer(response)
for reg in qs.all():
user = reg.user
profile = user.profile
comments = "---".join([comment.content for comment in reg.comments.all()])
bits = [user.username, user.first_name, user.last_name, user.email, profile.phone, profile.num, profile.comments if profile.comments else "", comments]
comments = "---".join(
[comment.content for comment in reg.comments.all()])
bits = [user.username, user.first_name, user.last_name, user.email,
profile.phone, profile.num,
profile.comments if profile.comments else "", comments]
writer.writerow([unicode(bit) for bit in bits])
return response
@buro_required
def export_mega_remarksonly(request):
filename = 'remarques_mega_2015.csv'
response = HttpResponse(content_type = 'text/csv')
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=' + filename
writer = unicodecsv.writer(response)
event = Event.objects.get(title = "Mega 15")
commentfield = event.commentfields.get(name = "Commentaires")
event = Event.objects.get(title="Mega 15")
commentfield = event.commentfields.get(name="Commentaires")
for val in commentfield.values.all():
reg = val.registration
user = reg.user
profile = user.profile
bits = [user.username, user.first_name, user.last_name, user.email, profile.phone, profile.num, profile.comments, val.content]
bits = [user.username, user.first_name, user.last_name, user.email,
profile.phone, profile.num, profile.comments, val.content]
writer.writerow([unicode(bit) for bit in bits])
return response
@buro_required
def export_mega_bytype(request, type):
types = {"orga-actif": "Orga élève",
@ -454,60 +546,75 @@ def export_mega_bytype(request, type):
if type not in types:
raise Http404
event = Event.objects.get(title = "Mega 15")
type_option = event.options.get(name = "Type")
participant_type = type_option.choices.get(value = types[type]).id
qs = EventRegistration.objects.filter(event = event).filter(options__id__exact = participant_type)
event = Event.objects.get(title="Mega 15")
type_option = event.options.get(name="Type")
participant_type = type_option.choices.get(value=types[type]).id
qs = EventRegistration.objects.filter(event=event).filter(
options__id__exact=participant_type)
return csv_export_mega(type + '_mega_2015.csv', qs)
@buro_required
def export_mega_orgas(request):
event = Event.objects.get(title = "Mega 15")
type_option = event.options.get(name = "Type")
participant_type_a = type_option.choices.get(value = "Conscrit étudiant").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))
event = Event.objects.get(title="Mega 15")
type_option = event.options.get(name="Type")
participant_type_a = type_option.choices.get(value="Conscrit étudiant").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))
return csv_export_mega('orgas_mega_15.csv', qs)
@buro_required
def export_mega_participants(request):
event = Event.objects.get(title = "Mega 15")
type_option = event.options.get(name = "Type")
participant_type_a = type_option.choices.get(value = "Conscrit étudiant").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))
event = Event.objects.get(title="Mega 15")
type_option = event.options.get(name="Type")
participant_type_a = type_option.choices.get(value="Conscrit étudiant").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))
return csv_export_mega('participants_mega_15.csv', qs)
@buro_required
def export_mega(request):
event = Event.objects.filter(title = "Mega 15")
qs = EventRegistration.objects.filter(event = event).order_by("user__username")
event = Event.objects.filter(title="Mega 15")
qs = EventRegistration.objects.filter(event=event) \
.order_by("user__username")
return csv_export_mega('all_mega_2015.csv', qs)
@buro_required
def utile_cof(request):
return render(request, "utile_cof.html", {})
return render(request, "utile_cof.html", {})
@buro_required
def utile_bda(request):
tirages = Tirage.objects.all()
return render(request, "utile_bda.html", {'tirages': tirages})
@buro_required
def liste_bdadiff(request):
titre = "BdA diffusion"
personnes = CofProfile.objects.filter(mailing_bda = True, is_cof = True).all()
return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes})
personnes = CofProfile.objects.filter(mailing_bda=True, is_cof=True).all()
return render(request, "liste_mails.html",
{"titre": titre, "personnes": personnes})
@buro_required
def liste_bdarevente(request):
titre = "BdA revente"
personnes = CofProfile.objects.filter(mailing_bda_revente = True, is_cof = True).all()
return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes})
personnes = CofProfile.objects.filter(mailing_bda_revente=True,
is_cof=True).all()
return render(request, "liste_mails.html", {"titre": titre,
"personnes": personnes})
@buro_required
def liste_diffcof(request):
titre = "Diffusion COF"
personnes = CofProfile.objects.filter(mailing_cof = True, is_cof = True).all()
return render(request, "liste_mails.html", {"titre": titre, "personnes": personnes})
personnes = CofProfile.objects.filter(mailing_cof=True, is_cof=True).all()
return render(request, "liste_mails.html", {"titre": titre,
"personnes": personnes})

View file

@ -2,8 +2,8 @@ from django.forms.widgets import Widget
from django.forms.utils import flatatt
from django.utils.safestring import mark_safe
class TriStateCheckbox(Widget):
class TriStateCheckbox(Widget):
def __init__(self, attrs=None, choices=()):
super(TriStateCheckbox, self).__init__(attrs)
# choices can be any iterable, but we may need to render this widget
@ -12,7 +12,8 @@ class TriStateCheckbox(Widget):
self.choices = list(choices)
def render(self, name, value, attrs=None, choices=()):
if value is None: value = 'none'
if value is None:
value = 'none'
final_attrs = self.build_attrs(attrs, value=value)
output = [u"<span class=\"tristate\"%s></span>" % flatatt(final_attrs)]
return mark_safe('\n'.join(output))