1 # -*- encoding: utf-8 -*-
5 from auf
.django
.emploi
.models
import CandidatPiece
, Candidat
, OffreEmploi
6 from auf
.django
.references
.models
import Region
, Bureau
, Implantation
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
.shortcuts
import render_to_response
12 from django
.template
import RequestContext
14 from auf
.django
.export
.admin
import ExportAdmin
15 from auf
.django
.emploi
.models
import STATUT_CHOICES
16 from django
.forms
.models
import BaseInlineFormSet
17 from django
.http
import HttpResponseRedirect
18 from django
.shortcuts
import redirect
19 from reversion
.admin
import VersionAdmin
21 from project
import groups
23 from project
.rh
import models
as rh
24 from project
.recrutement
.forms
import OffreEmploiForm
25 from project
.recrutement
.models
import \
26 Evaluateur
, CandidatEvaluation
, \
27 ProxyOffreEmploi
, ProxyCandidat
, MesCandidatEvaluation
, \
28 CourrielTemplate
, OffreEmploiEvaluateur
32 IMPLANTATIONS_CENTRALES
= [15, 19]
35 class BaseAdmin(admin
.ModelAdmin
):
39 'css/admin_custom.css',
40 'jquery-autocomplete/jquery.autocomplete.css',
43 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js',
44 'jquery-autocomplete/jquery.autocomplete.min.js',
48 class OrderedChangeList(admin
.views
.main
.ChangeList
):
50 Surcharge pour appliquer le order_by d'un annotate
52 def get_query_set(self
):
53 qs
= super(OrderedChangeList
, self
).get_query_set()
54 qs
= qs
.order_by('-moyenne')
58 class OffreEmploiAdminMixin(BaseAdmin
):
59 date_hierarchy
= 'date_creation'
61 'nom', 'date_limite', 'region', 'statut', 'est_affiche',
64 exclude
= ('actif', 'poste_nom', 'resume',)
65 list_filter
= ('statut',)
66 actions
= ['affecter_evaluateurs_offre_emploi', ]
67 form
= OffreEmploiForm
87 ### Actions à afficher
88 def get_actions(self
, request
):
89 actions
= super(OffreEmploiAdminMixin
, self
).get_actions(request
)
90 del actions
['delete_selected']
93 ### Affecter un évaluateurs à des offres d'emploi
94 def affecter_evaluateurs_offre_emploi(modeladmin
, obj
, candidats
):
95 selected
= obj
.POST
.getlist(admin
.ACTION_CHECKBOX_NAME
)
97 return HttpResponseRedirect(
98 reverse('affecter_evaluateurs_offre_emploi') +
99 "?ids=%s" % (",".join(selected
))
102 affecter_evaluateurs_offre_emploi
.short_description
= \
103 u
'Affecter évaluateur(s)'
105 ### Afficher la liste des candidats pour l'offre d'emploi
106 def _candidatsList(self
, obj
):
107 return "<a href='%s?offre_emploi__id__exact=%s'>Voir les candidats \
108 </a>" % (reverse('admin:recrutement_proxycandidat_changelist'), obj
.id)
109 _candidatsList
.allow_tags
= True
110 _candidatsList
.short_description
= "Afficher la liste des candidats"
113 def get_form(self
, request
, obj
=None, **kwargs
):
114 form
= super(OffreEmploiAdminMixin
, self
).get_form(request
, obj
, **kwargs
)
115 employe
= groups
.get_employe_from_user(request
.user
)
116 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
120 if 'region' in form
.declared_fields
.keys():
121 region_field
= form
.declared_fields
['region']
122 if 'region' in form
.base_fields
.keys():
123 region_field
= form
.base_fields
['region']
125 if groups
.DRH_NIVEAU_1
in user_groupes
or \
126 groups
.DRH_NIVEAU_2
in user_groupes
or \
127 groups
.HAUTE_DIRECTION
in user_groupes
:
128 region_field
.queryset
= Region
.objects
.all()
130 region_field
.queryset
= Region
.objects
.\
131 filter(id=employe
.implantation
.region
.id)
135 if 'poste' in form
.declared_fields
.keys():
136 poste_field
= form
.declared_fields
['poste']
137 if 'poste' in form
.base_fields
.keys():
138 poste_field
= form
.base_fields
['poste']
140 if groups
.DRH_NIVEAU_1
in user_groupes
or \
141 groups
.DRH_NIVEAU_2
in user_groupes
or \
142 groups
.HAUTE_DIRECTION
in user_groupes
:
143 poste_field
.queryset
= rh
.Poste
.objects
.all()
145 poste_field
.queryset
= rh
.Poste
.objects
.\
146 filter(implantation__region
=employe
.implantation
.region
).\
147 exclude(implantation__in
=IMPLANTATIONS_CENTRALES
)
151 if 'bureau' in form
.declared_fields
.keys():
152 bureau_field
= form
.declared_fields
['bureau']
153 if 'bureau' in form
.base_fields
.keys():
154 bureau_field
= form
.base_fields
['bureau']
156 if groups
.DRH_NIVEAU_1
in user_groupes
or \
157 groups
.DRH_NIVEAU_2
in user_groupes
or \
158 groups
.HAUTE_DIRECTION
in user_groupes
:
159 bureau_field
.queryset
= Bureau
.objects
.all()
161 bureau_field
.queryset
= \
162 Bureau
.objects
.filter(region
=employe
.implantation
.region
)
168 def queryset(self
, request
):
169 qs
= self
.model
._default_manager
.get_query_set() \
170 .select_related('offre_emploi')
171 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
172 if groups
.DRH_NIVEAU_1
in user_groupes
or \
173 groups
.DRH_NIVEAU_2
in user_groupes
or \
174 groups
.HAUTE_DIRECTION
in user_groupes
:
177 if groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
178 groups
.CORRESPONDANT_RH
in user_groupes
or \
179 groups
.ADMINISTRATEURS
in user_groupes
:
180 employe
= groups
.get_employe_from_user(request
.user
)
181 return qs
.filter(region
=employe
.implantation
.region
)
183 if Evaluateur
.objects
.filter(user
=request
.user
).exists():
184 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
186 e
.candidat
.offre_emploi_id
187 for e
in CandidatEvaluation
.objects
188 .select_related('candidat')
189 .filter(evaluateur
=evaluateur
)
191 return qs
.filter(id__in
=offre_ids
)
195 ### Permission add, delete, change
196 def has_add_permission(self
, request
):
197 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
198 if request
.user
.is_superuser
is True or \
199 groups
.DRH_NIVEAU_1
in user_groupes
or \
200 groups
.DRH_NIVEAU_2
in user_groupes
or \
201 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
202 groups
.ADMINISTRATEURS
in user_groupes
or \
203 groups
.HAUTE_DIRECTION
in user_groupes
:
207 def has_delete_permission(self
, request
, obj
=None):
208 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
209 if request
.user
.is_superuser
is True or \
210 groups
.DRH_NIVEAU_1
in user_groupes
or \
211 groups
.DRH_NIVEAU_2
in user_groupes
or \
212 groups
.HAUTE_DIRECTION
in user_groupes
:
216 employe
= groups
.get_employe_from_user(request
.user
)
217 if (groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
218 groups
.ADMINISTRATEURS
in user_groupes
) and (
219 employe
.implantation
.region
== obj
.lieu_affectation
.region
):
224 def has_change_permission(self
, request
, obj
=None):
225 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
226 if request
.user
.is_superuser
is True or \
227 groups
.DRH_NIVEAU_1
in user_groupes
or \
228 groups
.DRH_NIVEAU_2
in user_groupes
or \
229 groups
.HAUTE_DIRECTION
in user_groupes
:
233 employe
= groups
.get_employe_from_user(request
.user
)
234 if (groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
235 groups
.ADMINISTRATEURS
in user_groupes
) and (
236 employe
.implantation
.region
== obj
.lieu_affectation
.region
):
239 if groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
240 groups
.ADMINISTRATEURS
in user_groupes
:
246 def formfield_for_foreignkey(self
, db_field
, request
, **kwargs
):
247 if db_field
.name
== 'lieu_affectation':
248 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
249 if not (request
.user
.is_superuser
is True or \
250 groups
.DRH_NIVEAU_1
in user_groupes
or \
251 groups
.DRH_NIVEAU_2
in user_groupes
):
252 employe
= groups
.get_employe_from_user(request
.user
)
253 kwargs
["queryset"] = Implantation
.objects
.filter(region
=employe
.implantation
.region
)
254 return db_field
.formfield(**kwargs
)
255 return super(OffreEmploiAdminMixin
, self
).formfield_for_foreignkey(db_field
, request
, **kwargs
)
258 class OffreEmploiAdmin(VersionAdmin
, OffreEmploiAdminMixin
):
262 class ProxyOffreEmploiAdmin(OffreEmploiAdminMixin
):
264 'nom', 'date_limite', 'region', 'statut', 'est_affiche'
267 'description', 'bureau', 'duree_affectation', 'renumeration',
268 'debut_affectation', 'lieu_affectation', 'nom', 'resume',
269 'date_limite', 'region', 'poste'
275 ('Description générale', {
276 'fields': ('description', 'date_limite',)
279 'fields': ('lieu_affectation', 'bureau', 'region', 'poste',)
283 'debut_affectation', 'duree_affectation', 'renumeration',
289 ### Lieu de redirection après le change
290 def response_change(self
, request
, obj
):
291 return redirect('admin:recrutement_proxyoffreemploi_changelist')
293 ### Permissions add, delete, change
294 def has_add_permission(self
, request
):
297 def has_delete_permission(self
, request
, obj
=None):
300 def has_change_permission(self
, request
, obj
=None):
304 return not super(ProxyOffreEmploiAdmin
, self
).has_change_permission(request
, obj
)
307 class CandidatPieceInline(admin
.TabularInline
):
308 model
= CandidatPiece
309 fields
= ('candidat', 'nom', 'path',)
314 class ReadOnlyCandidatPieceInline(CandidatPieceInline
):
315 readonly_fields
= ('candidat', 'nom', 'path', )
319 class CandidatEvaluationInlineFormSet(BaseInlineFormSet
):
321 Empêche la suppression d'une évaluation pour le CandidatEvaluationInline
323 def __init__(self
, *args
, **kwargs
):
324 super(CandidatEvaluationInlineFormSet
, self
).__init__(*args
, **kwargs
)
325 self
.can_delete
= False
328 class CandidatEvaluationInline(admin
.TabularInline
):
329 model
= CandidatEvaluation
330 fields
= ('evaluateur', 'note', 'commentaire')
333 formset
= CandidatEvaluationInlineFormSet
336 def get_readonly_fields(self
, request
, obj
=None):
338 Empêche la modification des évaluations
341 return self
.readonly_fields
+ ('evaluateur', 'note', 'commentaire')
342 return self
.readonly_fields
345 class CandidatAdminMixin(BaseAdmin
, ExportAdmin
):
346 search_fields
= ('nom', 'prenom')
347 exclude
= ('actif', )
348 list_editable
= ('statut', )
349 list_display
= ('_candidat', 'offre_emploi',
350 'voir_offre_emploi', 'calculer_moyenne',
351 'afficher_candidat', '_date_creation', 'statut', )
352 list_filter
= ('offre_emploi__nom', 'offre_emploi__region', 'statut', )
356 'fields': ('offre_emploi', )
358 ('Informations personnelles', {
360 'nom', 'prenom', 'genre', 'nationalite',
361 'situation_famille', 'nombre_dependant'
366 'telephone', 'email', 'adresse', 'ville', 'etat_province',
367 'code_postal', 'pays'
370 ('Informations professionnelles', {
372 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
373 'domaine_professionnel'
377 'fields': ('statut', )
382 CandidatEvaluationInline
,
384 actions
= ['envoyer_courriel_candidats', 'changer_statut']
386 export_fields
= ['statut', 'offre_emploi', 'prenom', 'nom', 'genre',
387 'nationalite', 'situation_famille', 'nombre_dependant',
388 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
389 'domaine_professionnel', 'telephone', 'email', 'adresse',
390 'ville', 'etat_province', 'code_postal', 'pays']
392 def _candidat(self
, obj
):
393 txt
= u
"%s %s (%s)" % (obj
.nom
.upper(), obj
.prenom
, obj
.genre
)
394 txt
= textwrap
.wrap(txt
, 30)
395 return "<br/>".join(txt
)
396 _candidat
.short_description
= "Candidat"
397 _candidat
.admin_order_field
= "nom"
398 _candidat
.allow_tags
= True
400 def _date_creation(self
, obj
):
401 return obj
.date_creation
402 _date_creation
.admin_order_field
= "date_creation"
403 _date_creation
.short_description
= "Date de réception"
405 ### Actions à afficher
406 def get_actions(self
, request
):
407 actions
= super(CandidatAdminMixin
, self
).get_actions(request
)
408 del actions
['delete_selected']
411 ### Envoyer un courriel à des candidats
412 def envoyer_courriel_candidats(modeladmin
, obj
, candidats
):
413 selected
= obj
.POST
.getlist(admin
.ACTION_CHECKBOX_NAME
)
415 return HttpResponseRedirect(
416 reverse('selectionner_template') + "?ids=%s" % (",".join(selected
))
418 envoyer_courriel_candidats
.short_description
= u
'Envoyer courriel'
420 ### Changer le statut à des candidats
421 def changer_statut(modeladmin
, request
, queryset
):
422 if request
.POST
.get('post'):
423 queryset
.update(statut
=request
.POST
.get('statut'))
427 'action_checkbox_name': admin
.helpers
.ACTION_CHECKBOX_NAME
,
428 'queryset': queryset
,
429 'status': STATUT_CHOICES
,
432 return render_to_response("recrutement/selectionner_statut.html",
433 context
, context_instance
= RequestContext(request
))
435 changer_statut
.short_description
= u
'Changer statut'
437 ### Évaluer un candidat
438 def evaluer_candidat(self
, obj
):
439 return "<a href='%s?candidat__id__exact=%s'>" \
440 "Évaluer le candidat</a>" % (
441 reverse('admin:recrutement_candidatevaluation_changelist'),
444 evaluer_candidat
.allow_tags
= True
445 evaluer_candidat
.short_description
= 'Évaluation'
447 ### Afficher un candidat
448 def afficher_candidat(self
, obj
):
449 items
= [u
"<li><a href='%s%s'>%s</li>" % \
450 (settings
.OE_PRIVE_MEDIA_URL
, pj
.path
, pj
.get_nom_display()) \
451 for pj
in obj
.pieces_jointes()]
452 html
= "<a href='%s'>Candidature</a>" % (
453 reverse('admin:recrutement_proxycandidat_change', args
=(obj
.id,))
455 return "%s<ul>%s</ul>" % (html
, "\n".join(items
))
456 afficher_candidat
.allow_tags
= True
457 afficher_candidat
.short_description
= u
'Détails du candidat'
459 ### Voir l'offre d'emploi
460 def voir_offre_emploi(self
, obj
):
461 return "<a href='%s'>Voir l'offre d'emploi</a>" % (reverse(
462 'admin:recrutement_proxyoffreemploi_change',
463 args
=(obj
.offre_emploi
.id,)
465 voir_offre_emploi
.allow_tags
= True
466 voir_offre_emploi
.short_description
= "Afficher l'offre d'emploi"
468 ### Calculer la moyenne des notes
469 def calculer_moyenne(self
, obj
):
470 evaluations
= CandidatEvaluation
.objects
.filter(candidat
=obj
)
472 notes
= [evaluation
.note
for evaluation
in evaluations \
473 if evaluation
.note
is not None]
476 moyenne_votes
= round(float(sum(notes
)) / len(notes
), 2)
478 moyenne_votes
= "Non disponible"
480 totales
= len(evaluations
)
483 if obj
.statut
== 'REC':
484 if totales
== faites
:
486 elif faites
> 0 and float(totales
) / float(faites
) >= 2:
493 return """<span style="color: %s;">%s (%s/%s)</span>""" % (
494 color
, moyenne_votes
, faites
, totales
496 calculer_moyenne
.allow_tags
= True
497 calculer_moyenne
.short_description
= "Moyenne"
498 calculer_moyenne
.admin_order_field
= ""
500 ### Permissions add, delete, change
501 def has_add_permission(self
, request
):
502 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
503 if request
.user
.is_superuser
is True or \
504 groups
.CORRESPONDANT_RH
in user_groupes
or \
505 groups
.DRH_NIVEAU_1
in user_groupes
or \
506 groups
.DRH_NIVEAU_2
in user_groupes
or \
507 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
508 groups
.ADMINISTRATEURS
in user_groupes
or \
509 groups
.HAUTE_DIRECTION
in user_groupes
:
513 def has_delete_permission(self
, request
, obj
=None):
514 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
515 if request
.user
.is_superuser
is True or \
516 groups
.CORRESPONDANT_RH
in user_groupes
or \
517 groups
.DRH_NIVEAU_1
in user_groupes
or \
518 groups
.DRH_NIVEAU_2
in user_groupes
or \
519 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
520 groups
.ADMINISTRATEURS
in user_groupes
or \
521 groups
.HAUTE_DIRECTION
in user_groupes
:
525 def has_change_permission(self
, request
, obj
=None):
526 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
527 if request
.user
.is_superuser
is True or \
528 groups
.CORRESPONDANT_RH
in user_groupes
or \
529 groups
.DRH_NIVEAU_1
in user_groupes
or \
530 groups
.DRH_NIVEAU_2
in user_groupes
or \
531 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
532 groups
.ADMINISTRATEURS
in user_groupes
or \
533 groups
.HAUTE_DIRECTION
in user_groupes
:
537 def formfield_for_foreignkey(self
, db_field
, request
, **kwargs
):
538 if db_field
.name
== 'offre_emploi':
539 employe
= groups
.get_employe_from_user(request
.user
)
540 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
541 if request
.user
.is_superuser
is True or \
542 groups
.CORRESPONDANT_RH
in user_groupes
or \
543 groups
.DRH_NIVEAU_1
in user_groupes
or \
544 groups
.DRH_NIVEAU_2
in user_groupes
:
545 qs_offres
= OffreEmploi
.objects
.all()
547 qs_offres
=OffreEmploi
.objects
.filter(region
=employe
.implantation
.region
)
548 kwargs
["queryset"] = qs_offres
549 return db_field
.formfield(**kwargs
)
550 return super(CandidatAdminMixin
, self
).formfield_for_foreignkey(db_field
, request
, **kwargs
)
552 def get_changelist(self
, request
, **kwargs
):
553 return OrderedChangeList
555 def queryset(self
, request
):
557 Spécifie un queryset limité, autrement Django exécute un
558 select_related() sans paramètre, ce qui a pour effet de charger tous
559 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
560 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
561 génération d'une requête infinie.
563 qs
= self
.model
._default_manager
.get_query_set() \
564 .select_related('offre_emploi') \
565 .annotate(moyenne
=Avg('evaluations__note'))
567 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
568 if groups
.DRH_NIVEAU_1
in user_groupes
or \
569 groups
.DRH_NIVEAU_2
in user_groupes
or \
570 groups
.HAUTE_DIRECTION
in user_groupes
:
573 if groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
574 groups
.CORRESPONDANT_RH
in user_groupes
or \
575 groups
.ADMINISTRATEURS
in user_groupes
:
576 employe
= groups
.get_employe_from_user(request
.user
)
577 return qs
.filter(offre_emploi__region
=employe
.implantation
.region
)
579 if Evaluateur
.objects
.filter(user
=request
.user
).exists():
580 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
581 candidat_ids
= [e
.candidat
.id for e
in
582 CandidatEvaluation
.objects
.filter(evaluateur
=evaluateur
)]
583 return qs
.filter(id__in
=candidat_ids
)
587 class CandidatAdmin(VersionAdmin
, CandidatAdminMixin
):
588 change_list_template
= 'admin/recrutement/candidat/change_list.html'
592 class ProxyCandidatAdmin(CandidatAdminMixin
):
593 change_list_template
= 'admin/recrutement/candidat/change_list.html'
596 'statut', 'offre_emploi', 'prenom', 'nom', 'genre', 'nationalite',
597 'situation_famille', 'nombre_dependant', 'telephone', 'email',
598 'adresse', 'ville', 'etat_province', 'code_postal', 'pays',
599 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
600 'domaine_professionnel', 'pieces_jointes'
604 'fields': ('offre_emploi', )
606 ('Informations personnelles', {
608 'prenom', 'nom', 'genre', 'nationalite', 'situation_famille',
614 'telephone', 'email', 'adresse', 'ville', 'etat_province',
615 'code_postal', 'pays'
618 ('Informations professionnelles', {
620 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
621 'domaine_professionnel'
625 inlines
= (CandidatEvaluationInline
, )
627 def has_add_permission(self
, request
):
630 def has_delete_permission(self
, request
, obj
=None):
633 def has_change_permission(self
, request
, obj
=None):
635 return obj
in self
.queryset(request
)
637 # evaluateur = Evaluateur.objects.get(user=request.user)
638 # for e in obj.evaluations.all():
639 # if e.evaluateur == evaluateur:
644 return super(ProxyCandidatAdmin
, self
).has_change_permission(request
, obj
)
646 def get_actions(self
, request
):
650 class CandidatPieceAdmin(admin
.ModelAdmin
):
651 list_display
= ('nom', 'candidat', )
654 def queryset(self
, request
):
656 Spécifie un queryset limité, autrement Django exécute un
657 select_related() sans paramètre, ce qui a pour effet de charger tous
658 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
659 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
660 génération d'une requête infinie. Affiche la liste de candidats que
661 si le user connecté possède un Evaluateur
663 qs
= self
.model
._default_manager
.get_query_set()
664 return qs
.select_related('candidat')
667 class EvaluateurAdmin(BaseAdmin
, VersionAdmin
):
674 ### Actions à afficher
675 def get_actions(self
, request
):
676 actions
= super(EvaluateurAdmin
, self
).get_actions(request
)
677 del actions
['delete_selected']
680 ### Permissions add, delete, change
681 def has_add_permission(self
, request
):
682 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
683 if request
.user
.is_superuser
is True or \
684 groups
.DRH_NIVEAU_1
in user_groupes
or \
685 groups
.DRH_NIVEAU_2
in user_groupes
or \
686 groups
.HAUTE_DIRECTION
in user_groupes
:
690 def has_delete_permission(self
, request
, obj
=None):
691 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
692 if request
.user
.is_superuser
is True or \
693 groups
.DRH_NIVEAU_1
in user_groupes
or \
694 groups
.DRH_NIVEAU_2
in user_groupes
or \
695 groups
.HAUTE_DIRECTION
in user_groupes
:
699 def has_change_permission(self
, request
, obj
=None):
700 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
701 if request
.user
.is_superuser
is True or \
702 groups
.DRH_NIVEAU_1
in user_groupes
or \
703 groups
.DRH_NIVEAU_2
in user_groupes
or \
704 groups
.HAUTE_DIRECTION
in user_groupes
:
709 class CandidatEvaluationAdmin(BaseAdmin
):
710 search_fields
= ('candidat__nom', 'candidat__prenom')
712 '_candidat', '_statut', '_offre_emploi', 'evaluateur', '_note',
715 readonly_fields
= ('candidat', 'evaluateur')
716 list_filter
= ('candidat__statut', 'candidat__offre_emploi',)
718 ('Évaluation du candidat', {
719 'fields': ('candidat', 'evaluateur', 'note', 'commentaire', )
723 def get_actions(self
, request
):
724 # on stocke l'evaluateur connecté (pas forcément la meilleure place...)
726 self
.evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
728 self
.evaluateur
= None
730 actions
= super(CandidatEvaluationAdmin
, self
).get_actions(request
)
731 del actions
['delete_selected']
735 def _note(self
, obj
):
737 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
738 un lien pour Évaluer le candidat.
739 Sinon afficher la note.
741 page
= self
.model
.__name__
.lower()
742 redirect_url
= 'admin:recrutement_%s_change' % page
745 label
= "Candidat non évalué"
749 if self
.evaluateur
== obj
.evaluateur
:
750 return "<a href='%s'>%s</a>" % (
751 reverse(redirect_url
, args
=(obj
.id,)), label
755 _note
.allow_tags
= True
756 _note
.short_description
= "Note"
757 _note
.admin_order_field
= 'note'
759 def _statut(self
, obj
):
760 return obj
.candidat
.get_statut_display()
761 _statut
.order_field
= 'candidat__statut'
762 _statut
.short_description
= 'Statut'
764 ### Lien en lecture seule vers le candidat
765 def _candidat(self
, obj
):
766 return "<a href='%s'>%s</a>" \
767 % (reverse('admin:recrutement_proxycandidat_change',
768 args
=(obj
.candidat
.id,)), obj
.candidat
)
769 _candidat
.allow_tags
= True
770 _candidat
.short_description
= 'Candidat'
772 ### Afficher commentaire
773 def _commentaire(self
, obj
):
775 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
776 dans le champ commentaire, Aucun au lieu de (None)
777 Sinon afficher la note.
779 if obj
.commentaire
is None:
781 return obj
.commentaire
782 _commentaire
.allow_tags
= True
783 _commentaire
.short_description
= "Commentaire"
785 ### Afficher offre d'emploi
786 def _offre_emploi(self
, obj
):
787 return "<a href='%s'>%s</a>" % \
788 (reverse('admin:recrutement_proxyoffreemploi_change',
789 args
=(obj
.candidat
.offre_emploi
.id,)), obj
.candidat
.offre_emploi
)
790 _offre_emploi
.allow_tags
= True
791 _offre_emploi
.short_description
= "Voir offre d'emploi"
793 def has_add_permission(self
, request
):
796 def has_delete_permission(self
, request
, obj
=None):
799 def has_change_permission(self
, request
, obj
=None):
801 Permettre la visualisation dans la changelist
802 mais interdire l'accès à modifier l'objet si l'évaluateur n'est pas
805 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
807 if request
.user
.is_superuser
or \
808 groups
.CORRESPONDANT_RH
in user_groupes
or \
809 groups
.DRH_NIVEAU_1
in user_groupes
or \
810 groups
.DRH_NIVEAU_2
in user_groupes
or \
811 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
812 groups
.ADMINISTRATEURS
in user_groupes
or \
813 groups
.HAUTE_DIRECTION
in user_groupes
:
814 is_recrutement
= True
816 is_recrutement
= False
818 return is_recrutement
820 def queryset(self
, request
):
822 Afficher uniquement les évaluations de l'évaluateur, sauf si
823 l'utilisateur est dans les groupes suivants.
825 qs
= self
.model
._default_manager
.get_query_set() \
826 .select_related('offre_emploi')
827 user_groupes
= request
.user
.groups
.all()
828 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
830 if request
.user
.is_superuser
or \
831 groups
.CORRESPONDANT_RH
in user_groupes
or \
832 groups
.DRH_NIVEAU_1
in user_groupes
or \
833 groups
.DRH_NIVEAU_2
in user_groupes
or \
834 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
835 groups
.ADMINISTRATEURS
in user_groupes
or \
836 groups
.HAUTE_DIRECTION
in user_groupes
:
837 return qs
.filter(candidat__statut__in
=('REC', 'SEL'))
839 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
840 candidats_evaluations
= \
841 CandidatEvaluation
.objects
.filter(evaluateur
=evaluateur
,
842 candidat__statut__in
=('REC', ))
843 candidats_evaluations_ids
= [ce
.id for ce
in candidats_evaluations
]
844 return qs
.filter(id__in
=candidats_evaluations_ids
)
847 class MesCandidatEvaluationAdmin(CandidatEvaluationAdmin
):
850 def has_change_permission(self
, request
, obj
=None):
852 Evaluateur
.objects
.get(user
=request
.user
)
855 is_evaluateur
= False
857 if obj
is None and is_evaluateur
:
861 return request
.user
== obj
.evaluateur
.user
865 def queryset(self
, request
):
866 qs
= self
.model
._default_manager
.get_query_set() \
867 .select_related('offre_emploi')
868 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
869 candidats_evaluations
= \
870 CandidatEvaluation
.objects
.filter(evaluateur
=evaluateur
,
871 candidat__statut__in
=('REC', ))
872 candidats_evaluations_ids
= [ce
.id for ce
in candidats_evaluations
]
873 return qs
.filter(id__in
=candidats_evaluations_ids
)
876 class OffreEmploiEvaluateurAdmin(BaseAdmin
):
880 class CourrielTemplateAdmin(BaseAdmin
, VersionAdmin
):
881 ### Actions à afficher
882 def get_actions(self
, request
):
883 actions
= super(CourrielTemplateAdmin
, self
).get_actions(request
)
884 del actions
['delete_selected']
887 admin
.site
.register(OffreEmploi
, OffreEmploiAdmin
)
888 admin
.site
.register(ProxyOffreEmploi
, ProxyOffreEmploiAdmin
)
889 admin
.site
.register(Candidat
, CandidatAdmin
)
890 admin
.site
.register(ProxyCandidat
, ProxyCandidatAdmin
)
891 admin
.site
.register(CandidatEvaluation
, CandidatEvaluationAdmin
)
892 admin
.site
.register(MesCandidatEvaluation
, MesCandidatEvaluationAdmin
)
893 admin
.site
.register(Evaluateur
, EvaluateurAdmin
)
894 admin
.site
.register(CourrielTemplate
, CourrielTemplateAdmin
)
895 admin
.site
.register(OffreEmploiEvaluateur
, OffreEmploiEvaluateurAdmin
)