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