utils -> groups
[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.models import \
22 Evaluateur, CandidatEvaluation, \
23 ProxyOffreEmploi, ProxyCandidat, MesCandidatEvaluation, \
24 CourrielTemplate
25 from project.recrutement.workflow import \
26 grp_drh_recrutement, grp_drh2_recrutement, \
27 grp_directeurs_bureau_recrutement, \
28 grp_administrateurs_recrutement, \
29 grp_correspondants_rh_recrutement, \
30 grp_haute_direction_recrutement
31
32
33 ### CONSTANTES
34 IMPLANTATIONS_CENTRALES = [15, 19]
35
36
37 class 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
46
47 class OffreEmploiAdmin(VersionAdmin):
48 date_hierarchy = 'date_creation'
49 list_display = (
50 'nom', 'date_limite', 'region', 'statut', 'est_affiche',
51 '_candidatsList'
52 )
53 exclude = ('actif', 'poste_nom', 'resume',)
54 list_filter = ('statut',)
55 actions = ['affecter_evaluateurs_offre_emploi', ]
56 form = OffreEmploiForm
57
58 ### Actions à afficher
59 def get_actions(self, request):
60 actions = super(OffreEmploiAdmin, self).get_actions(request)
61 del actions['delete_selected']
62 return actions
63
64 ### Affecter un évaluateurs à des offres d'emploi
65 def affecter_evaluateurs_offre_emploi(modeladmin, obj, candidats):
66 selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
67
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)'
75
76 ### Afficher la liste des candidats pour l'offre d'emploi
77 def _candidatsList(self, obj):
78 return "<a href='%s?offre_emploi__id__exact=%s'>Voir les candidats \
79 </a>" % (reverse('admin:recrutement_candidat_changelist'), obj.id)
80 _candidatsList.allow_tags = True
81 _candidatsList.short_description = "Afficher la liste des candidats"
82
83 ### Formulaire
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)
87 user_groupes = request.user.groups.all()
88
89 # Region
90 if 'region' in form.declared_fields:
91 region_field = form.declared_fields['region']
92 else:
93 region_field = form.base_fields['region']
94
95 if grp_drh_recrutement in user_groupes or \
96 grp_drh2_recrutement in user_groupes or \
97 grp_haute_direction_recrutement in user_groupes:
98 region_field.queryset = Region.objects.all()
99 else:
100 region_field.queryset = Region.objects.\
101 filter(id=employe.implantation.region.id)
102
103 # Poste
104 if 'poste' in form.declared_fields:
105 poste_field = form.declared_fields['poste']
106 else:
107 poste_field = form.base_fields['poste']
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 poste_field.queryset = rh.Poste.objects.all()
113 else:
114 poste_field.queryset = rh.Poste.objects.\
115 filter(implantation__region=employe.implantation.region).\
116 exclude(implantation__in=IMPLANTATIONS_CENTRALES)
117
118 # Bureau
119 if 'bureau' in form.declared_fields:
120 bureau_field = form.declared_fields['bureau']
121 else:
122 bureau_field = form.base_fields['bureau']
123
124 if grp_drh_recrutement in user_groupes or \
125 grp_drh2_recrutement in user_groupes or \
126 grp_haute_direction_recrutement in user_groupes:
127 bureau_field.queryset = Bureau.objects.all()
128 else:
129 bureau_field.queryset = \
130 Bureau.objects.filter(region=employe.implantation.region)
131
132 return form
133
134 ### Queryset
135
136 def queryset(self, request):
137 qs = self.model._default_manager.get_query_set() \
138 .select_related('offre_emploi')
139 user_groupes = request.user.groups.all()
140 if grp_drh_recrutement in user_groupes or \
141 grp_drh2_recrutement in user_groupes or \
142 grp_haute_direction_recrutement in user_groupes:
143 return qs
144
145 if grp_directeurs_bureau_recrutement in user_groupes or \
146 grp_correspondants_rh_recrutement in user_groupes or \
147 grp_administrateurs_recrutement in user_groupes:
148 employe = get_emp(request.user)
149 return qs.filter(region=employe.implantation.region)
150
151 if Evaluateur.objects.filter(user=request.user).exists():
152 evaluateur = Evaluateur.objects.get(user=request.user)
153 offre_ids = [
154 e.candidat.offre_emploi_id
155 for e in CandidatEvaluation.objects
156 .select_related('candidat')
157 .filter(evaluateur=evaluateur)
158 ]
159 return qs.filter(id__in=offre_ids)
160
161 return qs.none()
162
163 ### Permission add, delete, change
164 def has_add_permission(self, request):
165 user_groupes = request.user.groups.all()
166 if request.user.is_superuser is True or \
167 grp_drh_recrutement in user_groupes or \
168 grp_drh2_recrutement in user_groupes or \
169 grp_directeurs_bureau_recrutement in user_groupes or \
170 grp_administrateurs_recrutement in user_groupes or \
171 grp_haute_direction_recrutement in user_groupes:
172 return True
173 return False
174
175 def has_delete_permission(self, request, obj=None):
176 user_groupes = request.user.groups.all()
177 if request.user.is_superuser is True or \
178 grp_drh_recrutement in user_groupes or \
179 grp_drh2_recrutement in user_groupes or \
180 grp_directeurs_bureau_recrutement in user_groupes or \
181 grp_administrateurs_recrutement in user_groupes or \
182 grp_haute_direction_recrutement in user_groupes:
183 return True
184 return False
185
186 def has_change_permission(self, request, obj=None):
187 user_groupes = request.user.groups.all()
188 if request.user.is_superuser is True or \
189 grp_drh_recrutement in user_groupes or \
190 grp_drh2_recrutement in user_groupes or \
191 grp_directeurs_bureau_recrutement in user_groupes or \
192 grp_administrateurs_recrutement in user_groupes or \
193 grp_haute_direction_recrutement in user_groupes:
194 return True
195 return False
196
197
198 class ProxyOffreEmploiAdmin(OffreEmploiAdmin):
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 )
207 fieldsets = (
208 ('Nom', {
209 'fields': ('nom',)
210 }),
211 ('Description générale', {
212 'fields': ('description', 'date_limite',)
213 }),
214 ('Coordonnées', {
215 'fields': ('lieu_affectation', 'bureau', 'region', 'poste',)
216 }),
217 ('Autre', {
218 'fields': (
219 'debut_affectation', 'duree_affectation', 'renumeration',
220 )
221 }),
222 )
223 inlines = []
224
225 ### Lieu de redirection après le change
226 def response_change(self, request, obj):
227 return redirect('admin:recrutement_proxyoffreemploi_changelist')
228
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
234 ### Permissions add, delete, change
235 def has_add_permission(self, request):
236 return False
237
238 def has_delete_permission(self, request, obj=None):
239 return False
240
241 def has_change_permission(self, request, obj=None):
242 user_groupes = request.user.groups.all()
243 if request.user.is_superuser is True or \
244 grp_correspondants_rh_recrutement in user_groupes or \
245 grp_drh_recrutement in user_groupes or \
246 grp_drh2_recrutement in user_groupes or \
247 grp_directeurs_bureau_recrutement in user_groupes or \
248 grp_administrateurs_recrutement in user_groupes or \
249 grp_haute_direction_recrutement in user_groupes:
250 return True
251
252 if obj is not None:
253 return True
254
255 return False
256
257
258 class CandidatPieceInline(admin.TabularInline):
259 model = CandidatPiece
260 fields = ('candidat', 'nom', 'path',)
261 extra = 1
262 max_num = 3
263
264
265 class ReadOnlyCandidatPieceInline(CandidatPieceInline):
266 readonly_fields = ('candidat', 'nom', 'path', )
267 cand_delete = False
268
269
270 class 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)
276 self.can_delete = False
277
278
279 class CandidatEvaluationInline(admin.TabularInline):
280 model = CandidatEvaluation
281 fields = ('evaluateur', 'note', 'commentaire')
282 max_num = 0
283 extra = 0
284 formset = CandidatEvaluationInlineFormSet
285
286 ### Fields readonly
287 def get_readonly_fields(self, request, obj=None):
288 """
289 Empêche la modification des évaluations
290 """
291 if obj:
292 return self.readonly_fields + ('evaluateur', 'note', 'commentaire')
293 return self.readonly_fields
294
295
296 class CandidatAdmin(VersionAdmin):
297 search_fields = ('nom', 'prenom')
298 exclude = ('actif', )
299 list_editable = ('statut', )
300 list_display = ('_candidat', 'offre_emploi',
301 'voir_offre_emploi', 'calculer_moyenne',
302 'afficher_candidat', '_date_creation', 'statut', )
303 list_filter = ('offre_emploi', 'offre_emploi__region', 'statut', )
304
305 fieldsets = (
306 ("Offre d'emploi", {
307 'fields': ('offre_emploi', )
308 }),
309 ('Informations personnelles', {
310 'fields': (
311 'prenom', 'nom', 'genre', 'nationalite',
312 'situation_famille', 'nombre_dependant'
313 )
314 }),
315 ('Coordonnées', {
316 'fields': (
317 'telephone', 'email', 'adresse', 'ville', 'etat_province',
318 'code_postal', 'pays'
319 )
320 }),
321 ('Informations professionnelles', {
322 'fields': (
323 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
324 'domaine_professionnel'
325 )
326 }),
327 ('Traitement', {
328 'fields': ('statut', )
329 }),
330 )
331 inlines = [
332 CandidatPieceInline,
333 CandidatEvaluationInline,
334 ]
335 actions = ['envoyer_courriel_candidats']
336
337 def _candidat(self, obj):
338 txt = u"%s %s (%s)" % (obj.nom.upper(), obj.prenom, obj.genre)
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
345 def _date_creation(self, obj):
346 return obj.date_creation
347 _date_creation.admin_order_field = "date_creation"
348 _date_creation.short_description = "Date de réception"
349
350 ### Actions à afficher
351 def get_actions(self, request):
352 actions = super(CandidatAdmin, self).get_actions(request)
353 del actions['delete_selected']
354 return actions
355
356 ### Envoyer un courriel à des candidats
357 def envoyer_courriel_candidats(modeladmin, obj, candidats):
358 selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
359
360 return HttpResponseRedirect(
361 reverse('selectionner_template') + "?ids=%s" % (",".join(selected))
362 )
363 envoyer_courriel_candidats.short_description = u'Envoyer courriel'
364
365 ### Évaluer un candidat
366 def evaluer_candidat(self, obj):
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
373 evaluer_candidat.short_description = 'Évaluation'
374
375 ### Afficher un candidat
376 def afficher_candidat(self, obj):
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()]
380 html = "<a href='%s'>Voir le candidat</a>" % (
381 reverse('admin:recrutement_proxycandidat_change', args=(obj.id,))
382 )
383 return "%s<ul>%s</ul>" % (html, "\n".join(items))
384 afficher_candidat.allow_tags = True
385 afficher_candidat.short_description = u'Détails du candidat'
386
387 ### Voir l'offre d'emploi
388 def voir_offre_emploi(self, obj):
389 return "<a href='%s'>Voir l'offre d'emploi</a>" % (reverse(
390 'admin:recrutement_proxyoffreemploi_change',
391 args=(obj.offre_emploi.id,)
392 ))
393 voir_offre_emploi.allow_tags = True
394 voir_offre_emploi.short_description = "Afficher l'offre d'emploi"
395
396 ### Calculer la moyenne des notes
397 def calculer_moyenne(self, obj):
398 evaluations = CandidatEvaluation.objects.filter(candidat=obj)
399
400 notes = [evaluation.note for evaluation in evaluations \
401 if evaluation.note is not None]
402
403 if len(notes) > 0:
404 moyenne_votes = round(float(sum(notes)) / len(notes), 2)
405 else:
406 moyenne_votes = "Non disponible"
407
408 totales = len(evaluations)
409 faites = len(notes)
410
411 if obj.statut == 'REC':
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
421 return """<span style="color: %s;">%s (%s/%s)</span>""" % (
422 color, moyenne_votes, faites, totales
423 )
424 calculer_moyenne.allow_tags = True
425 calculer_moyenne.short_description = "Moyenne"
426 calculer_moyenne.admin_order_field = ""
427
428 ### Permissions add, delete, change
429 def has_add_permission(self, request):
430 user_groupes = request.user.groups.all()
431 if request.user.is_superuser is True or \
432 grp_correspondants_rh_recrutement in user_groupes or \
433 grp_drh_recrutement in user_groupes or \
434 grp_drh2_recrutement in user_groupes or \
435 grp_directeurs_bureau_recrutement in user_groupes or \
436 grp_administrateurs_recrutement in user_groupes or \
437 grp_haute_direction_recrutement in user_groupes:
438 return True
439 return False
440
441 def has_delete_permission(self, request, obj=None):
442 user_groupes = request.user.groups.all()
443 if request.user.is_superuser is True or \
444 grp_correspondants_rh_recrutement in user_groupes or \
445 grp_drh_recrutement in user_groupes or \
446 grp_drh2_recrutement in user_groupes or \
447 grp_directeurs_bureau_recrutement in user_groupes or \
448 grp_administrateurs_recrutement in user_groupes or \
449 grp_haute_direction_recrutement in user_groupes:
450 return True
451 return False
452
453 def has_change_permission(self, request, obj=None):
454 user_groupes = request.user.groups.all()
455 if request.user.is_superuser is True or \
456 grp_correspondants_rh_recrutement in user_groupes or \
457 grp_drh_recrutement in user_groupes or \
458 grp_drh2_recrutement in user_groupes or \
459 grp_directeurs_bureau_recrutement in user_groupes or \
460 grp_administrateurs_recrutement in user_groupes or \
461 grp_haute_direction_recrutement in user_groupes:
462 return True
463 return False
464
465 def get_changelist(self, request, **kwargs):
466 return OrderedChangeList
467
468 def queryset(self, request):
469 """
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
474 génération d'une requête infinie.
475 """
476 qs = self.model._default_manager.get_query_set() \
477 .select_related('offre_emploi') \
478 .annotate(moyenne=Avg('evaluations__note'))
479
480 user_groupes = request.user.groups.all()
481 if grp_drh_recrutement in user_groupes or \
482 grp_drh2_recrutement in user_groupes or \
483 grp_haute_direction_recrutement in user_groupes:
484 return qs
485
486 if grp_directeurs_bureau_recrutement in user_groupes or \
487 grp_correspondants_rh_recrutement in user_groupes or \
488 grp_administrateurs_recrutement in user_groupes:
489 employe = get_emp(request.user)
490 return qs.filter(offre_emploi__region=employe.implantation.region)
491
492 if Evaluateur.objects.filter(user=request.user).exists():
493 evaluateur = Evaluateur.objects.get(user=request.user)
494 candidat_ids = [e.candidat.id for e in
495 CandidatEvaluation.objects.filter(evaluateur=evaluateur)]
496 return qs.filter(id__in=candidat_ids)
497 return qs.none()
498
499
500 class ProxyCandidatAdmin(CandidatAdmin):
501 list_editable = ()
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 )
509 fieldsets = (
510 ("Offre d'emploi", {
511 'fields': ('offre_emploi', )
512 }),
513 ('Informations personnelles', {
514 'fields': (
515 'prenom', 'nom', 'genre', 'nationalite', 'situation_famille',
516 'nombre_dependant'
517 )
518 }),
519 ('Coordonnées', {
520 'fields': (
521 'telephone', 'email', 'adresse', 'ville', 'etat_province',
522 'code_postal', 'pays'
523 )
524 }),
525 ('Informations professionnelles', {
526 'fields': (
527 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
528 'domaine_professionnel'
529 )
530 }),
531 )
532 inlines = (CandidatEvaluationInline, )
533
534 def has_add_permission(self, request):
535 return False
536
537 def has_delete_permission(self, request, obj=None):
538 return False
539
540 def has_change_permission(self, request, obj=None):
541 user_groupes = request.user.groups.all()
542 if request.user.is_superuser is True or \
543 grp_correspondants_rh_recrutement in user_groupes or \
544 grp_drh_recrutement in user_groupes or \
545 grp_drh2_recrutement in user_groupes or \
546 grp_directeurs_bureau_recrutement in user_groupes or \
547 grp_administrateurs_recrutement in user_groupes or \
548 grp_haute_direction_recrutement in user_groupes:
549 return True
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
557 return False
558
559 def get_actions(self, request):
560 return None
561
562
563 class CandidatPieceAdmin(admin.ModelAdmin):
564 list_display = ('nom', 'candidat', )
565
566 ### Queryset
567 def queryset(self, request):
568 """
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
575 """
576 qs = self.model._default_manager.get_query_set()
577 return qs.select_related('candidat')
578
579
580 class EvaluateurAdmin(VersionAdmin):
581 fieldsets = (
582 ("Utilisateur", {
583 'fields': ('user',)
584 }),
585 )
586
587 ### Actions à afficher
588 def get_actions(self, request):
589 actions = super(EvaluateurAdmin, self).get_actions(request)
590 del actions['delete_selected']
591 return actions
592
593 ### Permissions add, delete, change
594 def has_add_permission(self, request):
595 user_groupes = request.user.groups.all()
596 if request.user.is_superuser is True or \
597 grp_drh_recrutement in user_groupes or \
598 grp_drh2_recrutement in user_groupes or \
599 grp_haute_direction_recrutement in user_groupes:
600 return True
601 return False
602
603 def has_delete_permission(self, request, obj=None):
604 user_groupes = request.user.groups.all()
605 if request.user.is_superuser is True or \
606 grp_drh_recrutement in user_groupes or \
607 grp_drh2_recrutement in user_groupes or \
608 grp_haute_direction_recrutement in user_groupes:
609 return True
610 return False
611
612 def has_change_permission(self, request, obj=None):
613 user_groupes = request.user.groups.all()
614 if request.user.is_superuser is True or \
615 grp_drh_recrutement in user_groupes or \
616 grp_drh2_recrutement in user_groupes or \
617 grp_haute_direction_recrutement in user_groupes:
618 return True
619 return False
620
621
622 class CandidatEvaluationAdmin(admin.ModelAdmin):
623 search_fields = ('candidat__nom', 'candidat__prenom')
624 list_display = (
625 '_candidat', '_statut', '_offre_emploi', 'evaluateur', '_note',
626 '_commentaire'
627 )
628 readonly_fields = ('candidat', 'evaluateur')
629 list_filter = ('candidat__statut', 'candidat__offre_emploi',)
630 fieldsets = (
631 ('Évaluation du candidat', {
632 'fields': ('candidat', 'evaluateur', 'note', 'commentaire', )
633 }),
634 )
635
636 def get_actions(self, request):
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
643 actions = super(CandidatEvaluationAdmin, self).get_actions(request)
644 del actions['delete_selected']
645 return actions
646
647 ### Afficher la note
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 """
654 page = self.model.__name__.lower()
655 redirect_url = 'admin:recrutement_%s_change' % page
656
657 if obj.note is None:
658 label = "Candidat non évalué"
659 else:
660 label = obj.note
661
662 if self.evaluateur == obj.evaluateur:
663 return "<a href='%s'>%s</a>" % (
664 reverse(redirect_url, args=(obj.id,)), label
665 )
666 else:
667 return label
668 _note.allow_tags = True
669 _note.short_description = "Note"
670 _note.admin_order_field = 'note'
671
672 def _statut(self, obj):
673 return obj.candidat.get_statut_display()
674 _statut.order_field = 'candidat__statut'
675 _statut.short_description = 'Statut'
676
677 ### Lien en lecture seule vers le candidat
678 def _candidat(self, obj):
679 return "<a href='%s'>%s</a>" \
680 % (reverse('admin:recrutement_proxycandidat_change',
681 args=(obj.candidat.id,)), obj.candidat)
682 _candidat.allow_tags = True
683 _candidat.short_description = 'Candidat'
684
685 ### Afficher commentaire
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
696 _commentaire.short_description = "Commentaire"
697
698 ### Afficher offre d'emploi
699 def _offre_emploi(self, obj):
700 return "<a href='%s'>%s</a>" % \
701 (reverse('admin:recrutement_proxyoffreemploi_change',
702 args=(obj.candidat.offre_emploi.id,)), obj.candidat.offre_emploi)
703 _offre_emploi.allow_tags = True
704 _offre_emploi.short_description = "Voir offre d'emploi"
705
706 def has_add_permission(self, request):
707 return False
708
709 def has_delete_permission(self, request, obj=None):
710 return False
711
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 """
718 user_groupes = request.user.groups.all()
719
720 if request.user.is_superuser or \
721 grp_drh_recrutement in user_groupes or \
722 grp_drh2_recrutement in user_groupes or \
723 grp_correspondants_rh_recrutement in user_groupes or \
724 grp_directeurs_bureau_recrutement in user_groupes or \
725 grp_administrateurs_recrutement in user_groupes or \
726 grp_haute_direction_recrutement in user_groupes:
727 is_recrutement = True
728 else:
729 is_recrutement = False
730
731 return is_recrutement
732
733 def queryset(self, request):
734 """
735 Afficher uniquement les évaluations de l'évaluateur, sauf si
736 l'utilisateur est dans les groupes suivants.
737 """
738 qs = self.model._default_manager.get_query_set() \
739 .select_related('offre_emploi')
740 user_groupes = request.user.groups.all()
741
742 if grp_drh_recrutement in user_groupes or \
743 grp_drh2_recrutement in user_groupes or \
744 grp_correspondants_rh_recrutement in user_groupes or \
745 grp_directeurs_bureau_recrutement in user_groupes or \
746 grp_administrateurs_recrutement in user_groupes or \
747 grp_haute_direction_recrutement in user_groupes:
748 return qs
749
750 evaluateur = Evaluateur.objects.get(user=request.user)
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)
756
757
758 class 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
767 if obj is None and is_evaluateur:
768 return True
769
770 try:
771 return request.user == obj.evaluateur.user
772 except:
773 return False
774
775 def queryset(self, request):
776 qs = self.model._default_manager.get_query_set() \
777 .select_related('offre_emploi')
778 evaluateur = Evaluateur.objects.get(user=request.user)
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
786 class CourrielTemplateAdmin(VersionAdmin):
787 ### Actions à afficher
788 def get_actions(self, request):
789 actions = super(CourrielTemplateAdmin, self).get_actions(request)
790 del actions['delete_selected']
791 return actions
792
793 admin.site.register(OffreEmploi, OffreEmploiAdmin)
794 admin.site.register(ProxyOffreEmploi, ProxyOffreEmploiAdmin)
795 admin.site.register(Candidat, CandidatAdmin)
796 admin.site.register(ProxyCandidat, ProxyCandidatAdmin)
797 admin.site.register(CandidatEvaluation, CandidatEvaluationAdmin)
798 admin.site.register(MesCandidatEvaluation, MesCandidatEvaluationAdmin)
799 admin.site.register(Evaluateur, EvaluateurAdmin)
800 admin.site.register(CourrielTemplate, CourrielTemplateAdmin)