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