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