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