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