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