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