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(OffreEmploiAdmin
, 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()]
94 if 'region' in form
.declared_fields
:
95 region_field
= form
.declared_fields
['region']
97 region_field
= form
.base_fields
['region']
99 if groups
.DRH_NIVEAU_1
in user_groupes
or \
100 groups
.DRH_NIVEAU_2
in user_groupes
or \
101 groups
.HAUTE_DIRECTION
in user_groupes
:
102 region_field
.queryset
= Region
.objects
.all()
104 region_field
.queryset
= Region
.objects
.\
105 filter(id=employe
.implantation
.region
.id)
108 if 'poste' in form
.declared_fields
:
109 poste_field
= form
.declared_fields
['poste']
111 poste_field
= form
.base_fields
['poste']
113 if groups
.DRH_NIVEAU_1
in user_groupes
or \
114 groups
.DRH_NIVEAU_2
in user_groupes
or \
115 groups
.HAUTE_DIRECTION
in user_groupes
:
116 poste_field
.queryset
= rh
.Poste
.objects
.all()
118 poste_field
.queryset
= rh
.Poste
.objects
.\
119 filter(implantation__region
=employe
.implantation
.region
).\
120 exclude(implantation__in
=IMPLANTATIONS_CENTRALES
)
123 if 'bureau' in form
.declared_fields
:
124 bureau_field
= form
.declared_fields
['bureau']
126 bureau_field
= form
.base_fields
['bureau']
128 if groups
.DRH_NIVEAU_1
in user_groupes
or \
129 groups
.DRH_NIVEAU_2
in user_groupes
or \
130 groups
.HAUTE_DIRECTION
in user_groupes
:
131 bureau_field
.queryset
= Bureau
.objects
.all()
133 bureau_field
.queryset
= \
134 Bureau
.objects
.filter(region
=employe
.implantation
.region
)
140 def queryset(self
, request
):
141 qs
= self
.model
._default_manager
.get_query_set() \
142 .select_related('offre_emploi')
143 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
144 if groups
.DRH_NIVEAU_1
in user_groupes
or \
145 groups
.DRH_NIVEAU_2
in user_groupes
or \
146 groups
.HAUTE_DIRECTION
in user_groupes
:
149 if groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
150 groups
.CORRESPONDANT_RH
in user_groupes
or \
151 groups
.ADMINISTRATEURS
in user_groupes
:
152 employe
= groups
.get_employe_from_user(request
.user
)
153 return qs
.filter(region
=employe
.implantation
.region
)
155 if Evaluateur
.objects
.filter(user
=request
.user
).exists():
156 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
158 e
.candidat
.offre_emploi_id
159 for e
in CandidatEvaluation
.objects
160 .select_related('candidat')
161 .filter(evaluateur
=evaluateur
)
163 return qs
.filter(id__in
=offre_ids
)
167 ### Permission add, delete, change
168 def has_add_permission(self
, request
):
169 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
170 if request
.user
.is_superuser
is True or \
171 groups
.DRH_NIVEAU_1
in user_groupes
or \
172 groups
.DRH_NIVEAU_2
in user_groupes
or \
173 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
174 groups
.ADMINISTRATEURS
in user_groupes
or \
175 groups
.HAUTE_DIRECTION
in user_groupes
:
179 def has_delete_permission(self
, request
, obj
=None):
180 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
181 if request
.user
.is_superuser
is True or \
182 groups
.DRH_NIVEAU_1
in user_groupes
or \
183 groups
.DRH_NIVEAU_2
in user_groupes
or \
184 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
185 groups
.ADMINISTRATEURS
in user_groupes
or \
186 groups
.HAUTE_DIRECTION
in user_groupes
:
190 def has_change_permission(self
, request
, obj
=None):
191 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
192 if request
.user
.is_superuser
is True or \
193 groups
.DRH_NIVEAU_1
in user_groupes
or \
194 groups
.DRH_NIVEAU_2
in user_groupes
or \
195 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
196 groups
.ADMINISTRATEURS
in user_groupes
or \
197 groups
.HAUTE_DIRECTION
in user_groupes
:
202 class OffreEmploiAdmin(VersionAdmin
, OffreEmploiAdminMixin
):
206 class ProxyOffreEmploiAdmin(OffreEmploiAdminMixin
):
208 'nom', 'date_limite', 'region', 'statut', 'est_affiche'
211 'description', 'bureau', 'duree_affectation', 'renumeration',
212 'debut_affectation', 'lieu_affectation', 'nom', 'resume',
213 'date_limite', 'region', 'poste'
219 ('Description générale', {
220 'fields': ('description', 'date_limite',)
223 'fields': ('lieu_affectation', 'bureau', 'region', 'poste',)
227 'debut_affectation', 'duree_affectation', 'renumeration',
233 ### Lieu de redirection après le change
234 def response_change(self
, request
, obj
):
235 return redirect('admin:recrutement_proxyoffreemploi_changelist')
238 def get_form(self
, request
, obj
=None, **kwargs
):
239 form
= super(OffreEmploiAdmin
, self
).get_form(request
, obj
, **kwargs
)
242 ### Permissions add, delete, change
243 def has_add_permission(self
, request
):
246 def has_delete_permission(self
, request
, obj
=None):
249 def has_change_permission(self
, request
, obj
=None):
250 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
251 if request
.user
.is_superuser
is True or \
252 groups
.CORRESPONDANT_RH
in user_groupes
or \
253 groups
.DRH_NIVEAU_1
in user_groupes
or \
254 groups
.DRH_NIVEAU_2
in user_groupes
or \
255 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
256 groups
.ADMINISTRATEURS
in user_groupes
or \
257 groups
.HAUTE_DIRECTION
in user_groupes
:
266 class CandidatPieceInline(admin
.TabularInline
):
267 model
= CandidatPiece
268 fields
= ('candidat', 'nom', 'path',)
273 class ReadOnlyCandidatPieceInline(CandidatPieceInline
):
274 readonly_fields
= ('candidat', 'nom', 'path', )
278 class CandidatEvaluationInlineFormSet(BaseInlineFormSet
):
280 Empêche la suppression d'une évaluation pour le CandidatEvaluationInline
282 def __init__(self
, *args
, **kwargs
):
283 super(CandidatEvaluationInlineFormSet
, self
).__init__(*args
, **kwargs
)
284 self
.can_delete
= False
287 class CandidatEvaluationInline(admin
.TabularInline
):
288 model
= CandidatEvaluation
289 fields
= ('evaluateur', 'note', 'commentaire')
292 formset
= CandidatEvaluationInlineFormSet
295 def get_readonly_fields(self
, request
, obj
=None):
297 Empêche la modification des évaluations
300 return self
.readonly_fields
+ ('evaluateur', 'note', 'commentaire')
301 return self
.readonly_fields
304 class CandidatAdminMixin(BaseAdmin
):
305 search_fields
= ('nom', 'prenom')
306 exclude
= ('actif', )
307 list_editable
= ('statut', )
308 list_display
= ('_candidat', 'offre_emploi',
309 'voir_offre_emploi', 'calculer_moyenne',
310 'afficher_candidat', '_date_creation', 'statut', )
311 list_filter
= ('offre_emploi', 'offre_emploi__region', 'statut', )
315 'fields': ('offre_emploi', )
317 ('Informations personnelles', {
319 'prenom', 'nom', 'genre', 'nationalite',
320 'situation_famille', 'nombre_dependant'
325 'telephone', 'email', 'adresse', 'ville', 'etat_province',
326 'code_postal', 'pays'
329 ('Informations professionnelles', {
331 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
332 'domaine_professionnel'
336 'fields': ('statut', )
341 CandidatEvaluationInline
,
343 actions
= ['envoyer_courriel_candidats']
345 def _candidat(self
, obj
):
346 txt
= u
"%s %s (%s)" % (obj
.nom
.upper(), obj
.prenom
, obj
.genre
)
347 txt
= textwrap
.wrap(txt
, 30)
348 return "<br/>".join(txt
)
349 _candidat
.short_description
= "Candidat"
350 _candidat
.admin_order_field
= "nom"
351 _candidat
.allow_tags
= True
353 def _date_creation(self
, obj
):
354 return obj
.date_creation
355 _date_creation
.admin_order_field
= "date_creation"
356 _date_creation
.short_description
= "Date de réception"
358 ### Actions à afficher
359 def get_actions(self
, request
):
360 actions
= super(CandidatAdmin
, self
).get_actions(request
)
361 del actions
['delete_selected']
364 ### Envoyer un courriel à des candidats
365 def envoyer_courriel_candidats(modeladmin
, obj
, candidats
):
366 selected
= obj
.POST
.getlist(admin
.ACTION_CHECKBOX_NAME
)
368 return HttpResponseRedirect(
369 reverse('selectionner_template') + "?ids=%s" % (",".join(selected
))
371 envoyer_courriel_candidats
.short_description
= u
'Envoyer courriel'
373 ### Évaluer un candidat
374 def evaluer_candidat(self
, obj
):
375 return "<a href='%s?candidat__id__exact=%s'>" \
376 "Évaluer le candidat</a>" % (
377 reverse('admin:recrutement_candidatevaluation_changelist'),
380 evaluer_candidat
.allow_tags
= True
381 evaluer_candidat
.short_description
= 'Évaluation'
383 ### Afficher un candidat
384 def afficher_candidat(self
, obj
):
385 items
= [u
"<li><a href='%s%s'>%s</li>" % \
386 (settings
.OE_PRIVE_MEDIA_URL
, pj
.path
, pj
.get_nom_display()) \
387 for pj
in obj
.pieces_jointes()]
388 html
= "<a href='%s'>Voir le candidat</a>" % (
389 reverse('admin:recrutement_proxycandidat_change', args
=(obj
.id,))
391 return "%s<ul>%s</ul>" % (html
, "\n".join(items
))
392 afficher_candidat
.allow_tags
= True
393 afficher_candidat
.short_description
= u
'Détails du candidat'
395 ### Voir l'offre d'emploi
396 def voir_offre_emploi(self
, obj
):
397 return "<a href='%s'>Voir l'offre d'emploi</a>" % (reverse(
398 'admin:recrutement_proxyoffreemploi_change',
399 args
=(obj
.offre_emploi
.id,)
401 voir_offre_emploi
.allow_tags
= True
402 voir_offre_emploi
.short_description
= "Afficher l'offre d'emploi"
404 ### Calculer la moyenne des notes
405 def calculer_moyenne(self
, obj
):
406 evaluations
= CandidatEvaluation
.objects
.filter(candidat
=obj
)
408 notes
= [evaluation
.note
for evaluation
in evaluations \
409 if evaluation
.note
is not None]
412 moyenne_votes
= round(float(sum(notes
)) / len(notes
), 2)
414 moyenne_votes
= "Non disponible"
416 totales
= len(evaluations
)
419 if obj
.statut
== 'REC':
420 if totales
== faites
:
422 elif faites
> 0 and float(totales
) / float(faites
) >= 2:
429 return """<span style="color: %s;">%s (%s/%s)</span>""" % (
430 color
, moyenne_votes
, faites
, totales
432 calculer_moyenne
.allow_tags
= True
433 calculer_moyenne
.short_description
= "Moyenne"
434 calculer_moyenne
.admin_order_field
= ""
436 ### Permissions add, delete, change
437 def has_add_permission(self
, request
):
438 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
439 if request
.user
.is_superuser
is True or \
440 groups
.CORRESPONDANT_RH
in user_groupes
or \
441 groups
.DRH_NIVEAU_1
in user_groupes
or \
442 groups
.DRH_NIVEAU_2
in user_groupes
or \
443 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
444 groups
.ADMINISTRATEURS
in user_groupes
or \
445 groups
.HAUTE_DIRECTION
in user_groupes
:
449 def has_delete_permission(self
, request
, obj
=None):
450 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
451 if request
.user
.is_superuser
is True or \
452 groups
.CORRESPONDANT_RH
in user_groupes
or \
453 groups
.DRH_NIVEAU_1
in user_groupes
or \
454 groups
.DRH_NIVEAU_2
in user_groupes
or \
455 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
456 groups
.ADMINISTRATEURS
in user_groupes
or \
457 groups
.HAUTE_DIRECTION
in user_groupes
:
461 def has_change_permission(self
, request
, obj
=None):
462 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
463 if request
.user
.is_superuser
is True or \
464 groups
.CORRESPONDANT_RH
in user_groupes
or \
465 groups
.DRH_NIVEAU_1
in user_groupes
or \
466 groups
.DRH_NIVEAU_2
in user_groupes
or \
467 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
468 groups
.ADMINISTRATEURS
in user_groupes
or \
469 groups
.HAUTE_DIRECTION
in user_groupes
:
473 def get_changelist(self
, request
, **kwargs
):
474 return OrderedChangeList
476 def queryset(self
, request
):
478 Spécifie un queryset limité, autrement Django exécute un
479 select_related() sans paramètre, ce qui a pour effet de charger tous
480 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
481 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
482 génération d'une requête infinie.
484 qs
= self
.model
._default_manager
.get_query_set() \
485 .select_related('offre_emploi') \
486 .annotate(moyenne
=Avg('evaluations__note'))
488 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
489 if groups
.DRH_NIVEAU_1
in user_groupes
or \
490 groups
.DRH_NIVEAU_2
in user_groupes
or \
491 groups
.HAUTE_DIRECTION
in user_groupes
:
494 if groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
495 groups
.CORRESPONDANT_RH
in user_groupes
or \
496 groups
.ADMINISTRATEURS
in user_groupes
:
497 employe
= groups
.get_employe_from_user(request
.user
)
498 return qs
.filter(offre_emploi__region
=employe
.implantation
.region
)
500 if Evaluateur
.objects
.filter(user
=request
.user
).exists():
501 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
502 candidat_ids
= [e
.candidat
.id for e
in
503 CandidatEvaluation
.objects
.filter(evaluateur
=evaluateur
)]
504 return qs
.filter(id__in
=candidat_ids
)
508 class CandidatAdmin(VersionAdmin
, CandidatAdminMixin
):
512 class ProxyCandidatAdmin(CandidatAdminMixin
):
515 'statut', 'offre_emploi', 'prenom', 'nom', 'genre', 'nationalite',
516 'situation_famille', 'nombre_dependant', 'telephone', 'email',
517 'adresse', 'ville', 'etat_province', 'code_postal', 'pays',
518 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
519 'domaine_professionnel', 'pieces_jointes'
523 'fields': ('offre_emploi', )
525 ('Informations personnelles', {
527 'prenom', 'nom', 'genre', 'nationalite', 'situation_famille',
533 'telephone', 'email', 'adresse', 'ville', 'etat_province',
534 'code_postal', 'pays'
537 ('Informations professionnelles', {
539 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
540 'domaine_professionnel'
544 inlines
= (CandidatEvaluationInline
, )
546 def has_add_permission(self
, request
):
549 def has_delete_permission(self
, request
, obj
=None):
552 def has_change_permission(self
, request
, obj
=None):
553 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
554 if request
.user
.is_superuser
is True or \
555 groups
.CORRESPONDANT_RH
in user_groupes
or \
556 groups
.DRH_NIVEAU_1
in user_groupes
or \
557 groups
.DRH_NIVEAU_2
in user_groupes
or \
558 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
559 groups
.ADMINISTRATEURS
in user_groupes
or \
560 groups
.HAUTE_DIRECTION
in user_groupes
:
564 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
565 for e
in obj
.evaluations
.all():
566 if e
.evaluateur
== evaluateur
:
571 def get_actions(self
, request
):
575 class CandidatPieceAdmin(admin
.ModelAdmin
):
576 list_display
= ('nom', 'candidat', )
579 def queryset(self
, request
):
581 Spécifie un queryset limité, autrement Django exécute un
582 select_related() sans paramètre, ce qui a pour effet de charger tous
583 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
584 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
585 génération d'une requête infinie. Affiche la liste de candidats que
586 si le user connecté possède un Evaluateur
588 qs
= self
.model
._default_manager
.get_query_set()
589 return qs
.select_related('candidat')
592 class EvaluateurAdmin(BaseAdmin
, VersionAdmin
):
599 ### Actions à afficher
600 def get_actions(self
, request
):
601 actions
= super(EvaluateurAdmin
, self
).get_actions(request
)
602 del actions
['delete_selected']
605 ### Permissions add, delete, change
606 def has_add_permission(self
, request
):
607 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
608 if request
.user
.is_superuser
is True or \
609 groups
.DRH_NIVEAU_1
in user_groupes
or \
610 groups
.DRH_NIVEAU_2
in user_groupes
or \
611 groups
.HAUTE_DIRECTION
in user_groupes
:
615 def has_delete_permission(self
, request
, obj
=None):
616 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
617 if request
.user
.is_superuser
is True or \
618 groups
.DRH_NIVEAU_1
in user_groupes
or \
619 groups
.DRH_NIVEAU_2
in user_groupes
or \
620 groups
.HAUTE_DIRECTION
in user_groupes
:
624 def has_change_permission(self
, request
, obj
=None):
625 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
626 if request
.user
.is_superuser
is True or \
627 groups
.DRH_NIVEAU_1
in user_groupes
or \
628 groups
.DRH_NIVEAU_2
in user_groupes
or \
629 groups
.HAUTE_DIRECTION
in user_groupes
:
634 class CandidatEvaluationAdmin(BaseAdmin
):
635 search_fields
= ('candidat__nom', 'candidat__prenom')
637 '_candidat', '_statut', '_offre_emploi', 'evaluateur', '_note',
640 readonly_fields
= ('candidat', 'evaluateur')
641 list_filter
= ('candidat__statut', 'candidat__offre_emploi',)
643 ('Évaluation du candidat', {
644 'fields': ('candidat', 'evaluateur', 'note', 'commentaire', )
648 def get_actions(self
, request
):
649 # on stocke l'evaluateur connecté (pas forcément la meilleure place...)
651 self
.evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
653 self
.evaluateur
= None
655 actions
= super(CandidatEvaluationAdmin
, self
).get_actions(request
)
656 del actions
['delete_selected']
660 def _note(self
, obj
):
662 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
663 un lien pour Évaluer le candidat.
664 Sinon afficher la note.
666 page
= self
.model
.__name__
.lower()
667 redirect_url
= 'admin:recrutement_%s_change' % page
670 label
= "Candidat non évalué"
674 if self
.evaluateur
== obj
.evaluateur
:
675 return "<a href='%s'>%s</a>" % (
676 reverse(redirect_url
, args
=(obj
.id,)), label
680 _note
.allow_tags
= True
681 _note
.short_description
= "Note"
682 _note
.admin_order_field
= 'note'
684 def _statut(self
, obj
):
685 return obj
.candidat
.get_statut_display()
686 _statut
.order_field
= 'candidat__statut'
687 _statut
.short_description
= 'Statut'
689 ### Lien en lecture seule vers le candidat
690 def _candidat(self
, obj
):
691 return "<a href='%s'>%s</a>" \
692 % (reverse('admin:recrutement_proxycandidat_change',
693 args
=(obj
.candidat
.id,)), obj
.candidat
)
694 _candidat
.allow_tags
= True
695 _candidat
.short_description
= 'Candidat'
697 ### Afficher commentaire
698 def _commentaire(self
, obj
):
700 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
701 dans le champ commentaire, Aucun au lieu de (None)
702 Sinon afficher la note.
704 if obj
.commentaire
is None:
706 return obj
.commentaire
707 _commentaire
.allow_tags
= True
708 _commentaire
.short_description
= "Commentaire"
710 ### Afficher offre d'emploi
711 def _offre_emploi(self
, obj
):
712 return "<a href='%s'>%s</a>" % \
713 (reverse('admin:recrutement_proxyoffreemploi_change',
714 args
=(obj
.candidat
.offre_emploi
.id,)), obj
.candidat
.offre_emploi
)
715 _offre_emploi
.allow_tags
= True
716 _offre_emploi
.short_description
= "Voir offre d'emploi"
718 def has_add_permission(self
, request
):
721 def has_delete_permission(self
, request
, obj
=None):
724 def has_change_permission(self
, request
, obj
=None):
726 Permettre la visualisation dans la changelist
727 mais interdire l'accès à modifier l'objet si l'évaluateur n'est pas
730 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
732 if request
.user
.is_superuser
or \
733 groups
.CORRESPONDANT_RH
in user_groupes
or \
734 groups
.DRH_NIVEAU_1
in user_groupes
or \
735 groups
.DRH_NIVEAU_2
in user_groupes
or \
736 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
737 groups
.ADMINISTRATEURS
in user_groupes
or \
738 groups
.HAUTE_DIRECTION
in user_groupes
:
739 is_recrutement
= True
741 is_recrutement
= False
743 return is_recrutement
745 def queryset(self
, request
):
747 Afficher uniquement les évaluations de l'évaluateur, sauf si
748 l'utilisateur est dans les groupes suivants.
750 qs
= self
.model
._default_manager
.get_query_set() \
751 .select_related('offre_emploi')
752 user_groupes
= request
.user
.groups
.all()
753 user_groupes
= [g
.name
for g
in request
.user
.groups
.all()]
755 if request
.user
.is_superuser
or \
756 groups
.CORRESPONDANT_RH
in user_groupes
or \
757 groups
.DRH_NIVEAU_1
in user_groupes
or \
758 groups
.DRH_NIVEAU_2
in user_groupes
or \
759 groups
.DIRECTEUR_DE_BUREAU
in user_groupes
or \
760 groups
.ADMINISTRATEURS
in user_groupes
or \
761 groups
.HAUTE_DIRECTION
in user_groupes
:
764 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
765 candidats_evaluations
= \
766 CandidatEvaluation
.objects
.filter(evaluateur
=evaluateur
,
767 candidat__statut__in
=('REC', ))
768 candidats_evaluations_ids
= [ce
.id for ce
in candidats_evaluations
]
769 return qs
.filter(id__in
=candidats_evaluations_ids
)
772 class MesCandidatEvaluationAdmin(CandidatEvaluationAdmin
):
774 def has_change_permission(self
, request
, obj
=None):
776 Evaluateur
.objects
.get(user
=request
.user
)
779 is_evaluateur
= False
781 if obj
is None and is_evaluateur
:
785 return request
.user
== obj
.evaluateur
.user
789 def queryset(self
, request
):
790 qs
= self
.model
._default_manager
.get_query_set() \
791 .select_related('offre_emploi')
792 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
793 candidats_evaluations
= \
794 CandidatEvaluation
.objects
.filter(evaluateur
=evaluateur
,
795 candidat__statut__in
=('REC', ))
796 candidats_evaluations_ids
= [ce
.id for ce
in candidats_evaluations
]
797 return qs
.filter(id__in
=candidats_evaluations_ids
)
800 class CourrielTemplateAdmin(BaseAdmin
, VersionAdmin
):
801 ### Actions à afficher
802 def get_actions(self
, request
):
803 actions
= super(CourrielTemplateAdmin
, self
).get_actions(request
)
804 del actions
['delete_selected']
807 admin
.site
.register(OffreEmploi
, OffreEmploiAdmin
)
808 admin
.site
.register(ProxyOffreEmploi
, ProxyOffreEmploiAdmin
)
809 admin
.site
.register(Candidat
, CandidatAdmin
)
810 admin
.site
.register(ProxyCandidat
, ProxyCandidatAdmin
)
811 admin
.site
.register(CandidatEvaluation
, CandidatEvaluationAdmin
)
812 admin
.site
.register(MesCandidatEvaluation
, MesCandidatEvaluationAdmin
)
813 admin
.site
.register(Evaluateur
, EvaluateurAdmin
)
814 admin
.site
.register(CourrielTemplate
, CourrielTemplateAdmin
)