sécurité : seuls admin ont accès à DAE [élargir plus tard]
[auf_rh_dae.git] / project / dae / views.py
1 # -*- encoding: utf-8 -*-
2 from collections import defaultdict
3 from datetime import date
4 from simplejson import dumps
5 import warnings
6
7 from django.core.urlresolvers import reverse
8 from django.http import Http404, HttpResponse
9 from django.shortcuts import redirect, render_to_response, get_object_or_404
10 from django.template import RequestContext
11
12 from reversion.models import Version
13
14 from project.dae.forms import (ChoosePosteForm, DossierForm, EmployeForm,
15 PosteForm, PosteFinancementForm, PostePieceForm,
16 DossierPieceForm)
17 from project.dae import models as dae
18 from project.rh_v1 import models as rh
19
20 from project.decorators import admin_required
21 from forms import PosteValidationForm
22
23 @admin_required
24 def index(request):
25 return render_to_response('dae/index.html', {}, RequestContext(request))
26
27 @admin_required
28 def poste(request, key=None):
29 """ Formulaire pour un poste.
30
31 Permet de créer ou modifier un poste. Si le poste n'existe que dans rh_v1
32 il est automatiquement copié dans dae.
33
34 """
35 poste, data, vars = None, dict(), dict()
36
37 if key:
38 # Poste existant
39 data['poste'] = key
40 source, id = key.split('-')
41
42 if source == 'dae':
43 poste = get_object_or_404(dae.Poste, pk=id)
44 elif source == 'rh':
45 p = get_object_or_404(rh.Poste, pk=id)
46 # Initialisation avec les valeurs du poste de rh_v1
47 poste = dae.Poste(id_rh=p, nom=p.type_poste.nom)
48 for field in ('implantation', 'type_poste', 'actif'):
49 setattr(poste, field, getattr(p, field))
50 else:
51 # Nouveau poste
52 vars['new'] = True
53
54 if request.POST:
55 data.update(dict(request.POST.items()))
56 form = PosteForm(data, instance=poste)
57 piecesForm = PostePieceForm(request.POST, request.FILES, instance=poste)
58 if 'save' in data and form.is_valid():
59 poste = form.save()
60 piecesForm.save()
61 return redirect('poste', key='dae-%s' % poste.id)
62 else:
63 # 'initial' évite la validation prémature lors d'une copie de poste de
64 # rh_v1 vers dae.
65 form = PosteForm(initial=data, instance=poste)
66 piecesForm = PostePieceForm(instance=poste)
67
68 vars.update(dict(form=form, poste=poste, poste_key=key, piecesForm=piecesForm))
69
70 return render_to_response('dae/poste.html', vars, RequestContext(request))
71
72 @admin_required
73 def postes_liste(request):
74 """ Liste des postes. """
75 vars = dict()
76 vars['postes'] = []
77
78 for p in dae.Poste.objects.all().order_by('-date_creation'):
79 premiere_revision = Version.objects.get_for_object(p)[0].revision
80 if request.POST:
81 validationForm = PosteValidationForm(request.POST, instance=p, prefix=p.id)
82 if validationForm.is_valid():
83 p = validationForm.save()
84 else:
85 validationForm = PosteValidationForm(instance=p, prefix=p.id)
86
87 vars['postes'].append((p, premiere_revision, validationForm))
88
89 if request.POST:
90 return redirect(reverse('dae_postes_liste'))
91
92 return render_to_response('dae/postes_liste.html', vars,
93 RequestContext(request))
94
95 @admin_required
96 def financement(request, key=None, id=None):
97 """ Formulaire pour une source de financement pour un poste. """
98 poste, financement, data, vars = None, None, dict(), dict()
99
100 if request.POST:
101 data.update(dict(request.POST.items()))
102
103 if key:
104 source, poste_id = key.split('-')
105 vars['poste_key'] = key
106 if source == 'dae':
107 poste = get_object_or_404(dae.Poste, pk=poste_id)
108 if id:
109 # Financement existant
110 financement = get_object_or_404(dae.PosteFinancement, pk=id)
111 vars['financement_id'] = id
112 else:
113 # Nouveau financement
114 financement = dae.PosteFinancement(poste_id=poste_id)
115 vars['new'] = True
116
117 if not financement:
118 return Http404
119
120 if request.POST:
121 form = PosteFinancementForm(data, instance=financement)
122 if 'delete' in data:
123 financement.delete()
124 elif 'save' in data and form.is_valid():
125 financement = form.save()
126 return redirect('poste', key='dae-%s' % poste.id)
127 else:
128 form = PosteFinancementForm(initial=data, instance=financement)
129
130 vars.update(dict(form=form, financement=financement))
131
132 if 'ajax' in request.GET:
133 template = 'dae/financement.html'
134 else:
135 template = 'dae/financement-full.html'
136 return render_to_response(template, vars, RequestContext(request))
137
138 @admin_required
139 def filtered_type_remun():
140 # Exclusion de "Indemnité de fonction" des types de rémun utilisés
141 return rh.TypeRemuneration.objects.exclude(pk=7)
142
143 @admin_required
144 def embauche(request, key=None, dossier=None):
145 """ Formulaire d'autorisation d'embauche. """
146 if not key:
147 vars = dict(step='poste', form=ChoosePosteForm())
148 else:
149 type_remun = filtered_type_remun()
150 vars = dict(type_remun=type_remun)
151 source, id = key.split('-')
152 if source != 'dae':
153 return Http404
154 poste = get_object_or_404(dae.Poste, pk=id)
155 if not dossier:
156 vars['new'] = True
157
158 if request.POST:
159 if request.POST['employe'] == '':
160 # Nouvel employé
161 employe = dae.Employe()
162 else:
163 employe_source, id = request.POST['employe'].split('-')
164 if employe_source == 'dae':
165 # Employé DAE
166 employe = get_object_or_404(dae.Employe, pk=id)
167 elif employe_source == 'rh':
168 # Employé RH, on le copie dans DAE
169 e = get_object_or_404(rh.Employe, pk=id)
170 employe = dae.Employe(id_rh=e, prenom=e.prenom, nom=e.nom,
171 genre=e.genre)
172 else:
173 raise Http404
174
175 employe_form = EmployeForm(request.POST, instance=employe)
176
177 if 'save' in request.POST:
178 if employe_form.is_valid():
179 data = dict(request.POST.items())
180 #with warnings.catch_warnings():
181 # warnings.simplefilter('ignore')
182 employe = employe_form.save()
183 data['employe'] = 'dae-%s' % employe.id
184 employe_form = EmployeForm(data, instance=employe)
185
186 if not dossier:
187 dossier = dae.Dossier(poste=poste, employe=employe)
188 else:
189 dossier = get_object_or_404(dae.Dossier, pk=dossier)
190 dossier_form = DossierForm(request.POST, instance=dossier)
191 piecesForm = DossierPieceForm(request.POST, request.FILES, instance=dossier)
192
193 if dossier_form.is_valid():
194 dossier = dossier_form.save()
195 piecesForm.save()
196 if not dossier.remuneration_set.all():
197 # Pré-peuplement des entrées de la section "coût
198 # global", à l'exclusion de "Indemnité de fonction"
199 for type in type_remun.all():
200 dae.Remuneration(dossier=dossier, type=type,
201 devise=dossier.devise).save()
202
203 else:
204 # Sauvegarde du coût global
205 cg_lines = defaultdict(dict)
206 for k, v in request.POST.items():
207 if k.startswith('cg-'):
208 prefix, field_name, cg_id = k.split('-')
209 cg_lines[int(cg_id)][unicode(field_name)] = v
210
211 for r in dossier.remuneration_set.all():
212 print 'trying %r' % r
213 if r.id in cg_lines:
214 if cg_lines[r.id]['montant'] == '':
215 r.delete()
216 else:
217 for k, v in cg_lines[r.id].items():
218 setattr(r, k, v)
219 r.save()
220
221 return redirect('embauche', key='dae-%s' % poste.id,
222 dossier=dossier.id)
223 else:
224 dossier_form = DossierForm(instance=dossier)
225 piecesForm = DossierPieceForm(instance=dossier)
226 else:
227 # Initialisation d'un formulaire vide
228 dossier_rh = rh.Dossier()
229 poste_rh = poste.id_rh
230 if dossier:
231 dossier = get_object_or_404(dae.Dossier, pk=dossier)
232 employe = dossier.employe
233 data = dict(employe='dae-%s' % employe.id)
234 employe_form = EmployeForm(initial=data, instance=employe)
235 else:
236 dossier = pre_filled_dossier(dossier_rh, 'new', poste_rh)
237 employe_form = EmployeForm()
238
239 dossier_form = DossierForm(instance=dossier)
240 piecesForm = DossierPieceForm(instance=dossier)
241
242 vars = dict(step='employe', poste=poste, dossier=dossier, piecesForm=piecesForm,
243 forms=dict(employe=employe_form, dossier=dossier_form, ))
244
245 return render_to_response('dae/embauche.html', vars,
246 RequestContext(request))
247 @admin_required
248 def embauches_liste(request):
249 """ Liste des embauches. """
250 vars = dict()
251 vars['embauches'] = []
252 for d in dae.Dossier.objects.all().order_by('-date_creation'):
253 premiere_revision = Version.objects.get_for_object(d)[0].revision
254 vars['embauches'].append((d, premiere_revision))
255 return render_to_response('dae/embauches_liste.html', vars,
256 RequestContext(request))
257 @admin_required
258 def employe(request, key):
259 """ Récupération AJAX de l'employé pour la page d'embauche. """
260 data = dict(employe=key)
261
262 if key == '':
263 # Nouvel employé
264 employe = dae.Employe()
265 else:
266 # Employé existant
267 source, id = key.split('-')
268
269 if source == 'dae':
270 employe = get_object_or_404(dae.Employe, pk=id)
271 elif source == 'rh':
272 e = get_object_or_404(rh.Employe, id=id)
273 # Initialisation avec les valeurs de l'employé de rh_v1
274 employe = dae.Employe(id_rh=e)
275 for field in ('prenom', 'nom', 'genre'):
276 setattr(employe, field, getattr(e, field))
277
278 return HttpResponse(EmployeForm(initial=data, instance=employe).as_table())
279
280 @admin_required
281 def dossier(request, poste_key, employe_key):
282 """ Récupération AJAX du dossier pour la page d'embauche. """
283 data = dict()
284
285 poste_source, poste_id = poste_key.split('-')
286 poste = get_object_or_404(dae.Poste, pk=poste_id)
287 poste_rh = get_object_or_404(rh.Poste, pk=poste.id_rh_id)
288
289 if employe_key == '':
290 employe_source = 'new'
291 dossier_rh = rh.Dossier()
292 else:
293 # Récupération des données de RH v1
294 employe_source, employe_id = employe_key.split('-')
295 if employe_source == 'dae':
296 employe = get_object_or_404(dae.Employe, pk=employe_id)
297 employe_source, employe_id = 'rh', employe.id_rh_id
298 if employe_source == 'rh':
299 employe_rh = get_object_or_404(rh.Employe, pk=employe_id)
300 try:
301 dossier_rh = rh.Dossier.objects.get(employe=employe_rh,
302 mandat_date_fin=None)
303 except (rh.Dossier.DoesNotExist):
304 dossier_rh = rh.Dossier()
305
306 # Récupération du dossier dae existant ou pré-remplissage
307 # des valeurs par défaut
308 if employe_source == 'dae':
309 try:
310 dossier = dae.Dossier.objects.get(employe=employe, poste=poste)
311 except (dae.Dossier.DoesNotExist):
312 dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
313 else:
314 dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
315
316 dossier_form = DossierForm(initial=data, instance=dossier)
317 vars = dict(form=dossier_form)
318
319 return render_to_response('dae/embauche-dossier.html', vars,
320 RequestContext(request))
321
322 @admin_required
323 def salaire(request, implantation, devise, classement):
324 if not devise or not classement:
325 raise Http404
326
327 taux_impl = rh.TauxChange.objects.filter(implantation=implantation) \
328 .order_by('-annee')
329 taux = rh.TauxChange.objects.filter(devise=devise).order_by('-annee')
330 vp = rh.ValeurPoint.objects.filter(implantation=implantation) \
331 .order_by('-annee')
332 if vp.count() * taux.count() * taux_impl.count() == 0:
333 raise Http404
334
335 classement = get_object_or_404(rh.Classement, pk=classement)
336 taux, taux_impl, vp = taux[0].taux, taux_impl[0].taux, vp[0].valeur
337
338 salaire_euro = round(vp * classement.coefficient * taux_impl, 2)
339 data = dict(salaire_euro=salaire_euro, taux=taux,
340 salaire_devise=round(salaire_euro / taux, 2))
341
342 return HttpResponse(dumps(data))
343
344 @admin_required
345 def pre_filled_dossier(dossier_rh, employe_source, poste_rh):
346 dossier = dae.Dossier()
347
348 if employe_source != 'new' and dossier_rh.id:
349 dossier.statut_anterieur = dossier_rh.statut
350
351 # Certains dossiers ont un classement à zéro
352 if dossier_rh.classement_id > 0:
353 dossier.classement_anterieur = dossier_rh.classement
354
355 # Récupération du salaire de base
356 remun = dossier_rh.remuneration_set.filter(type=1)
357 if remun:
358 dossier.salaire_anterieur = remun[0].montant
359
360 # Récupération du titulaire précédent
361 try:
362 dossiers = rh.Dossier.objects.order_by('-mandat_date_fin')
363 dossiers = dossiers.filter(poste1=poste_rh) \
364 | dossiers.filter(poste2=poste_rh)
365 if len(dossiers):
366 # Ce bloc ignore toutes les erreurs, car les données de rh
367 # manquantes peuvent en générer
368 d = dossiers[0]
369 try:
370 titulaire = d.employe
371 dossier.employe_anterieur = titulaire
372 dossier.classement_titulaire_anterieur = d.classement
373 dossier.statut_titulaire_anterieur = d.statut
374 dossier.salaire_titulaire_anterieur = \
375 d.remuneration_set.all()[0].montant
376 except:
377 pass
378 # TODO: afficher l'info, les champs ne sont pas dans le
379 # modèle dae.Dossier: nom, prenom, classement, salaire
380 pass
381
382 except (rh.Dossier.DoesNotExist):
383 dossier_rh = rh.Dossier()
384
385 return dossier
386
387 @admin_required
388 def coefficient(request):
389 """ Appel AJAX :
390 input : classement
391 output : coefficient
392 """
393 data = dict()
394 if request.POST and 'classement' in request.POST:
395 classement = request.POST.get('classement')
396 classement = rh.Classement.objects.get(pk=classement)
397 data['coefficient'] = classement.coefficient
398 return HttpResponse(dumps(data))
399
400 @admin_required
401 def valeur(request):
402 """ Appel AJAX :
403 input : valeur_point
404 output : valeur
405 """
406 data = dict()
407 if request.POST and 'valeur_point' in request.POST:
408 valeur_point = request.POST.get('valeur_point')
409 valeur_point = rh.ValeurPoint.objects.get(pk=valeur_point)
410 data['valeur'] = valeur_point.valeur
411 return HttpResponse(dumps(data))
412
413 @admin_required
414 def devise(request):
415 """ Appel AJAX :
416 input : valeur_point
417 output : devise, devise_code, taux_euro
418 """
419 data = dict()
420 if request.POST and 'valeur_point' in request.POST:
421 valeur_point = request.POST.get('valeur_point')
422 valeur_point = rh.ValeurPoint.objects.get(pk=valeur_point)
423 annee = valeur_point.annee
424 implantation = valeur_point.implantation
425 taux = rh.TauxChange.objects.get(annee=annee,
426 implantation=implantation)
427 data['devise'] = taux.devise.id
428 data['devise_code'] = taux.devise.code
429 data['taux_euro'] = taux.taux
430 return HttpResponse(dumps(data))
431
432 @admin_required
433 def devise_code(request):
434 """ Appel AJAX :
435 input : devise
436 output : devise_code, taux_euro
437 """
438 data = dict()
439 if request.POST and 'devise' in request.POST:
440 devise = request.POST.get('devise')
441 devise = rh.Devise.objects.get(pk=devise)
442 annee = date.today().year
443 taux = rh.TauxChange.objects.filter(annee=annee, devise=devise)
444 data['devise_code'] = devise.code
445 data['taux_euro'] = taux[0].taux
446 return HttpResponse(dumps(data))
447
448 @admin_required
449 def add_remun(request, dossier, type_remun):
450 dossier = get_object_or_404(dae.Dossier, pk=dossier)
451 type_remun = get_object_or_404(rh.TypeRemuneration, pk=type_remun)
452 dae.Remuneration(dossier=dossier, devise=dossier.devise,
453 type=type_remun).save()
454
455 return render_to_response('dae/embauche-remun.html', dict(dossier=dossier),
456 RequestContext(request))