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