1 # -*- encoding: utf-8 -*-
4 from collections
import defaultdict
5 from datetime
import date
6 from simplejson
import dumps
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
15 from reversion
.models
import Version
17 from project
.dae
import models
as dae
18 from project
.rh_v1
import models
as rh
20 from project
.decorators
import admin_required
25 return render_to_response('dae/index.html', {}, RequestContext(request
))
28 def poste(request
, key
=None):
29 """ Formulaire pour un poste.
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.
35 poste
, data
, vars = None, dict(), dict()
40 source
, id = key
.split('-')
43 poste
= get_object_or_404(dae
.Poste
, pk
=id)
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
))
55 data
.update(dict(request
.POST
.items()))
56 form
= PosteForm(data
, instance
=poste
)
57 financementForm
= FinancementForm(request
.POST
, instance
=poste
)
58 piecesForm
= PostePieceForm(request
.POST
, request
.FILES
, instance
=poste
)
59 if 'save' in data
and form
.is_valid() and piecesForm
.is_valid() and financementForm
.is_valid():
61 piecesForm
.instance
= poste
63 financementForm
.instance
= poste
64 financementForm
.save()
65 messages
.add_message(request
, messages
.SUCCESS
, "Le poste %s a été sauvegardé." % poste
)
66 return redirect('poste', key
='dae-%s' % poste
.id)
68 messages
.add_message(request
, messages
.ERROR
, 'Il y a des erreurs dans le formulaire.')
71 # 'initial' évite la validation prémature lors d'une copie de poste de
73 form
= PosteForm(initial
=data
, instance
=poste
)
74 piecesForm
= PostePieceForm(instance
=poste
)
75 financementForm
= FinancementForm(instance
=poste
)
77 vars.update(dict(form
=form
, poste
=poste
, poste_key
=key
, piecesForm
=piecesForm
, financementForm
=financementForm
))
79 return render_to_response('dae/poste.html', vars, RequestContext(request
))
82 def postes_liste(request
):
83 """ Liste des postes. """
87 for p
in dae
.Poste
.objects
.all().order_by('-date_creation'):
88 versions
= Version
.objects
.get_for_object(p
)
90 premiere_revision
= versions
[0].revision
92 premiere_revision
= None
95 validationForm
= PosteValidationForm(request
.POST
, instance
=p
, prefix
=p
.id)
96 if validationForm
.is_valid():
97 p
= validationForm
.save()
99 validationForm
= PosteValidationForm(instance
=p
, prefix
=p
.id)
101 vars['postes'].append((p
, premiere_revision
, validationForm
))
104 return redirect(reverse('dae_postes_liste'))
106 return render_to_response('dae/postes_liste.html', vars,
107 RequestContext(request
))
109 def filtered_type_remun():
110 # Exclusion de "Indemnité de fonction" des types de rémun utilisés
111 return rh
.TypeRemuneration
.objects
.exclude(pk
=7)
114 def embauche(request
, key
=None, dossier
=None):
115 """ Formulaire d'autorisation d'embauche. """
117 vars = dict(step
='poste', form
=ChoosePosteForm())
119 type_remun
= filtered_type_remun()
120 vars = dict(type_remun
=type_remun
)
121 source
, id = key
.split('-')
124 poste
= get_object_or_404(dae
.Poste
, pk
=id)
129 if request
.POST
['employe'] == '':
131 employe
= dae
.Employe()
133 employe_source
, id = request
.POST
['employe'].split('-')
134 if employe_source
== 'dae':
136 employe
= get_object_or_404(dae
.Employe
, pk
=id)
137 elif employe_source
== 'rh':
138 # Employé RH, on le copie dans DAE
139 e
= get_object_or_404(rh
.Employe
, pk
=id)
140 employe
= dae
.Employe(id_rh
=e
, prenom
=e
.prenom
, nom
=e
.nom
,
145 employe_form
= EmployeForm(request
.POST
, instance
=employe
)
147 if 'save' in request
.POST
:
148 if employe_form
.is_valid():
149 data
= dict(request
.POST
.items())
150 #with warnings.catch_warnings():
151 # warnings.simplefilter('ignore')
152 employe
= employe_form
.save()
153 data
['employe'] = 'dae-%s' % employe
.id
154 employe_form
= EmployeForm(data
, instance
=employe
)
157 dossier
= dae
.Dossier(poste
=poste
, employe
=employe
)
159 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier
)
160 dossier_form
= DossierForm(request
.POST
, instance
=dossier
)
161 piecesForm
= DossierPieceForm(request
.POST
, request
.FILES
, instance
=dossier
)
163 if dossier_form
.is_valid() and piecesForm
.is_valid():
164 dossier
= dossier_form
.save()
165 piecesForm
.instance
= dossier
167 if not dossier
.remuneration_set
.all():
168 # Pré-peuplement des entrées de la section "coût
169 # global", à l'exclusion de "Indemnité de fonction"
170 for type in type_remun
.all():
171 dae
.Remuneration(dossier
=dossier
, type=type,
172 devise
=dossier
.devise
).save()
175 # Sauvegarde du coût global
176 cg_lines
= defaultdict(dict)
177 for k
, v
in request
.POST
.items():
178 if k
.startswith('cg-'):
179 prefix
, field_name
, cg_id
= k
.split('-')
180 cg_lines
[int(cg_id
)][unicode(field_name
)] = v
182 for r
in dossier
.remuneration_set
.all():
183 print 'trying %r' % r
185 if cg_lines
[r
.id]['montant'] == '':
188 for k
, v
in cg_lines
[r
.id].items():
192 messages
.add_message(request
, messages
.SUCCESS
, "Le dossier %s a été sauvegardé." % dossier
)
193 return redirect('embauche', key
='dae-%s' % poste
.id,
196 messages
.add_message(request
, messages
.ERROR
, 'Il y a des erreurs dans le formulaire.')
199 dossier_form
= DossierForm(instance
=dossier
)
200 piecesForm
= DossierPieceForm(instance
=dossier
)
202 # Initialisation d'un formulaire vide
203 dossier_rh
= rh
.Dossier()
204 poste_rh
= poste
.id_rh
206 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier
)
207 employe
= dossier
.employe
208 data
= dict(employe
='dae-%s' % employe
.id)
209 employe_form
= EmployeForm(initial
=data
, instance
=employe
)
211 dossier
= pre_filled_dossier(dossier_rh
, 'new', poste_rh
)
212 employe_form
= EmployeForm()
214 dossier_form
= DossierForm(instance
=dossier
)
215 piecesForm
= DossierPieceForm(instance
=dossier
)
217 vars = dict(step
='employe', poste
=poste
, dossier
=dossier
, piecesForm
=piecesForm
,
218 forms
=dict(employe
=employe_form
, dossier
=dossier_form
, ))
220 return render_to_response('dae/embauche.html', vars,
221 RequestContext(request
))
223 def embauches_liste(request
):
224 """ Liste des embauches. """
226 vars['embauches'] = []
227 for d
in dae
.Dossier
.objects
.all().order_by('-date_creation'):
228 versions
= Version
.objects
.get_for_object(d
)
229 if len(versions
) > 0:
230 premiere_revision
= versions
[0].revision
232 premiere_revision
= None
233 vars['embauches'].append((d
, premiere_revision
))
234 return render_to_response('dae/embauches_liste.html', vars,
235 RequestContext(request
))
237 def employe(request
, key
):
238 """ Récupération AJAX de l'employé pour la page d'embauche. """
239 data
= dict(employe
=key
)
243 employe
= dae
.Employe()
246 source
, id = key
.split('-')
249 employe
= get_object_or_404(dae
.Employe
, pk
=id)
251 e
= get_object_or_404(rh
.Employe
, id=id)
252 # Initialisation avec les valeurs de l'employé de rh_v1
253 employe
= dae
.Employe(id_rh
=e
)
254 for field
in ('prenom', 'nom', 'genre'):
255 setattr(employe
, field
, getattr(e
, field
))
257 return HttpResponse(EmployeForm(initial
=data
, instance
=employe
).as_table())
259 def dossier(request
, poste_key
, employe_key
):
260 """ Récupération AJAX du dossier pour la page d'embauche. """
263 poste_source
, poste_id
= poste_key
.split('-')
264 poste
= get_object_or_404(dae
.Poste
, pk
=poste_id
)
266 # Récupérer la devise de l'implantation lié au poste
267 implantation_devise
= poste
.get_default_devise()
268 data
.update({'devise' : implantation_devise
.id})
270 if poste
.id_rh_id
is not None:
271 poste_rh
= get_object_or_404(rh
.Poste
, pk
=poste
.id_rh_id
)
275 if employe_key
== '':
276 employe_source
= 'new'
277 dossier_rh
= rh
.Dossier()
279 # Récupération des données de RH v1
280 employe_source
, employe_id
= employe_key
.split('-')
281 if employe_source
== 'dae':
282 employe
= get_object_or_404(dae
.Employe
, pk
=employe_id
)
283 employe_source
, employe_id
= 'rh', employe
.id_rh_id
284 if employe_source
== 'rh':
285 employe_rh
= get_object_or_404(rh
.Employe
, pk
=employe_id
)
287 dossier_rh
= rh
.Dossier
.objects
.get(employe
=employe_rh
,
288 mandat_date_fin
=None)
289 except (rh
.Dossier
.DoesNotExist
):
290 dossier_rh
= rh
.Dossier()
292 # Récupération du dossier dae existant ou pré-remplissage
293 # des valeurs par défaut
294 if employe_source
== 'dae':
296 dossier
= dae
.Dossier
.objects
.get(employe
=employe
, poste
=poste
)
297 except (dae
.Dossier
.DoesNotExist
):
298 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
300 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
302 dossier_form
= DossierForm(initial
=data
, instance
=dossier
)
303 vars = dict(form
=dossier_form
, poste
=poste
)
305 return render_to_response('dae/embauche-dossier.html', vars,
306 RequestContext(request
))
308 def salaire(request
, implantation
, devise
, classement
):
309 if not devise
or not classement
:
312 taux_impl
= rh
.TauxChange
.objects
.filter(implantation
=implantation
) \
314 taux
= rh
.TauxChange
.objects
.filter(devise
=devise
).order_by('-annee')
315 vp
= rh
.ValeurPoint
.objects
.filter(implantation
=implantation
) \
317 if vp
.count() * taux
.count() * taux_impl
.count() == 0:
320 classement
= get_object_or_404(rh
.Classement
, pk
=classement
)
321 taux
, taux_impl
, vp
= taux
[0].taux
, taux_impl
[0].taux
, vp
[0].valeur
323 salaire_euro
= round(vp
* classement
.coefficient
* taux_impl
, 2)
324 data
= dict(salaire_euro
=salaire_euro
, taux
=taux
,
325 salaire_devise
=round(salaire_euro
/ taux
, 2))
327 return HttpResponse(dumps(data
))
329 def pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
):
330 dossier
= dae
.Dossier()
332 if employe_source
!= 'new' and dossier_rh
.id:
333 dossier
.statut_anterieur
= dossier_rh
.statut
335 # Certains dossiers ont un classement à zéro
336 if dossier_rh
.classement_id
> 0:
337 dossier
.classement_anterieur
= dossier_rh
.classement
339 # Récupération du salaire de base
340 remun
= dossier_rh
.remuneration_set
.filter(type=1)
342 dossier
.salaire_anterieur
= remun
[0].montant
344 # Récupération du titulaire précédent
346 dossiers
= rh
.Dossier
.objects
.order_by('-mandat_date_fin')
347 dossiers
= dossiers
.filter(poste1
=poste_rh
) | dossiers
.filter(poste2
=poste_rh
)
349 # Ce bloc ignore toutes les erreurs, car les données de rh
350 # manquantes peuvent en générer
353 titulaire
= d
.employe
354 dossier
.employe_anterieur
= titulaire
355 dossier
.classement_titulaire_anterieur
= d
.classement
356 dossier
.statut_titulaire_anterieur
= d
.statut
357 dossier
.salaire_titulaire_anterieur
= \
358 d
.remuneration_set
.all()[0].montant
361 # TODO: afficher l'info, les champs ne sont pas dans le
362 # modèle dae.Dossier: nom, prenom, classement, salaire
365 except (rh
.Dossier
.DoesNotExist
):
366 dossier_rh
= rh
.Dossier()
370 def coefficient(request
):
375 method
= request
.method
376 params
= getattr(request
, method
, [])
378 if 'classement' in params
and params
.get('classement') is not u
"":
379 classement
= params
.get('classement')
380 classement
= rh
.Classement
.objects
.get(pk
=classement
)
381 data
['coefficient'] = classement
.coefficient
383 data
['coefficient'] = 0
384 return HttpResponse(dumps(data
))
387 def liste_valeurs_point(request
):
389 input : implantation_id
390 output : JSON liste de valeur point
392 method
= request
.method
393 params
= getattr(request
, method
, [])
395 annee_courante
= datetime
.datetime
.now().year
396 if 'implantation_id' in params
and params
.get('implantation_id') is not u
"":
397 implantation_id
= params
.get('implantation_id')
398 objects
= rh
.ValeurPoint
.objects
.filter(implantation
=implantation_id
, annee__in
=(annee_courante
-1, annee_courante
)).order_by("-annee")
400 objects
= rh
.ValeurPoint
.objects
.filter(annee__in
=(annee_courante
-1, annee_courante
)).order_by("-annee")
402 data
.append({'id' : o
.id, 'label' : o
.__unicode__(), })
403 return HttpResponse(dumps(data
))
408 output : devise, devise_code, taux_euro
410 method
= request
.method
411 params
= getattr(request
, method
, [])
413 if 'valeur_point' in params
and params
.get('valeur_point') is not u
"":
414 valeur_point
= params
.get('valeur_point')
415 valeur_point
= rh
.ValeurPoint
.objects
.get(pk
=valeur_point
)
416 annee
= valeur_point
.annee
417 implantation
= valeur_point
.implantation
418 taux
= rh
.TauxChange
.objects
.get(annee
=annee
,
419 implantation
=implantation
)
420 data
['devise'] = taux
.devise
.id
421 data
['valeur'] = valeur_point
.valeur
422 data
['devise_code'] = taux
.devise
.code
423 data
['taux_euro'] = taux
.taux
425 return HttpResponseGone("Vous devez choisir une valeur de point")
426 return HttpResponse(dumps(data
))
428 def devise_code(request
):
431 output : devise_code, taux_euro
433 method
= request
.method
434 params
= getattr(request
, method
, [])
436 if 'devise' in params
:
437 devise
= params
.get('devise')
438 devise
= rh
.Devise
.objects
.get(pk
=devise
)
439 annee
= date
.today().year
440 taux
= rh
.TauxChange
.objects
.filter(annee
=annee
, devise
=devise
)
442 return HttpResponseGone("Le taux n'est pas disponible")
443 data
['devise_code'] = devise
.code
444 data
['taux_euro'] = taux
[0].taux
445 return HttpResponse(dumps(data
))
447 def add_remun(request
, dossier
, type_remun
):
448 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier
)
449 type_remun
= get_object_or_404(rh
.TypeRemuneration
, pk
=type_remun
)
450 dae
.Remuneration(dossier
=dossier
, devise
=dossier
.devise
,
451 type=type_remun
).save()
453 return render_to_response('dae/embauche-remun.html', dict(dossier
=dossier
),
454 RequestContext(request
))