Commit | Line | Data |
---|---|---|
df59fcab | 1 | # -*- encoding: utf-8 -*- |
2 | ||
6067184b | 3 | from django.core.urlresolvers import reverse |
4 | from django.http import HttpResponseRedirect | |
df59fcab | 5 | from django.contrib import admin |
38df74bb | 6 | from django.shortcuts import get_object_or_404 |
7 | ||
6067184b | 8 | from reversion.admin import VersionAdmin |
38df74bb | 9 | from datamaster_modeles.models import Employe, Implantation, Region |
6067184b | 10 | |
df59fcab | 11 | from recrutement.models import * |
f6724c20 NBV |
12 | from recrutement.workflow import grp_administrateurs_recrutement,\ |
13 | grp_evaluateurs_recrutement, grp_drh_recrutement | |
df59fcab | 14 | |
d2b30f5f | 15 | class OffreEmploiAdmin(VersionAdmin): |
7f9e891e | 16 | date_hierarchy = 'date_creation' |
ec517164 | 17 | list_display = ('nom', 'resume', 'date_limite', 'region', '_candidatsList') |
f6724c20 | 18 | |
8941aee7 | 19 | # Afficher la liste des candidats pour l'offre d'emploi |
596fe324 | 20 | def _candidatsList(self, obj): |
8ea41642 | 21 | return "<a href='%s?offre_emploi__id__exact=%s'>Voir les candidats \ |
22 | </a>" % (reverse('admin:recrutement_candidat_changelist'), obj.id) | |
2f78949d | 23 | _candidatsList.allow_tags = True |
f6724c20 | 24 | _candidatsList.short_description = "Afficher la liste des candidats" |
362a3534 | 25 | |
2f78949d | 26 | def queryset(self, request): |
2f78949d | 27 | qs = self.model._default_manager.get_query_set() |
f6724c20 NBV |
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 | # Si le user n'est ni un évaluateur ni un administrateur régional, | |
32 | # retourner none | |
33 | # Vérifier groupes | |
34 | if grp_evaluateurs_recrutement in user_groupes: | |
35 | user = Evaluateur.objects.get(user=request.user) | |
36 | elif grp_administrateurs_recrutement in user_groupes: | |
37 | user = AdministrateurRegional.objects.get(user=request.user) | |
38 | else: | |
39 | return qs.none() | |
40 | ||
41 | if type(user) is AdministrateurRegional: | |
42 | region_ids = [g.id for g in user.regions.all()] | |
43 | return qs.select_related('offre_emploi').\ | |
44 | filter(region__in=region_ids) | |
45 | if type(user) is Evaluateur: | |
46 | ||
47 | candidats = [g for g in user.candidats.all()] | |
48 | offre_emploi_ids = [offre.id for offre in candidats] | |
49 | return qs.select_related('offre_emploi').\ | |
50 | filter(id__in=offre_emploi_ids) | |
51 | ||
3bcef02d | 52 | return qs.none() |
f6724c20 NBV |
53 | return qs.select_related('offre_emploi') |
54 | ||
55 | def has_change_permission(self, request, obj=None): | |
56 | user_groupes = request.user.groups.all() | |
57 | if grp_drh_recrutement in user_groupes or \ | |
58 | grp_administrateurs_recrutement in user_groupes: | |
59 | return True | |
60 | return False | |
61 | ||
62 | class ProxyOffreEmploiAdmin(OffreEmploiAdmin): | |
63 | list_display = ('nom', 'resume', 'date_limite', 'region', '_candidatsList', ) | |
64 | readonly_fields = ('actif', 'description', 'poste', 'bureau', | |
65 | 'duree_affectation', 'renumeration', | |
66 | 'debut_affectation', 'lieu_affectation', 'nom', | |
67 | 'resume', 'date_limite', 'region') | |
68 | fieldsets = ( | |
69 | (None, { | |
70 | 'fields': ('nom', ) | |
71 | }), | |
72 | (None, { | |
73 | 'fields': ('poste', 'resume','description', 'date_limite', ) | |
74 | }), | |
75 | (None, { | |
76 | 'fields': ('lieu_affectation', 'bureau', 'region', ) | |
77 | }), | |
78 | (None, { | |
79 | 'fields': ('debut_affectation', 'duree_affectation', | |
80 | 'renumeration', ) | |
81 | }), | |
82 | ) | |
83 | def has_add_permission(self, request): | |
84 | return False | |
85 | ||
86 | def has_delete_permission(self, request, obj=None): | |
87 | return False | |
88 | ||
2d083449 NBV |
89 | def has_change_permission(self, request, obj=None): |
90 | user_groupes = request.user.groups.all() | |
91 | if grp_evaluateurs_recrutement in user_groupes: | |
92 | return True | |
93 | return False | |
94 | ||
f6724c20 NBV |
95 | def _candidatsList(self, obj): |
96 | return "<a href='%s?offre_emploi__id__exact=%s'>Voir les candidats \ | |
97 | </a>" % (reverse('admin:recrutement_proxycandidat_changelist'), | |
98 | obj.id) | |
99 | _candidatsList.allow_tags = True | |
100 | _candidatsList.short_description = "Afficher la liste des candidats" | |
362a3534 | 101 | |
cced6a23 | 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" | |
74cbc7a7 | 110 | verbose_name_plural = "pièces jointes" |
cced6a23 | 111 | |
170c9aa2 | 112 | class CandidatPieceInline(admin.TabularInline): |
cced6a23 | 113 | model = ProxyCandidatPiece |
114 | fields = ('candidat', 'nom', 'path', ) | |
170c9aa2 | 115 | extra = 1 |
116 | ||
27c81d11 | 117 | class ProxyEvaluateur(Evaluateur.candidats.through): |
cced6a23 | 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 | ||
eb579d40 | 126 | class EvaluateurInline(admin.TabularInline): |
cced6a23 | 127 | model = ProxyEvaluateur |
eb579d40 | 128 | extra = 1 |
129 | ||
d2b30f5f | 130 | class CandidatAdmin(VersionAdmin): |
7f9e891e | 131 | date_hierarchy = 'date_creation' |
0fd8a26d | 132 | list_display = ('nom', 'prenom', 'offre_emploi','statut', |
8941aee7 | 133 | 'voir_offre_emploi', 'evaluer_candidat', #'note_evaluateur', |
134 | 'calculer_moyenne', 'afficher_candidat',) | |
8ea41642 | 135 | list_filter = ('offre_emploi', ) |
7f9e891e | 136 | fieldsets = ( |
4896b661 | 137 | ("Offre d'emploi", { |
138 | 'fields': ('offre_emploi', ) | |
139 | }), | |
7f9e891e | 140 | ('Informations personnelles', { |
141 | 'fields': ('prenom','nom','genre', 'nationalite', 'date_naissance', | |
142 | 'situation_famille', 'nombre_dependant',) | |
143 | }), | |
ec517164 | 144 | ('Coordonnées', { |
145 | 'fields': ('telephone', 'email', 'adresse', 'ville', | |
146 | 'etat_province', 'code_postal', 'pays', ) | |
7f9e891e | 147 | }), |
148 | ('Informations professionnelles', { | |
4896b661 | 149 | 'fields': ('niveau_diplome','employeur_actuel', |
8ea41642 | 150 | 'poste_actuel', 'domaine_professionnel',) |
7f9e891e | 151 | }), |
152 | ('Options avancées', { | |
153 | 'classes': ('collapse',), | |
154 | 'fields': ('actif', 'statut', ) | |
155 | }), | |
156 | ) | |
170c9aa2 | 157 | inlines = [ |
158 | CandidatPieceInline, | |
eb579d40 | 159 | EvaluateurInline, |
170c9aa2 | 160 | ] |
f9983b5a | 161 | |
4e8340cf | 162 | actions = ['affecter_candidats_evaluateur', 'envoyer_courriel_candidats'] |
362a3534 | 163 | # Affecter un évaluateurs à des candidats |
7061f835 | 164 | def affecter_candidats_evaluateur(modeladmin, obj, candidats): |
596fe324 | 165 | selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME) |
2adf9e0c | 166 | |
8ea41642 | 167 | return HttpResponseRedirect(reverse('affecter_evaluateurs_candidats')+ |
168 | "?ids=%s" % (",".join(selected))) | |
d835c9f3 | 169 | affecter_candidats_evaluateur.short_description = u'Affecter évaluateur' |
362a3534 | 170 | |
4e8340cf | 171 | # Envoyer un courriel à des candidats |
52765380 | 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 | ||
05503d56 | 179 | # Évaluer un candidat |
596fe324 | 180 | def evaluer_candidat(self, obj): |
8ea41642 | 181 | return "<a href='%s?id=%s'>Évaluer le candidat \ |
182 | </a>" % (reverse('evaluer_candidat'), obj.id) | |
596fe324 | 183 | evaluer_candidat.allow_tags = True |
d835c9f3 | 184 | evaluer_candidat.short_description = 'Évaluer' |
596fe324 | 185 | |
7d82fd33 | 186 | # Afficher un candidat |
187 | def afficher_candidat(self, obj): | |
188 | return "<a href='%s?id=%s'>Voir le candidat \ | |
f6724c20 | 189 | </a>" % (reverse('recrutement_proxycandidat_change'), obj.id) |
7d82fd33 | 190 | afficher_candidat.allow_tags = True |
f6724c20 | 191 | afficher_candidat.short_description = u'Afficher les détails du candidat' |
7d82fd33 | 192 | |
8941aee7 | 193 | # Voir l'offre d'emploi |
194 | def voir_offre_emploi(self, obj): | |
195 | return "<a href='%s?id=%s'>Voir l'offre d'emploi</a> \ | |
196 | " % (reverse('admin:recrutement_offreemploi_changelist'), | |
197 | obj.offre_emploi.id) | |
198 | voir_offre_emploi.allow_tags = True | |
199 | voir_offre_emploi.short_description = "Afficher l'offre d'emploi" | |
200 | ||
201 | """ # Afficher note poster par l'évaluateur | |
202 | def note_evaluateur(self, obj): | |
203 | import pdb;pdb.set_trace() | |
27c81d11 | 204 | evaluateur = Evaluateur.objects.get(user=obj.user) |
8941aee7 | 205 | import pdb;pdb.set_trace() |
206 | note_eval = CandidatEvaluation.objects.filter(evaluateur=evaluateur, | |
207 | candidat=obj.user) | |
208 | return "blabla" | |
209 | note_evaluateur.allow_tags = True | |
210 | note_evaluateur.short_description = "Votre note" | |
211 | """ | |
212 | ||
213 | # Calculer la moyenne des notes | |
214 | def calculer_moyenne(self, obj): | |
215 | evaluations = CandidatEvaluation.objects.filter(candidat=obj) | |
216 | offre_emploi = obj.offre_emploi | |
217 | ||
f6724c20 NBV |
218 | notes = [evaluation.note for evaluation in evaluations.all() \ |
219 | if evaluation.note is not None] | |
8941aee7 | 220 | |
221 | if len(notes) > 0 and offre_emploi.date_limite <= datetime.date.today(): | |
222 | moyenne_votes = float(sum(notes)) / len(notes) | |
223 | else: | |
224 | moyenne_votes = "Non disponible" | |
225 | return moyenne_votes | |
226 | calculer_moyenne.allow_tags = True | |
227 | calculer_moyenne.short_description = "Moyenne des notes" | |
228 | ||
f6724c20 NBV |
229 | def add_delete_permission(self, request, obj=None) : |
230 | user_groupes = request.user.groups.all() | |
231 | if grp_drh_recrutement in user_groupes or \ | |
232 | grp_administrateurs_recrutement in user_groupes: | |
233 | return True | |
234 | return False | |
4896b661 | 235 | |
f6724c20 NBV |
236 | def has_add_permission(self, request): |
237 | return self.add_delete_permission(request, request) | |
4896b661 | 238 | |
f6724c20 NBV |
239 | def has_delete_permission(self, request, obj=None): |
240 | return self.add_delete_permission(request, request) | |
241 | ||
242 | def has_change_permission(self, request, obj=None): | |
243 | user_groupes = request.user.groups.all() | |
244 | if grp_drh_recrutement in user_groupes or \ | |
2d083449 | 245 | grp_administrateurs_recrutement in user_groupes: |
f6724c20 NBV |
246 | return True |
247 | return False | |
4896b661 | 248 | |
596fe324 | 249 | def queryset(self, obj): |
f9983b5a | 250 | """ |
8ea41642 | 251 | Spécifie un queryset limité, autrement Django exécute un |
252 | select_related() sans paramètre, ce qui a pour effet de charger tous | |
253 | les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les | |
254 | modèles de Region, il existe plusieurs boucles, ce qui conduit à la | |
255 | génération d'une requête infinie. | |
d835c9f3 | 256 | |
f9983b5a | 257 | """ |
f6724c20 NBV |
258 | qs = self.model._default_manager.get_query_set() |
259 | # Si user est superuser afficher tous les candidats | |
260 | user_groupes = obj.user.groups.all() | |
261 | if not grp_drh_recrutement in user_groupes: | |
262 | # Si le user n'est ni un évaluateur ni un administrateur régional, | |
263 | # retourner none | |
264 | ||
265 | # Vérifier groupes | |
266 | if grp_evaluateurs_recrutement in user_groupes: | |
267 | user = Evaluateur.objects.get(user=obj.user) | |
268 | #elif grp_administrateurs_recrutement in user_groupes: | |
269 | # user = AdministrateurRegional.objects.get(user=obj.user) | |
270 | else: | |
271 | return qs.none() | |
272 | ||
273 | ids = [c.id for c in user.candidats.all()] | |
274 | return qs.select_related('candidats').filter(id__in=ids) | |
275 | return qs.select_related('candidats') | |
276 | ||
277 | class ProxyCandidatAdmin(CandidatAdmin): | |
278 | #TODO: init boucler sur les fields pour le readonly | |
279 | list_display = ('nom', 'prenom', 'offre_emploi','statut', | |
2d083449 NBV |
280 | 'voir_offre_emploi', 'evaluer_candidat', #'note_evaluateur', |
281 | 'calculer_moyenne',) | |
f6724c20 NBV |
282 | readonly_fields = ('statut', 'offre_emploi', 'prenom', 'nom', |
283 | 'genre', 'nationalite', 'date_naissance', | |
284 | 'situation_famille', 'nombre_dependant', 'telephone', | |
285 | 'email', 'adresse', 'ville', 'etat_province', | |
286 | 'code_postal', 'pays', 'niveau_diplome', | |
287 | 'employeur_actuel', 'poste_actuel', | |
288 | 'domaine_professionnel',) | |
2d083449 NBV |
289 | fieldsets = ( |
290 | ("Offre d'emploi", { | |
291 | 'fields': ('offre_emploi', ) | |
292 | }), | |
293 | ('Informations personnelles', { | |
294 | 'fields': ('prenom','nom','genre', 'nationalite', 'date_naissance', | |
295 | 'situation_famille', 'nombre_dependant',) | |
296 | }), | |
297 | ('Coordonnées', { | |
298 | 'fields': ('telephone', 'email', 'adresse', 'ville', | |
299 | 'etat_province', 'code_postal', 'pays', ) | |
300 | }), | |
301 | ('Informations professionnelles', { | |
302 | 'fields': ('niveau_diplome','employeur_actuel', | |
303 | 'poste_actuel', 'domaine_professionnel',) | |
304 | }), | |
305 | ) | |
f6724c20 | 306 | inlines = [] |
2d083449 | 307 | |
f6724c20 NBV |
308 | def has_add_permission(self, request): |
309 | return False | |
310 | ||
311 | def has_delete_permission(self, request, obj=None): | |
312 | return False | |
2adf9e0c | 313 | |
2d083449 NBV |
314 | def has_change_permission(self, request, obj=None): |
315 | user_groupes = request.user.groups.all() | |
316 | if grp_evaluateurs_recrutement in user_groupes: | |
317 | return True | |
318 | return False | |
319 | ||
f6724c20 NBV |
320 | def voir_offre_emploi(self, obj): |
321 | return "<a href='%s?id=%s'>Voir l'offre d'emploi</a> \ | |
322 | " % (reverse('admin:recrutement_proxyoffreemploi_changelist'), | |
323 | obj.offre_emploi.id) | |
324 | voir_offre_emploi.allow_tags = True | |
325 | voir_offre_emploi.short_description = "Afficher l'offre d'emploi" | |
df59fcab | 326 | |
2e9ee615 | 327 | class CandidatPieceAdmin(admin.ModelAdmin): |
170c9aa2 | 328 | list_display = ('nom', 'candidat', ) |
329 | ||
330 | def queryset(self, request): | |
331 | """ | |
332 | Spécifie un queryset limité, autrement Django exécute un | |
333 | select_related() sans paramètre, ce qui a pour effet de charger tous | |
334 | les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les | |
335 | modèles de Region, il existe plusieurs boucles, ce qui conduit à la | |
336 | génération d'une requête infinie. | |
d835c9f3 | 337 | Affiche la liste de candidats que si le user connecté |
27c81d11 | 338 | possède un Evaluateur |
170c9aa2 | 339 | """ |
340 | qs = self.model._default_manager.get_query_set() | |
341 | return qs.select_related('candidat') | |
2e9ee615 | 342 | |
d2b30f5f | 343 | class EvaluateurAdmin(VersionAdmin): |
eb579d40 | 344 | fieldsets = ( |
f6724c20 | 345 | (None, {'fields': ('user', )}), |
eb579d40 | 346 | (None, {'fields': ('candidats',)}), |
347 | ) | |
4418c732 | 348 | |
f6724c20 | 349 | # Peut-être qu'on peut enlever cette def, à cause des permissions |
d835c9f3 | 350 | def queryset(self, request): |
351 | """ | |
352 | Affiche la liste d'évaluateur que si le user connecté | |
27c81d11 | 353 | possède un Evaluateur |
d835c9f3 | 354 | """ |
f6724c20 NBV |
355 | user_groupes = obj.user.groups.all() |
356 | if grp_drh_recrutement in user_groupes: | |
357 | return self.model._default_manager.get_query_set() | |
358 | ||
359 | return qs.none() | |
d835c9f3 | 360 | |
b89fef74 | 361 | class AdministrateurRegionalAdmin(VersionAdmin): |
27c81d11 | 362 | pass |
363 | ||
d2b30f5f | 364 | class CandidatEvaluationAdmin(VersionAdmin): |
596fe324 | 365 | list_display = ('candidat', 'evaluateur', 'note', 'commentaire', 'date', ) |
366 | ||
4e8340cf | 367 | class CourrielTemplateAdmin(VersionAdmin): |
368 | pass | |
369 | ||
df59fcab | 370 | admin.site.register(OffreEmploi, OffreEmploiAdmin) |
371 | admin.site.register(Candidat, CandidatAdmin) | |
4e8340cf | 372 | admin.site.register(CourrielTemplate, CourrielTemplateAdmin) |
27c81d11 | 373 | admin.site.register(Evaluateur, EvaluateurAdmin) |
b89fef74 | 374 | admin.site.register(AdministrateurRegional, AdministrateurRegionalAdmin) |
f6724c20 NBV |
375 | admin.site.register(ProxyOffreEmploi, ProxyOffreEmploiAdmin) |
376 | admin.site.register(ProxyCandidat, ProxyCandidatAdmin) |