Changement de l'ordre des status d'un Candidat, Changement de nom du fieldset Options...
[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):
beef7690 27 query = self.model._default_manager.get_query_set()
f6724c20
NBV
28 # Si user est superuser afficher toutes les offres d'emploi
29 user_groupes = request.user.groups.all()
30 if not grp_drh_recrutement in user_groupes:
beef7690
NBV
31 """
32 Filtrer les offre d'emploi pour afficher seulement les offres
33 d'emploi actives
34 """
35 qs = query.filter(date_limite__gte=datetime.date.today())
36 """
37 Si le user n'est ni un évaluateur ni un administrateur régional,
38 retourner none
39 Vérifier groupes
40 """
f6724c20 41 if grp_evaluateurs_recrutement in user_groupes:
ca73c3c6
NBV
42 try:
43 user = Evaluateur.objects.get(user=request.user)
44 except Evaluateur.DoesNotExist:
45 return qs.none()
f6724c20 46 elif grp_administrateurs_recrutement in user_groupes:
ca73c3c6
NBV
47 try:
48 user = AdministrateurRegional.objects.get(user=request.user)
49 except AdministrateurRegional.DoesNotExist:
50 return qs.none()
f6724c20
NBV
51 else:
52 return qs.none()
53
54 if type(user) is AdministrateurRegional:
55 region_ids = [g.id for g in user.regions.all()]
56 return qs.select_related('offre_emploi').\
57 filter(region__in=region_ids)
beef7690 58 if type(user) is Evaluateur:
f6724c20 59 candidats = [g for g in user.candidats.all()]
beef7690 60 offre_emploi_ids = [c.offre_emploi.id for c in candidats]
f6724c20 61 return qs.select_related('offre_emploi').\
beef7690 62 filter(id__in=offre_emploi_ids)
3bcef02d 63 return qs.none()
beef7690 64 return query.select_related('offre_emploi')
f6724c20
NBV
65
66 def has_change_permission(self, request, obj=None):
67 user_groupes = request.user.groups.all()
68 if grp_drh_recrutement in user_groupes or \
69 grp_administrateurs_recrutement in user_groupes:
70 return True
71 return False
72
73class ProxyOffreEmploiAdmin(OffreEmploiAdmin):
beef7690 74 list_display = ('nom', 'resume', 'date_limite', 'region', )
65c4cbd9 75 readonly_fields = ('description', 'poste', 'bureau',
f6724c20
NBV
76 'duree_affectation', 'renumeration',
77 'debut_affectation', 'lieu_affectation', 'nom',
78 'resume', 'date_limite', 'region')
79 fieldsets = (
720c3ad5 80 ('Nom', {
f6724c20
NBV
81 'fields': ('nom', )
82 }),
720c3ad5 83 ('Description générale', {
f6724c20
NBV
84 'fields': ('poste', 'resume','description', 'date_limite', )
85 }),
720c3ad5 86 ('Coordonnées', {
f6724c20
NBV
87 'fields': ('lieu_affectation', 'bureau', 'region', )
88 }),
720c3ad5 89 ('Autre', {
f6724c20
NBV
90 'fields': ('debut_affectation', 'duree_affectation',
91 'renumeration', )
92 }),
93 )
94 def has_add_permission(self, request):
95 return False
96
97 def has_delete_permission(self, request, obj=None):
98 return False
99
2d083449
NBV
100 def has_change_permission(self, request, obj=None):
101 user_groupes = request.user.groups.all()
beef7690
NBV
102 if grp_evaluateurs_recrutement in user_groupes or \
103 grp_drh_recrutement in user_groupes:
2d083449
NBV
104 return True
105 return False
106
cced6a23 107class ProxyCandidatPiece(CandidatPiece):
108 """
109 Ce proxy sert uniquement dans l'admin à disposer d'un libellé
110 plus ergonomique.
111 """
112 class Meta:
113 proxy = True
114 verbose_name = "pièce jointe"
74cbc7a7 115 verbose_name_plural = "pièces jointes"
cced6a23 116
170c9aa2 117class CandidatPieceInline(admin.TabularInline):
cced6a23 118 model = ProxyCandidatPiece
119 fields = ('candidat', 'nom', 'path', )
170c9aa2 120 extra = 1
121
27c81d11 122class ProxyEvaluateur(Evaluateur.candidats.through):
cced6a23 123 """
124 Ce proxy sert uniquement dans l'admin à disposer d'un libellé
125 plus ergonomique.
126 """
127 class Meta:
128 proxy = True
129 verbose_name = "évaluateur"
130
eb579d40 131class EvaluateurInline(admin.TabularInline):
cced6a23 132 model = ProxyEvaluateur
720c3ad5 133 fields = ('evaluateur',)
eb579d40 134 extra = 1
135
d2b30f5f 136class CandidatAdmin(VersionAdmin):
7f9e891e 137 date_hierarchy = 'date_creation'
0fd8a26d 138 list_display = ('nom', 'prenom', 'offre_emploi','statut',
720c3ad5 139 'voir_offre_emploi', #'note_evaluateur',
8941aee7 140 'calculer_moyenne', 'afficher_candidat',)
8ea41642 141 list_filter = ('offre_emploi', )
7f9e891e 142 fieldsets = (
4896b661 143 ("Offre d'emploi", {
144 'fields': ('offre_emploi', )
145 }),
7f9e891e 146 ('Informations personnelles', {
147 'fields': ('prenom','nom','genre', 'nationalite', 'date_naissance',
148 'situation_famille', 'nombre_dependant',)
149 }),
ec517164 150 ('Coordonnées', {
151 'fields': ('telephone', 'email', 'adresse', 'ville',
152 'etat_province', 'code_postal', 'pays', )
7f9e891e 153 }),
154 ('Informations professionnelles', {
4896b661 155 'fields': ('niveau_diplome','employeur_actuel',
8ea41642 156 'poste_actuel', 'domaine_professionnel',)
7f9e891e 157 }),
65c4cbd9
NBV
158 ('Traitement', {
159 'fields': ('statut', )
7f9e891e 160 }),
161 )
170c9aa2 162 inlines = [
163 CandidatPieceInline,
eb579d40 164 EvaluateurInline,
170c9aa2 165 ]
f9983b5a 166
4e8340cf 167 actions = ['affecter_candidats_evaluateur', 'envoyer_courriel_candidats']
362a3534 168 # Affecter un évaluateurs à des candidats
7061f835 169 def affecter_candidats_evaluateur(modeladmin, obj, candidats):
596fe324 170 selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
2adf9e0c 171
8ea41642 172 return HttpResponseRedirect(reverse('affecter_evaluateurs_candidats')+
173 "?ids=%s" % (",".join(selected)))
d835c9f3 174 affecter_candidats_evaluateur.short_description = u'Affecter évaluateur'
362a3534 175
4e8340cf 176 # Envoyer un courriel à des candidats
52765380 177 def envoyer_courriel_candidats(modeladmin, obj, candidats):
178 selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
179
180 return HttpResponseRedirect(reverse('envoyer_courriel_candidats')+
181 "?ids=%s" % (",".join(selected)))
182 envoyer_courriel_candidats.short_description = u'Envoyer courriel'
183
05503d56 184 # Évaluer un candidat
beef7690
NBV
185 # TODO: Revérifier, si c'est mieux de rediriger vers Évaluation candidat et ensuite
186 # permettre l'évaluation ou laisser le reverse(evaluer_candidat)
596fe324 187 def evaluer_candidat(self, obj):
beef7690
NBV
188 return "<a href='%s?candidat__id__exact=%s'>Évaluer le candidat </a>" % \
189 (reverse('admin:recrutement_candidatevaluation_changelist'),
190 obj.id)
596fe324 191 evaluer_candidat.allow_tags = True
beef7690 192 evaluer_candidat.short_description = 'Évaluation'
596fe324 193
7d82fd33 194 # Afficher un candidat
195 def afficher_candidat(self, obj):
beef7690 196 return "<a href='%s'>Voir le candidat</a>" % (reverse('admin:recrutement_proxycandidat_change', args=(obj.id,)))
7d82fd33 197 afficher_candidat.allow_tags = True
f6724c20 198 afficher_candidat.short_description = u'Afficher les détails du candidat'
7d82fd33 199
8941aee7 200 # Voir l'offre d'emploi
201 def voir_offre_emploi(self, obj):
720c3ad5
NBV
202 return "<a href='%s'>Voir l'offre d'emploi</a>" % \
203 (reverse('admin:recrutement_proxyoffreemploi_change',
204 args=(obj.offre_emploi.id,)))
8941aee7 205 voir_offre_emploi.allow_tags = True
206 voir_offre_emploi.short_description = "Afficher l'offre d'emploi"
207
8941aee7 208 # Calculer la moyenne des notes
209 def calculer_moyenne(self, obj):
210 evaluations = CandidatEvaluation.objects.filter(candidat=obj)
211 offre_emploi = obj.offre_emploi
212
f6724c20
NBV
213 notes = [evaluation.note for evaluation in evaluations.all() \
214 if evaluation.note is not None]
8941aee7 215
216 if len(notes) > 0 and offre_emploi.date_limite <= datetime.date.today():
217 moyenne_votes = float(sum(notes)) / len(notes)
218 else:
219 moyenne_votes = "Non disponible"
220 return moyenne_votes
221 calculer_moyenne.allow_tags = True
222 calculer_moyenne.short_description = "Moyenne des notes"
223
f6724c20
NBV
224 def add_delete_permission(self, request, obj=None) :
225 user_groupes = request.user.groups.all()
226 if grp_drh_recrutement in user_groupes or \
227 grp_administrateurs_recrutement in user_groupes:
228 return True
229 return False
4896b661 230
f6724c20
NBV
231 def has_add_permission(self, request):
232 return self.add_delete_permission(request, request)
4896b661 233
f6724c20
NBV
234 def has_delete_permission(self, request, obj=None):
235 return self.add_delete_permission(request, request)
236
237 def has_change_permission(self, request, obj=None):
238 user_groupes = request.user.groups.all()
239 if grp_drh_recrutement in user_groupes or \
2d083449 240 grp_administrateurs_recrutement in user_groupes:
f6724c20
NBV
241 return True
242 return False
4896b661 243
596fe324 244 def queryset(self, obj):
f9983b5a 245 """
8ea41642 246 Spécifie un queryset limité, autrement Django exécute un
247 select_related() sans paramètre, ce qui a pour effet de charger tous
248 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
249 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
250 génération d'une requête infinie.
d835c9f3 251
f9983b5a 252 """
f6724c20
NBV
253 qs = self.model._default_manager.get_query_set()
254 # Si user est superuser afficher tous les candidats
255 user_groupes = obj.user.groups.all()
256 if not grp_drh_recrutement in user_groupes:
257 # Si le user n'est ni un évaluateur ni un administrateur régional,
258 # retourner none
259
260 # Vérifier groupes
261 if grp_evaluateurs_recrutement in user_groupes:
ca73c3c6
NBV
262 try:
263 user = Evaluateur.objects.get(user=obj.user)
264 except Evaluateur.DoesNotExist:
265 return qs.none()
efedc086
NBV
266 """
267 elif grp_administrateurs_recrutement in user_groupes:
268 try:
269 user = AdministrateurRegional.objects.get(user=obj.user)
270 except AdministrateurRegional.DoesNotExist:
271 return qs.none()
272 """
f6724c20
NBV
273 else:
274 return qs.none()
f6724c20
NBV
275 ids = [c.id for c in user.candidats.all()]
276 return qs.select_related('candidats').filter(id__in=ids)
277 return qs.select_related('candidats')
278
279class ProxyCandidatAdmin(CandidatAdmin):
f6724c20
NBV
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',)
2d083449
NBV
287 fieldsets = (
288 ("Offre d'emploi", {
289 'fields': ('offre_emploi', )
290 }),
291 ('Informations personnelles', {
292 'fields': ('prenom','nom','genre', 'nationalite', 'date_naissance',
293 'situation_famille', 'nombre_dependant',)
294 }),
295 ('Coordonnées', {
296 'fields': ('telephone', 'email', 'adresse', 'ville',
297 'etat_province', 'code_postal', 'pays', )
298 }),
299 ('Informations professionnelles', {
300 'fields': ('niveau_diplome','employeur_actuel',
301 'poste_actuel', 'domaine_professionnel',)
302 }),
303 )
f6724c20 304 inlines = []
2d083449 305
f6724c20
NBV
306 def has_add_permission(self, request):
307 return False
308
309 def has_delete_permission(self, request, obj=None):
310 return False
2adf9e0c 311
2d083449
NBV
312 def has_change_permission(self, request, obj=None):
313 user_groupes = request.user.groups.all()
beef7690
NBV
314 if grp_drh_recrutement in user_groupes or \
315 grp_administrateurs_recrutement in user_groupes or \
316 grp_evaluateurs_recrutement in user_groupes:
2d083449
NBV
317 return True
318 return False
319
2e9ee615 320class CandidatPieceAdmin(admin.ModelAdmin):
170c9aa2 321 list_display = ('nom', 'candidat', )
322
323 def queryset(self, request):
324 """
325 Spécifie un queryset limité, autrement Django exécute un
326 select_related() sans paramètre, ce qui a pour effet de charger tous
327 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
328 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
329 génération d'une requête infinie.
d835c9f3 330 Affiche la liste de candidats que si le user connecté
27c81d11 331 possède un Evaluateur
170c9aa2 332 """
333 qs = self.model._default_manager.get_query_set()
334 return qs.select_related('candidat')
2e9ee615 335
d2b30f5f 336class EvaluateurAdmin(VersionAdmin):
eb579d40 337 fieldsets = (
f6724c20 338 (None, {'fields': ('user', )}),
720c3ad5 339 #(None, {'fields': ('candidats',)}),
eb579d40 340 )
4418c732 341
b89fef74 342class AdministrateurRegionalAdmin(VersionAdmin):
27c81d11 343 pass
344
d2b30f5f 345class CandidatEvaluationAdmin(VersionAdmin):
beef7690
NBV
346 list_display = ('_offre_emploi', '_candidat', '_note', '_commentaire',
347 'evaluateur',)
348 readonly_fields = ('candidat', 'evaluateur')
349 fieldsets = (
350 ('Évaluation du candidat', {
351 'fields': ('candidat', 'evaluateur', 'note', 'commentaire', )
352 }),
353 )
354
355 def _note(self, obj):
356 """
357 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
358 un lien pour Évaluer le candidat.
359 Sinon afficher la note.
360 """
361 if obj.note is None:
362 return "<a href='%s'>Évaluer le candidat </a>" % \
363 (reverse('admin:recrutement_candidatevaluation_change',
364 args=(obj.candidat.id,)))
365 return obj.note
366 _note.allow_tags = True
367 _note.short_description = "Votre note"
368 _note.admin_order_field = 'note'
369
370 def _candidat(self, obj):
371 return "<a href='%s'>%s</a>" \
372 % (reverse('admin:recrutement_proxycandidat_change',
373 args=(obj.candidat.id,)), obj.candidat)
374 _candidat.allow_tags = True
375 _candidat.short_description = 'Candidat'
376
377 def _commentaire(self, obj):
378 """
379 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
380 dans le champ commentaire, Aucun au lieu de (None)
381 Sinon afficher la note.
382 """
383 if obj.commentaire is None:
384 return "Aucun"
385 return obj.commentaire
386 _commentaire.allow_tags = True
387 _commentaire.short_description = "Commentaire"
720c3ad5 388
720c3ad5 389
beef7690
NBV
390 def _offre_emploi(self, obj):
391 return "<a href='%s'>%s</a>" % \
392 (reverse('admin:recrutement_proxyoffreemploi_change',
393 args=(obj.candidat.offre_emploi.id,)), obj.candidat.offre_emploi)
394 _offre_emploi.allow_tags = True
395 _offre_emploi.short_description = "Voir offre d'emploi"
396 _offre_emploi.admin_order_field = 'offre_emploi'
397
720c3ad5 398 def queryset(self, request):
beef7690
NBV
399 """
400 Afficher uniquement les évaluations de l'évaluateur, sauf si
401 l'utilisateur est super admin.
402 """
720c3ad5 403 qs = self.model._default_manager.get_query_set()
beef7690
NBV
404 user_groupes = request.user.groups.all()
405 if grp_drh_recrutement in user_groupes:
406 return qs.select_related('offre_emploi')
407
ca73c3c6 408 try:
d069cdf1 409 evaluateur = Evaluateur.objects.get(user=request.user)
ca73c3c6
NBV
410 except Evaluateur.DoesNotExist:
411 return qs.none()
412
413 candidats_evaluations = CandidatEvaluation.objects.\
414 filter(evaluateur=evaluateur)
415 candidats_evaluations_ids = [ce.id for ce in \
416 candidats_evaluations.all()]
417 return qs.select_related('offre_emploi').\
418 filter(id__in=candidats_evaluations_ids)
596fe324 419
4e8340cf 420class CourrielTemplateAdmin(VersionAdmin):
421 pass
422
df59fcab 423admin.site.register(OffreEmploi, OffreEmploiAdmin)
424admin.site.register(Candidat, CandidatAdmin)
720c3ad5 425admin.site.register(CandidatEvaluation, CandidatEvaluationAdmin)
beef7690 426#admin.site.register(CourrielTemplate, CourrielTemplateAdmin)
27c81d11 427admin.site.register(Evaluateur, EvaluateurAdmin)
beef7690 428#admin.site.register(AdministrateurRegional, AdministrateurRegionalAdmin)
f6724c20
NBV
429admin.site.register(ProxyOffreEmploi, ProxyOffreEmploiAdmin)
430admin.site.register(ProxyCandidat, ProxyCandidatAdmin)