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