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