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