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