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