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
.shortcuts
import render_to_response
12 from django
.template
import RequestContext
14 from auf
.django
.emploi
.models
import STATUT_CHOICES
15 from django
.forms
.models
import BaseInlineFormSet
16 from django
.http
import HttpResponseRedirect
17 from django
.shortcuts
import redirect
18 from reversion
.admin
import VersionAdmin
20 from auf
.django
.emploi
.models
import OffreEmploi
, Candidat
, CandidatPiece
21 from auf
.django
.references
.models
import Region
, Bureau
, Implantation
22 from auf
.django
.export
.admin
import ExportAdmin
24 from project
.groups
import get_employe_from_user
as get_emp
25 from project
.rh
import models
as rh
26 from project
.recrutement
.forms
import OffreEmploiForm
27 from project
.recrutement
.groups
import \
29 grp_directeurs_bureau
, \
30 grp_administrateurs
, \
31 grp_correspondants_rh
, \
33 from project
.recrutement
.models
import \
34 Evaluateur
, CandidatEvaluation
, \
35 ProxyOffreEmploi
, ProxyCandidat
, MesCandidatEvaluation
, \
39 IMPLANTATIONS_CENTRALES
= [15, 19]
42 class BaseAdmin(admin
.ModelAdmin
):
46 'css/admin_custom.css',
47 'jquery-autocomplete/jquery.autocomplete.css',
50 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js',
51 'jquery-autocomplete/jquery.autocomplete.min.js',
55 class OrderedChangeList(admin
.views
.main
.ChangeList
):
57 Surcharge pour appliquer le order_by d'un annotate
59 def get_query_set(self
):
60 qs
= super(OrderedChangeList
, self
).get_query_set()
61 qs
= qs
.order_by('-moyenne')
65 class OffreEmploiAdminMixin(BaseAdmin
):
66 date_hierarchy
= 'date_creation'
68 'nom', 'date_limite', 'region', 'statut', 'est_affiche',
71 exclude
= ('actif', 'poste_nom', 'resume',)
72 list_filter
= ('statut',)
73 actions
= ['affecter_evaluateurs_offre_emploi', ]
74 form
= OffreEmploiForm
94 ### Actions à afficher
95 def get_actions(self
, request
):
96 actions
= super(OffreEmploiAdminMixin
, self
).get_actions(request
)
97 del actions
['delete_selected']
100 ### Affecter un évaluateurs à des offres d'emploi
101 def affecter_evaluateurs_offre_emploi(modeladmin
, obj
, candidats
):
102 selected
= obj
.POST
.getlist(admin
.ACTION_CHECKBOX_NAME
)
104 return HttpResponseRedirect(
105 reverse('affecter_evaluateurs_offre_emploi') +
106 "?ids=%s" % (",".join(selected
))
109 affecter_evaluateurs_offre_emploi
.short_description
= \
110 u
'Affecter évaluateur(s)'
112 ### Afficher la liste des candidats pour l'offre d'emploi
113 def _candidatsList(self
, obj
):
114 return "<a href='%s?offre_emploi__id__exact=%s'>Voir les candidats \
115 </a>" % (reverse('admin:emploi_candidat_changelist'), obj
.id)
116 _candidatsList
.allow_tags
= True
117 _candidatsList
.short_description
= "Afficher la liste des candidats"
120 def get_form(self
, request
, obj
=None, **kwargs
):
121 form
= super(OffreEmploiAdminMixin
, self
).get_form(request
, obj
, **kwargs
)
122 employe
= get_emp(request
.user
)
123 user_groupes
= request
.user
.groups
.all()
126 if 'region' in form
.declared_fields
:
127 region_field
= form
.declared_fields
['region']
129 region_field
= form
.base_fields
['region']
131 if grp_drh
in user_groupes
or \
132 grp_drh2
in user_groupes
or \
133 grp_haute_direction
in user_groupes
:
134 region_field
.queryset
= Region
.objects
.all()
136 region_field
.queryset
= Region
.objects
.\
137 filter(id=employe
.implantation
.region
.id)
140 if 'poste' in form
.declared_fields
:
141 poste_field
= form
.declared_fields
['poste']
143 poste_field
= form
.base_fields
['poste']
145 if grp_drh
in user_groupes
or \
146 grp_drh2
in user_groupes
or \
147 grp_haute_direction
in user_groupes
:
148 poste_field
.queryset
= rh
.Poste
.objects
.all()
150 poste_field
.queryset
= rh
.Poste
.objects
.\
151 filter(implantation__region
=employe
.implantation
.region
).\
152 exclude(implantation__in
=IMPLANTATIONS_CENTRALES
)
155 if 'bureau' in form
.declared_fields
:
156 bureau_field
= form
.declared_fields
['bureau']
158 bureau_field
= form
.base_fields
['bureau']
160 if grp_drh
in user_groupes
or \
161 grp_drh2
in user_groupes
or \
162 grp_haute_direction
in user_groupes
:
163 bureau_field
.queryset
= Bureau
.objects
.all()
165 bureau_field
.queryset
= \
166 Bureau
.objects
.filter(region
=employe
.implantation
.region
)
172 def queryset(self
, request
):
173 qs
= self
.model
._default_manager
.get_query_set() \
174 .select_related('offre_emploi')
175 user_groupes
= request
.user
.groups
.all()
176 if grp_drh
in user_groupes
or \
177 grp_drh2
in user_groupes
or \
178 grp_haute_direction
in user_groupes
:
181 if grp_directeurs_bureau
in user_groupes
or \
182 grp_correspondants_rh
in user_groupes
or \
183 grp_administrateurs
in user_groupes
:
184 employe
= get_emp(request
.user
)
185 return qs
.filter(region
=employe
.implantation
.region
)
187 if Evaluateur
.objects
.filter(user
=request
.user
).exists():
188 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
190 e
.candidat
.offre_emploi_id
191 for e
in CandidatEvaluation
.objects
192 .select_related('candidat')
193 .filter(evaluateur
=evaluateur
)
195 return qs
.filter(id__in
=offre_ids
)
199 ### Permission add, delete, change
200 def has_add_permission(self
, request
):
201 user_groupes
= request
.user
.groups
.all()
202 if request
.user
.is_superuser
is True or \
203 grp_drh
in user_groupes
or \
204 grp_drh2
in user_groupes
or \
205 grp_directeurs_bureau
in user_groupes
or \
206 grp_administrateurs
in user_groupes
or \
207 grp_haute_direction
in user_groupes
:
211 def has_delete_permission(self
, request
, obj
=None):
212 user_groupes
= request
.user
.groups
.all()
213 if request
.user
.is_superuser
is True or \
214 grp_drh
in user_groupes
or \
215 grp_drh2
in user_groupes
or \
216 grp_directeurs_bureau
in user_groupes
or \
217 grp_administrateurs
in user_groupes
or \
218 grp_haute_direction
in user_groupes
:
222 def has_change_permission(self
, request
, obj
=None):
223 user_groupes
= request
.user
.groups
.all()
224 if request
.user
.is_superuser
is True or \
225 grp_drh
in user_groupes
or \
226 grp_drh2
in user_groupes
or \
227 grp_directeurs_bureau
in user_groupes
or \
228 grp_administrateurs
in user_groupes
or \
229 grp_haute_direction
in user_groupes
:
233 def formfield_for_foreignkey(self
, db_field
, request
, **kwargs
):
234 if db_field
.name
== 'lieu_affectation':
235 employe
= get_emp(request
.user
)
236 kwargs
["queryset"] = Implantation
.objects
.filter(region
=employe
.implantation
.region
)
237 return db_field
.formfield(**kwargs
)
238 return super(OffreEmploiAdminMixin
, self
).formfield_for_foreignkey(db_field
, request
, **kwargs
)
241 class OffreEmploiAdmin(VersionAdmin
, OffreEmploiAdminMixin
):
245 class ProxyOffreEmploiAdmin(OffreEmploiAdminMixin
):
247 'nom', 'date_limite', 'region', 'statut', 'est_affiche'
250 'description', 'bureau', 'duree_affectation', 'renumeration',
251 'debut_affectation', 'lieu_affectation', 'nom', 'resume',
252 'date_limite', 'region', 'poste'
258 ('Description générale', {
259 'fields': ('description', 'date_limite',)
262 'fields': ('lieu_affectation', 'bureau', 'region', 'poste',)
266 'debut_affectation', 'duree_affectation', 'renumeration',
272 ### Lieu de redirection après le change
273 def response_change(self
, request
, obj
):
274 return redirect('admin:recrutement_proxyoffreemploi_changelist')
277 def get_form(self
, request
, obj
=None, **kwargs
):
278 form
= super(OffreEmploiAdmin
, self
).get_form(request
, obj
, **kwargs
)
281 ### Permissions add, delete, change
282 def has_add_permission(self
, request
):
285 def has_delete_permission(self
, request
, obj
=None):
288 def has_change_permission(self
, request
, obj
=None):
292 return not super(ProxyOffreEmploiAdmin
, self
).has_change_permission(request
, obj
)
295 class CandidatPieceInline(admin
.TabularInline
):
296 model
= CandidatPiece
297 fields
= ('candidat', 'nom', 'path',)
302 class ReadOnlyCandidatPieceInline(CandidatPieceInline
):
303 readonly_fields
= ('candidat', 'nom', 'path', )
307 class CandidatEvaluationInlineFormSet(BaseInlineFormSet
):
309 Empêche la suppression d'une évaluation pour le CandidatEvaluationInline
311 def __init__(self
, *args
, **kwargs
):
312 super(CandidatEvaluationInlineFormSet
, self
).__init__(*args
, **kwargs
)
313 self
.can_delete
= False
316 class CandidatEvaluationInline(admin
.TabularInline
):
317 model
= CandidatEvaluation
318 fields
= ('evaluateur', 'note', 'commentaire')
321 formset
= CandidatEvaluationInlineFormSet
324 def get_readonly_fields(self
, request
, obj
=None):
326 Empêche la modification des évaluations
329 return self
.readonly_fields
+ ('evaluateur', 'note', 'commentaire')
330 return self
.readonly_fields
333 class CandidatAdminMixin(BaseAdmin
, ExportAdmin
):
334 change_list_template
= 'admin/recrutement/candidat/change_list.html'
335 search_fields
= ('nom', 'prenom')
336 exclude
= ('actif', )
337 list_editable
= ('statut', )
338 list_display
= ('_candidat', 'offre_emploi',
339 'voir_offre_emploi', 'calculer_moyenne',
340 'afficher_candidat', '_date_creation', 'statut', )
341 list_filter
= ('offre_emploi__nom', 'offre_emploi__region', 'statut', )
345 'fields': ('offre_emploi', )
347 ('Informations personnelles', {
349 'nom', 'prenom', 'genre', 'nationalite',
350 'situation_famille', 'nombre_dependant'
355 'telephone', 'email', 'adresse', 'ville', 'etat_province',
356 'code_postal', 'pays'
359 ('Informations professionnelles', {
361 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
362 'domaine_professionnel'
366 'fields': ('statut', )
371 CandidatEvaluationInline
,
373 actions
= ['envoyer_courriel_candidats', 'changer_statut']
375 export_fields
= ['statut', 'offre_emploi', 'prenom', 'nom', 'genre',
376 'nationalite', 'situation_famille', 'nombre_dependant',
377 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
378 'domaine_professionnel', 'telephone', 'email', 'adresse',
379 'ville', 'etat_province', 'code_postal', 'pays']
381 def _candidat(self
, obj
):
382 txt
= u
"%s %s (%s)" % (obj
.nom
.upper(), obj
.prenom
, obj
.genre
)
383 txt
= textwrap
.wrap(txt
, 30)
384 return "<br/>".join(txt
)
385 _candidat
.short_description
= "Candidat"
386 _candidat
.admin_order_field
= "nom"
387 _candidat
.allow_tags
= True
389 def _date_creation(self
, obj
):
390 return obj
.date_creation
391 _date_creation
.admin_order_field
= "date_creation"
392 _date_creation
.short_description
= "Date de réception"
394 ### Actions à afficher
395 def get_actions(self
, request
):
396 actions
= super(CandidatAdminMixin
, self
).get_actions(request
)
397 del actions
['delete_selected']
400 ### Envoyer un courriel à des candidats
401 def envoyer_courriel_candidats(modeladmin
, obj
, candidats
):
402 selected
= obj
.POST
.getlist(admin
.ACTION_CHECKBOX_NAME
)
404 return HttpResponseRedirect(
405 reverse('selectionner_template') + "?ids=%s" % (",".join(selected
))
407 envoyer_courriel_candidats
.short_description
= u
'Envoyer courriel'
409 ### Changer le statut à des candidats
410 def changer_statut(modeladmin
, request
, queryset
):
411 if request
.POST
.get('post'):
412 queryset
.update(statut
=request
.POST
.get('statut'))
416 'action_checkbox_name': admin
.helpers
.ACTION_CHECKBOX_NAME
,
417 'queryset': queryset
,
418 'status': STATUT_CHOICES
,
421 return render_to_response("recrutement/selectionner_statut.html",
422 context
, context_instance
= RequestContext(request
))
424 changer_statut
.short_description
= u
'Changer statut'
426 ### Évaluer un candidat
427 def evaluer_candidat(self
, obj
):
428 return "<a href='%s?candidat__id__exact=%s'>" \
429 "Évaluer le candidat</a>" % (
430 reverse('admin:recrutement_candidatevaluation_changelist'),
433 evaluer_candidat
.allow_tags
= True
434 evaluer_candidat
.short_description
= 'Évaluation'
436 ### Afficher un candidat
437 def afficher_candidat(self
, obj
):
438 items
= [u
"<li><a href='%s%s'>%s</li>" % \
439 (settings
.OE_PRIVE_MEDIA_URL
, pj
.path
, pj
.get_nom_display()) \
440 for pj
in obj
.pieces_jointes()]
441 html
= "<a href='%s'>Candidature</a>" % (
442 reverse('admin:recrutement_proxycandidat_change', args
=(obj
.id,))
444 return "%s<ul>%s</ul>" % (html
, "\n".join(items
))
445 afficher_candidat
.allow_tags
= True
446 afficher_candidat
.short_description
= u
'Détails du candidat'
448 ### Voir l'offre d'emploi
449 def voir_offre_emploi(self
, obj
):
450 return "<a href='%s'>Voir l'offre d'emploi</a>" % (reverse(
451 'admin:recrutement_proxyoffreemploi_change',
452 args
=(obj
.offre_emploi
.id,)
454 voir_offre_emploi
.allow_tags
= True
455 voir_offre_emploi
.short_description
= "Afficher l'offre d'emploi"
457 ### Calculer la moyenne des notes
458 def calculer_moyenne(self
, obj
):
459 evaluations
= CandidatEvaluation
.objects
.filter(candidat
=obj
)
461 notes
= [evaluation
.note
for evaluation
in evaluations \
462 if evaluation
.note
is not None]
465 moyenne_votes
= round(float(sum(notes
)) / len(notes
), 2)
467 moyenne_votes
= "Non disponible"
469 totales
= len(evaluations
)
472 if obj
.statut
== 'REC':
473 if totales
== faites
:
475 elif faites
> 0 and float(totales
) / float(faites
) >= 2:
482 return """<span style="color: %s;">%s (%s/%s)</span>""" % (
483 color
, moyenne_votes
, faites
, totales
485 calculer_moyenne
.allow_tags
= True
486 calculer_moyenne
.short_description
= "Moyenne"
487 calculer_moyenne
.admin_order_field
= ""
489 ### Permissions add, delete, change
490 def has_add_permission(self
, request
):
491 user_groupes
= request
.user
.groups
.all()
492 if request
.user
.is_superuser
is True or \
493 grp_correspondants_rh
in user_groupes
or \
494 grp_drh
in user_groupes
or \
495 grp_drh2
in user_groupes
or \
496 grp_directeurs_bureau
in user_groupes
or \
497 grp_administrateurs
in user_groupes
or \
498 grp_haute_direction
in user_groupes
:
502 def has_delete_permission(self
, request
, obj
=None):
503 user_groupes
= request
.user
.groups
.all()
504 if request
.user
.is_superuser
is True or \
505 grp_correspondants_rh
in user_groupes
or \
506 grp_drh
in user_groupes
or \
507 grp_drh2
in user_groupes
or \
508 grp_directeurs_bureau
in user_groupes
or \
509 grp_administrateurs
in user_groupes
or \
510 grp_haute_direction
in user_groupes
:
514 def has_change_permission(self
, request
, obj
=None):
515 user_groupes
= request
.user
.groups
.all()
516 if request
.user
.is_superuser
is True or \
517 grp_correspondants_rh
in user_groupes
or \
518 grp_drh
in user_groupes
or \
519 grp_drh2
in user_groupes
or \
520 grp_directeurs_bureau
in user_groupes
or \
521 grp_administrateurs
in user_groupes
or \
522 grp_haute_direction
in user_groupes
:
526 def formfield_for_foreignkey(self
, db_field
, request
, **kwargs
):
527 if db_field
.name
== 'offre_emploi':
528 employe
= get_emp(request
.user
)
529 kwargs
["queryset"] = OffreEmploi
.objects
.filter(region
=employe
.implantation
.region
)
530 return db_field
.formfield(**kwargs
)
531 return super(CandidatAdminMixin
, self
).formfield_for_foreignkey(db_field
, request
, **kwargs
)
533 def get_changelist(self
, request
, **kwargs
):
534 return OrderedChangeList
536 def queryset(self
, request
):
538 Spécifie un queryset limité, autrement Django exécute un
539 select_related() sans paramètre, ce qui a pour effet de charger tous
540 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
541 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
542 génération d'une requête infinie.
544 qs
= self
.model
._default_manager
.get_query_set() \
545 .select_related('offre_emploi') \
546 .annotate(moyenne
=Avg('evaluations__note'))
548 user_groupes
= request
.user
.groups
.all()
549 if grp_drh
in user_groupes
or \
550 grp_drh2
in user_groupes
or \
551 grp_haute_direction
in user_groupes
:
554 if grp_directeurs_bureau
in user_groupes
or \
555 grp_correspondants_rh
in user_groupes
or \
556 grp_administrateurs
in user_groupes
:
557 employe
= get_emp(request
.user
)
558 return qs
.filter(offre_emploi__region
=employe
.implantation
.region
)
560 if Evaluateur
.objects
.filter(user
=request
.user
).exists():
561 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
562 candidat_ids
= [e
.candidat
.id for e
in
563 CandidatEvaluation
.objects
.filter(evaluateur
=evaluateur
)]
564 return qs
.filter(id__in
=candidat_ids
)
568 class CandidatAdmin(VersionAdmin
, CandidatAdminMixin
):
572 class ProxyCandidatAdmin(CandidatAdminMixin
):
575 'statut', 'offre_emploi', 'prenom', 'nom', 'genre', 'nationalite',
576 'situation_famille', 'nombre_dependant', 'telephone', 'email',
577 'adresse', 'ville', 'etat_province', 'code_postal', 'pays',
578 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
579 'domaine_professionnel', 'pieces_jointes'
583 'fields': ('offre_emploi', )
585 ('Informations personnelles', {
587 'prenom', 'nom', 'genre', 'nationalite', 'situation_famille',
593 'telephone', 'email', 'adresse', 'ville', 'etat_province',
594 'code_postal', 'pays'
597 ('Informations professionnelles', {
599 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
600 'domaine_professionnel'
604 inlines
= (CandidatEvaluationInline
, )
606 def has_add_permission(self
, request
):
609 def has_delete_permission(self
, request
, obj
=None):
612 def has_change_permission(self
, request
, obj
=None):
614 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
615 for e
in obj
.evaluations
.all():
616 if e
.evaluateur
== evaluateur
:
619 return not super(ProxyCandidatAdmin
, self
).has_change_permission(request
, obj
)
621 def get_actions(self
, request
):
625 class CandidatPieceAdmin(admin
.ModelAdmin
):
626 list_display
= ('nom', 'candidat', )
629 def queryset(self
, request
):
631 Spécifie un queryset limité, autrement Django exécute un
632 select_related() sans paramètre, ce qui a pour effet de charger tous
633 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
634 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
635 génération d'une requête infinie. Affiche la liste de candidats que
636 si le user connecté possède un Evaluateur
638 qs
= self
.model
._default_manager
.get_query_set()
639 return qs
.select_related('candidat')
642 class EvaluateurAdmin(BaseAdmin
, VersionAdmin
):
649 ### Actions à afficher
650 def get_actions(self
, request
):
651 actions
= super(EvaluateurAdmin
, self
).get_actions(request
)
652 del actions
['delete_selected']
655 ### Permissions add, delete, change
656 def has_add_permission(self
, request
):
657 user_groupes
= request
.user
.groups
.all()
658 if request
.user
.is_superuser
is True or \
659 grp_drh
in user_groupes
or \
660 grp_drh2
in user_groupes
or \
661 grp_haute_direction
in user_groupes
:
665 def has_delete_permission(self
, request
, obj
=None):
666 user_groupes
= request
.user
.groups
.all()
667 if request
.user
.is_superuser
is True or \
668 grp_drh
in user_groupes
or \
669 grp_drh2
in user_groupes
or \
670 grp_haute_direction
in user_groupes
:
674 def has_change_permission(self
, request
, obj
=None):
675 user_groupes
= request
.user
.groups
.all()
676 if request
.user
.is_superuser
is True or \
677 grp_drh
in user_groupes
or \
678 grp_drh2
in user_groupes
or \
679 grp_haute_direction
in user_groupes
:
684 class CandidatEvaluationAdmin(BaseAdmin
):
685 search_fields
= ('candidat__nom', 'candidat__prenom')
687 '_candidat', '_statut', '_offre_emploi', 'evaluateur', '_note',
690 readonly_fields
= ('candidat', 'evaluateur')
691 list_filter
= ('candidat__statut', 'candidat__offre_emploi',)
693 ('Évaluation du candidat', {
694 'fields': ('candidat', 'evaluateur', 'note', 'commentaire', )
698 def get_actions(self
, request
):
699 # on stocke l'evaluateur connecté (pas forcément la meilleure place...)
701 self
.evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
703 self
.evaluateur
= None
705 actions
= super(CandidatEvaluationAdmin
, self
).get_actions(request
)
706 del actions
['delete_selected']
710 def _note(self
, obj
):
712 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
713 un lien pour Évaluer le candidat.
714 Sinon afficher la note.
716 page
= self
.model
.__name__
.lower()
717 redirect_url
= 'admin:recrutement_%s_change' % page
720 label
= "Candidat non évalué"
724 if self
.evaluateur
== obj
.evaluateur
:
725 return "<a href='%s'>%s</a>" % (
726 reverse(redirect_url
, args
=(obj
.id,)), label
730 _note
.allow_tags
= True
731 _note
.short_description
= "Note"
732 _note
.admin_order_field
= 'note'
734 def _statut(self
, obj
):
735 return obj
.candidat
.get_statut_display()
736 _statut
.order_field
= 'candidat__statut'
737 _statut
.short_description
= 'Statut'
739 ### Lien en lecture seule vers le candidat
740 def _candidat(self
, obj
):
741 return "<a href='%s'>%s</a>" \
742 % (reverse('admin:recrutement_proxycandidat_change',
743 args
=(obj
.candidat
.id,)), obj
.candidat
)
744 _candidat
.allow_tags
= True
745 _candidat
.short_description
= 'Candidat'
747 ### Afficher commentaire
748 def _commentaire(self
, obj
):
750 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
751 dans le champ commentaire, Aucun au lieu de (None)
752 Sinon afficher la note.
754 if obj
.commentaire
is None:
756 return obj
.commentaire
757 _commentaire
.allow_tags
= True
758 _commentaire
.short_description
= "Commentaire"
760 ### Afficher offre d'emploi
761 def _offre_emploi(self
, obj
):
762 return "<a href='%s'>%s</a>" % \
763 (reverse('admin:recrutement_proxyoffreemploi_change',
764 args
=(obj
.candidat
.offre_emploi
.id,)), obj
.candidat
.offre_emploi
)
765 _offre_emploi
.allow_tags
= True
766 _offre_emploi
.short_description
= "Voir offre d'emploi"
768 def has_add_permission(self
, request
):
771 def has_delete_permission(self
, request
, obj
=None):
774 def has_change_permission(self
, request
, obj
=None):
776 Permettre la visualisation dans la changelist
777 mais interdire l'accès à modifier l'objet si l'évaluateur n'est pas
780 user_groupes
= request
.user
.groups
.all()
782 if request
.user
.is_superuser
or \
783 grp_drh
in user_groupes
or \
784 grp_drh2
in user_groupes
or \
785 grp_correspondants_rh
in user_groupes
or \
786 grp_directeurs_bureau
in user_groupes
or \
787 grp_administrateurs
in user_groupes
or \
788 grp_haute_direction
in user_groupes
:
789 is_recrutement
= True
791 is_recrutement
= False
793 return is_recrutement
795 def queryset(self
, request
):
797 Afficher uniquement les évaluations de l'évaluateur, sauf si
798 l'utilisateur est dans les groupes suivants.
800 qs
= self
.model
._default_manager
.get_query_set() \
801 .select_related('offre_emploi')
802 user_groupes
= request
.user
.groups
.all()
804 if grp_drh
in user_groupes
or \
805 grp_drh2
in user_groupes
or \
806 grp_correspondants_rh
in user_groupes
or \
807 grp_directeurs_bureau
in user_groupes
or \
808 grp_administrateurs
in user_groupes
or \
809 grp_haute_direction
in user_groupes
:
810 return qs
.filter(candidat__statut__in
=('REC', 'SEL'))
812 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
813 candidats_evaluations
= \
814 CandidatEvaluation
.objects
.filter(evaluateur
=evaluateur
,
815 candidat__statut__in
=('REC', ))
816 candidats_evaluations_ids
= [ce
.id for ce
in candidats_evaluations
]
817 return qs
.filter(id__in
=candidats_evaluations_ids
)
820 class MesCandidatEvaluationAdmin(CandidatEvaluationAdmin
):
823 def has_change_permission(self
, request
, obj
=None):
825 Evaluateur
.objects
.get(user
=request
.user
)
828 is_evaluateur
= False
830 if obj
is None and is_evaluateur
:
834 return request
.user
== obj
.evaluateur
.user
838 def queryset(self
, request
):
839 qs
= self
.model
._default_manager
.get_query_set() \
840 .select_related('offre_emploi')
841 evaluateur
= Evaluateur
.objects
.get(user
=request
.user
)
842 candidats_evaluations
= \
843 CandidatEvaluation
.objects
.filter(evaluateur
=evaluateur
,
844 candidat__statut__in
=('REC', ))
845 candidats_evaluations_ids
= [ce
.id for ce
in candidats_evaluations
]
846 return qs
.filter(id__in
=candidats_evaluations_ids
)
849 class CourrielTemplateAdmin(BaseAdmin
, VersionAdmin
):
850 ### Actions à afficher
851 def get_actions(self
, request
):
852 actions
= super(CourrielTemplateAdmin
, self
).get_actions(request
)
853 del actions
['delete_selected']
856 admin
.site
.register(OffreEmploi
, OffreEmploiAdmin
)
857 admin
.site
.register(ProxyOffreEmploi
, ProxyOffreEmploiAdmin
)
858 admin
.site
.register(Candidat
, CandidatAdmin
)
859 admin
.site
.register(ProxyCandidat
, ProxyCandidatAdmin
)
860 admin
.site
.register(CandidatEvaluation
, CandidatEvaluationAdmin
)
861 admin
.site
.register(MesCandidatEvaluation
, MesCandidatEvaluationAdmin
)
862 admin
.site
.register(Evaluateur
, EvaluateurAdmin
)
863 admin
.site
.register(CourrielTemplate
, CourrielTemplateAdmin
)