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