Retrait de la vue evaluer_candidat
[auf_rh_dae.git] / project / recrutement / admin.py
1 # -*- encoding: utf-8 -*-
2
3 from django.core.urlresolvers import reverse
4 from django.http import HttpResponseRedirect
5 from django.contrib import admin
6 from django.shortcuts import get_object_or_404
7
8 from reversion.admin import VersionAdmin
9 from datamaster_modeles.models import Employe, Implantation, Region
10
11 from recrutement.models import *
12 from recrutement.workflow import grp_administrateurs_recrutement,\
13 grp_evaluateurs_recrutement, grp_drh_recrutement
14
15 class OffreEmploiAdmin(VersionAdmin):
16 date_hierarchy = 'date_creation'
17 list_display = ('nom', 'resume', 'date_limite', 'region', '_candidatsList')
18
19 # Afficher la liste des candidats pour l'offre d'emploi
20 def _candidatsList(self, obj):
21 return "<a href='%s?offre_emploi__id__exact=%s'>Voir les candidats \
22 </a>" % (reverse('admin:recrutement_candidat_changelist'), obj.id)
23 _candidatsList.allow_tags = True
24 _candidatsList.short_description = "Afficher la liste des candidats"
25
26 def queryset(self, request):
27 qs = self.model._default_manager.get_query_set()
28 # Si user est superuser afficher toutes les offres d'emploi
29 user_groupes = request.user.groups.all()
30 if not grp_drh_recrutement in user_groupes:
31 """
32 Si le user n'est ni un évaluateur ni un administrateur régional,
33 retourner none
34 Vérifier groupes
35 """
36 if grp_evaluateurs_recrutement in user_groupes:
37 try:
38 user = Evaluateur.objects.get(user=request.user)
39 except Evaluateur.DoesNotExist:
40 return qs.none()
41 elif grp_administrateurs_recrutement in user_groupes:
42 try:
43 user = AdministrateurRegional.objects.get(user=request.user)
44 except AdministrateurRegional.DoesNotExist:
45 return qs.none()
46 else:
47 return qs.none()
48
49 if type(user) is AdministrateurRegional:
50 region_ids = [g.id for g in user.regions.all()]
51 return qs.select_related('offre_emploi').\
52 filter(region__in=region_ids)
53 if type(user) is Evaluateur:
54 candidats = [g for g in user.candidats.all()]
55 offre_emploi_ids = [c.offre_emploi.id for c in candidats]
56 return qs.select_related('offre_emploi').\
57 filter(id__in=offre_emploi_ids)
58 return qs.none()
59 return qs.select_related('offre_emploi')
60
61 def has_change_permission(self, request, obj=None):
62 user_groupes = request.user.groups.all()
63 if grp_drh_recrutement in user_groupes or \
64 grp_administrateurs_recrutement in user_groupes:
65 return True
66 return False
67
68 class ProxyOffreEmploiAdmin(OffreEmploiAdmin):
69 list_display = ('nom', 'resume', 'date_limite', 'region', )
70 readonly_fields = ('description', 'poste', 'bureau',
71 'duree_affectation', 'renumeration',
72 'debut_affectation', 'lieu_affectation', 'nom',
73 'resume', 'date_limite', 'region')
74 fieldsets = (
75 ('Nom', {
76 'fields': ('nom', )
77 }),
78 ('Description générale', {
79 'fields': ('poste', 'resume','description', 'date_limite', )
80 }),
81 ('Coordonnées', {
82 'fields': ('lieu_affectation', 'bureau', 'region', )
83 }),
84 ('Autre', {
85 'fields': ('debut_affectation', 'duree_affectation',
86 'renumeration', )
87 }),
88 )
89 def has_add_permission(self, request):
90 return False
91
92 def has_delete_permission(self, request, obj=None):
93 return False
94
95 def has_change_permission(self, request, obj=None):
96 user_groupes = request.user.groups.all()
97 if grp_evaluateurs_recrutement in user_groupes or \
98 grp_drh_recrutement in user_groupes:
99 return True
100 return False
101
102 class ProxyCandidatPiece(CandidatPiece):
103 """
104 Ce proxy sert uniquement dans l'admin à disposer d'un libellé
105 plus ergonomique.
106 """
107 class Meta:
108 proxy = True
109 verbose_name = "pièce jointe"
110 verbose_name_plural = "pièces jointes"
111
112 class CandidatPieceInline(admin.TabularInline):
113 model = ProxyCandidatPiece
114 fields = ('candidat', 'nom', 'path', )
115 extra = 1
116
117 class ProxyEvaluateur(Evaluateur.candidats.through):
118 """
119 Ce proxy sert uniquement dans l'admin à disposer d'un libellé
120 plus ergonomique.
121 """
122 class Meta:
123 proxy = True
124 verbose_name = "évaluateur"
125
126 class EvaluateurInline(admin.TabularInline):
127 model = ProxyEvaluateur
128 fields = ('evaluateur',)
129 extra = 1
130
131 class CandidatAdmin(VersionAdmin):
132 date_hierarchy = 'date_creation'
133 list_display = ('nom', 'prenom', 'offre_emploi','statut',
134 'voir_offre_emploi', #'note_evaluateur',
135 'calculer_moyenne', 'afficher_candidat',)
136 list_filter = ('offre_emploi', )
137 fieldsets = (
138 ("Offre d'emploi", {
139 'fields': ('offre_emploi', )
140 }),
141 ('Informations personnelles', {
142 'fields': ('prenom','nom','genre', 'nationalite', 'date_naissance',
143 'situation_famille', 'nombre_dependant',)
144 }),
145 ('Coordonnées', {
146 'fields': ('telephone', 'email', 'adresse', 'ville',
147 'etat_province', 'code_postal', 'pays', )
148 }),
149 ('Informations professionnelles', {
150 'fields': ('niveau_diplome','employeur_actuel',
151 'poste_actuel', 'domaine_professionnel',)
152 }),
153 ('Traitement', {
154 'fields': ('statut', )
155 }),
156 )
157 inlines = [
158 CandidatPieceInline,
159 EvaluateurInline,
160 ]
161
162 actions = ['affecter_candidats_evaluateur', 'envoyer_courriel_candidats']
163 # Affecter un évaluateurs à des candidats
164 def affecter_candidats_evaluateur(modeladmin, obj, candidats):
165 selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
166
167 return HttpResponseRedirect(reverse('affecter_evaluateurs_candidats')+
168 "?ids=%s" % (",".join(selected)))
169 affecter_candidats_evaluateur.short_description = u'Affecter évaluateur'
170
171 # Envoyer un courriel à des candidats
172 def envoyer_courriel_candidats(modeladmin, obj, candidats):
173 selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
174
175 return HttpResponseRedirect(reverse('envoyer_courriel_candidats')+
176 "?ids=%s" % (",".join(selected)))
177 envoyer_courriel_candidats.short_description = u'Envoyer courriel'
178
179 # Évaluer un candidat
180 def evaluer_candidat(self, obj):
181 return "<a href='%s?candidat__id__exact=%s'>Évaluer le candidat </a>" % \
182 (reverse('admin:recrutement_candidatevaluation_changelist'),
183 obj.id)
184 evaluer_candidat.allow_tags = True
185 evaluer_candidat.short_description = 'Évaluation'
186
187 # Afficher un candidat
188 def afficher_candidat(self, obj):
189 return "<a href='%s'>Voir le candidat</a>" % \
190 (reverse('admin:recrutement_proxycandidat_change', args=(obj.id,)))
191 afficher_candidat.allow_tags = True
192 afficher_candidat.short_description = u'Afficher les détails du candidat'
193
194 # Voir l'offre d'emploi
195 def voir_offre_emploi(self, obj):
196 return "<a href='%s'>Voir l'offre d'emploi</a>" % \
197 (reverse('admin:recrutement_proxyoffreemploi_change',
198 args=(obj.offre_emploi.id,)))
199 voir_offre_emploi.allow_tags = True
200 voir_offre_emploi.short_description = "Afficher l'offre d'emploi"
201
202 # Calculer la moyenne des notes
203 def calculer_moyenne(self, obj):
204 evaluations = CandidatEvaluation.objects.filter(candidat=obj)
205 offre_emploi = obj.offre_emploi
206
207 notes = [evaluation.note for evaluation in evaluations.all() \
208 if evaluation.note is not None]
209
210 if len(notes) > 0 and offre_emploi.date_limite <= datetime.date.today():
211 moyenne_votes = float(sum(notes)) / len(notes)
212 else:
213 moyenne_votes = "Non disponible"
214 return moyenne_votes
215 calculer_moyenne.allow_tags = True
216 calculer_moyenne.short_description = "Moyenne des notes"
217
218 def add_delete_permission(self, request, obj=None) :
219 user_groupes = request.user.groups.all()
220 if grp_drh_recrutement in user_groupes or \
221 grp_administrateurs_recrutement in user_groupes:
222 return True
223 return False
224
225 def has_add_permission(self, request):
226 return self.add_delete_permission(request, request)
227
228 def has_delete_permission(self, request, obj=None):
229 return self.add_delete_permission(request, request)
230
231 def has_change_permission(self, request, obj=None):
232 user_groupes = request.user.groups.all()
233 if grp_drh_recrutement in user_groupes or \
234 grp_administrateurs_recrutement in user_groupes:
235 return True
236 return False
237
238 def queryset(self, obj):
239 """
240 Spécifie un queryset limité, autrement Django exécute un
241 select_related() sans paramètre, ce qui a pour effet de charger tous
242 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
243 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
244 génération d'une requête infinie.
245
246 """
247 qs = self.model._default_manager.get_query_set()
248 # Si user est superuser afficher tous les candidats
249 user_groupes = obj.user.groups.all()
250 if not grp_drh_recrutement in user_groupes:
251 # Si le user n'est ni un évaluateur ni un administrateur régional,
252 # retourner none
253
254 # Vérifier groupes
255 if grp_evaluateurs_recrutement in user_groupes:
256 try:
257 user = Evaluateur.objects.get(user=obj.user)
258 except Evaluateur.DoesNotExist:
259 return qs.none()
260 """
261 elif grp_administrateurs_recrutement in user_groupes:
262 try:
263 user = AdministrateurRegional.objects.get(user=obj.user)
264 except AdministrateurRegional.DoesNotExist:
265 return qs.none()
266 """
267 else:
268 return qs.none()
269 ids = [c.id for c in user.candidats.all()]
270 return qs.select_related('candidats').filter(id__in=ids)
271 return qs.select_related('candidats')
272
273 class ProxyCandidatAdmin(CandidatAdmin):
274 readonly_fields = ('statut', 'offre_emploi', 'prenom', 'nom',
275 'genre', 'nationalite', 'date_naissance',
276 'situation_famille', 'nombre_dependant', 'telephone',
277 'email', 'adresse', 'ville', 'etat_province',
278 'code_postal', 'pays', 'niveau_diplome',
279 'employeur_actuel', 'poste_actuel',
280 'domaine_professionnel',)
281 fieldsets = (
282 ("Offre d'emploi", {
283 'fields': ('offre_emploi', )
284 }),
285 ('Informations personnelles', {
286 'fields': ('prenom','nom','genre', 'nationalite', 'date_naissance',
287 'situation_famille', 'nombre_dependant',)
288 }),
289 ('Coordonnées', {
290 'fields': ('telephone', 'email', 'adresse', 'ville',
291 'etat_province', 'code_postal', 'pays', )
292 }),
293 ('Informations professionnelles', {
294 'fields': ('niveau_diplome','employeur_actuel',
295 'poste_actuel', 'domaine_professionnel',)
296 }),
297 )
298 inlines = []
299
300 def has_add_permission(self, request):
301 return False
302
303 def has_delete_permission(self, request, obj=None):
304 return False
305
306 def has_change_permission(self, request, obj=None):
307 user_groupes = request.user.groups.all()
308 if grp_drh_recrutement in user_groupes or \
309 grp_administrateurs_recrutement in user_groupes or \
310 grp_evaluateurs_recrutement in user_groupes:
311 return True
312 return False
313
314 class CandidatPieceAdmin(admin.ModelAdmin):
315 list_display = ('nom', 'candidat', )
316
317 def queryset(self, request):
318 """
319 Spécifie un queryset limité, autrement Django exécute un
320 select_related() sans paramètre, ce qui a pour effet de charger tous
321 les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
322 modèles de Region, il existe plusieurs boucles, ce qui conduit à la
323 génération d'une requête infinie.
324 Affiche la liste de candidats que si le user connecté
325 possède un Evaluateur
326 """
327 qs = self.model._default_manager.get_query_set()
328 return qs.select_related('candidat')
329
330 class EvaluateurAdmin(VersionAdmin):
331 fieldsets = (
332 (None, {'fields': ('user', )}),
333 #(None, {'fields': ('candidats',)}),
334 )
335
336 class AdministrateurRegionalAdmin(VersionAdmin):
337 pass
338
339 class CandidatEvaluationAdmin(VersionAdmin):
340 list_display = ('_offre_emploi', '_candidat', '_note', '_commentaire',
341 'evaluateur',)
342 readonly_fields = ('candidat', 'evaluateur')
343 fieldsets = (
344 ('Évaluation du candidat', {
345 'fields': ('candidat', 'evaluateur', 'note', 'commentaire', )
346 }),
347 )
348
349 def _note(self, obj):
350 """
351 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
352 un lien pour Évaluer le candidat.
353 Sinon afficher la note.
354 """
355 if obj.note is None:
356 return "<a href='%s'>Évaluer le candidat </a>" % \
357 (reverse('admin:recrutement_candidatevaluation_change',
358 args=(obj.candidat.id,)))
359 return obj.note
360 _note.allow_tags = True
361 _note.short_description = "Votre note"
362 _note.admin_order_field = 'note'
363
364 def _candidat(self, obj):
365 return "<a href='%s'>%s</a>" \
366 % (reverse('admin:recrutement_proxycandidat_change',
367 args=(obj.candidat.id,)), obj.candidat)
368 _candidat.allow_tags = True
369 _candidat.short_description = 'Candidat'
370
371 def _commentaire(self, obj):
372 """
373 Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
374 dans le champ commentaire, Aucun au lieu de (None)
375 Sinon afficher la note.
376 """
377 if obj.commentaire is None:
378 return "Aucun"
379 return obj.commentaire
380 _commentaire.allow_tags = True
381 _commentaire.short_description = "Commentaire"
382
383
384 def _offre_emploi(self, obj):
385 return "<a href='%s'>%s</a>" % \
386 (reverse('admin:recrutement_proxyoffreemploi_change',
387 args=(obj.candidat.offre_emploi.id,)), obj.candidat.offre_emploi)
388 _offre_emploi.allow_tags = True
389 _offre_emploi.short_description = "Voir offre d'emploi"
390 _offre_emploi.admin_order_field = 'offre_emploi'
391
392 def queryset(self, request):
393 """
394 Afficher uniquement les évaluations de l'évaluateur, sauf si
395 l'utilisateur est super admin.
396 """
397 qs = self.model._default_manager.get_query_set()
398 user_groupes = request.user.groups.all()
399 if grp_drh_recrutement in user_groupes:
400 return qs.select_related('offre_emploi')
401
402 try:
403 evaluateur = Evaluateur.objects.get(user=request.user)
404 except Evaluateur.DoesNotExist:
405 return qs.none()
406
407 candidats_evaluations = CandidatEvaluation.objects.\
408 filter(evaluateur=evaluateur)
409 candidats_evaluations_ids = [ce.id for ce in \
410 candidats_evaluations.all()]
411 return qs.select_related('offre_emploi').\
412 filter(id__in=candidats_evaluations_ids)
413
414 class CourrielTemplateAdmin(VersionAdmin):
415 pass
416
417 admin.site.register(OffreEmploi, OffreEmploiAdmin)
418 admin.site.register(ProxyOffreEmploi, ProxyOffreEmploiAdmin)
419 admin.site.register(Candidat, CandidatAdmin)
420 admin.site.register(ProxyCandidat, ProxyCandidatAdmin)
421 admin.site.register(CandidatEvaluation, CandidatEvaluationAdmin)
422 admin.site.register(Evaluateur, EvaluateurAdmin)
423 #admin.site.register(AdministrateurRegional, AdministrateurRegionalAdmin)
424 #admin.site.register(CourrielTemplate, CourrielTemplateAdmin)