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