Commit | Line | Data |
---|---|---|
e9bbd6ba | 1 | # -*- encoding: utf-8 -*- |
22343fe7 | 2 | |
e90b19fd | 3 | import urllib |
c9122f1d | 4 | from datetime import date |
a7de62d7 | 5 | from itertools import izip |
eabb27fd | 6 | import StringIO |
9b0a8554 | 7 | |
9f55f18a | 8 | import pygraphviz as pgv |
e949324b | 9 | |
4ba84959 EMS |
10 | from django import forms |
11 | from django.conf import settings | |
12 | from django.contrib.auth.decorators import login_required | |
13 | from django.core.servers.basehttp import FileWrapper | |
dcd1b959 | 14 | from django.core.urlresolvers import reverse |
fbe60a9d | 15 | from django.db.models import Q |
4ba84959 | 16 | from django.http import HttpResponse |
22343fe7 | 17 | from django.shortcuts import render_to_response, get_object_or_404 |
e9bbd6ba | 18 | from django.template import RequestContext |
4ba84959 | 19 | from django.utils.encoding import smart_str |
a9faef67 | 20 | |
75f0e87b | 21 | from datamaster_modeles import models as ref |
e9bbd6ba | 22 | |
4ba84959 EMS |
23 | from project.rh import models as rh |
24 | from project.rh.lib import calc_remun | |
25 | from project.rh.decorators import drh_or_admin_required | |
26 | from project.rh.templatetags.rapports import SortHeaders | |
27 | from project.rh.change_list import RechercheTemporelle | |
28 | from project.rh import graph as rh_graph | |
29 | from project.rh.masse_salariale import MasseSalariale | |
9817fed5 | 30 | |
9817fed5 | 31 | # pas de reference a DAE devrait etre refactorisé |
75f0e87b DB |
32 | from project.dae.utils import get_employe_from_user |
33 | from project.dae.decorators import redirect_interdiction | |
34 | from project.dae.workflow import grp_drh, grp_correspondants_rh | |
22343fe7 | 35 | |
22343fe7 | 36 | |
c9122f1d | 37 | @login_required |
38 | def profil(request): | |
39 | """Profil personnel de l'employé - éditable""" | |
40 | rc = RequestContext(request) | |
41 | c = {} | |
22343fe7 | 42 | |
c9122f1d | 43 | employe = rc['this_employe'] |
22343fe7 | 44 | |
c9122f1d | 45 | c['user'] = request.user |
46 | c['employe'] = employe | |
c9122f1d | 47 | return render_to_response('rh/profil.html', c, rc) |
22343fe7 OL |
48 | |
49 | ||
3411ac33 | 50 | @login_required |
a9faef67 | 51 | def employes_liste(request): |
52 | """Liste des employés.""" | |
5ea6b5bb | 53 | today = date.today() |
54 | employes = rh.Employe.objects \ | |
5ea6b5bb | 55 | .exclude(dossiers__date_debut__gt=today) \ |
56 | .exclude(dossiers__date_fin__lt=today) \ | |
57 | .order_by('nom') | |
a9faef67 | 58 | c = { |
22343fe7 OL |
59 | 'user': request.user, |
60 | 'employes': employes, | |
a9faef67 | 61 | } |
22343fe7 OL |
62 | return render_to_response('rh/employes_liste.html', |
63 | c, | |
64 | RequestContext(request)) | |
65 | ||
66 | ||
3411ac33 | 67 | @login_required |
a9faef67 | 68 | def employe(request, id): |
69 | """Information publique sur un employé.""" | |
70 | try: | |
71 | employe = rh.Employe.objects.get(pk=id) | |
72 | except: | |
73 | employe = rh.Employe.objects.none() | |
74 | c = { | |
22343fe7 OL |
75 | 'user': request.user, |
76 | 'employe': employe, | |
a9faef67 | 77 | } |
78 | return render_to_response('rh/employe.html', c, RequestContext(request)) | |
63e17dff PP |
79 | |
80 | ||
08faf06e JPC |
81 | @login_required |
82 | @drh_or_admin_required | |
63e17dff PP |
83 | def rapports_poste(request): |
84 | ||
fd009814 PP |
85 | lookup_params = dict(request.GET.items()) |
86 | ||
87 | for key, value in lookup_params.items(): | |
9d53bc73 JPC |
88 | if key == 'o' or key == 'ot': |
89 | del lookup_params[key] | |
90 | continue | |
fd009814 PP |
91 | if not isinstance(key, str): |
92 | # 'key' will be used as a keyword argument later, so Python | |
93 | # requires it to be a string. | |
94 | del lookup_params[key] | |
95 | lookup_params[smart_str(key)] = value | |
96 | ||
7821915f | 97 | if key == 'comble': |
7821915f PP |
98 | del lookup_params[key] |
99 | ||
00ca4d9f EMS |
100 | sort_order = 'ASC' if request.GET.get('ot') == 'asc' else 'DESC' |
101 | ||
ed3cbb32 | 102 | postes = rh.Poste.objects.select_related('implantation') \ |
00ca4d9f EMS |
103 | .extra(select={ |
104 | 'employe_id': | |
105 | 'SELECT GROUP_CONCAT(employe SEPARATOR "|") ' | |
106 | 'FROM rh_dossier ' | |
107 | 'WHERE poste = rh_poste.id ' | |
108 | 'AND rh_dossier.date_fin IS NULL ' + ( | |
109 | 'ORDER BY employe ' + sort_order | |
110 | if request.GET.get('o') == 'employe_id' else '' | |
111 | ) | |
9202c5db | 112 | }) \ |
00ca4d9f EMS |
113 | .extra(select={ |
114 | 'employe_nom': | |
115 | 'SELECT GROUP_CONCAT(rh_employe.nom SEPARATOR "|") ' | |
116 | 'FROM rh_dossier INNER JOIN rh_employe ' | |
117 | 'ON rh_dossier.employe = rh_employe.id ' | |
118 | 'WHERE poste = rh_poste.id ' | |
119 | 'AND rh_dossier.date_fin IS NULL ' + ( | |
120 | 'ORDER BY rh_employe.nom ' + sort_order | |
121 | if request.GET.get('o') == 'employe_nom' else '' | |
122 | ) | |
9202c5db | 123 | }) \ |
00ca4d9f EMS |
124 | .extra(select={ |
125 | 'employe_prenom': | |
126 | 'SELECT GROUP_CONCAT(rh_employe.prenom SEPARATOR "|") ' | |
127 | 'FROM rh_dossier INNER JOIN rh_employe ' | |
128 | 'ON rh_dossier.employe = rh_employe.id ' | |
129 | 'WHERE poste = rh_poste.id ' | |
130 | 'AND rh_dossier.date_fin IS NULL ' + ( | |
131 | 'ORDER BY rh_employe.prenom ' + sort_order | |
132 | if request.GET.get('o') == 'employe_prenom' else '' | |
133 | ) | |
9202c5db | 134 | }) |
9d53bc73 | 135 | |
65e02621 | 136 | postes = postes.filter(**lookup_params) |
9d53bc73 | 137 | if 'o' in request.GET: |
00ca4d9f EMS |
138 | postes = postes.order_by( |
139 | ('-' if sort_order == "DESC" else '') + request.GET['o'] | |
140 | ) | |
65e02621 | 141 | |
a7de62d7 JPC |
142 | out = [] |
143 | for p in postes: | |
144 | out.append({ | |
145 | 'id': p.id, | |
146 | 'nom': p.nom, | |
147 | 'implantation': p.implantation, | |
00ca4d9f EMS |
148 | 'employes': [] if not p.employe_id else [ |
149 | {'id': id, 'nom': nom, 'prenom': prenom} | |
150 | for id, nom, prenom in izip( | |
151 | p.employe_id.split('|'), | |
152 | p.employe_nom.split('|'), | |
153 | p.employe_prenom.split('|') | |
154 | ) | |
155 | ] | |
156 | }) | |
a7de62d7 | 157 | |
4dade240 JPC |
158 | headers = [ |
159 | ("id", u"# du poste"), | |
160 | ("nom", u"Nom du poste"), | |
65e02621 | 161 | ("implantation__id", u"Implantation"), |
4dade240 | 162 | ("employe_nom", u"Nom"), |
4dade240 JPC |
163 | ] |
164 | h = SortHeaders(request, headers, order_field_type="ot", order_field="o") | |
63e17dff PP |
165 | c = { |
166 | 'title': 'Rapport des postes', | |
a7de62d7 JPC |
167 | 'postes': out, |
168 | 'count': len(out), | |
65e02621 | 169 | 'headers': list(h.headers()), |
63e17dff PP |
170 | } |
171 | ||
00ca4d9f EMS |
172 | return render_to_response( |
173 | 'rh/rapports/postes.html', c, RequestContext(request) | |
174 | ) | |
175 | ||
f2d65e83 | 176 | |
02c1b3dc JPC |
177 | @login_required |
178 | @drh_or_admin_required | |
f2d65e83 | 179 | def rapports_contrat(request): |
dcd1b959 OL |
180 | if 'HTTP_REFERER' in request.META.keys(): |
181 | referer = request.META['HTTP_REFERER'] | |
182 | referer = "/".join(referer.split('/')[3:]) | |
183 | referer = "/%s" % referer.split('?')[0] | |
184 | if referer != reverse('rhr_contrats'): | |
185 | params = request.GET.copy() | |
186 | params.update({'statut': 'Actif'}) | |
187 | request.GET = params | |
f2d65e83 PP |
188 | |
189 | lookup_params = dict(request.GET.items()) | |
65e02621 JPC |
190 | if 'ot' in lookup_params: |
191 | del lookup_params['ot'] | |
192 | if 'o' in lookup_params: | |
193 | del lookup_params['o'] | |
f2d65e83 PP |
194 | |
195 | for key, value in lookup_params.items(): | |
196 | if not isinstance(key, str): | |
197 | # 'key' will be used as a keyword argument later, so Python | |
198 | # requires it to be a string. | |
199 | del lookup_params[key] | |
200 | lookup_params[smart_str(key)] = value | |
201 | ||
00ca4d9f EMS |
202 | contrats = rh.Contrat.objects.select_related( |
203 | 'dossier', 'dossier__poste', 'dossier__poste__implantation', | |
204 | 'type_contrat', 'dossier__employe' | |
205 | ) | |
22343fe7 | 206 | |
6bee05ff | 207 | cl = RechercheTemporelle(dict(request.GET.items()), rh.Contrat) |
f0f6b03e | 208 | lookup_params = cl.purge_params(lookup_params) |
dcd1b959 OL |
209 | q_temporel = cl.get_q_temporel(contrats) |
210 | q = Q(**lookup_params) & q_temporel | |
211 | contrats = contrats.filter(q).exclude(dossier__employe__supprime=1) | |
f0f6b03e | 212 | |
65e02621 | 213 | if 'o' in request.GET: |
00ca4d9f EMS |
214 | contrats = contrats.order_by( |
215 | ('-' if request.GET.get('ot') == "desc" else '') + request.GET['o'] | |
216 | ) | |
f2d65e83 | 217 | |
8ee135b7 JPC |
218 | employes = set([c.dossier.employe_id for c in contrats]) |
219 | ||
65e02621 JPC |
220 | headers = [ |
221 | ("dossier__employe__id", u"# de l'employé"), | |
d50a5e5d | 222 | ("dossier__employe__nom", u"Employé"), |
65e02621 | 223 | ("type_contrat__nom", u"Poste"), |
d50a5e5d OL |
224 | ("dossier__poste__implantation__region", u"Région"), |
225 | ("dossier__poste__implantation", u"Implantation"), | |
65e02621 JPC |
226 | ("type_contrat__nom", u"Type de contrat"), |
227 | ("date_debut", u"Date début"), | |
228 | ("date_fin", u"Date fin"), | |
229 | ] | |
230 | h = SortHeaders(request, headers, order_field_type="ot", order_field="o") | |
231 | ||
f2d65e83 | 232 | c = { |
00ca4d9f | 233 | 'cl': cl, |
f2d65e83 PP |
234 | 'title': 'Rapport des contrats', |
235 | 'contrats': contrats, | |
8ee135b7 | 236 | 'count': len(contrats), |
00ca4d9f | 237 | 'count_employe': len(employes), |
65e02621 | 238 | 'headers': list(h.headers()), |
f2d65e83 PP |
239 | } |
240 | ||
00ca4d9f EMS |
241 | return render_to_response( |
242 | 'rh/rapports/contrats.html', c, RequestContext(request) | |
243 | ) | |
e2c0b1ac PP |
244 | |
245 | ||
02c1b3dc JPC |
246 | @login_required |
247 | @drh_or_admin_required | |
98d6eb6c | 248 | def rapports_masse_salariale(request): |
df37184c | 249 | |
e90b19fd | 250 | class RechercheTemporelle(forms.Form): |
aecb222b | 251 | CHOICE_ANNEES = range( |
00ca4d9f EMS |
252 | rh.Remuneration.objects.exclude(date_debut=None) |
253 | .order_by('date_debut')[0].date_debut.year, | |
254 | date.today().year + 1 | |
255 | ) | |
256 | ||
257 | annee = forms.CharField( | |
258 | initial=date.today().year, | |
259 | widget=forms.Select( | |
260 | choices=((a, a) for a in reversed(CHOICE_ANNEES)) | |
261 | ) | |
444f3223 | 262 | ) |
aecb222b | 263 | |
48c0abfe JPC |
264 | region = forms.CharField( |
265 | widget=forms.Select(choices=[('', '')] + | |
266 | [(i.id, i) for i in ref.Region.objects.all()] | |
267 | ) | |
268 | ) | |
269 | ||
270 | implantation = forms.CharField( | |
271 | widget=forms.Select(choices=[('', '')] + | |
272 | [(i.id, i) for i in ref.Implantation.objects.all()] | |
273 | ) | |
274 | ) | |
275 | ||
aecb222b JPC |
276 | #date_debut = forms.DateField(widget=adminwidgets.AdminDateWidget) |
277 | #date_fin = forms.DateField(widget=adminwidgets.AdminDateWidget) | |
e90b19fd | 278 | |
e90b19fd | 279 | form = RechercheTemporelle(request.GET) |
00ca4d9f EMS |
280 | get_filtre = [ |
281 | (k, v) for k, v in request.GET.items() | |
282 | if k not in ('date_debut', 'date_fin', 'implantation') | |
283 | ] | |
e90b19fd OL |
284 | query_string = urllib.urlencode(get_filtre) |
285 | ||
aecb222b JPC |
286 | date_debut = None |
287 | date_fin = None | |
444f3223 JPC |
288 | if request.GET.get('annee', None): |
289 | date_debut = "01-01-%s" % request.GET.get('annee', None) | |
290 | date_fin = "31-12-%s" % request.GET.get('annee', None) | |
df37184c | 291 | |
48c0abfe JPC |
292 | implantation = request.GET.get('implantation') |
293 | region = request.GET.get('region') | |
df37184c JPC |
294 | |
295 | custom_filter = {} | |
296 | if implantation: | |
297 | custom_filter['dossier__poste__implantation'] = implantation | |
298 | if region: | |
299 | custom_filter['dossier__poste__implantation__region'] = region | |
300 | ||
df37184c | 301 | c = { |
e90b19fd OL |
302 | 'title': 'Rapport de masse salariale', |
303 | 'form': form, | |
df37184c | 304 | 'headers': [], |
e90b19fd | 305 | 'query_string': query_string, |
df37184c | 306 | } |
22b53270 | 307 | if date_debut or date_fin: |
c99116c3 JPC |
308 | masse = MasseSalariale(date_debut, date_fin, custom_filter, |
309 | request.GET.get('ne_pas_grouper', False)) | |
515b83c3 | 310 | if masse.rapport: |
eabb27fd | 311 | if request.GET.get('ods'): |
00ca4d9f EMS |
312 | for h in ( |
313 | h for h in masse.headers if 'background-color' in h[2] | |
314 | ): | |
eabb27fd JPC |
315 | del h[2]['background-color'] |
316 | masse.ods() | |
317 | output = StringIO.StringIO() | |
318 | masse.doc.save(output) | |
319 | output.seek(0) | |
320 | ||
00ca4d9f EMS |
321 | response = HttpResponse( |
322 | FileWrapper(output), | |
323 | content_type=( | |
324 | 'application/vnd.oasis.opendocument.spreadsheet' | |
325 | ) | |
326 | ) | |
eabb27fd JPC |
327 | response['Content-Disposition'] = \ |
328 | 'attachment; filename=Masse Salariale %s.ods' % \ | |
329 | masse.annee | |
330 | return response | |
331 | else: | |
332 | c['rapport'] = masse.rapport | |
333 | c['header_keys'] = [h[0] for h in masse.headers] | |
334 | #on enleve le background pour le header | |
00ca4d9f EMS |
335 | for h in ( |
336 | h for h in masse.headers if 'background-color' in h[2] | |
337 | ): | |
eabb27fd JPC |
338 | h[2]['background'] = 'none' |
339 | h = SortHeaders(request, masse.headers, order_field_type="ot", | |
340 | not_sortable=c['header_keys'], order_field="o") | |
341 | c['headers'] = list(h.headers()) | |
342 | for key, nom, opts in masse.headers: | |
343 | c['headers'] | |
344 | c['total'] = masse.grand_totaux[0] | |
345 | c['total_euro'] = masse.grand_totaux[1] | |
346 | c['colspan'] = len(c['header_keys']) - 1 | |
347 | get_filtre.append(('ods', True)) | |
348 | query_string = urllib.urlencode(get_filtre) | |
349 | c['url_ods'] = "%s?%s" % ( | |
350 | reverse('rhr_masse_salariale'), query_string) | |
22b53270 | 351 | |
00ca4d9f EMS |
352 | return render_to_response( |
353 | 'rh/rapports/masse_salariale.html', c, RequestContext(request) | |
354 | ) | |
98d6eb6c JPC |
355 | |
356 | ||
357 | @login_required | |
358 | @drh_or_admin_required | |
e2c0b1ac PP |
359 | def rapports_remuneration(request): |
360 | ||
361 | lookup_params = dict(request.GET.items()) | |
9202c5db JPC |
362 | if 'ot' in lookup_params: |
363 | del lookup_params['ot'] | |
364 | if 'o' in lookup_params: | |
365 | del lookup_params['o'] | |
e2c0b1ac PP |
366 | |
367 | for key, value in lookup_params.items(): | |
368 | if not isinstance(key, str): | |
369 | # 'key' will be used as a keyword argument later, so Python | |
370 | # requires it to be a string. | |
371 | del lookup_params[key] | |
372 | lookup_params[smart_str(key)] = value | |
373 | ||
374 | employes = rh.Employe.objects.all() | |
9202c5db | 375 | if 'o' in request.GET: |
00ca4d9f EMS |
376 | employes = employes.order_by( |
377 | ('-' if request.GET.get('ot') == "desc" else '') + request.GET['o'] | |
378 | ) | |
9202c5db | 379 | |
e2c0b1ac PP |
380 | employes = employes.filter(**lookup_params) |
381 | ||
382 | output = [] | |
9202c5db JPC |
383 | headers = [ |
384 | ("id", u"# de l'employé"), | |
385 | ("nom", u"Nom"), | |
386 | ("prenom", u"Prénom"), | |
387 | ("", u"Salaire"), | |
388 | ("", u"RAS"), | |
389 | ("", u"Indemnités"), | |
390 | ("", u"Accessoire"), | |
391 | ("", u"Charges patronales"), | |
392 | ("", u"Total"), | |
393 | ] | |
394 | h = SortHeaders(request, headers, order_field_type="ot", order_field="o") | |
e2c0b1ac PP |
395 | |
396 | for employe in employes: | |
397 | line = {} | |
398 | output.append(line) | |
399 | ||
da6c523f | 400 | dossiers = employe.rh_dossiers.all() |
e2c0b1ac PP |
401 | |
402 | remun = {} | |
403 | remun_sum_euro = 0 | |
404 | ||
405 | for dossier in dossiers: | |
00ca4d9f EMS |
406 | this_remun, this_remun_sum, this_remun_sum_euro = \ |
407 | calc_remun(dossier) | |
e2c0b1ac PP |
408 | |
409 | for item in this_remun: | |
410 | if item not in remun: | |
411 | remun[item] = this_remun[item] | |
412 | else: | |
413 | remun[item][0] += this_remun[item][0] | |
414 | remun[item][1] += this_remun[item][1] | |
415 | ||
416 | remun_sum_euro += this_remun_sum_euro | |
417 | ||
418 | line['remun_sum_euro'] = remun_sum_euro | |
419 | ||
420 | for r in remun: | |
421 | if r == u'Indemnité': | |
e2c0b1ac PP |
422 | line['Indemnite'] = remun[r][1] |
423 | else: | |
424 | line[r] = remun[r][1] | |
425 | ||
426 | line['id'] = employe.id | |
427 | line['nom'] = employe.nom | |
428 | line['prenom'] = employe.prenom | |
429 | ||
e2c0b1ac PP |
430 | c = { |
431 | 'title': 'Rapport de remuneration', | |
432 | 'employes': output, | |
9202c5db | 433 | 'headers': list(h.headers()), |
e2c0b1ac PP |
434 | } |
435 | ||
00ca4d9f EMS |
436 | return render_to_response( |
437 | 'rh/rapports/remuneration.html', c, RequestContext(request) | |
438 | ) | |
439 | ||
3ebc0952 | 440 | |
783e077a JPC |
441 | @login_required |
442 | @drh_or_admin_required | |
c8b22fd1 JPC |
443 | def rapports_employe_sans_contrat(request): |
444 | ||
445 | lookup_params = dict(request.GET.items()) | |
446 | if 'ot' in lookup_params: | |
447 | del lookup_params['ot'] | |
448 | if 'o' in lookup_params: | |
449 | del lookup_params['o'] | |
450 | ||
451 | for key, value in lookup_params.items(): | |
452 | if not isinstance(key, str): | |
453 | # 'key' will be used as a keyword argument later, so Python | |
454 | # requires it to be a string. | |
455 | del lookup_params[key] | |
456 | lookup_params[smart_str(key)] = value | |
457 | ||
458 | employes_query = rh.Employe.objects | |
459 | if 'o' in request.GET: | |
00ca4d9f EMS |
460 | employes_query = employes_query.order_by( |
461 | ('-' if request.GET.get('ot') == "desc" else '') + request.GET['o'] | |
462 | ) | |
c8b22fd1 | 463 | |
7c5645f0 | 464 | employes = {} |
22343fe7 | 465 | |
00ca4d9f EMS |
466 | dossiers_en_cours = rh.Dossier.objects.filter( |
467 | Q(date_fin=None) | Q(date_fin__gt=date.today()) | |
468 | ) | |
469 | tous_contrats_echus = rh.Contrat.objects.filter( | |
470 | date_fin__lt=date.today(), dossier__in=dossiers_en_cours | |
471 | ) | |
00c9d7c2 OL |
472 | contrats = tous_contrats_echus.filter(**lookup_params).all() |
473 | for c in contrats: | |
474 | if c.dossier.employe.id not in employes.keys(): | |
00ca4d9f EMS |
475 | employes[c.dossier.employe.id] = { |
476 | 'employe': c.dossier.employe, | |
477 | 'dossiers': [] | |
478 | } | |
479 | employes[c.dossier.employe.id]['dossiers'] += [c.dossier] | |
c8b22fd1 JPC |
480 | |
481 | headers = [ | |
1d2d4dc2 JPC |
482 | ("id", u"# de l'employé"), |
483 | ("nom", u"Nom"), | |
484 | ("prenom", u"Prénom"), | |
80518280 | 485 | ("dossier", u"Dossiers"), |
c8b22fd1 | 486 | ] |
00ca4d9f EMS |
487 | h = SortHeaders( |
488 | request, headers, order_field_type="ot", order_field="o", | |
489 | not_sortable=('dossier',) | |
490 | ) | |
c8b22fd1 JPC |
491 | |
492 | c = { | |
493 | 'title': u'Rapport des employés sans contrat', | |
494 | 'employes': employes, | |
495 | 'count': len(employes), | |
496 | 'headers': list(h.headers()), | |
497 | } | |
498 | ||
00ca4d9f EMS |
499 | return render_to_response( |
500 | 'rh/rapports/employes_sans_contrat.html', c, RequestContext(request) | |
501 | ) | |
502 | ||
c8b22fd1 JPC |
503 | |
504 | @login_required | |
505 | @drh_or_admin_required | |
857b5c24 JPC |
506 | def rapports_postes_modelisation(request): |
507 | c = {} | |
508 | data = [] | |
3c1ba807 | 509 | |
7bf28694 EMS |
510 | for categorie in rh.CategorieEmploi.objects.all(): |
511 | types = rh.TypePoste.objects.filter(categorie_emploi=categorie) | |
3c1ba807 JPC |
512 | data_types = [] |
513 | for t in types.all(): | |
514 | postes = rh.Poste.objects.filter(type_poste=t) | |
515 | data_types.append({ | |
516 | 'num_postes': postes.count(), | |
517 | 'postes': postes.all(), | |
7bf28694 | 518 | 'type': categorie, |
857b5c24 | 519 | }) |
3c1ba807 | 520 | |
857b5c24 | 521 | data.append({ |
7bf28694 | 522 | 'categorie': categorie, |
3c1ba807 | 523 | 'nb_types': types.count(), |
00ca4d9f EMS |
524 | 'types': data_types |
525 | }) | |
857b5c24 JPC |
526 | |
527 | c['data'] = data | |
528 | ||
00ca4d9f EMS |
529 | return render_to_response( |
530 | 'rh/rapports/postes_modelisation.html', c, RequestContext(request) | |
531 | ) | |
857b5c24 JPC |
532 | |
533 | ||
534 | @login_required | |
535 | @drh_or_admin_required | |
783e077a JPC |
536 | def rapports_postes_implantation(request): |
537 | c = {} | |
538 | data = [] | |
539 | for r in ref.Region.objects.all(): | |
540 | implantations = [] | |
541 | for i in ref.Implantation.objects.filter(region=r): | |
542 | implantations.append({ | |
543 | 'implantation': i, | |
544 | 'postes': rh.Poste.objects.filter(implantation=i), | |
545 | 'num_postes': rh.Poste.objects.filter(implantation=i).count(), | |
546 | }) | |
547 | data.append({ | |
548 | 'region': r, | |
549 | 'implantations': implantations | |
550 | }) | |
551 | ||
552 | c['data'] = data | |
553 | ||
00ca4d9f EMS |
554 | return render_to_response( |
555 | 'rh/rapports/postes_implantation.html', c, RequestContext(request) | |
556 | ) | |
783e077a JPC |
557 | |
558 | ||
559 | @login_required | |
560 | @drh_or_admin_required | |
561 | def rapports_postes_service(request): | |
562 | c = {} | |
9988aafb JPC |
563 | data = [] |
564 | for s in rh.Service.objects.all(): | |
565 | postes = rh.Poste.objects.filter(service=s).all() | |
566 | num_postes = rh.Poste.objects.filter(service=s).count() | |
22343fe7 | 567 | data.append({'service': s, 'num_postes': num_postes, 'postes': postes}) |
783e077a | 568 | |
9988aafb | 569 | c['data'] = data |
00ca4d9f EMS |
570 | return render_to_response( |
571 | 'rh/rapports/postes_service.html', c, RequestContext(request) | |
572 | ) | |
783e077a JPC |
573 | |
574 | ||
32373f2e OL |
575 | def region_protected(model): |
576 | def wrapper(func): | |
577 | def wrapped(request, id): | |
32373f2e OL |
578 | if request.user.is_superuser: |
579 | return func(request, id) | |
580 | user_groups = request.user.groups.all() | |
581 | if grp_drh in user_groups: | |
582 | return func(request, id) | |
583 | if grp_correspondants_rh in user_groups: | |
584 | employe = get_employe_from_user(request.user) | |
00ca4d9f EMS |
585 | q = Q(**{ |
586 | model.prefix_implantation: employe.implantation.region | |
587 | }) | |
32373f2e | 588 | qs = model.objects.filter(q) |
718abc4d | 589 | if int(id) in [o.id for o in qs]: |
32373f2e OL |
590 | return func(request, id) |
591 | return redirect_interdiction(request) | |
592 | return wrapped | |
593 | return wrapper | |
594 | ||
595 | ||
596 | @region_protected(rh.Dossier) | |
3ebc0952 | 597 | def dossier_apercu(request, dossier_id): |
baf9b78c | 598 | d = get_object_or_404(rh.Dossier, pk=dossier_id) |
3ebc0952 | 599 | c = { |
838bc59d | 600 | 'title': u"Dossier %s" % (d, ), |
00ca4d9f EMS |
601 | 'is_popup': request.GET.get('_popup', False), |
602 | 'dossier': d, | |
603 | 'pieces': rh.DossierPiece.objects.filter(dossier__exact=d), | |
604 | 'contrats': rh.Contrat.objects.filter(dossier__exact=d), | |
605 | 'commentaires': rh.DossierCommentaire.objects.filter(dossier=d).all(), | |
abf91905 | 606 | 'media_url': settings.PRIVE_MEDIA_URL, |
3ebc0952 | 607 | } |
00ca4d9f EMS |
608 | return render_to_response( |
609 | 'admin/rh/dossier/apercu.html', c, RequestContext(request) | |
610 | ) | |
611 | ||
4a1f2ece | 612 | |
fbe60a9d OL |
613 | @region_protected(rh.Poste) |
614 | def poste_apercu(request, poste_id): | |
c8cb18e3 | 615 | p = get_object_or_404(rh.Poste, pk=poste_id) |
fbe60a9d | 616 | c = { |
c8cb18e3 | 617 | 'title': u"Poste %s" % (p, ), |
00ca4d9f EMS |
618 | 'is_popup': request.GET.get('_popup', False), |
619 | 'poste': p, | |
620 | 'financements': ( | |
621 | rh.PosteFinancement.objects.filter(poste=poste_id).all() | |
622 | ), | |
623 | 'pieces': rh.PostePiece.objects.filter(poste=poste_id).all(), | |
624 | 'dossiers': ( | |
625 | rh.Dossier.objects.filter(poste=poste_id) | |
626 | .order_by("-date_debut").all() | |
627 | ), | |
628 | 'comparaisons': ( | |
629 | rh.PosteComparaison.objects.filter(poste=poste_id).all() | |
630 | ), | |
631 | 'commentaires': ( | |
632 | rh.PosteCommentaire.objects.filter(poste=poste_id).all() | |
633 | ), | |
abf91905 | 634 | 'media_url': settings.PRIVE_MEDIA_URL, |
fbe60a9d | 635 | } |
00ca4d9f EMS |
636 | return render_to_response( |
637 | 'admin/rh/poste/apercu.html', c, RequestContext(request) | |
638 | ) | |
639 | ||
fbe60a9d | 640 | |
4a1f2ece OL |
641 | def employe_apercu(request, employe_id): |
642 | employe = get_object_or_404(rh.Employe, pk=employe_id) | |
fbe60a9d | 643 | user_groups = request.user.groups.all() |
fbe60a9d OL |
644 | dossiers = None |
645 | ||
646 | if request.user.is_superuser or \ | |
647 | grp_drh in user_groups: | |
648 | q = Q(employe=employe) | |
649 | if grp_correspondants_rh in user_groups: | |
00ca4d9f EMS |
650 | regions = [ |
651 | d.poste.implantation.region for d in employe.rh_dossiers.all() | |
652 | ] | |
fbe60a9d | 653 | q = Q(employe=employe) & Q(implantation__region__in=regions) |
22343fe7 OL |
654 | |
655 | dossiers = rh.Dossier.objects.filter(q).order_by('-date_debut') | |
656 | ||
4a1f2ece | 657 | c = { |
ce740bb5 | 658 | 'title': u"Employe %s" % (employe, ), |
00ca4d9f EMS |
659 | 'is_popup': request.GET.get('_popup', False), |
660 | 'employe': employe, | |
661 | 'dossiers': dossiers, | |
abf91905 | 662 | 'media_url': settings.PRIVE_MEDIA_URL, |
4a1f2ece | 663 | } |
00ca4d9f EMS |
664 | return render_to_response( |
665 | 'admin/rh/employe/apercu.html', c, RequestContext(request) | |
666 | ) | |
667 | ||
150d83ec | 668 | |
77bd83d1 JPC |
669 | @login_required |
670 | @drh_or_admin_required | |
56264a85 | 671 | def organigrammes_employe(request, id, level="all"): |
08faf06e JPC |
672 | |
673 | poste = get_object_or_404(rh.Poste, pk=id) | |
00ca4d9f EMS |
674 | dossiers_by_poste = dict( |
675 | (d.poste_id, d) | |
676 | for d in rh.Dossier.objects.select_related('employe', 'poste').all() | |
677 | ) | |
5c0f1778 JPC |
678 | postes_by_id = dict((p.id, p) for p in rh.Poste.objects.all()) |
679 | ||
680 | e = dossiers_by_poste[poste.id].employe | |
681 | name = u"Organigramme de [%s] %s %s" % (e.id, e.nom.upper(), e.prenom) | |
58014aec | 682 | graph = pgv.AGraph() |
5c0f1778 | 683 | |
f187a10f | 684 | if rh.Poste.objects.filter(responsable=poste).count() > 0: |
58014aec JPC |
685 | postes_handle = [poste] |
686 | while postes_handle: | |
00ca4d9f EMS |
687 | postes_handle = rh.Poste.objects.select_related('implantation') \ |
688 | .filter( | |
689 | Q(date_fin__gt=date.today()) | Q(date_fin=None), | |
690 | Q(date_debut__lt=date.today()) | Q(date_debut=None), | |
691 | responsable__in=postes_handle | |
692 | ).exclude(supprime=True).exclude(responsable=None).all() | |
32373f2e | 693 | |
58014aec JPC |
694 | for p in postes_handle: |
695 | if p.responsable_id != p.id: | |
00ca4d9f EMS |
696 | graph.add_edge( |
697 | dossiers_by_poste[p.responsable_id].poste_id, p.id | |
698 | ) | |
13ad5ad5 | 699 | |
f187a10f | 700 | else: |
5c0f1778 JPC |
701 | graph.add_node(poste.id) |
702 | ||
4afec2e1 JPC |
703 | if level != "all": |
704 | postes_niveau = [poste.id] | |
705 | for niveau in range(int(level)): | |
00ca4d9f EMS |
706 | postes_niveau = [ |
707 | p.id for p in | |
708 | rh.Poste.objects.filter(responsable__in=postes_niveau).all() | |
709 | ] | |
4afec2e1 JPC |
710 | |
711 | while postes_niveau: | |
00ca4d9f EMS |
712 | postes_niveau = [ |
713 | p.id for p in | |
714 | rh.Poste.objects.filter(responsable__in=postes_niveau).all() | |
715 | ] | |
4afec2e1 JPC |
716 | if postes_niveau: |
717 | for p in postes_niveau: | |
718 | if graph.has_node(p): | |
4cc81304 | 719 | graph.delete_node(p) |
4afec2e1 | 720 | |
58014aec | 721 | a = graph |
4afec2e1 | 722 | a.name = name.encode('ascii', 'xmlcharrefreplace') |
5c0f1778 JPC |
723 | |
724 | poste_remontant = poste | |
725 | while poste_remontant.responsable_id: | |
726 | a.add_edge(poste_remontant.responsable_id, poste_remontant.id) | |
727 | poste_remontant = poste_remontant.responsable | |
728 | ||
729 | rh_graph.bind_poste_to_graph(a, postes_by_id) | |
730 | #a.graph_attr['normalize'] = True | |
731 | #a.graph_attr['level'] = 2 | |
732 | a.layout(prog='dot') | |
733 | ||
734 | svg = a.draw(format='svg') | |
735 | ||
736 | c = { | |
737 | 'svg': svg | |
738 | } | |
a251ac8d JPC |
739 | |
740 | if 'forcer' in request.GET: | |
741 | response = HttpResponse(svg, mimetype='image/svg+xml') | |
00ca4d9f EMS |
742 | response['Content-Disposition'] = \ |
743 | 'attachment; filename=organigramme.svg' | |
a251ac8d JPC |
744 | return response |
745 | ||
00ca4d9f EMS |
746 | return render_to_response( |
747 | 'rh/organigrammes/employe.html', c, RequestContext(request), | |
748 | mimetype="image/svg+xml" | |
749 | ) | |
5c0f1778 JPC |
750 | |
751 | ||
752 | @login_required | |
753 | @drh_or_admin_required | |
754 | def organigrammes_service(request, id): | |
755 | ||
756 | service = get_object_or_404(rh.Service, pk=id) | |
82af5c19 JPC |
757 | svg = rh_graph.organigramme_postes_cluster( \ |
758 | cluster_filter={"service": service}, \ | |
759 | titre=u"Organigramme du service %s" % service.nom, | |
760 | cluster_titre=service.nom) | |
5c0f1778 | 761 | |
82af5c19 JPC |
762 | c = { |
763 | 'svg': svg | |
764 | } | |
5c0f1778 | 765 | |
00ca4d9f EMS |
766 | return render_to_response( |
767 | 'rh/organigrammes/vide.html', c, RequestContext(request), | |
768 | mimetype="image/svg+xml" | |
769 | ) | |
770 | ||
5c0f1778 | 771 | |
82af5c19 JPC |
772 | @login_required |
773 | @drh_or_admin_required | |
774 | def organigrammes_implantation(request, id): | |
5c0f1778 | 775 | |
82af5c19 JPC |
776 | implantation = get_object_or_404(ref.Implantation, pk=id) |
777 | svg = rh_graph.organigramme_postes_cluster( \ | |
778 | cluster_filter={"implantation": implantation}, \ | |
779 | titre=u"Organigramme de l'implantation %s" % implantation.nom, | |
780 | cluster_titre=implantation.nom) | |
5c0f1778 JPC |
781 | |
782 | c = { | |
783 | 'svg': svg | |
784 | } | |
785 | ||
00ca4d9f EMS |
786 | return render_to_response( |
787 | 'rh/organigrammes/vide.html', c, RequestContext(request), | |
788 | mimetype="image/svg+xml" | |
789 | ) | |
790 | ||
5c0f1778 | 791 | |
9da4c195 JPC |
792 | @login_required |
793 | @drh_or_admin_required | |
794 | def organigrammes_region(request, id): | |
795 | ||
796 | region = get_object_or_404(ref.Region, pk=id) | |
797 | svg = rh_graph.organigramme_postes_cluster( \ | |
798 | cluster_filter={"implantation__region": region}, \ | |
799 | titre=u"Organigramme du bureau de %s" % region.nom, | |
800 | cluster_titre=region.nom) | |
801 | ||
802 | c = { | |
803 | 'svg': svg | |
804 | } | |
805 | ||
00ca4d9f EMS |
806 | return render_to_response( |
807 | 'rh/organigrammes/vide.html', c, RequestContext(request), | |
808 | mimetype="image/svg+xml" | |
809 | ) |