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