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