fix proxy candidat 403
[auf_rh_dae.git] / project / recrutement / admin.py
CommitLineData
df59fcab 1# -*- encoding: utf-8 -*-
2
1b4c8020 3import textwrap
6067184b 4from django.core.urlresolvers import reverse
5from django.http import HttpResponseRedirect
df59fcab 6from django.contrib import admin
3a542b85 7from django.forms.models import BaseInlineFormSet
97b168d6 8from django.db.models import Avg
d2cbe75d 9from django.conf import settings
38df74bb 10
6067184b 11from reversion.admin import VersionAdmin
78db8c08 12from datamaster_modeles.models import Region, Bureau
e2968e84 13from project.rh import models as rh
7d9736ba
NBV
14
15from project.dae.utils import get_employe_from_user as get_emp
df59fcab 16from recrutement.models import *
c69ecb4f 17from recrutement.workflow import grp_drh_recrutement, grp_directeurs_bureau_recrutement, \
940c9dd8
OL
18 grp_administrateurs_recrutement, \
19 grp_correspondants_rh_recrutement
3bc5ea42 20
a084e988 21from recrutement.forms import *
df59fcab 22
7d9736ba 23### CONSTANTES
d333c690
NBV
24IMPLANTATIONS_CENTRALES = [15, 19]
25
97b168d6
OL
26class OrderedChangeList(admin.views.main.ChangeList):
27 """
28 Surcharge pour appliquer le order_by d'un annotate
29 """
30 def get_query_set(self):
31 qs = super(OrderedChangeList, self).get_query_set()
32 qs = qs.order_by('-moyenne')
33 return qs
34
d2b30f5f 35class OffreEmploiAdmin(VersionAdmin):
7f9e891e 36 date_hierarchy = 'date_creation'
c281435b 37 list_display = ('nom', 'date_limite', 'region', 'statut',
e2968e84 38 'est_affiche', '_candidatsList', )
7d0ae1ba
NBV
39 exclude = ('actif', 'poste_nom', 'resume',)
40 list_filter = ('statut',)
c4874d66 41 actions = ['affecter_evaluateurs_offre_emploi', ]
a084e988 42 form = OffreEmploiForm
2c3c54ee 43
7d9736ba 44 ### Actions à afficher
a029f641
NBV
45 def get_actions(self, request):
46 actions = super(OffreEmploiAdmin, self).get_actions(request)
47 del actions['delete_selected']
540dfae4 48 return actions
a029f641 49
7d9736ba 50 ### Affecter un évaluateurs à des offres d'emploi
c4874d66
NBV
51 def affecter_evaluateurs_offre_emploi(modeladmin, obj, candidats):
52 selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
53
54 return HttpResponseRedirect(reverse('affecter_evaluateurs_offre_emploi')+
55 "?ids=%s" % (",".join(selected)))
56 affecter_evaluateurs_offre_emploi.short_description = u'Affecter évaluateur(s)'
57
7d9736ba 58 ### Afficher la liste des candidats pour l'offre d'emploi
596fe324 59 def _candidatsList(self, obj):
8ea41642 60 return "<a href='%s?offre_emploi__id__exact=%s'>Voir les candidats \
61 </a>" % (reverse('admin:recrutement_candidat_changelist'), obj.id)
2f78949d 62 _candidatsList.allow_tags = True
f6724c20 63 _candidatsList.short_description = "Afficher la liste des candidats"
362a3534 64
7d9736ba 65 ### Formulaire
3a542b85
NBV
66 def get_form(self, request, obj=None, **kwargs):
67 form = super(OffreEmploiAdmin, self).get_form(request, obj, **kwargs)
68 employe = get_emp(request.user)
3a542b85 69 user_groupes = request.user.groups.all()
be343ed2 70
13389dae 71
7d9736ba 72 # Region
d333c690
NBV
73 if form.declared_fields.has_key('region'):
74 region_field = form.declared_fields['region']
75 else:
76 region_field = form.base_fields['region']
77
78 if grp_drh_recrutement in user_groupes:
79 region_field.queryset = Region.objects.all()
80 else:
81 region_field.queryset = Region.objects.\
82 filter(id=employe.implantation.region.id)
83
7d9736ba 84 # Poste
d333c690
NBV
85 if form.declared_fields.has_key('poste'):
86 poste_field = form.declared_fields['poste']
87 else:
88 poste_field = form.base_fields['poste']
89
d333c690
NBV
90 if grp_drh_recrutement in user_groupes:
91 poste_field.queryset = rh.Poste.objects.all()
92 else:
7d9736ba
NBV
93 poste_field.queryset = rh.Poste.objects.\
94 filter(implantation__region=employe.implantation.region).\
95 exclude(implantation__in=IMPLANTATIONS_CENTRALES)
d333c690 96
7d9736ba 97 # Bureau
d333c690
NBV
98 if form.declared_fields.has_key('bureau'):
99 bureau_field = form.declared_fields['bureau']
100 else:
101 bureau_field = form.base_fields['bureau']
102
103 if grp_drh_recrutement in user_groupes:
104 bureau_field.queryset = Bureau.objects.all()
105 else:
7d9736ba
NBV
106 bureau_field.queryset = Bureau.objects.\
107 filter(region=employe.implantation.region)
13389dae 108
3a542b85 109 return form
be343ed2 110
7d9736ba 111 ### Queryset
2f78949d 112 def queryset(self, request):
940c9dd8 113 qs = self.model._default_manager.get_query_set().select_related('offre_emploi')
f6724c20 114 user_groupes = request.user.groups.all()
7d9736ba 115 if grp_drh_recrutement in user_groupes:
940c9dd8 116 return qs
f6724c20 117
7d9736ba 118 if grp_directeurs_bureau_recrutement in user_groupes or \
940c9dd8 119 grp_correspondants_rh_recrutement in user_groupes or \
7d9736ba
NBV
120 grp_administrateurs_recrutement in user_groupes:
121 employe = get_emp(request.user)
940c9dd8 122 return qs.filter(region=employe.implantation.region)
7d9736ba 123
c69ecb4f 124 if Evaluateur.objects.filter(user=request.user).exists():
940c9dd8
OL
125 evaluateur = Evaluateur.objects.get(user=request.user)
126 offre_ids = [e.candidat.offre_emploi_id for e in
127 CandidatEvaluation.objects.select_related('candidat').filter(evaluateur=evaluateur)]
128 return qs.filter(id__in=offre_ids)
129
7d9736ba
NBV
130 return qs.none()
131
132 ### Permission add, delete, change
3a542b85
NBV
133 def has_add_permission(self, request):
134 user_groupes = request.user.groups.all()
26add0fd
OL
135 if request.user.is_superuser is True or \
136 grp_drh_recrutement in user_groupes or \
3a542b85 137 grp_directeurs_bureau_recrutement in user_groupes or \
7d9736ba 138 grp_administrateurs_recrutement in user_groupes:
3a542b85
NBV
139 return True
140 return False
141
7d9736ba
NBV
142 def has_delete_permission(self, request, obj=None):
143 user_groupes = request.user.groups.all()
26add0fd
OL
144 if request.user.is_superuser is True or \
145 grp_drh_recrutement in user_groupes or \
7d9736ba
NBV
146 grp_directeurs_bureau_recrutement in user_groupes or \
147 grp_administrateurs_recrutement in user_groupes:
148 return True
149 return False
150
f6724c20
NBV
151 def has_change_permission(self, request, obj=None):
152 user_groupes = request.user.groups.all()
26add0fd
OL
153 if request.user.is_superuser is True or \
154 grp_drh_recrutement in user_groupes or \
3a542b85 155 grp_directeurs_bureau_recrutement in user_groupes or \
7d9736ba 156 grp_administrateurs_recrutement in user_groupes:
f6724c20
NBV
157 return True
158 return False
159
160class ProxyOffreEmploiAdmin(OffreEmploiAdmin):
7d9736ba 161 list_display = ('nom', 'date_limite', 'region', 'statut',
4fd0c4a2 162 'est_affiche')
7d0ae1ba
NBV
163 readonly_fields = ('description', 'bureau', 'duree_affectation',
164 'renumeration', 'debut_affectation', 'lieu_affectation',
13389dae 165 'nom', 'resume', 'date_limite', 'region', 'poste')
f6724c20 166 fieldsets = (
720c3ad5 167 ('Nom', {
f6724c20
NBV
168 'fields': ('nom', )
169 }),
720c3ad5 170 ('Description générale', {
13389dae 171 'fields': ('description', 'date_limite', )
f6724c20 172 }),
720c3ad5 173 ('Coordonnées', {
13389dae 174 'fields': ('lieu_affectation', 'bureau', 'region', 'poste',)
f6724c20 175 }),
720c3ad5 176 ('Autre', {
f6724c20
NBV
177 'fields': ('debut_affectation', 'duree_affectation',
178 'renumeration', )
179 }),
180 )
464e5825 181 inlines = []
7d9736ba 182
b8778e64 183
7d9736ba 184 ### Lieu de redirection après le change
a029f641 185 def response_change(self, request, obj):
464e5825
NBV
186 return HttpResponseRedirect(reverse\
187 ('admin:recrutement_proxyoffreemploi_changelist'))
a029f641 188
be343ed2
NBV
189 ### Formulaire
190 def get_form(self, request, obj=None, **kwargs):
191 form = super(OffreEmploiAdmin, self).get_form(request, obj, **kwargs)
192 return form
193
7d9736ba 194 ### Permissions add, delete, change
f6724c20
NBV
195 def has_add_permission(self, request):
196 return False
197
198 def has_delete_permission(self, request, obj=None):
199 return False
200
2d083449 201 def has_change_permission(self, request, obj=None):
c69ecb4f 202 return True
2d083449 203
572c8d08
NBV
204class CandidatPieceInline(admin.TabularInline):
205 model = CandidatPiece
206 fields = ('candidat', 'nom', 'path',)
207 extra = 1
208 max_num = 3
209
c69ecb4f
OL
210class ReadOnlyCandidatPieceInline(CandidatPieceInline):
211 readonly_fields = ('candidat', 'nom', 'path', )
212 cand_delete = False
213
214
572c8d08
NBV
215class CandidatEvaluationInlineFormSet(BaseInlineFormSet):
216 """
217 Empêche la suppression d'une évaluation pour le CandidatEvaluationInline
218 """
219 def __init__(self, *args, **kwargs):
220 super(CandidatEvaluationInlineFormSet, self).__init__(*args, **kwargs)
221 self.can_delete = False
222
223class CandidatEvaluationInline(admin.TabularInline):
224 model = CandidatEvaluation
225 fields = ('evaluateur', 'note', 'commentaire')
226 max_num = 0
227 extra = 0
228 formset = CandidatEvaluationInlineFormSet
7d9736ba
NBV
229
230 ### Fields readonly
572c8d08
NBV
231 def get_readonly_fields(self, request, obj=None):
232 """
233 Empêche la modification des évaluations
234 """
235 if obj:
236 return self.readonly_fields+('evaluateur', 'note', 'commentaire')
237 return self.readonly_fields
238
d2b30f5f 239class CandidatAdmin(VersionAdmin):
f1ea8529 240 search_fields = ('nom', 'prenom' )
7d0ae1ba 241 exclude = ('actif', )
940c9dd8 242 list_editable = ('statut', )
1b4c8020 243 list_display = ('_candidat', 'offre_emploi',
940c9dd8
OL
244 'voir_offre_emploi', 'calculer_moyenne',
245 'afficher_candidat', '_date_creation', 'statut', )
246 list_filter = ('offre_emploi', 'offre_emploi__region', 'statut', )
7d0ae1ba 247
7f9e891e 248 fieldsets = (
4896b661 249 ("Offre d'emploi", {
250 'fields': ('offre_emploi', )
251 }),
7f9e891e 252 ('Informations personnelles', {
4fd0c4a2 253 'fields': ('prenom','nom','genre', 'nationalite',
7f9e891e 254 'situation_famille', 'nombre_dependant',)
255 }),
ec517164 256 ('Coordonnées', {
257 'fields': ('telephone', 'email', 'adresse', 'ville',
258 'etat_province', 'code_postal', 'pays', )
7f9e891e 259 }),
260 ('Informations professionnelles', {
4896b661 261 'fields': ('niveau_diplome','employeur_actuel',
8ea41642 262 'poste_actuel', 'domaine_professionnel',)
7f9e891e 263 }),
65c4cbd9
NBV
264 ('Traitement', {
265 'fields': ('statut', )
7f9e891e 266 }),
267 )
170c9aa2 268 inlines = [
269 CandidatPieceInline,
572c8d08 270 CandidatEvaluationInline,
170c9aa2 271 ]
540dfae4 272 actions = ['envoyer_courriel_candidats']
a029f641 273
1b4c8020
OL
274 def _candidat(self, obj):
275 txt = u"%s %s (%s)" % ( obj.nom.upper(), obj.prenom,
276 obj.genre)
277 txt = textwrap.wrap(txt, 30)
278 return "<br/>".join(txt)
279 _candidat.short_description = "Candidat"
280 _candidat.admin_order_field = "nom"
281 _candidat.allow_tags = True
282
940c9dd8
OL
283 def _date_creation(self, obj):
284 return obj.date_creation
1b4c8020
OL
285 _date_creation.admin_order_field = "date_creation"
286 _date_creation.short_description = "Date de réception"
940c9dd8 287
7d9736ba 288 ### Actions à afficher
a029f641
NBV
289 def get_actions(self, request):
290 actions = super(CandidatAdmin, self).get_actions(request)
291 del actions['delete_selected']
540dfae4 292 return actions
362a3534 293
7d9736ba 294 ### Envoyer un courriel à des candidats
52765380 295 def envoyer_courriel_candidats(modeladmin, obj, candidats):
296 selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
297
32834000 298 return HttpResponseRedirect(reverse('selectionner_template')+
52765380 299 "?ids=%s" % (",".join(selected)))
300 envoyer_courriel_candidats.short_description = u'Envoyer courriel'
301
7d9736ba 302 ### Évaluer un candidat
596fe324 303 def evaluer_candidat(self, obj):
dc7faf2b 304 return "<a href='%s?candidat__id__exact=%s'>Évaluer le candidat</a>" % \
beef7690
NBV
305 (reverse('admin:recrutement_candidatevaluation_changelist'),
306 obj.id)
596fe324 307 evaluer_candidat.allow_tags = True
beef7690 308 evaluer_candidat.short_description = 'Évaluation'
596fe324 309
7d9736ba 310 ### Afficher un candidat
7d82fd33 311 def afficher_candidat(self, obj):
d2cbe75d
OL
312 items = [u"<li><a href='%s%s'>%s</li>" % \
313 (settings.OE_PRIVE_MEDIA_URL, pj.path, pj.get_nom_display()) \
314 for pj in obj.pieces_jointes()]
315 html = "<a href='%s'>Voir le candidat</a>" % \
382501c1 316 (reverse('admin:recrutement_proxycandidat_change', args=(obj.id,)))
d2cbe75d 317 return "%s<ul>%s</ul>" % (html, "\n".join(items))
7d82fd33 318 afficher_candidat.allow_tags = True
8e0d552d 319 afficher_candidat.short_description = u'Détails du candidat'
7d82fd33 320
7d9736ba 321 ### Voir l'offre d'emploi
8941aee7 322 def voir_offre_emploi(self, obj):
720c3ad5
NBV
323 return "<a href='%s'>Voir l'offre d'emploi</a>" % \
324 (reverse('admin:recrutement_proxyoffreemploi_change',
325 args=(obj.offre_emploi.id,)))
8941aee7 326 voir_offre_emploi.allow_tags = True
327 voir_offre_emploi.short_description = "Afficher l'offre d'emploi"
328
7d9736ba 329 ### Calculer la moyenne des notes
8941aee7 330 def calculer_moyenne(self, obj):
331 evaluations = CandidatEvaluation.objects.filter(candidat=obj)
8941aee7 332
940c9dd8 333 notes = [evaluation.note for evaluation in evaluations \
f6724c20 334 if evaluation.note is not None]
8941aee7 335
7d0ae1ba 336 if len(notes) > 0:
d6790a12 337 moyenne_votes = round(float(sum(notes)) / len(notes), 2)
8941aee7 338 else:
339 moyenne_votes = "Non disponible"
940c9dd8
OL
340
341 totales = len(evaluations)
342 faites = len(notes)
343
344 if obj.statut == 'REC':
345 if totales == faites:
346 color = "green"
347 elif faites > 0 and float(totales) / float(faites) >= 2:
348 color = "orange"
349 else:
350 color = "red"
351 else:
352 color = "black"
353
354 return """<span style="color: %s;">%s (%s/%s)</span>""" % (color, moyenne_votes, faites, totales)
8941aee7 355 calculer_moyenne.allow_tags = True
3eb0be91 356 calculer_moyenne.short_description = "Moyenne"
d6790a12 357 calculer_moyenne.admin_order_field = ""
8941aee7 358
7d9736ba 359 ### Permissions add, delete, change
3a542b85 360 def has_add_permission(self, request):
f6724c20 361 user_groupes = request.user.groups.all()
26add0fd 362 if request.user.is_superuser is True or \
07df182e 363 grp_correspondants_rh_recrutement in user_groupes or \
26add0fd 364 grp_drh_recrutement in user_groupes or \
3a542b85 365 grp_directeurs_bureau_recrutement in user_groupes or \
7d9736ba 366 grp_administrateurs_recrutement in user_groupes:
f6724c20 367 return True
3a542b85 368 return False
4896b661 369
f6724c20 370 def has_delete_permission(self, request, obj=None):
3a542b85 371 user_groupes = request.user.groups.all()
26add0fd 372 if request.user.is_superuser is True or \
07df182e 373 grp_correspondants_rh_recrutement in user_groupes or \
26add0fd 374 grp_drh_recrutement in user_groupes or \
3a542b85 375 grp_directeurs_bureau_recrutement in user_groupes or \
7d9736ba 376 grp_administrateurs_recrutement in user_groupes:
3a542b85
NBV
377 return True
378 return False
f6724c20
NBV
379
380 def has_change_permission(self, request, obj=None):
381 user_groupes = request.user.groups.all()
26add0fd 382 if request.user.is_superuser is True or \
940c9dd8 383 grp_correspondants_rh_recrutement in user_groupes or \
26add0fd 384 grp_drh_recrutement in user_groupes or \
3a542b85 385 grp_directeurs_bureau_recrutement in user_groupes or \
7d9736ba 386 grp_administrateurs_recrutement in user_groupes:
f6724c20 387 return True
97b168d6
OL
388 return False
389
390 def get_changelist(self, request, **kwargs):
391 return OrderedChangeList
4896b661 392
d46075cb 393 def queryset(self, request):
f9983b5a 394 """
8ea41642 395 Spécifie un queryset limité, autrement Django exécute un
396 select_related() sans paramètre, ce qui a pour effet de charger tous
397 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
398 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
399 génération d'une requête infinie.
d835c9f3 400
f9983b5a 401 """
97b168d6
OL
402
403 qs = self.model._default_manager.get_query_set().select_related('offre_emploi').annotate(moyenne=Avg('evaluations__note'))
404
d46075cb 405 user_groupes = request.user.groups.all()
7d9736ba 406 if grp_drh_recrutement in user_groupes:
d6790a12 407 return qs
7d9736ba
NBV
408
409 if grp_directeurs_bureau_recrutement in user_groupes or \
940c9dd8 410 grp_correspondants_rh_recrutement in user_groupes or \
7d9736ba
NBV
411 grp_administrateurs_recrutement in user_groupes:
412 employe = get_emp(request.user)
d6790a12 413 return qs.filter(offre_emploi__region=employe.implantation.region)
7d9736ba 414
c69ecb4f 415 if Evaluateur.objects.filter(user=request.user).exists():
940c9dd8
OL
416 evaluateur = Evaluateur.objects.get(user=request.user)
417 candidat_ids = [e.candidat.id for e in
418 CandidatEvaluation.objects.filter(evaluateur=evaluateur)]
d6790a12 419 return qs.filter(id__in=candidat_ids)
7d9736ba 420 return qs.none()
f6724c20 421
613e8dfe 422
f6724c20 423class ProxyCandidatAdmin(CandidatAdmin):
940c9dd8 424 list_editable = ()
f6724c20 425 readonly_fields = ('statut', 'offre_emploi', 'prenom', 'nom',
4fd0c4a2
NBV
426 'genre', 'nationalite', 'situation_famille',
427 'nombre_dependant', 'telephone', 'email', 'adresse',
428 'ville', 'etat_province', 'code_postal', 'pays',
429 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
8e0d552d 430 'domaine_professionnel', 'pieces_jointes',)
2d083449
NBV
431 fieldsets = (
432 ("Offre d'emploi", {
433 'fields': ('offre_emploi', )
434 }),
435 ('Informations personnelles', {
4fd0c4a2 436 'fields': ('prenom','nom','genre', 'nationalite',
2d083449
NBV
437 'situation_famille', 'nombre_dependant',)
438 }),
439 ('Coordonnées', {
440 'fields': ('telephone', 'email', 'adresse', 'ville',
441 'etat_province', 'code_postal', 'pays', )
442 }),
443 ('Informations professionnelles', {
444 'fields': ('niveau_diplome','employeur_actuel',
445 'poste_actuel', 'domaine_professionnel',)
8e0d552d 446 }),
2d083449 447 )
c69ecb4f 448 inlines = (CandidatEvaluationInline, )
2d083449 449
f6724c20
NBV
450 def has_add_permission(self, request):
451 return False
452
453 def has_delete_permission(self, request, obj=None):
454 return False
2adf9e0c 455
2d083449 456 def has_change_permission(self, request, obj=None):
b44ee2a0
OL
457 user_groupes = request.user.groups.all()
458 if request.user.is_superuser is True or \
459 grp_correspondants_rh_recrutement in user_groupes or \
460 grp_drh_recrutement in user_groupes or \
461 grp_directeurs_bureau_recrutement in user_groupes or \
462 grp_administrateurs_recrutement in user_groupes:
463 return True
464
465 if obj is not None:
466 evaluateur = Evaluateur.objects.get(user=request.user)
467 for e in obj.evaluations.all():
468 if e.evaluateur == evaluateur:
469 return True
470
471 return False
2d083449 472
fe6fe6bb
OL
473 def get_actions(self, request):
474 return None
475
2e9ee615 476class CandidatPieceAdmin(admin.ModelAdmin):
170c9aa2 477 list_display = ('nom', 'candidat', )
478
7d9736ba 479 ### Queryset
170c9aa2 480 def queryset(self, request):
481 """
482 Spécifie un queryset limité, autrement Django exécute un
483 select_related() sans paramètre, ce qui a pour effet de charger tous
484 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
485 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
486 génération d'une requête infinie.
d835c9f3 487 Affiche la liste de candidats que si le user connecté
27c81d11 488 possède un Evaluateur
170c9aa2 489 """
490 qs = self.model._default_manager.get_query_set()
491 return qs.select_related('candidat')
2e9ee615 492
d2b30f5f 493class EvaluateurAdmin(VersionAdmin):
eb579d40 494 fieldsets = (
540dfae4
NBV
495 ("Utilisateur", {
496 'fields': ('user',)
497 }),
eb579d40 498 )
4418c732 499
7d9736ba 500 ### Actions à afficher
a029f641
NBV
501 def get_actions(self, request):
502 actions = super(EvaluateurAdmin, self).get_actions(request)
503 del actions['delete_selected']
540dfae4 504 return actions
a029f641 505
7d9736ba
NBV
506 ### Permissions add, delete, change
507 def has_add_permission(self, request):
508 user_groupes = request.user.groups.all()
26add0fd 509 if request.user.is_superuser is True or \
783ee3f6 510 grp_drh_recrutement in user_groupes:
7d9736ba
NBV
511 return True
512 return False
513
514 def has_delete_permission(self, request, obj=None):
515 user_groupes = request.user.groups.all()
26add0fd 516 if request.user.is_superuser is True or \
783ee3f6 517 grp_drh_recrutement in user_groupes:
7d9736ba
NBV
518 return True
519 return False
520
521 def has_change_permission(self, request, obj=None):
522 user_groupes = request.user.groups.all()
26add0fd 523 if request.user.is_superuser is True or \
783ee3f6 524 grp_drh_recrutement in user_groupes:
7d9736ba
NBV
525 return True
526 return False
27c81d11 527
940c9dd8
OL
528class CandidatEvaluationAdmin(admin.ModelAdmin):
529 search_fields = ('candidat__nom', 'candidat__prenom' )
530 list_display = ('_candidat', '_statut', '_offre_emploi', 'evaluateur', '_note',
b903198b 531 '_commentaire', )
940c9dd8
OL
532 readonly_fields = ('candidat', 'evaluateur')
533 list_filter = ('candidat__statut', 'candidat__offre_emploi',)
beef7690
NBV
534 fieldsets = (
535 ('Évaluation du candidat', {
536 'fields': ('candidat', 'evaluateur', 'note', 'commentaire', )
537 }),
538 )
539
a029f641 540 def get_actions(self, request):
5fe6986f
OL
541 # on stocke l'evaluateur connecté (pas forcément la meilleure place...)
542 try:
543 self.evaluateur = Evaluateur.objects.get(user=request.user)
544 except:
545 self.evaluateur = None
546
a029f641
NBV
547 actions = super(CandidatEvaluationAdmin, self).get_actions(request)
548 del actions['delete_selected']
540dfae4 549 return actions
a029f641 550
7d9736ba 551 ### Afficher la note
beef7690
NBV
552 def _note(self, obj):
553 """
554 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
555 un lien pour Évaluer le candidat.
556 Sinon afficher la note.
557 """
c44cb3de
OL
558 page = self.model.__name__.lower()
559 redirect_url = 'admin:recrutement_%s_change' % page
5fe6986f 560
beef7690 561 if obj.note is None:
5fe6986f
OL
562 label = "Candidat non évalué"
563 else:
564 label = obj.note
565
566 if self.evaluateur == obj.evaluateur:
567 return "<a href='%s'>%s</a>" % (reverse(redirect_url, args=(obj.id,)), label)
568 else:
569 return label
beef7690 570 _note.allow_tags = True
7d0ae1ba 571 _note.short_description = "Note"
beef7690
NBV
572 _note.admin_order_field = 'note'
573
940c9dd8
OL
574 def _statut(self, obj):
575 return obj.candidat.get_statut_display()
576 _statut.order_field = 'candidat__statut'
577 _statut.short_description = 'Statut'
578
579
7d9736ba 580 ### Lien en lecture seule vers le candidat
beef7690
NBV
581 def _candidat(self, obj):
582 return "<a href='%s'>%s</a>" \
583 % (reverse('admin:recrutement_proxycandidat_change',
584 args=(obj.candidat.id,)), obj.candidat)
585 _candidat.allow_tags = True
586 _candidat.short_description = 'Candidat'
587
7d9736ba 588 ### Afficher commentaire
beef7690
NBV
589 def _commentaire(self, obj):
590 """
591 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
592 dans le champ commentaire, Aucun au lieu de (None)
593 Sinon afficher la note.
594 """
595 if obj.commentaire is None:
596 return "Aucun"
597 return obj.commentaire
598 _commentaire.allow_tags = True
599 _commentaire.short_description = "Commentaire"
720c3ad5 600
7d9736ba 601 ### Afficher offre d'emploi
beef7690
NBV
602 def _offre_emploi(self, obj):
603 return "<a href='%s'>%s</a>" % \
604 (reverse('admin:recrutement_proxyoffreemploi_change',
dc7faf2b 605 args=(obj.candidat.offre_emploi.id,)), obj.candidat.offre_emploi)
beef7690
NBV
606 _offre_emploi.allow_tags = True
607 _offre_emploi.short_description = "Voir offre d'emploi"
beef7690 608
7d9736ba 609 def has_add_permission(self, request):
940c9dd8
OL
610 return False
611
612 def has_delete_permission(self, request, obj=None):
613 return False
7d9736ba 614
21b02da5
NBV
615 def has_change_permission(self, request, obj=None):
616 """
617 Permettre la visualisation dans la changelist
618 mais interdire l'accès à modifier l'objet si l'évaluateur n'est pas
619 le request.user
620 """
f133459f
OL
621 user_groupes = request.user.groups.all()
622
3bc5ea42
OL
623 if request.user.is_superuser or \
624 grp_drh_recrutement in user_groupes or \
f133459f
OL
625 grp_correspondants_rh_recrutement in user_groupes or \
626 grp_directeurs_bureau_recrutement in user_groupes or \
627 grp_administrateurs_recrutement in user_groupes:
c5a263d6 628 is_recrutement = True
f133459f 629 else:
6c6c51bb 630 is_recrutement = False
f133459f 631
f6996aa3 632 return is_recrutement
940c9dd8 633
720c3ad5 634 def queryset(self, request):
beef7690
NBV
635 """
636 Afficher uniquement les évaluations de l'évaluateur, sauf si
7d9736ba 637 l'utilisateur est dans les groupes suivants.
beef7690 638 """
940c9dd8 639 qs = self.model._default_manager.get_query_set().select_related('offre_emploi')
beef7690 640 user_groupes = request.user.groups.all()
940c9dd8 641
3a542b85 642 if grp_drh_recrutement in user_groupes or \
940c9dd8 643 grp_correspondants_rh_recrutement in user_groupes or \
3a542b85 644 grp_directeurs_bureau_recrutement in user_groupes or \
7d9736ba 645 grp_administrateurs_recrutement in user_groupes:
940c9dd8
OL
646 return qs
647
648 evaluateur = Evaluateur.objects.get(user=request.user)
649 candidats_evaluations = \
650 CandidatEvaluation.objects.filter(evaluateur=evaluateur,
651 candidat__statut__in=('REC', ))
652 candidats_evaluations_ids = [ce.id for ce in candidats_evaluations]
653 return qs.filter(id__in=candidats_evaluations_ids)
596fe324 654
3bc5ea42
OL
655
656class MesCandidatEvaluationAdmin(CandidatEvaluationAdmin):
657
658 def has_change_permission(self, request, obj=None):
659 try:
660 Evaluateur.objects.get(user=request.user)
661 is_evaluateur = True
662 except:
663 is_evaluateur = False
664
5fe6986f 665 if obj is None and is_evaluateur:
3bc5ea42
OL
666 return True
667
668 try:
669 return request.user == obj.evaluateur.user
670 except:
671 return False
672
673 def queryset(self, request):
674 qs = self.model._default_manager.get_query_set().select_related('offre_emploi')
675 evaluateur = Evaluateur.objects.get(user=request.user)
676 candidats_evaluations = \
677 CandidatEvaluation.objects.filter(evaluateur=evaluateur,
678 candidat__statut__in=('REC', ))
679 candidats_evaluations_ids = [ce.id for ce in candidats_evaluations]
680 return qs.filter(id__in=candidats_evaluations_ids)
681
682
4e8340cf 683class CourrielTemplateAdmin(VersionAdmin):
7d9736ba 684 ### Actions à afficher
a029f641
NBV
685 def get_actions(self, request):
686 actions = super(CourrielTemplateAdmin, self).get_actions(request)
687 del actions['delete_selected']
540dfae4 688 return actions
4e8340cf 689
df59fcab 690admin.site.register(OffreEmploi, OffreEmploiAdmin)
382501c1 691admin.site.register(ProxyOffreEmploi, ProxyOffreEmploiAdmin)
df59fcab 692admin.site.register(Candidat, CandidatAdmin)
382501c1 693admin.site.register(ProxyCandidat, ProxyCandidatAdmin)
720c3ad5 694admin.site.register(CandidatEvaluation, CandidatEvaluationAdmin)
3bc5ea42 695admin.site.register(MesCandidatEvaluation, MesCandidatEvaluationAdmin)
27c81d11 696admin.site.register(Evaluateur, EvaluateurAdmin)
32834000 697admin.site.register(CourrielTemplate, CourrielTemplateAdmin)