9301ce0d30c91233d7d1e107b172ddadf8cc740a
[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 if poste.id_rh_id is not None:
307 poste_rh = get_object_or_404(rh.Poste, pk=poste.id_rh_id)
308 else:
309 poste_rh = None
310
311 if employe_key == '':
312 employe_source = 'new'
313 dossier_rh = rh.Dossier()
314 else:
315 # Récupération des données de RH v1
316 employe_source, employe_id = employe_key.split('-')
317 if employe_source == 'dae':
318 employe = get_object_or_404(dae.Employe, pk=employe_id)
319 employe_source, employe_id = 'rh', employe.id_rh_id
320 if employe_source == 'rh':
321 employe_rh = get_object_or_404(rh.Employe, pk=employe_id)
322 try:
323 dossier_rh = rh.Dossier.objects.get(employe=employe_rh,
324 mandat_date_fin=None)
325 except (rh.Dossier.DoesNotExist):
326 dossier_rh = rh.Dossier()
327
328 # Récupération du dossier dae existant ou pré-remplissage
329 # des valeurs par défaut
330 if employe_source == 'dae':
331 try:
332 dossier = dae.Dossier.objects.get(employe=employe, poste=poste)
333 except (dae.Dossier.DoesNotExist):
334 dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
335 else:
336 dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
337
338 dossier_form = DossierForm(initial=data, instance=dossier)
339 vars = dict(form=dossier_form)
340
341 return render_to_response('dae/embauche-dossier.html', vars,
342 RequestContext(request))
343
344 def salaire(request, implantation, devise, classement):
345 if not devise or not classement:
346 raise Http404
347
348 taux_impl = rh.TauxChange.objects.filter(implantation=implantation) \
349 .order_by('-annee')
350 taux = rh.TauxChange.objects.filter(devise=devise).order_by('-annee')
351 vp = rh.ValeurPoint.objects.filter(implantation=implantation) \
352 .order_by('-annee')
353 if vp.count() * taux.count() * taux_impl.count() == 0:
354 raise Http404
355
356 classement = get_object_or_404(rh.Classement, pk=classement)
357 taux, taux_impl, vp = taux[0].taux, taux_impl[0].taux, vp[0].valeur
358
359 salaire_euro = round(vp * classement.coefficient * taux_impl, 2)
360 data = dict(salaire_euro=salaire_euro, taux=taux,
361 salaire_devise=round(salaire_euro / taux, 2))
362
363 return HttpResponse(dumps(data))
364
365 def pre_filled_dossier(dossier_rh, employe_source, poste_rh):
366 dossier = dae.Dossier()
367
368 if employe_source != 'new' and dossier_rh.id:
369 dossier.statut_anterieur = dossier_rh.statut
370
371 # Certains dossiers ont un classement à zéro
372 if dossier_rh.classement_id > 0:
373 dossier.classement_anterieur = dossier_rh.classement
374
375 # Récupération du salaire de base
376 remun = dossier_rh.remuneration_set.filter(type=1)
377 if remun:
378 dossier.salaire_anterieur = remun[0].montant
379
380 # Récupération du titulaire précédent
381 try:
382 dossiers = rh.Dossier.objects.order_by('-mandat_date_fin')
383 dossiers = dossiers.filter(poste1=poste_rh) | dossiers.filter(poste2=poste_rh)
384 if len(dossiers):
385 # Ce bloc ignore toutes les erreurs, car les données de rh
386 # manquantes peuvent en générer
387 d = dossiers[0]
388 try:
389 titulaire = d.employe
390 dossier.employe_anterieur = titulaire
391 dossier.classement_titulaire_anterieur = d.classement
392 dossier.statut_titulaire_anterieur = d.statut
393 dossier.salaire_titulaire_anterieur = \
394 d.remuneration_set.all()[0].montant
395 except:
396 pass
397 # TODO: afficher l'info, les champs ne sont pas dans le
398 # modèle dae.Dossier: nom, prenom, classement, salaire
399 pass
400
401 except (rh.Dossier.DoesNotExist):
402 dossier_rh = rh.Dossier()
403
404 return dossier
405
406 def coefficient(request):
407 """ Appel AJAX :
408 input : classement
409 output : coefficient
410 """
411 method = request.method
412 params = getattr(request, method, [])
413 data = dict()
414 if 'classement' in params:
415 classement = params.get('classement')
416 classement = rh.Classement.objects.get(pk=classement)
417 data['coefficient'] = classement.coefficient
418 return HttpResponse(dumps(data))
419
420
421 def liste_valeurs_point(request):
422 """ Appel AJAX :
423 input : implantation_id
424 output : JSON liste de valeur point
425 """
426 method = request.method
427 params = getattr(request, method, [])
428 data = []
429 annee_courante = datetime.datetime.now().year
430 if 'implantation_id' in params and params.get('implantation_id') is not u"":
431 implantation_id = params.get('implantation_id')
432 objects = rh.ValeurPoint.objects.filter(implantation=implantation_id, annee__in=(annee_courante-1, annee_courante)).order_by("-annee")
433 else:
434 objects = rh.ValeurPoint.objects.filter(annee__in=(annee_courante-1, annee_courante)).order_by("-annee")
435 for o in objects:
436 data.append({'id' : o.id, 'label' : o.__unicode__(), })
437 return HttpResponse(dumps(data))
438
439 def devise(request):
440 """ Appel AJAX :
441 input : valeur_point
442 output : devise, devise_code, taux_euro
443 """
444 method = request.method
445 params = getattr(request, method, [])
446 data = dict()
447 if 'valeur_point' in params and params.get('valeur_point') is not u"":
448 valeur_point = params.get('valeur_point')
449 valeur_point = rh.ValeurPoint.objects.get(pk=valeur_point)
450 annee = valeur_point.annee
451 implantation = valeur_point.implantation
452 taux = rh.TauxChange.objects.get(annee=annee,
453 implantation=implantation)
454 data['devise'] = taux.devise.id
455 data['valeur'] = valeur_point.valeur
456 data['devise_code'] = taux.devise.code
457 data['taux_euro'] = taux.taux
458 return HttpResponse(dumps(data))
459
460 def devise_code(request):
461 """ Appel AJAX :
462 input : devise
463 output : devise_code, taux_euro
464 """
465 method = request.method
466 params = getattr(request, method, [])
467 data = dict()
468 if 'devise' in params:
469 devise = params.get('devise')
470 devise = rh.Devise.objects.get(pk=devise)
471 annee = date.today().year
472 taux = rh.TauxChange.objects.filter(annee=annee, devise=devise)
473 if len(taux) == 0:
474 return HttpResponseGone("Le taux n'est pas disponible")
475 data['devise_code'] = devise.code
476 data['taux_euro'] = taux[0].taux
477 return HttpResponse(dumps(data))
478
479 def add_remun(request, dossier, type_remun):
480 dossier = get_object_or_404(dae.Dossier, pk=dossier)
481 type_remun = get_object_or_404(rh.TypeRemuneration, pk=type_remun)
482 dae.Remuneration(dossier=dossier, devise=dossier.devise,
483 type=type_remun).save()
484
485 return render_to_response('dae/embauche-remun.html', dict(dossier=dossier),
486 RequestContext(request))