Merge branch 'dev' of ssh://git.auf/auf_rh_dae into dev
[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 def embauches_liste(request):
247 """ Liste des embauches. """
248 vars = dict()
249 vars['embauches'] = []
250 for d in dae.Dossier.objects.all().order_by('-date_creation'):
251 premiere_revision = Version.objects.get_for_object(d)[0].revision
252 vars['embauches'].append((d, premiere_revision))
253 return render_to_response('dae/embauches_liste.html', vars,
254 RequestContext(request))
255
256 def employe(request, key):
257 """ Récupération AJAX de l'employé pour la page d'embauche. """
258 data = dict(employe=key)
259
260 if key == '':
261 # Nouvel employé
262 employe = dae.Employe()
263 else:
264 # Employé existant
265 source, id = key.split('-')
266
267 if source == 'dae':
268 employe = get_object_or_404(dae.Employe, pk=id)
269 elif source == 'rh':
270 e = get_object_or_404(rh.Employe, id=id)
271 # Initialisation avec les valeurs de l'employé de rh_v1
272 employe = dae.Employe(id_rh=e)
273 for field in ('prenom', 'nom', 'genre'):
274 setattr(employe, field, getattr(e, field))
275
276 return HttpResponse(EmployeForm(initial=data, instance=employe).as_table())
277
278
279 def dossier(request, poste_key, employe_key):
280 """ Récupération AJAX du dossier pour la page d'embauche. """
281 data = dict()
282
283 poste_source, poste_id = poste_key.split('-')
284 poste = get_object_or_404(dae.Poste, pk=poste_id)
285 poste_rh = get_object_or_404(rh.Poste, pk=poste.id_rh_id)
286
287 if employe_key == '':
288 employe_source = 'new'
289 dossier_rh = rh.Dossier()
290 else:
291 # Récupération des données de RH v1
292 employe_source, employe_id = employe_key.split('-')
293 if employe_source == 'dae':
294 employe = get_object_or_404(dae.Employe, pk=employe_id)
295 employe_source, employe_id = 'rh', employe.id_rh_id
296 if employe_source == 'rh':
297 employe_rh = get_object_or_404(rh.Employe, pk=employe_id)
298 try:
299 dossier_rh = rh.Dossier.objects.get(employe=employe_rh,
300 mandat_date_fin=None)
301 except (rh.Dossier.DoesNotExist):
302 dossier_rh = rh.Dossier()
303
304 # Récupération du dossier dae existant ou pré-remplissage
305 # des valeurs par défaut
306 if employe_source == 'dae':
307 try:
308 dossier = dae.Dossier.objects.get(employe=employe, poste=poste)
309 except (dae.Dossier.DoesNotExist):
310 dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
311 else:
312 dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
313
314 dossier_form = DossierForm(initial=data, instance=dossier)
315 vars = dict(form=dossier_form)
316
317 return render_to_response('dae/embauche-dossier.html', vars,
318 RequestContext(request))
319
320
321 def salaire(request, implantation, devise, classement):
322 if not devise or not classement:
323 raise Http404
324
325 taux_impl = rh.TauxChange.objects.filter(implantation=implantation) \
326 .order_by('-annee')
327 taux = rh.TauxChange.objects.filter(devise=devise).order_by('-annee')
328 vp = rh.ValeurPoint.objects.filter(implantation=implantation) \
329 .order_by('-annee')
330 if vp.count() * taux.count() * taux_impl.count() == 0:
331 raise Http404
332
333 classement = get_object_or_404(rh.Classement, pk=classement)
334 taux, taux_impl, vp = taux[0].taux, taux_impl[0].taux, vp[0].valeur
335
336 salaire_euro = round(vp * classement.coefficient * taux_impl, 2)
337 data = dict(salaire_euro=salaire_euro, taux=taux,
338 salaire_devise=round(salaire_euro / taux, 2))
339
340 return HttpResponse(dumps(data))
341
342
343 def pre_filled_dossier(dossier_rh, employe_source, poste_rh):
344 dossier = dae.Dossier()
345
346 if employe_source != 'new' and dossier_rh.id:
347 dossier.statut_anterieur = dossier_rh.statut
348
349 # Certains dossiers ont un classement à zéro
350 if dossier_rh.classement_id > 0:
351 dossier.classement_anterieur = dossier_rh.classement
352
353 # Récupération du salaire de base
354 remun = dossier_rh.remuneration_set.filter(type=1)
355 if remun:
356 dossier.salaire_anterieur = remun[0].montant
357
358 # Récupération du titulaire précédent
359 try:
360 dossiers = rh.Dossier.objects.order_by('-mandat_date_fin')
361 dossiers = dossiers.filter(poste1=poste_rh) \
362 | dossiers.filter(poste2=poste_rh)
363 if len(dossiers):
364 # Ce bloc ignore toutes les erreurs, car les données de rh
365 # manquantes peuvent en générer
366 d = dossiers[0]
367 try:
368 titulaire = d.employe
369 dossier.employe_anterieur = titulaire
370 dossier.classement_titulaire_anterieur = d.classement
371 dossier.statut_titulaire_anterieur = d.statut
372 dossier.salaire_titulaire_anterieur = \
373 d.remuneration_set.all()[0].montant
374 except:
375 pass
376 # TODO: afficher l'info, les champs ne sont pas dans le
377 # modèle dae.Dossier: nom, prenom, classement, salaire
378 pass
379
380 except (rh.Dossier.DoesNotExist):
381 dossier_rh = rh.Dossier()
382
383 return dossier
384
385 def coefficient(request):
386 """ Appel AJAX :
387 input : classement
388 output : coefficient
389 """
390 data = dict()
391 if request.POST and 'classement' in request.POST:
392 classement = request.POST.get('classement')
393 classement = rh.Classement.objects.get(pk=classement)
394 data['coefficient'] = classement.coefficient
395 return HttpResponse(dumps(data))
396
397 def valeur(request):
398 """ Appel AJAX :
399 input : valeur_point
400 output : valeur
401 """
402 data = dict()
403 if request.POST and 'valeur_point' in request.POST:
404 valeur_point = request.POST.get('valeur_point')
405 valeur_point = rh.ValeurPoint.objects.get(pk=valeur_point)
406 data['valeur'] = valeur_point.valeur
407 return HttpResponse(dumps(data))
408
409 def devise(request):
410 """ Appel AJAX :
411 input : valeur_point
412 output : devise, devise_code, taux_euro
413 """
414 data = dict()
415 if request.POST and 'valeur_point' in request.POST:
416 valeur_point = request.POST.get('valeur_point')
417 valeur_point = rh.ValeurPoint.objects.get(pk=valeur_point)
418 annee = valeur_point.annee
419 implantation = valeur_point.implantation
420 taux = rh.TauxChange.objects.get(annee=annee,
421 implantation=implantation)
422 data['devise'] = taux.devise.id
423 data['devise_code'] = taux.devise.code
424 data['taux_euro'] = taux.taux
425 return HttpResponse(dumps(data))
426
427 def devise_code(request):
428 """ Appel AJAX :
429 input : devise
430 output : devise_code, taux_euro
431 """
432 data = dict()
433 if request.POST and 'devise' in request.POST:
434 devise = request.POST.get('devise')
435 devise = rh.Devise.objects.get(pk=devise)
436 annee = date.today().year
437 taux = rh.TauxChange.objects.filter(annee=annee, devise=devise)
438 data['devise_code'] = devise.code
439 data['taux_euro'] = taux[0].taux
440 return HttpResponse(dumps(data))
441
442
443 def add_remun(request, dossier, type_remun):
444 dossier = get_object_or_404(dae.Dossier, pk=dossier)
445 type_remun = get_object_or_404(rh.TypeRemuneration, pk=type_remun)
446 dae.Remuneration(dossier=dossier, devise=dossier.devise,
447 type=type_remun).save()
448
449 return render_to_response('dae/embauche-remun.html', dict(dossier=dossier),
450 RequestContext(request))