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