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