gestioCOF/gestioncof/admin.py
2018-10-06 13:15:33 +02:00

333 lines
9.9 KiB
Python

from dal.autocomplete import ModelSelect2
from django import forms
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import Group, Permission, User
from django.core.urlresolvers import reverse
from django.db.models import Q
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from gestioncof.models import (
Club,
CofProfile,
Event,
EventCommentField,
EventOption,
EventOptionChoice,
EventRegistration,
Survey,
SurveyQuestion,
SurveyQuestionAnswer,
)
from gestioncof.petits_cours_models import (
PetitCoursAbility,
PetitCoursAttribution,
PetitCoursAttributionCounter,
PetitCoursDemande,
PetitCoursSubject,
)
def add_link_field(target_model="", field="", link_text=str, desc_text=str):
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)))
link.allow_tags = True
link.short_description = desc_text(reverse_name + " link")
cls.link = 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"
)
class SurveyQuestionInline(admin.TabularInline):
model = SurveyQuestion
class SurveyQuestionAdmin(admin.ModelAdmin):
search_fields = ("survey__title", "answer")
inlines = [SurveyQuestionAnswerInline]
class SurveyAdmin(admin.ModelAdmin):
search_fields = ("title", "details")
inlines = [SurveyQuestionInline]
class EventOptionChoiceInline(admin.TabularInline):
model = EventOptionChoice
@add_link_field(desc_text=lambda x: "Choix", link_text=lambda x: "Éditer les choix")
class EventOptionInline(admin.TabularInline):
model = EventOption
class EventCommentFieldInline(admin.TabularInline):
model = EventCommentField
class EventOptionAdmin(admin.ModelAdmin):
search_fields = ("event__title", "name")
inlines = [EventOptionChoiceInline]
class EventAdmin(admin.ModelAdmin):
search_fields = ("title", "location", "description")
inlines = [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):
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:
"""
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:
return getattr(self.profile, field)
except CofProfile.DoesNotExist:
return ""
getter.short_description = short_description
getter.boolean = boolean
return getter
User.profile_login_clipper = FkeyLookup("profile__login_clipper", "Login clipper")
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)
class UserProfileAdmin(UserAdmin):
def is_buro(self, obj):
try:
return obj.profile.is_buro
except CofProfile.DoesNotExist:
return False
is_buro.short_description = "Membre du Buro"
is_buro.boolean = True
def is_cof(self, obj):
try:
return obj.profile.is_cof
except CofProfile.DoesNotExist:
return False
is_cof.short_description = "Membre du COF"
is_cof.boolean = True
list_display = 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")
list_filter = UserAdmin.list_filter + (
"profile__is_cof",
"profile__is_buro",
"profile__mailing_cof",
"profile__mailing_bda",
)
search_fields = UserAdmin.search_fields + ("profile__phone",)
inlines = [CofProfileInline]
staff_fieldsets = [
(None, {"fields": ["username", "password"]}),
(_("Personal info"), {"fields": ["first_name", "last_name", "email"]}),
]
def get_fieldsets(self, request, user=None):
if not request.user.is_superuser:
return self.staff_fieldsets
return super().get_fieldsets(request, user)
def save_model(self, request, user, form, change):
cof_group, created = Group.objects.get_or_create(name="COF")
if created:
# Si le groupe COF n'était pas déjà dans la bdd
# On lui assigne les bonnes permissions
perms = Permission.objects.filter(
Q(content_type__app_label="gestioncof")
| Q(content_type__app_label="bda")
| (Q(content_type__app_label="auth") & Q(content_type__model="user"))
)
cof_group.permissions = perms
# On y associe les membres du Burô
cof_group.user_set = User.objects.filter(profile__is_buro=True)
# Sauvegarde
cof_group.save()
# le Burô est staff et appartient au groupe COF
if user.profile.is_buro:
user.is_staff = True
user.groups.add(cof_group)
else:
user.is_staff = False
user.groups.remove(cof_group)
user.save()
# FIXME: This is absolutely horrible.
def user_str(self):
if self.first_name and self.last_name:
return "{} ({})".format(self.get_full_name(), self.username)
else:
return self.username
User.__str__ = user_str
class EventRegistrationAdminForm(forms.ModelForm):
class Meta:
widgets = {"user": ModelSelect2(url="cof-user-autocomplete")}
class EventRegistrationAdmin(admin.ModelAdmin):
form = EventRegistrationAdminForm
list_display = ("__str__", "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")
search_fields = (
"user__username",
"user__first_name",
"user__last_name",
"user__email",
"matiere__name",
"niveau",
)
list_filter = ("matiere", "niveau", "agrege")
class PetitCoursAttributionAdmin(admin.ModelAdmin):
list_display = ("user", "demande", "matiere", "rank")
search_fields = ("user__username", "matiere__name")
class PetitCoursAttributionCounterAdmin(admin.ModelAdmin):
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_on_bottom = True
def reset(self, request, queryset):
queryset.update(count=0)
reset.short_description = "Remise à zéro du compteur"
class PetitCoursDemandeAdmin(admin.ModelAdmin):
list_display = (
"name",
"email",
"agrege_requis",
"niveau",
"created",
"traitee",
"processed",
)
list_filter = ("traitee", "niveau")
search_fields = ("name", "email", "phone", "lieu", "remarques")
class ClubAdminForm(forms.ModelForm):
def clean(self):
cleaned_data = super().clean()
respos = cleaned_data.get("respos")
members = cleaned_data.get("membres")
for respo in respos.all():
if respo not in members:
raise forms.ValidationError(
"Erreur : le respo %s n'est pas membre du club."
% respo.get_full_name()
)
return cleaned_data
class ClubAdmin(admin.ModelAdmin):
list_display = ["name"]
form = ClubAdminForm
admin.site.register(Survey, SurveyAdmin)
admin.site.register(SurveyQuestion, SurveyQuestionAdmin)
admin.site.register(Event, EventAdmin)
admin.site.register(EventOption, EventOptionAdmin)
admin.site.unregister(User)
admin.site.register(User, UserProfileAdmin)
admin.site.register(CofProfile)
admin.site.register(Club, ClubAdmin)
admin.site.register(PetitCoursSubject)
admin.site.register(PetitCoursAbility, PetitCoursAbilityAdmin)
admin.site.register(PetitCoursAttribution, PetitCoursAttributionAdmin)
admin.site.register(PetitCoursAttributionCounter, PetitCoursAttributionCounterAdmin)
admin.site.register(PetitCoursDemande, PetitCoursDemandeAdmin)
admin.site.register(EventRegistration, EventRegistrationAdmin)