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