1 # -*- encoding: utf-8 -*-
5 from auf
.django
.emploi
.models
import OffreEmploi
, Candidat
, CandidatPiece
6 from auf
.django
.references
.models
import Region
, Bureau
7 from django
.conf
import settings
8 from django
.contrib
import admin
9 from django
.core
.urlresolvers
import reverse
10 from django
.db
.models
import Avg
11 from django
.forms
.models
import BaseInlineFormSet
12 from django
.http
import HttpResponseRedirect
13 from django
.shortcuts
import redirect
14 from reversion
.admin
import VersionAdmin
16 from project
import groups
17 from project
.rh
import models
as rh
18 from project
.recrutement
.forms
import OffreEmploiForm
19 from project
.recrutement
.models
import \
20 Evaluateur
, CandidatEvaluation
, \
21 ProxyOffreEmploi
, ProxyCandidat
, MesCandidatEvaluation
, \
25 IMPLANTATIONS_CENTRALES
= [15, 19]
28 class BaseAdmin(admin
.ModelAdmin
):
32 'css/admin_custom.css',
33 'jquery-autocomplete/jquery.autocomplete.css',
36 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js',
37 'jquery-autocomplete/jquery.autocomplete.min.js',
41 class OrderedChangeList(admin
.views
.main
.ChangeList
):
43 Surcharge pour appliquer le order_by d'un annotate
45 def get_query_set(self
):
46 qs
= super(OrderedChangeList
, self
).get_query_set()
47 qs
= qs
.order_by('-moyenne')
51 class OffreEmploiAdminMixin(BaseAdmin
):
52 date_hierarchy
= 'date_creation'
54 'nom', 'date_limite', 'region', 'statut', 'est_affiche',
57 exclude
= ('actif', 'poste_nom', 'resume',)
58 list_filter
= ('statut',)
59 actions
= ['affecter_evaluateurs_offre_emploi', ]
60 form
= OffreEmploiForm
62 ### Actions à afficher
63 def get_actions(self
, request
):
64 actions
= super(OffreEmploiAdminMixin
, self
).get_actions(request
)
65 del actions
['delete_selected']
68 ### Affecter un évaluateurs à des offres d'emploi
69 def affecter_evaluateurs_offre_emploi(modeladmin
, obj
, candidats
):
70 selected
= obj
.POST
.getlist(admin
.ACTION_CHECKBOX_NAME
)
72 return HttpResponseRedirect(
73 reverse('affecter_evaluateurs_offre_emploi') +
74 "?ids=%s" % (",".join(selected
))
77 affecter_evaluateurs_offre_emploi
.short_description
= \
78 u
'Affecter évaluateur(s)'
80 ### Afficher la liste des candidats pour l'offre d'emploi
81 def _candidatsList(self
, obj
):
82 return "<a href='%s?offre_emploi__id__exact=%s'>Voir les candidats \
83 </a>" % (reverse('admin:recrutement_proxycandidat_changelist'), obj
.id)
84 _candidatsList
.allow_tags
= True
85 _candidatsList
.short_description
= "Afficher la liste des candidats"
88 def get_form(self
, request
, obj
=None, **kwargs
):
89 form
= super(OffreEmploiAdminMixin
, self
).get_form(request
, obj
, **kwargs
)
90 employe
= groups
.get_employe_from_user(request
.user
)
91 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
95 if 'region' in form
.declared_fields
:
96 region_field
= form
.declared_fields
['region']
98 elif 'region' in form
.base_fields
:
99 region_field
= form
.base_fields
['region']
105 if groups
.DRH_NIVEAU_1
in user_groupes
or \
106 groups
.DRH_NIVEAU_2
in user_groupes
or \
107 groups
.HAUTE_DIRECTION
in user_groupes
:
108 region_field
.queryset
= Region
.objects
.all()
110 region_field
.queryset
= Region
.objects
.\
111 filter(id=employe
.implantation
.region
.id)
114 if 'poste' in form
.declared_fields
:
115 poste_field
= form
.declared_fields
['poste']
117 elif 'poste' in form
.base_fields
:
118 poste_field
= form
.base_fields
['poste']
124 if groups
.DRH_NIVEAU_1
in user_groupes
or \
125 groups
.DRH_NIVEAU_2
in user_groupes
or \
126 groups
.HAUTE_DIRECTION
in user_groupes
:
127 poste_field
.queryset
= rh
.Poste
.objects
.all()
129 poste_field
.queryset
= rh
.Poste
.objects
.\
130 filter(implantation__region
=employe
.implantation
.region
).\
131 exclude(implantation__in
=IMPLANTATIONS_CENTRALES
)
134 if 'bureau' in form
.declared_fields
:
135 bureau_field
= form
.declared_fields
['bureau']
137 elif 'bureau' in form
.base_fields
:
138 bureau_field
= form
.base_fields
['bureau']
143 if groups
.DRH_NIVEAU_1
in user_groupes
or \
144 groups
.DRH_NIVEAU_2
in user_groupes
or \
145 groups
.HAUTE_DIRECTION
in user_groupes
:
146 bureau_field
.queryset
= Bureau
.objects
.all()
148 bureau_field
.queryset
= \
149 Bureau
.objects
.filter(region
=employe
.implantation
.region
)
155 def queryset(self
, request
):
156 qs
= self
.model
._default_manager
.get_query_set() \
157 .select_related('offre_emploi')
158 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
159 if groups
.DRH_NIVEAU_1
in user_groupes
or \
160 groups
.DRH_NIVEAU_2
in user_groupes
or \
161 groups
.HAUTE_DIRECTION
in user_groupes
:
164 if groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
165 groups
.CORRESPONDANT_RH
in user_groupes
or \
166 groups
.ADMINISTRATEURS
in user_groupes
:
167 employe
= groups
.get_employe_from_user(request
.user
)
168 return qs
.filter(region
=employe
.implantation
.region
)
170 if Evaluateur
.objects
.filter(user
=request
.user
).exists():
171 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
173 e
.candidat
.offre_emploi_id
174 for e
in CandidatEvaluation
.objects
175 .select_related('candidat')
176 .filter(evaluateur
=evaluateur
)
178 return qs
.filter(id__in
=offre_ids
)
182 ### Permission add, delete, change
183 def has_add_permission(self
, request
):
184 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
185 if request
.user
.is_superuser
is True or \
186 groups
.DRH_NIVEAU_1
in user_groupes
or \
187 groups
.DRH_NIVEAU_2
in user_groupes
or \
188 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
189 groups
.ADMINISTRATEURS
in user_groupes
or \
190 groups
.HAUTE_DIRECTION
in user_groupes
:
194 def has_delete_permission(self
, request
, obj
=None):
195 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
196 if request
.user
.is_superuser
is True or \
197 groups
.DRH_NIVEAU_1
in user_groupes
or \
198 groups
.DRH_NIVEAU_2
in user_groupes
or \
199 groups
.HAUTE_DIRECTION
in user_groupes
:
203 employe
= groups
.get_employe_from_user(request
.user
)
204 if (groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
205 groups
.ADMINISTRATEURS
in user_groupes
) and (
206 employe
.implantation
.region
== obj
.lieu_affectation
.region
):
211 def has_change_permission(self
, request
, obj
=None):
212 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
213 if request
.user
.is_superuser
is True or \
214 groups
.DRH_NIVEAU_1
in user_groupes
or \
215 groups
.DRH_NIVEAU_2
in user_groupes
or \
216 groups
.HAUTE_DIRECTION
in user_groupes
:
220 employe
= groups
.get_employe_from_user(request
.user
)
221 if (groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
222 groups
.ADMINISTRATEURS
in user_groupes
) and (
223 employe
.implantation
.region
== obj
.lieu_affectation
.region
):
226 if groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
227 groups
.ADMINISTRATEURS
in user_groupes
:
234 class OffreEmploiAdmin(VersionAdmin
, OffreEmploiAdminMixin
):
238 class ProxyOffreEmploiAdmin(OffreEmploiAdminMixin
):
240 'nom', 'date_limite', 'region', 'statut', 'est_affiche'
243 'description', 'bureau', 'duree_affectation', 'renumeration',
244 'debut_affectation', 'lieu_affectation', 'nom', 'resume',
245 'date_limite', 'region', 'poste'
251 ('Description générale', {
252 'fields': ('description', 'date_limite',)
255 'fields': ('lieu_affectation', 'bureau', 'region', 'poste',)
259 'debut_affectation', 'duree_affectation', 'renumeration',
265 ### Lieu de redirection après le change
266 def response_change(self
, request
, obj
):
267 return redirect('admin:recrutement_proxyoffreemploi_changelist')
270 def get_form(self
, request
, obj
=None, **kwargs
):
271 form
= super(ProxyOffreEmploiAdmin
, self
).get_form(request
, obj
, **kwargs
)
274 ### Permissions add, delete, change
275 def has_add_permission(self
, request
):
278 def has_delete_permission(self
, request
, obj
=None):
281 def has_change_permission(self
, request
, obj
=None):
282 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
283 if request
.user
.is_superuser
is True or \
284 groups
.CORRESPONDANT_RH
in user_groupes
or \
285 groups
.DRH_NIVEAU_1
in user_groupes
or \
286 groups
.DRH_NIVEAU_2
in user_groupes
or \
287 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
288 groups
.ADMINISTRATEURS
in user_groupes
or \
289 groups
.HAUTE_DIRECTION
in user_groupes
:
298 class CandidatPieceInline(admin
.TabularInline
):
299 model
= CandidatPiece
300 fields
= ('candidat', 'nom', 'path',)
305 class ReadOnlyCandidatPieceInline(CandidatPieceInline
):
306 readonly_fields
= ('candidat', 'nom', 'path', )
310 class CandidatEvaluationInlineFormSet(BaseInlineFormSet
):
312 Empêche la suppression d'une évaluation pour le CandidatEvaluationInline
314 def __init__(self
, *args
, **kwargs
):
315 super(CandidatEvaluationInlineFormSet
, self
).__init__(*args
, **kwargs
)
316 self
.can_delete
= False
319 class CandidatEvaluationInline(admin
.TabularInline
):
320 model
= CandidatEvaluation
321 fields
= ('evaluateur', 'note', 'commentaire')
324 formset
= CandidatEvaluationInlineFormSet
327 def get_readonly_fields(self
, request
, obj
=None):
329 Empêche la modification des évaluations
332 return self
.readonly_fields
+ ('evaluateur', 'note', 'commentaire')
333 return self
.readonly_fields
336 class CandidatAdminMixin(BaseAdmin
):
337 search_fields
= ('nom', 'prenom')
338 exclude
= ('actif', )
339 list_editable
= ('statut', )
340 list_display
= ('_candidat', 'offre_emploi',
341 'voir_offre_emploi', 'calculer_moyenne',
342 'afficher_candidat', '_date_creation', 'statut', )
343 list_filter
= ('offre_emploi', 'offre_emploi__region', 'statut', )
347 'fields': ('offre_emploi', )
349 ('Informations personnelles', {
351 'prenom', 'nom', 'genre', 'nationalite',
352 'situation_famille', 'nombre_dependant'
357 'telephone', 'email', 'adresse', 'ville', 'etat_province',
358 'code_postal', 'pays'
361 ('Informations professionnelles', {
363 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
364 'domaine_professionnel'
368 'fields': ('statut', )
373 CandidatEvaluationInline
,
375 actions
= ['envoyer_courriel_candidats']
377 def _candidat(self
, obj
):
378 txt
= u
"%s %s (%s)" % (obj
.nom
.upper(), obj
.prenom
, obj
.genre
)
379 txt
= textwrap
.wrap(txt
, 30)
380 return "<br/>".join(txt
)
381 _candidat
.short_description
= "Candidat"
382 _candidat
.admin_order_field
= "nom"
383 _candidat
.allow_tags
= True
385 def _date_creation(self
, obj
):
386 return obj
.date_creation
387 _date_creation
.admin_order_field
= "date_creation"
388 _date_creation
.short_description
= "Date de réception"
390 ### Actions à afficher
391 def get_actions(self
, request
):
392 actions
= super(CandidatAdminMixin
, self
).get_actions(request
)
393 del actions
['delete_selected']
396 ### Envoyer un courriel à des candidats
397 def envoyer_courriel_candidats(modeladmin
, obj
, candidats
):
398 selected
= obj
.POST
.getlist(admin
.ACTION_CHECKBOX_NAME
)
400 return HttpResponseRedirect(
401 reverse('selectionner_template') + "?ids=%s" % (",".join(selected
))
403 envoyer_courriel_candidats
.short_description
= u
'Envoyer courriel'
405 ### Évaluer un candidat
406 def evaluer_candidat(self
, obj
):
407 return "<a href='%s?candidat__id__exact=%s'>" \
408 "Évaluer le candidat</a>" % (
409 reverse('admin:recrutement_candidatevaluation_changelist'),
412 evaluer_candidat
.allow_tags
= True
413 evaluer_candidat
.short_description
= 'Évaluation'
415 ### Afficher un candidat
416 def afficher_candidat(self
, obj
):
417 items
= [u
"<li><a href='%s%s'>%s</li>" % \
418 (settings
.OE_PRIVE_MEDIA_URL
, pj
.path
, pj
.get_nom_display()) \
419 for pj
in obj
.pieces_jointes()]
420 html
= "<a href='%s'>Voir le candidat</a>" % (
421 reverse('admin:recrutement_proxycandidat_change', args
=(obj
.id,))
423 return "%s<ul>%s</ul>" % (html
, "\n".join(items
))
424 afficher_candidat
.allow_tags
= True
425 afficher_candidat
.short_description
= u
'Détails du candidat'
427 ### Voir l'offre d'emploi
428 def voir_offre_emploi(self
, obj
):
429 return "<a href='%s'>Voir l'offre d'emploi</a>" % (reverse(
430 'admin:recrutement_proxyoffreemploi_change',
431 args
=(obj
.offre_emploi
.id,)
433 voir_offre_emploi
.allow_tags
= True
434 voir_offre_emploi
.short_description
= "Afficher l'offre d'emploi"
436 ### Calculer la moyenne des notes
437 def calculer_moyenne(self
, obj
):
438 evaluations
= CandidatEvaluation
.objects
.filter(candidat
=obj
)
440 notes
= [evaluation
.note
for evaluation
in evaluations \
441 if evaluation
.note
is not None]
444 moyenne_votes
= round(float(sum(notes
)) / len(notes
), 2)
446 moyenne_votes
= "Non disponible"
448 totales
= len(evaluations
)
451 if obj
.statut
== 'REC':
452 if totales
== faites
:
454 elif faites
> 0 and float(totales
) / float(faites
) >= 2:
461 return """<span style="color: %s;">%s (%s/%s)</span>""" % (
462 color
, moyenne_votes
, faites
, totales
464 calculer_moyenne
.allow_tags
= True
465 calculer_moyenne
.short_description
= "Moyenne"
466 calculer_moyenne
.admin_order_field
= ""
468 ### Permissions add, delete, change
469 def has_add_permission(self
, request
):
470 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
471 if request
.user
.is_superuser
is True or \
472 groups
.CORRESPONDANT_RH
in user_groupes
or \
473 groups
.DRH_NIVEAU_1
in user_groupes
or \
474 groups
.DRH_NIVEAU_2
in user_groupes
or \
475 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
476 groups
.ADMINISTRATEURS
in user_groupes
or \
477 groups
.HAUTE_DIRECTION
in user_groupes
:
481 def has_delete_permission(self
, request
, obj
=None):
482 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
483 if request
.user
.is_superuser
is True or \
484 groups
.CORRESPONDANT_RH
in user_groupes
or \
485 groups
.DRH_NIVEAU_1
in user_groupes
or \
486 groups
.DRH_NIVEAU_2
in user_groupes
or \
487 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
488 groups
.ADMINISTRATEURS
in user_groupes
or \
489 groups
.HAUTE_DIRECTION
in user_groupes
:
493 def has_change_permission(self
, request
, obj
=None):
494 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
495 if request
.user
.is_superuser
is True or \
496 groups
.CORRESPONDANT_RH
in user_groupes
or \
497 groups
.DRH_NIVEAU_1
in user_groupes
or \
498 groups
.DRH_NIVEAU_2
in user_groupes
or \
499 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
500 groups
.ADMINISTRATEURS
in user_groupes
or \
501 groups
.HAUTE_DIRECTION
in user_groupes
:
505 def get_changelist(self
, request
, **kwargs
):
506 return OrderedChangeList
508 def queryset(self
, request
):
510 Spécifie un queryset limité, autrement Django exécute un
511 select_related() sans paramètre, ce qui a pour effet de charger tous
512 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
513 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
514 génération d'une requête infinie.
516 qs
= self
.model
._default_manager
.get_query_set() \
517 .select_related('offre_emploi') \
518 .annotate(moyenne
=Avg('evaluations__note'))
520 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
521 if groups
.DRH_NIVEAU_1
in user_groupes
or \
522 groups
.DRH_NIVEAU_2
in user_groupes
or \
523 groups
.HAUTE_DIRECTION
in user_groupes
:
526 if groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
527 groups
.CORRESPONDANT_RH
in user_groupes
or \
528 groups
.ADMINISTRATEURS
in user_groupes
:
529 employe
= groups
.get_employe_from_user(request
.user
)
530 return qs
.filter(offre_emploi__region
=employe
.implantation
.region
)
532 if Evaluateur
.objects
.filter(user
=request
.user
).exists():
533 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
534 candidat_ids
= [e
.candidat
.id for e
in
535 CandidatEvaluation
.objects
.filter(evaluateur
=evaluateur
)]
536 return qs
.filter(id__in
=candidat_ids
)
540 class CandidatAdmin(VersionAdmin
, CandidatAdminMixin
):
544 class ProxyCandidatAdmin(CandidatAdminMixin
):
547 'statut', 'offre_emploi', 'prenom', 'nom', 'genre', 'nationalite',
548 'situation_famille', 'nombre_dependant', 'telephone', 'email',
549 'adresse', 'ville', 'etat_province', 'code_postal', 'pays',
550 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
551 'domaine_professionnel', 'pieces_jointes'
555 'fields': ('offre_emploi', )
557 ('Informations personnelles', {
559 'prenom', 'nom', 'genre', 'nationalite', 'situation_famille',
565 'telephone', 'email', 'adresse', 'ville', 'etat_province',
566 'code_postal', 'pays'
569 ('Informations professionnelles', {
571 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
572 'domaine_professionnel'
576 inlines
= (CandidatEvaluationInline
, )
578 def has_add_permission(self
, request
):
581 def has_delete_permission(self
, request
, obj
=None):
584 def has_change_permission(self
, request
, obj
=None):
585 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
586 if request
.user
.is_superuser
is True or \
587 groups
.CORRESPONDANT_RH
in user_groupes
or \
588 groups
.DRH_NIVEAU_1
in user_groupes
or \
589 groups
.DRH_NIVEAU_2
in user_groupes
or \
590 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
591 groups
.ADMINISTRATEURS
in user_groupes
or \
592 groups
.HAUTE_DIRECTION
in user_groupes
:
596 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
597 for e
in obj
.evaluations
.all():
598 if e
.evaluateur
== evaluateur
:
603 def get_actions(self
, request
):
607 class CandidatPieceAdmin(admin
.ModelAdmin
):
608 list_display
= ('nom', 'candidat', )
611 def queryset(self
, request
):
613 Spécifie un queryset limité, autrement Django exécute un
614 select_related() sans paramètre, ce qui a pour effet de charger tous
615 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
616 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
617 génération d'une requête infinie. Affiche la liste de candidats que
618 si le user connecté possède un Evaluateur
620 qs
= self
.model
._default_manager
.get_query_set()
621 return qs
.select_related('candidat')
624 class EvaluateurAdmin(BaseAdmin
, VersionAdmin
):
631 ### Actions à afficher
632 def get_actions(self
, request
):
633 actions
= super(EvaluateurAdmin
, self
).get_actions(request
)
634 del actions
['delete_selected']
637 ### Permissions add, delete, change
638 def has_add_permission(self
, request
):
639 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
640 if request
.user
.is_superuser
is True or \
641 groups
.DRH_NIVEAU_1
in user_groupes
or \
642 groups
.DRH_NIVEAU_2
in user_groupes
or \
643 groups
.HAUTE_DIRECTION
in user_groupes
:
647 def has_delete_permission(self
, request
, obj
=None):
648 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
649 if request
.user
.is_superuser
is True or \
650 groups
.DRH_NIVEAU_1
in user_groupes
or \
651 groups
.DRH_NIVEAU_2
in user_groupes
or \
652 groups
.HAUTE_DIRECTION
in user_groupes
:
656 def has_change_permission(self
, request
, obj
=None):
657 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
658 if request
.user
.is_superuser
is True or \
659 groups
.DRH_NIVEAU_1
in user_groupes
or \
660 groups
.DRH_NIVEAU_2
in user_groupes
or \
661 groups
.HAUTE_DIRECTION
in user_groupes
:
666 class CandidatEvaluationAdmin(BaseAdmin
):
667 search_fields
= ('candidat__nom', 'candidat__prenom')
669 '_candidat', '_statut', '_offre_emploi', 'evaluateur', '_note',
672 readonly_fields
= ('candidat', 'evaluateur')
673 list_filter
= ('candidat__statut', 'candidat__offre_emploi',)
675 ('Évaluation du candidat', {
676 'fields': ('candidat', 'evaluateur', 'note', 'commentaire', )
680 def get_actions(self
, request
):
681 # on stocke l'evaluateur connecté (pas forcément la meilleure place...)
683 self
.evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
685 self
.evaluateur
= None
687 actions
= super(CandidatEvaluationAdmin
, self
).get_actions(request
)
688 del actions
['delete_selected']
692 def _note(self
, obj
):
694 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
695 un lien pour Évaluer le candidat.
696 Sinon afficher la note.
698 page
= self
.model
.__name__
.lower()
699 redirect_url
= 'admin:recrutement_%s_change' % page
702 label
= "Candidat non évalué"
706 if self
.evaluateur
== obj
.evaluateur
:
707 return "<a href='%s'>%s</a>" % (
708 reverse(redirect_url
, args
=(obj
.id,)), label
712 _note
.allow_tags
= True
713 _note
.short_description
= "Note"
714 _note
.admin_order_field
= 'note'
716 def _statut(self
, obj
):
717 return obj
.candidat
.get_statut_display()
718 _statut
.order_field
= 'candidat__statut'
719 _statut
.short_description
= 'Statut'
721 ### Lien en lecture seule vers le candidat
722 def _candidat(self
, obj
):
723 return "<a href='%s'>%s</a>" \
724 % (reverse('admin:recrutement_proxycandidat_change',
725 args
=(obj
.candidat
.id,)), obj
.candidat
)
726 _candidat
.allow_tags
= True
727 _candidat
.short_description
= 'Candidat'
729 ### Afficher commentaire
730 def _commentaire(self
, obj
):
732 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
733 dans le champ commentaire, Aucun au lieu de (None)
734 Sinon afficher la note.
736 if obj
.commentaire
is None:
738 return obj
.commentaire
739 _commentaire
.allow_tags
= True
740 _commentaire
.short_description
= "Commentaire"
742 ### Afficher offre d'emploi
743 def _offre_emploi(self
, obj
):
744 return "<a href='%s'>%s</a>" % \
745 (reverse('admin:recrutement_proxyoffreemploi_change',
746 args
=(obj
.candidat
.offre_emploi
.id,)), obj
.candidat
.offre_emploi
)
747 _offre_emploi
.allow_tags
= True
748 _offre_emploi
.short_description
= "Voir offre d'emploi"
750 def has_add_permission(self
, request
):
753 def has_delete_permission(self
, request
, obj
=None):
756 def has_change_permission(self
, request
, obj
=None):
758 Permettre la visualisation dans la changelist
759 mais interdire l'accès à modifier l'objet si l'évaluateur n'est pas
762 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
764 if request
.user
.is_superuser
or \
765 groups
.CORRESPONDANT_RH
in user_groupes
or \
766 groups
.DRH_NIVEAU_1
in user_groupes
or \
767 groups
.DRH_NIVEAU_2
in user_groupes
or \
768 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
769 groups
.ADMINISTRATEURS
in user_groupes
or \
770 groups
.HAUTE_DIRECTION
in user_groupes
:
771 is_recrutement
= True
773 is_recrutement
= False
775 return is_recrutement
777 def queryset(self
, request
):
779 Afficher uniquement les évaluations de l'évaluateur, sauf si
780 l'utilisateur est dans les groupes suivants.
782 qs
= self
.model
._default_manager
.get_query_set() \
783 .select_related('offre_emploi')
784 user_groupes
= request
.user
.groups
.all()
785 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
787 if request
.user
.is_superuser
or \
788 groups
.CORRESPONDANT_RH
in user_groupes
or \
789 groups
.DRH_NIVEAU_1
in user_groupes
or \
790 groups
.DRH_NIVEAU_2
in user_groupes
or \
791 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
792 groups
.ADMINISTRATEURS
in user_groupes
or \
793 groups
.HAUTE_DIRECTION
in user_groupes
:
796 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
797 candidats_evaluations
= \
798 CandidatEvaluation
.objects
.filter(evaluateur
=evaluateur
,
799 candidat__statut__in
=('REC', ))
800 candidats_evaluations_ids
= [ce
.id for ce
in candidats_evaluations
]
801 return qs
.filter(id__in
=candidats_evaluations_ids
)
804 class MesCandidatEvaluationAdmin(CandidatEvaluationAdmin
):
806 def has_change_permission(self
, request
, obj
=None):
808 Evaluateur
.objects
.get(user
=request
.user
)
811 is_evaluateur
= False
813 if obj
is None and is_evaluateur
:
817 return request
.user
== obj
.evaluateur
.user
821 def queryset(self
, request
):
822 qs
= self
.model
._default_manager
.get_query_set() \
823 .select_related('offre_emploi')
824 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
825 candidats_evaluations
= \
826 CandidatEvaluation
.objects
.filter(evaluateur
=evaluateur
,
827 candidat__statut__in
=('REC', ))
828 candidats_evaluations_ids
= [ce
.id for ce
in candidats_evaluations
]
829 return qs
.filter(id__in
=candidats_evaluations_ids
)
832 class CourrielTemplateAdmin(BaseAdmin
, VersionAdmin
):
833 ### Actions à afficher
834 def get_actions(self
, request
):
835 actions
= super(CourrielTemplateAdmin
, self
).get_actions(request
)
836 del actions
['delete_selected']
839 admin
.site
.register(OffreEmploi
, OffreEmploiAdmin
)
840 admin
.site
.register(ProxyOffreEmploi
, ProxyOffreEmploiAdmin
)
841 admin
.site
.register(Candidat
, CandidatAdmin
)
842 admin
.site
.register(ProxyCandidat
, ProxyCandidatAdmin
)
843 admin
.site
.register(CandidatEvaluation
, CandidatEvaluationAdmin
)
844 admin
.site
.register(MesCandidatEvaluation
, MesCandidatEvaluationAdmin
)
845 admin
.site
.register(Evaluateur
, EvaluateurAdmin
)
846 admin
.site
.register(CourrielTemplate
, CourrielTemplateAdmin
)