Permissions des groupes, affichage de listes selon permissions
[auf_rh_dae.git] / project / recrutement / admin.py
CommitLineData
df59fcab 1# -*- encoding: utf-8 -*-
2
6067184b 3from django.core.urlresolvers import reverse
4from django.http import HttpResponseRedirect
df59fcab 5from django.contrib import admin
38df74bb 6from django.shortcuts import get_object_or_404
7
6067184b 8from reversion.admin import VersionAdmin
38df74bb 9from datamaster_modeles.models import Employe, Implantation, Region
6067184b 10
df59fcab 11from recrutement.models import *
f6724c20
NBV
12from recrutement.workflow import grp_administrateurs_recrutement,\
13 grp_evaluateurs_recrutement, grp_drh_recrutement
df59fcab 14
d2b30f5f 15class OffreEmploiAdmin(VersionAdmin):
7f9e891e 16 date_hierarchy = 'date_creation'
ec517164 17 list_display = ('nom', 'resume', 'date_limite', 'region', '_candidatsList')
f6724c20 18
8941aee7 19 # Afficher la liste des candidats pour l'offre d'emploi
596fe324 20 def _candidatsList(self, obj):
8ea41642 21 return "<a href='%s?offre_emploi__id__exact=%s'>Voir les candidats \
22 </a>" % (reverse('admin:recrutement_candidat_changelist'), obj.id)
2f78949d 23 _candidatsList.allow_tags = True
f6724c20 24 _candidatsList.short_description = "Afficher la liste des candidats"
362a3534 25
2f78949d 26 def queryset(self, request):
d835c9f3 27 """
28 N'affiche la liste de candidats que si le user connecté
27c81d11 29 possède un Evaluateur
2f78949d 30 """
31 qs = self.model._default_manager.get_query_set()
f6724c20
NBV
32 # Si user est superuser afficher toutes les offres d'emploi
33 user_groupes = request.user.groups.all()
34 if not grp_drh_recrutement in user_groupes:
35 # Si le user n'est ni un évaluateur ni un administrateur régional,
36 # retourner none
37 # Vérifier groupes
38 if grp_evaluateurs_recrutement in user_groupes:
39 user = Evaluateur.objects.get(user=request.user)
40 elif grp_administrateurs_recrutement in user_groupes:
41 user = AdministrateurRegional.objects.get(user=request.user)
42 else:
43 return qs.none()
44
45 if type(user) is AdministrateurRegional:
46 region_ids = [g.id for g in user.regions.all()]
47 return qs.select_related('offre_emploi').\
48 filter(region__in=region_ids)
49 if type(user) is Evaluateur:
50
51 candidats = [g for g in user.candidats.all()]
52 offre_emploi_ids = [offre.id for offre in candidats]
53 return qs.select_related('offre_emploi').\
54 filter(id__in=offre_emploi_ids)
55
3bcef02d 56 return qs.none()
f6724c20
NBV
57 return qs.select_related('offre_emploi')
58
59 def has_change_permission(self, request, obj=None):
60 user_groupes = request.user.groups.all()
61 if grp_drh_recrutement in user_groupes or \
62 grp_administrateurs_recrutement in user_groupes:
63 return True
64 return False
65
66class ProxyOffreEmploiAdmin(OffreEmploiAdmin):
67 list_display = ('nom', 'resume', 'date_limite', 'region', '_candidatsList', )
68 readonly_fields = ('actif', 'description', 'poste', 'bureau',
69 'duree_affectation', 'renumeration',
70 'debut_affectation', 'lieu_affectation', 'nom',
71 'resume', 'date_limite', 'region')
72 fieldsets = (
73 (None, {
74 'fields': ('nom', )
75 }),
76 (None, {
77 'fields': ('poste', 'resume','description', 'date_limite', )
78 }),
79 (None, {
80 'fields': ('lieu_affectation', 'bureau', 'region', )
81 }),
82 (None, {
83 'fields': ('debut_affectation', 'duree_affectation',
84 'renumeration', )
85 }),
86 )
87 def has_add_permission(self, request):
88 return False
89
90 def has_delete_permission(self, request, obj=None):
91 return False
92
93 def _candidatsList(self, obj):
94 return "<a href='%s?offre_emploi__id__exact=%s'>Voir les candidats \
95 </a>" % (reverse('admin:recrutement_proxycandidat_changelist'),
96 obj.id)
97 _candidatsList.allow_tags = True
98 _candidatsList.short_description = "Afficher la liste des candidats"
362a3534 99
cced6a23 100class ProxyCandidatPiece(CandidatPiece):
101 """
102 Ce proxy sert uniquement dans l'admin à disposer d'un libellé
103 plus ergonomique.
104 """
105 class Meta:
106 proxy = True
107 verbose_name = "pièce jointe"
74cbc7a7 108 verbose_name_plural = "pièces jointes"
cced6a23 109
170c9aa2 110class CandidatPieceInline(admin.TabularInline):
cced6a23 111 model = ProxyCandidatPiece
112 fields = ('candidat', 'nom', 'path', )
170c9aa2 113 extra = 1
114
27c81d11 115class ProxyEvaluateur(Evaluateur.candidats.through):
cced6a23 116 """
117 Ce proxy sert uniquement dans l'admin à disposer d'un libellé
118 plus ergonomique.
119 """
120 class Meta:
121 proxy = True
122 verbose_name = "évaluateur"
123
eb579d40 124class EvaluateurInline(admin.TabularInline):
cced6a23 125 model = ProxyEvaluateur
eb579d40 126 extra = 1
127
d2b30f5f 128class CandidatAdmin(VersionAdmin):
7f9e891e 129 date_hierarchy = 'date_creation'
0fd8a26d 130 list_display = ('nom', 'prenom', 'offre_emploi','statut',
8941aee7 131 'voir_offre_emploi', 'evaluer_candidat', #'note_evaluateur',
132 'calculer_moyenne', 'afficher_candidat',)
8ea41642 133 list_filter = ('offre_emploi', )
7f9e891e 134 fieldsets = (
4896b661 135 ("Offre d'emploi", {
136 'fields': ('offre_emploi', )
137 }),
7f9e891e 138 ('Informations personnelles', {
139 'fields': ('prenom','nom','genre', 'nationalite', 'date_naissance',
140 'situation_famille', 'nombre_dependant',)
141 }),
ec517164 142 ('Coordonnées', {
143 'fields': ('telephone', 'email', 'adresse', 'ville',
144 'etat_province', 'code_postal', 'pays', )
7f9e891e 145 }),
146 ('Informations professionnelles', {
4896b661 147 'fields': ('niveau_diplome','employeur_actuel',
8ea41642 148 'poste_actuel', 'domaine_professionnel',)
7f9e891e 149 }),
150 ('Options avancées', {
151 'classes': ('collapse',),
152 'fields': ('actif', 'statut', )
153 }),
154 )
170c9aa2 155 inlines = [
156 CandidatPieceInline,
eb579d40 157 EvaluateurInline,
170c9aa2 158 ]
f9983b5a 159
4e8340cf 160 actions = ['affecter_candidats_evaluateur', 'envoyer_courriel_candidats']
362a3534 161 # Affecter un évaluateurs à des candidats
7061f835 162 def affecter_candidats_evaluateur(modeladmin, obj, candidats):
596fe324 163 selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
2adf9e0c 164
8ea41642 165 return HttpResponseRedirect(reverse('affecter_evaluateurs_candidats')+
166 "?ids=%s" % (",".join(selected)))
d835c9f3 167 affecter_candidats_evaluateur.short_description = u'Affecter évaluateur'
362a3534 168
4e8340cf 169 # Envoyer un courriel à des candidats
52765380 170 def envoyer_courriel_candidats(modeladmin, obj, candidats):
171 selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
172
173 return HttpResponseRedirect(reverse('envoyer_courriel_candidats')+
174 "?ids=%s" % (",".join(selected)))
175 envoyer_courriel_candidats.short_description = u'Envoyer courriel'
176
05503d56 177 # Évaluer un candidat
596fe324 178 def evaluer_candidat(self, obj):
8ea41642 179 return "<a href='%s?id=%s'>Évaluer le candidat \
180 </a>" % (reverse('evaluer_candidat'), obj.id)
596fe324 181 evaluer_candidat.allow_tags = True
d835c9f3 182 evaluer_candidat.short_description = 'Évaluer'
596fe324 183
7d82fd33 184 # Afficher un candidat
185 def afficher_candidat(self, obj):
186 return "<a href='%s?id=%s'>Voir le candidat \
f6724c20 187 </a>" % (reverse('recrutement_proxycandidat_change'), obj.id)
7d82fd33 188 afficher_candidat.allow_tags = True
f6724c20 189 afficher_candidat.short_description = u'Afficher les détails du candidat'
7d82fd33 190
8941aee7 191 # Voir l'offre d'emploi
192 def voir_offre_emploi(self, obj):
193 return "<a href='%s?id=%s'>Voir l'offre d'emploi</a> \
194 " % (reverse('admin:recrutement_offreemploi_changelist'),
195 obj.offre_emploi.id)
196 voir_offre_emploi.allow_tags = True
197 voir_offre_emploi.short_description = "Afficher l'offre d'emploi"
198
199 """ # Afficher note poster par l'évaluateur
200 def note_evaluateur(self, obj):
201 import pdb;pdb.set_trace()
27c81d11 202 evaluateur = Evaluateur.objects.get(user=obj.user)
8941aee7 203 import pdb;pdb.set_trace()
204 note_eval = CandidatEvaluation.objects.filter(evaluateur=evaluateur,
205 candidat=obj.user)
206 return "blabla"
207 note_evaluateur.allow_tags = True
208 note_evaluateur.short_description = "Votre note"
209 """
210
211 # Calculer la moyenne des notes
212 def calculer_moyenne(self, obj):
213 evaluations = CandidatEvaluation.objects.filter(candidat=obj)
214 offre_emploi = obj.offre_emploi
215
f6724c20
NBV
216 notes = [evaluation.note for evaluation in evaluations.all() \
217 if evaluation.note is not None]
8941aee7 218
219 if len(notes) > 0 and offre_emploi.date_limite <= datetime.date.today():
220 moyenne_votes = float(sum(notes)) / len(notes)
221 else:
222 moyenne_votes = "Non disponible"
223 return moyenne_votes
224 calculer_moyenne.allow_tags = True
225 calculer_moyenne.short_description = "Moyenne des notes"
226
f6724c20
NBV
227 def add_delete_permission(self, request, obj=None) :
228 user_groupes = request.user.groups.all()
229 if grp_drh_recrutement in user_groupes or \
230 grp_administrateurs_recrutement in user_groupes:
231 return True
232 return False
4896b661 233
f6724c20
NBV
234 def has_add_permission(self, request):
235 return self.add_delete_permission(request, request)
4896b661 236
f6724c20
NBV
237 def has_delete_permission(self, request, obj=None):
238 return self.add_delete_permission(request, request)
239
240 def has_change_permission(self, request, obj=None):
241 user_groupes = request.user.groups.all()
242 if grp_drh_recrutement in user_groupes or \
243 grp_administrateurs_recrutement in user_groupes or \
244 grp_evaluateurs_recrutement in user_groupes:
245 return True
246 return False
4896b661 247
596fe324 248 def queryset(self, obj):
f9983b5a 249 """
8ea41642 250 Spécifie un queryset limité, autrement Django exécute un
251 select_related() sans paramètre, ce qui a pour effet de charger tous
252 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
253 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
254 génération d'une requête infinie.
d835c9f3 255
f9983b5a 256 """
f6724c20
NBV
257 qs = self.model._default_manager.get_query_set()
258 # Si user est superuser afficher tous les candidats
259 user_groupes = obj.user.groups.all()
260 if not grp_drh_recrutement in user_groupes:
261 # Si le user n'est ni un évaluateur ni un administrateur régional,
262 # retourner none
263
264 # Vérifier groupes
265 if grp_evaluateurs_recrutement in user_groupes:
266 user = Evaluateur.objects.get(user=obj.user)
267 #elif grp_administrateurs_recrutement in user_groupes:
268 # user = AdministrateurRegional.objects.get(user=obj.user)
269 else:
270 return qs.none()
271
272 ids = [c.id for c in user.candidats.all()]
273 return qs.select_related('candidats').filter(id__in=ids)
274 return qs.select_related('candidats')
275
276class ProxyCandidatAdmin(CandidatAdmin):
277 #TODO: init boucler sur les fields pour le readonly
278 list_display = ('nom', 'prenom', 'offre_emploi','statut',
279 'voir_offre_emploi')
280 readonly_fields = ('statut', 'offre_emploi', 'prenom', 'nom',
281 'genre', 'nationalite', 'date_naissance',
282 'situation_famille', 'nombre_dependant', 'telephone',
283 'email', 'adresse', 'ville', 'etat_province',
284 'code_postal', 'pays', 'niveau_diplome',
285 'employeur_actuel', 'poste_actuel',
286 'domaine_professionnel',)
287
288 inlines = []
289 def has_add_permission(self, request):
290 return False
291
292 def has_delete_permission(self, request, obj=None):
293 return False
2adf9e0c 294
f6724c20
NBV
295 def voir_offre_emploi(self, obj):
296 return "<a href='%s?id=%s'>Voir l'offre d'emploi</a> \
297 " % (reverse('admin:recrutement_proxyoffreemploi_changelist'),
298 obj.offre_emploi.id)
299 voir_offre_emploi.allow_tags = True
300 voir_offre_emploi.short_description = "Afficher l'offre d'emploi"
df59fcab 301
2e9ee615 302class CandidatPieceAdmin(admin.ModelAdmin):
170c9aa2 303 list_display = ('nom', 'candidat', )
304
305 def queryset(self, request):
306 """
307 Spécifie un queryset limité, autrement Django exécute un
308 select_related() sans paramètre, ce qui a pour effet de charger tous
309 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
310 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
311 génération d'une requête infinie.
d835c9f3 312 Affiche la liste de candidats que si le user connecté
27c81d11 313 possède un Evaluateur
170c9aa2 314 """
315 qs = self.model._default_manager.get_query_set()
316 return qs.select_related('candidat')
2e9ee615 317
d2b30f5f 318class EvaluateurAdmin(VersionAdmin):
eb579d40 319 fieldsets = (
f6724c20 320 (None, {'fields': ('user', )}),
eb579d40 321 (None, {'fields': ('candidats',)}),
322 )
4418c732 323
f6724c20 324 # Peut-être qu'on peut enlever cette def, à cause des permissions
d835c9f3 325 def queryset(self, request):
326 """
327 Affiche la liste d'évaluateur que si le user connecté
27c81d11 328 possède un Evaluateur
d835c9f3 329 """
f6724c20
NBV
330 user_groupes = obj.user.groups.all()
331 if grp_drh_recrutement in user_groupes:
332 return self.model._default_manager.get_query_set()
333
334 return qs.none()
d835c9f3 335
b89fef74 336class AdministrateurRegionalAdmin(VersionAdmin):
27c81d11 337 pass
338
d2b30f5f 339class CandidatEvaluationAdmin(VersionAdmin):
596fe324 340 list_display = ('candidat', 'evaluateur', 'note', 'commentaire', 'date', )
341
4e8340cf 342class CourrielTemplateAdmin(VersionAdmin):
343 pass
344
df59fcab 345admin.site.register(OffreEmploi, OffreEmploiAdmin)
346admin.site.register(Candidat, CandidatAdmin)
4e8340cf 347admin.site.register(CourrielTemplate, CourrielTemplateAdmin)
27c81d11 348admin.site.register(Evaluateur, EvaluateurAdmin)
b89fef74 349admin.site.register(AdministrateurRegional, AdministrateurRegionalAdmin)
f6724c20
NBV
350admin.site.register(ProxyOffreEmploi, ProxyOffreEmploiAdmin)
351admin.site.register(ProxyCandidat, ProxyCandidatAdmin)