fix voir emploi
[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):
71aec2c3
OL
202 user_groupes = request.user.groups.all()
203 if request.user.is_superuser is True or \
204 grp_correspondants_rh_recrutement in user_groupes or \
205 grp_drh_recrutement in user_groupes or \
206 grp_directeurs_bureau_recrutement in user_groupes or \
207 grp_administrateurs_recrutement in user_groupes:
208 return True
46c508f5
OL
209
210 if obj is not None:
211 return True
212
71aec2c3 213 return False
2d083449 214
572c8d08
NBV
215class CandidatPieceInline(admin.TabularInline):
216 model = CandidatPiece
217 fields = ('candidat', 'nom', 'path',)
218 extra = 1
219 max_num = 3
220
c69ecb4f
OL
221class ReadOnlyCandidatPieceInline(CandidatPieceInline):
222 readonly_fields = ('candidat', 'nom', 'path', )
223 cand_delete = False
224
225
572c8d08
NBV
226class CandidatEvaluationInlineFormSet(BaseInlineFormSet):
227 """
228 Empêche la suppression d'une évaluation pour le CandidatEvaluationInline
229 """
230 def __init__(self, *args, **kwargs):
231 super(CandidatEvaluationInlineFormSet, self).__init__(*args, **kwargs)
232 self.can_delete = False
233
234class CandidatEvaluationInline(admin.TabularInline):
235 model = CandidatEvaluation
236 fields = ('evaluateur', 'note', 'commentaire')
237 max_num = 0
238 extra = 0
239 formset = CandidatEvaluationInlineFormSet
7d9736ba
NBV
240
241 ### Fields readonly
572c8d08
NBV
242 def get_readonly_fields(self, request, obj=None):
243 """
244 Empêche la modification des évaluations
245 """
246 if obj:
247 return self.readonly_fields+('evaluateur', 'note', 'commentaire')
248 return self.readonly_fields
249
d2b30f5f 250class CandidatAdmin(VersionAdmin):
f1ea8529 251 search_fields = ('nom', 'prenom' )
7d0ae1ba 252 exclude = ('actif', )
940c9dd8 253 list_editable = ('statut', )
1b4c8020 254 list_display = ('_candidat', 'offre_emploi',
940c9dd8
OL
255 'voir_offre_emploi', 'calculer_moyenne',
256 'afficher_candidat', '_date_creation', 'statut', )
257 list_filter = ('offre_emploi', 'offre_emploi__region', 'statut', )
7d0ae1ba 258
7f9e891e 259 fieldsets = (
4896b661 260 ("Offre d'emploi", {
261 'fields': ('offre_emploi', )
262 }),
7f9e891e 263 ('Informations personnelles', {
4fd0c4a2 264 'fields': ('prenom','nom','genre', 'nationalite',
7f9e891e 265 'situation_famille', 'nombre_dependant',)
266 }),
ec517164 267 ('Coordonnées', {
268 'fields': ('telephone', 'email', 'adresse', 'ville',
269 'etat_province', 'code_postal', 'pays', )
7f9e891e 270 }),
271 ('Informations professionnelles', {
4896b661 272 'fields': ('niveau_diplome','employeur_actuel',
8ea41642 273 'poste_actuel', 'domaine_professionnel',)
7f9e891e 274 }),
65c4cbd9
NBV
275 ('Traitement', {
276 'fields': ('statut', )
7f9e891e 277 }),
278 )
170c9aa2 279 inlines = [
280 CandidatPieceInline,
572c8d08 281 CandidatEvaluationInline,
170c9aa2 282 ]
540dfae4 283 actions = ['envoyer_courriel_candidats']
a029f641 284
1b4c8020
OL
285 def _candidat(self, obj):
286 txt = u"%s %s (%s)" % ( obj.nom.upper(), obj.prenom,
287 obj.genre)
288 txt = textwrap.wrap(txt, 30)
289 return "<br/>".join(txt)
290 _candidat.short_description = "Candidat"
291 _candidat.admin_order_field = "nom"
292 _candidat.allow_tags = True
293
940c9dd8
OL
294 def _date_creation(self, obj):
295 return obj.date_creation
1b4c8020
OL
296 _date_creation.admin_order_field = "date_creation"
297 _date_creation.short_description = "Date de réception"
940c9dd8 298
7d9736ba 299 ### Actions à afficher
a029f641
NBV
300 def get_actions(self, request):
301 actions = super(CandidatAdmin, self).get_actions(request)
302 del actions['delete_selected']
540dfae4 303 return actions
362a3534 304
7d9736ba 305 ### Envoyer un courriel à des candidats
52765380 306 def envoyer_courriel_candidats(modeladmin, obj, candidats):
307 selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
308
32834000 309 return HttpResponseRedirect(reverse('selectionner_template')+
52765380 310 "?ids=%s" % (",".join(selected)))
311 envoyer_courriel_candidats.short_description = u'Envoyer courriel'
312
7d9736ba 313 ### Évaluer un candidat
596fe324 314 def evaluer_candidat(self, obj):
dc7faf2b 315 return "<a href='%s?candidat__id__exact=%s'>Évaluer le candidat</a>" % \
beef7690
NBV
316 (reverse('admin:recrutement_candidatevaluation_changelist'),
317 obj.id)
596fe324 318 evaluer_candidat.allow_tags = True
beef7690 319 evaluer_candidat.short_description = 'Évaluation'
596fe324 320
7d9736ba 321 ### Afficher un candidat
7d82fd33 322 def afficher_candidat(self, obj):
d2cbe75d
OL
323 items = [u"<li><a href='%s%s'>%s</li>" % \
324 (settings.OE_PRIVE_MEDIA_URL, pj.path, pj.get_nom_display()) \
325 for pj in obj.pieces_jointes()]
326 html = "<a href='%s'>Voir le candidat</a>" % \
382501c1 327 (reverse('admin:recrutement_proxycandidat_change', args=(obj.id,)))
d2cbe75d 328 return "%s<ul>%s</ul>" % (html, "\n".join(items))
7d82fd33 329 afficher_candidat.allow_tags = True
8e0d552d 330 afficher_candidat.short_description = u'Détails du candidat'
7d82fd33 331
7d9736ba 332 ### Voir l'offre d'emploi
8941aee7 333 def voir_offre_emploi(self, obj):
720c3ad5
NBV
334 return "<a href='%s'>Voir l'offre d'emploi</a>" % \
335 (reverse('admin:recrutement_proxyoffreemploi_change',
336 args=(obj.offre_emploi.id,)))
8941aee7 337 voir_offre_emploi.allow_tags = True
338 voir_offre_emploi.short_description = "Afficher l'offre d'emploi"
339
7d9736ba 340 ### Calculer la moyenne des notes
8941aee7 341 def calculer_moyenne(self, obj):
342 evaluations = CandidatEvaluation.objects.filter(candidat=obj)
8941aee7 343
940c9dd8 344 notes = [evaluation.note for evaluation in evaluations \
f6724c20 345 if evaluation.note is not None]
8941aee7 346
7d0ae1ba 347 if len(notes) > 0:
d6790a12 348 moyenne_votes = round(float(sum(notes)) / len(notes), 2)
8941aee7 349 else:
350 moyenne_votes = "Non disponible"
940c9dd8
OL
351
352 totales = len(evaluations)
353 faites = len(notes)
354
355 if obj.statut == 'REC':
356 if totales == faites:
357 color = "green"
358 elif faites > 0 and float(totales) / float(faites) >= 2:
359 color = "orange"
360 else:
361 color = "red"
362 else:
363 color = "black"
364
365 return """<span style="color: %s;">%s (%s/%s)</span>""" % (color, moyenne_votes, faites, totales)
8941aee7 366 calculer_moyenne.allow_tags = True
3eb0be91 367 calculer_moyenne.short_description = "Moyenne"
d6790a12 368 calculer_moyenne.admin_order_field = ""
8941aee7 369
7d9736ba 370 ### Permissions add, delete, change
3a542b85 371 def has_add_permission(self, request):
f6724c20 372 user_groupes = request.user.groups.all()
26add0fd 373 if request.user.is_superuser is True or \
07df182e 374 grp_correspondants_rh_recrutement in user_groupes or \
26add0fd 375 grp_drh_recrutement in user_groupes or \
3a542b85 376 grp_directeurs_bureau_recrutement in user_groupes or \
7d9736ba 377 grp_administrateurs_recrutement in user_groupes:
f6724c20 378 return True
3a542b85 379 return False
4896b661 380
f6724c20 381 def has_delete_permission(self, request, obj=None):
3a542b85 382 user_groupes = request.user.groups.all()
26add0fd 383 if request.user.is_superuser is True or \
07df182e 384 grp_correspondants_rh_recrutement in user_groupes or \
26add0fd 385 grp_drh_recrutement in user_groupes or \
3a542b85 386 grp_directeurs_bureau_recrutement in user_groupes or \
7d9736ba 387 grp_administrateurs_recrutement in user_groupes:
3a542b85
NBV
388 return True
389 return False
f6724c20
NBV
390
391 def has_change_permission(self, request, obj=None):
392 user_groupes = request.user.groups.all()
26add0fd 393 if request.user.is_superuser is True or \
940c9dd8 394 grp_correspondants_rh_recrutement in user_groupes or \
26add0fd 395 grp_drh_recrutement in user_groupes or \
3a542b85 396 grp_directeurs_bureau_recrutement in user_groupes or \
7d9736ba 397 grp_administrateurs_recrutement in user_groupes:
f6724c20 398 return True
97b168d6
OL
399 return False
400
401 def get_changelist(self, request, **kwargs):
402 return OrderedChangeList
4896b661 403
d46075cb 404 def queryset(self, request):
f9983b5a 405 """
8ea41642 406 Spécifie un queryset limité, autrement Django exécute un
407 select_related() sans paramètre, ce qui a pour effet de charger tous
408 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
409 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
410 génération d'une requête infinie.
d835c9f3 411
f9983b5a 412 """
97b168d6
OL
413
414 qs = self.model._default_manager.get_query_set().select_related('offre_emploi').annotate(moyenne=Avg('evaluations__note'))
415
d46075cb 416 user_groupes = request.user.groups.all()
7d9736ba 417 if grp_drh_recrutement in user_groupes:
d6790a12 418 return qs
7d9736ba
NBV
419
420 if grp_directeurs_bureau_recrutement in user_groupes or \
940c9dd8 421 grp_correspondants_rh_recrutement in user_groupes or \
7d9736ba
NBV
422 grp_administrateurs_recrutement in user_groupes:
423 employe = get_emp(request.user)
d6790a12 424 return qs.filter(offre_emploi__region=employe.implantation.region)
7d9736ba 425
c69ecb4f 426 if Evaluateur.objects.filter(user=request.user).exists():
940c9dd8
OL
427 evaluateur = Evaluateur.objects.get(user=request.user)
428 candidat_ids = [e.candidat.id for e in
429 CandidatEvaluation.objects.filter(evaluateur=evaluateur)]
d6790a12 430 return qs.filter(id__in=candidat_ids)
7d9736ba 431 return qs.none()
f6724c20 432
613e8dfe 433
f6724c20 434class ProxyCandidatAdmin(CandidatAdmin):
940c9dd8 435 list_editable = ()
f6724c20 436 readonly_fields = ('statut', 'offre_emploi', 'prenom', 'nom',
4fd0c4a2
NBV
437 'genre', 'nationalite', 'situation_famille',
438 'nombre_dependant', 'telephone', 'email', 'adresse',
439 'ville', 'etat_province', 'code_postal', 'pays',
440 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
8e0d552d 441 'domaine_professionnel', 'pieces_jointes',)
2d083449
NBV
442 fieldsets = (
443 ("Offre d'emploi", {
444 'fields': ('offre_emploi', )
445 }),
446 ('Informations personnelles', {
4fd0c4a2 447 'fields': ('prenom','nom','genre', 'nationalite',
2d083449
NBV
448 'situation_famille', 'nombre_dependant',)
449 }),
450 ('Coordonnées', {
451 'fields': ('telephone', 'email', 'adresse', 'ville',
452 'etat_province', 'code_postal', 'pays', )
453 }),
454 ('Informations professionnelles', {
455 'fields': ('niveau_diplome','employeur_actuel',
456 'poste_actuel', 'domaine_professionnel',)
8e0d552d 457 }),
2d083449 458 )
c69ecb4f 459 inlines = (CandidatEvaluationInline, )
2d083449 460
f6724c20
NBV
461 def has_add_permission(self, request):
462 return False
463
464 def has_delete_permission(self, request, obj=None):
465 return False
2adf9e0c 466
2d083449 467 def has_change_permission(self, request, obj=None):
71aec2c3
OL
468 user_groupes = request.user.groups.all()
469 if request.user.is_superuser is True or \
470 grp_correspondants_rh_recrutement in user_groupes or \
471 grp_drh_recrutement in user_groupes or \
472 grp_directeurs_bureau_recrutement in user_groupes or \
473 grp_administrateurs_recrutement in user_groupes:
474 return True
b44ee2a0
OL
475
476 if obj is not None:
477 evaluateur = Evaluateur.objects.get(user=request.user)
478 for e in obj.evaluations.all():
479 if e.evaluateur == evaluateur:
480 return True
481
71aec2c3 482 return False
2d083449 483
fe6fe6bb
OL
484 def get_actions(self, request):
485 return None
486
2e9ee615 487class CandidatPieceAdmin(admin.ModelAdmin):
170c9aa2 488 list_display = ('nom', 'candidat', )
489
7d9736ba 490 ### Queryset
170c9aa2 491 def queryset(self, request):
492 """
493 Spécifie un queryset limité, autrement Django exécute un
494 select_related() sans paramètre, ce qui a pour effet de charger tous
495 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
496 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
497 génération d'une requête infinie.
d835c9f3 498 Affiche la liste de candidats que si le user connecté
27c81d11 499 possède un Evaluateur
170c9aa2 500 """
501 qs = self.model._default_manager.get_query_set()
502 return qs.select_related('candidat')
2e9ee615 503
d2b30f5f 504class EvaluateurAdmin(VersionAdmin):
eb579d40 505 fieldsets = (
540dfae4
NBV
506 ("Utilisateur", {
507 'fields': ('user',)
508 }),
eb579d40 509 )
4418c732 510
7d9736ba 511 ### Actions à afficher
a029f641
NBV
512 def get_actions(self, request):
513 actions = super(EvaluateurAdmin, self).get_actions(request)
514 del actions['delete_selected']
540dfae4 515 return actions
a029f641 516
7d9736ba
NBV
517 ### Permissions add, delete, change
518 def has_add_permission(self, request):
519 user_groupes = request.user.groups.all()
26add0fd 520 if request.user.is_superuser is True or \
783ee3f6 521 grp_drh_recrutement in user_groupes:
7d9736ba
NBV
522 return True
523 return False
524
525 def has_delete_permission(self, request, obj=None):
526 user_groupes = request.user.groups.all()
26add0fd 527 if request.user.is_superuser is True or \
783ee3f6 528 grp_drh_recrutement in user_groupes:
7d9736ba
NBV
529 return True
530 return False
531
532 def has_change_permission(self, request, obj=None):
533 user_groupes = request.user.groups.all()
26add0fd 534 if request.user.is_superuser is True or \
783ee3f6 535 grp_drh_recrutement in user_groupes:
7d9736ba
NBV
536 return True
537 return False
27c81d11 538
940c9dd8
OL
539class CandidatEvaluationAdmin(admin.ModelAdmin):
540 search_fields = ('candidat__nom', 'candidat__prenom' )
541 list_display = ('_candidat', '_statut', '_offre_emploi', 'evaluateur', '_note',
b903198b 542 '_commentaire', )
940c9dd8
OL
543 readonly_fields = ('candidat', 'evaluateur')
544 list_filter = ('candidat__statut', 'candidat__offre_emploi',)
beef7690
NBV
545 fieldsets = (
546 ('Évaluation du candidat', {
547 'fields': ('candidat', 'evaluateur', 'note', 'commentaire', )
548 }),
549 )
550
a029f641 551 def get_actions(self, request):
5fe6986f
OL
552 # on stocke l'evaluateur connecté (pas forcément la meilleure place...)
553 try:
554 self.evaluateur = Evaluateur.objects.get(user=request.user)
555 except:
556 self.evaluateur = None
557
a029f641
NBV
558 actions = super(CandidatEvaluationAdmin, self).get_actions(request)
559 del actions['delete_selected']
540dfae4 560 return actions
a029f641 561
7d9736ba 562 ### Afficher la note
beef7690
NBV
563 def _note(self, obj):
564 """
565 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
566 un lien pour Évaluer le candidat.
567 Sinon afficher la note.
568 """
c44cb3de
OL
569 page = self.model.__name__.lower()
570 redirect_url = 'admin:recrutement_%s_change' % page
5fe6986f 571
beef7690 572 if obj.note is None:
5fe6986f
OL
573 label = "Candidat non évalué"
574 else:
575 label = obj.note
576
577 if self.evaluateur == obj.evaluateur:
578 return "<a href='%s'>%s</a>" % (reverse(redirect_url, args=(obj.id,)), label)
579 else:
580 return label
beef7690 581 _note.allow_tags = True
7d0ae1ba 582 _note.short_description = "Note"
beef7690
NBV
583 _note.admin_order_field = 'note'
584
940c9dd8
OL
585 def _statut(self, obj):
586 return obj.candidat.get_statut_display()
587 _statut.order_field = 'candidat__statut'
588 _statut.short_description = 'Statut'
589
590
7d9736ba 591 ### Lien en lecture seule vers le candidat
beef7690
NBV
592 def _candidat(self, obj):
593 return "<a href='%s'>%s</a>" \
594 % (reverse('admin:recrutement_proxycandidat_change',
595 args=(obj.candidat.id,)), obj.candidat)
596 _candidat.allow_tags = True
597 _candidat.short_description = 'Candidat'
598
7d9736ba 599 ### Afficher commentaire
beef7690
NBV
600 def _commentaire(self, obj):
601 """
602 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
603 dans le champ commentaire, Aucun au lieu de (None)
604 Sinon afficher la note.
605 """
606 if obj.commentaire is None:
607 return "Aucun"
608 return obj.commentaire
609 _commentaire.allow_tags = True
610 _commentaire.short_description = "Commentaire"
720c3ad5 611
7d9736ba 612 ### Afficher offre d'emploi
beef7690
NBV
613 def _offre_emploi(self, obj):
614 return "<a href='%s'>%s</a>" % \
615 (reverse('admin:recrutement_proxyoffreemploi_change',
dc7faf2b 616 args=(obj.candidat.offre_emploi.id,)), obj.candidat.offre_emploi)
beef7690
NBV
617 _offre_emploi.allow_tags = True
618 _offre_emploi.short_description = "Voir offre d'emploi"
beef7690 619
7d9736ba 620 def has_add_permission(self, request):
940c9dd8
OL
621 return False
622
623 def has_delete_permission(self, request, obj=None):
624 return False
7d9736ba 625
21b02da5
NBV
626 def has_change_permission(self, request, obj=None):
627 """
628 Permettre la visualisation dans la changelist
629 mais interdire l'accès à modifier l'objet si l'évaluateur n'est pas
630 le request.user
631 """
f133459f
OL
632 user_groupes = request.user.groups.all()
633
3bc5ea42
OL
634 if request.user.is_superuser or \
635 grp_drh_recrutement in user_groupes or \
f133459f
OL
636 grp_correspondants_rh_recrutement in user_groupes or \
637 grp_directeurs_bureau_recrutement in user_groupes or \
638 grp_administrateurs_recrutement in user_groupes:
c5a263d6 639 is_recrutement = True
f133459f 640 else:
6c6c51bb 641 is_recrutement = False
f133459f 642
f6996aa3 643 return is_recrutement
f133459f 644
720c3ad5 645 def queryset(self, request):
beef7690
NBV
646 """
647 Afficher uniquement les évaluations de l'évaluateur, sauf si
7d9736ba 648 l'utilisateur est dans les groupes suivants.
beef7690 649 """
940c9dd8 650 qs = self.model._default_manager.get_query_set().select_related('offre_emploi')
beef7690 651 user_groupes = request.user.groups.all()
940c9dd8 652
3a542b85 653 if grp_drh_recrutement in user_groupes or \
940c9dd8 654 grp_correspondants_rh_recrutement in user_groupes or \
3a542b85 655 grp_directeurs_bureau_recrutement in user_groupes or \
7d9736ba 656 grp_administrateurs_recrutement in user_groupes:
940c9dd8
OL
657 return qs
658
659 evaluateur = Evaluateur.objects.get(user=request.user)
660 candidats_evaluations = \
661 CandidatEvaluation.objects.filter(evaluateur=evaluateur,
662 candidat__statut__in=('REC', ))
663 candidats_evaluations_ids = [ce.id for ce in candidats_evaluations]
664 return qs.filter(id__in=candidats_evaluations_ids)
596fe324 665
3bc5ea42
OL
666
667class MesCandidatEvaluationAdmin(CandidatEvaluationAdmin):
668
669 def has_change_permission(self, request, obj=None):
670 try:
671 Evaluateur.objects.get(user=request.user)
672 is_evaluateur = True
673 except:
674 is_evaluateur = False
675
5fe6986f 676 if obj is None and is_evaluateur:
3bc5ea42
OL
677 return True
678
679 try:
680 return request.user == obj.evaluateur.user
681 except:
682 return False
683
684 def queryset(self, request):
685 qs = self.model._default_manager.get_query_set().select_related('offre_emploi')
686 evaluateur = Evaluateur.objects.get(user=request.user)
687 candidats_evaluations = \
688 CandidatEvaluation.objects.filter(evaluateur=evaluateur,
689 candidat__statut__in=('REC', ))
690 candidats_evaluations_ids = [ce.id for ce in candidats_evaluations]
691 return qs.filter(id__in=candidats_evaluations_ids)
692
693
4e8340cf 694class CourrielTemplateAdmin(VersionAdmin):
7d9736ba 695 ### Actions à afficher
a029f641
NBV
696 def get_actions(self, request):
697 actions = super(CourrielTemplateAdmin, self).get_actions(request)
698 del actions['delete_selected']
540dfae4 699 return actions
4e8340cf 700
df59fcab 701admin.site.register(OffreEmploi, OffreEmploiAdmin)
382501c1 702admin.site.register(ProxyOffreEmploi, ProxyOffreEmploiAdmin)
df59fcab 703admin.site.register(Candidat, CandidatAdmin)
382501c1 704admin.site.register(ProxyCandidat, ProxyCandidatAdmin)
720c3ad5 705admin.site.register(CandidatEvaluation, CandidatEvaluationAdmin)
3bc5ea42 706admin.site.register(MesCandidatEvaluation, MesCandidatEvaluationAdmin)
27c81d11 707admin.site.register(Evaluateur, EvaluateurAdmin)
32834000 708admin.site.register(CourrielTemplate, CourrielTemplateAdmin)