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