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_consulter(request
, key
):
29 source
, id = key
.split('-')
30 poste
= get_object_or_404(dae
.Poste
, pk
=id)
31 vars = {'poste' : poste
, }
32 return render_to_response('dae/poste_consulter.html', vars, RequestContext(request
))
35 def poste(request
, key
=None):
36 """ Formulaire pour un poste.
38 Permet de créer ou modifier un poste. Si le poste n'existe que dans rh_v1
39 il est automatiquement copié dans dae.
42 poste
, data
, vars = None, dict(), dict()
47 source
, id = key
.split('-')
50 poste
= get_object_or_404(dae
.Poste
, pk
=id)
52 p
= get_object_or_404(rh
.Poste
, pk
=id)
53 # Initialisation avec les valeurs du poste de rh_v1
54 poste
= dae
.Poste(id_rh
=p
, nom
=p
.type_poste
.nom
)
55 for field
in ('implantation', 'type_poste', 'actif'):
56 setattr(poste
, field
, getattr(p
, field
))
62 data
.update(dict(request
.POST
.items()))
63 form
= PosteForm(data
, instance
=poste
)
64 financementForm
= FinancementForm(request
.POST
, instance
=poste
)
65 piecesForm
= PostePieceForm(request
.POST
, request
.FILES
, instance
=poste
)
66 if 'save' in data
and form
.is_valid() and piecesForm
.is_valid() and financementForm
.is_valid():
68 piecesForm
.instance
= poste
70 financementForm
.instance
= poste
71 financementForm
.save()
72 messages
.add_message(request
, messages
.SUCCESS
, "Le poste %s a été sauvegardé." % poste
)
73 return redirect('poste_consulter', key
='dae-%s' % poste
.id)
75 messages
.add_message(request
, messages
.ERROR
, 'Il y a des erreurs dans le formulaire.')
78 # 'initial' évite la validation prémature lors d'une copie de poste de
80 form
= PosteForm(initial
=data
, instance
=poste
)
81 piecesForm
= PostePieceForm(instance
=poste
)
82 financementForm
= FinancementForm(instance
=poste
)
84 vars.update(dict(form
=form
, poste
=poste
, poste_key
=key
, piecesForm
=piecesForm
, financementForm
=financementForm
))
86 return render_to_response('dae/poste.html', vars, RequestContext(request
))
89 def postes_liste(request
):
90 """ Liste des postes. """
92 vars['postes'] = dae
.Poste
.objects
.all().order_by('-date_creation')
93 return render_to_response('dae/postes_liste.html', vars,
94 RequestContext(request
))
96 def filtered_type_remun():
97 # Exclusion de "Indemnité de fonction" des types de rémun utilisés
98 return rh
.TypeRemuneration
.objects
.exclude(pk
=7)
100 def get_dossiers_connexes(poste
):
101 # Chargement des données de comparaison
102 comparaison_dossiers
= []
103 famille
= poste
.type_poste
.famille_emploi
104 # postes DAE (vieux dossiers)
105 postes_region
= dae
.Poste
.objects
.filter(implantation__region
=poste
.implantation
.region
)
106 for p
in postes_region
:
107 dossiers
= p
.get_dossiers()
108 if len(dossiers
) > 0 and dossiers
[0].poste1
.type_poste
.famille_emploi
== famille
:
109 comparaison_dossiers
.append(dossiers
[0])
110 # poste RHv1 (vieux dossiers)
111 postes_region
= rh
.Poste
.objects
.filter(implantation__region
=poste
.implantation
.region
)
112 for p
in postes_region
:
113 dossiers
= p
.poste1
.all().order_by('rh_v1_dossier.date_creation') # through key incohérente... (dossiers)
114 if len(dossiers
) > 0 and dossiers
[0].poste1
.type_poste
.famille_emploi
== famille
:
115 comparaison_dossiers
.append(dossiers
[0])
116 return comparaison_dossiers
120 def embauche_consulter(request
, dossier_id
):
121 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier_id
)
124 'comparaison_dossiers' : get_dossiers_connexes(dossier
.poste
),
126 return render_to_response('dae/embauche_consulter.html', vars, RequestContext(request
))
129 def embauche(request
, key
=None, dossier
=None):
130 """ Formulaire d'autorisation d'embauche. """
132 vars = dict(step
='poste', form
=ChoosePosteForm())
134 type_remun
= filtered_type_remun()
135 vars = dict(type_remun
=type_remun
)
136 source
, id = key
.split('-')
139 poste
= get_object_or_404(dae
.Poste
, pk
=id)
144 if request
.POST
['employe'] == '':
146 employe
= dae
.Employe()
148 employe_source
, id = request
.POST
['employe'].split('-')
149 if employe_source
== 'dae':
151 employe
= get_object_or_404(dae
.Employe
, pk
=id)
152 elif employe_source
== 'rh':
153 # Employé RH, on le copie dans DAE
154 e
= get_object_or_404(rh
.Employe
, pk
=id)
155 employe
= dae
.Employe(id_rh
=e
, prenom
=e
.prenom
, nom
=e
.nom
,
160 employe_form
= EmployeForm(request
.POST
, instance
=employe
)
162 if 'save' in request
.POST
:
163 if employe_form
.is_valid():
164 data
= dict(request
.POST
.items())
165 #with warnings.catch_warnings():
166 # warnings.simplefilter('ignore')
167 employe
= employe_form
.save()
168 data
['employe'] = 'dae-%s' % employe
.id
169 employe_form
= EmployeForm(data
, instance
=employe
)
172 dossier
= dae
.Dossier(poste
=poste
, employe
=employe
)
174 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier
)
175 dossier_form
= DossierForm(request
.POST
, instance
=dossier
)
176 piecesForm
= DossierPieceForm(request
.POST
, request
.FILES
, instance
=dossier
)
177 justificationsNouveauForm
= JustificationNouvelEmployeForm(request
.POST
, instance
=dossier
)
178 justificationsAutreForm
= JustificationAutreEmployeForm(request
.POST
, instance
=dossier
)
180 if dossier_form
.is_valid() and piecesForm
.is_valid() and justificationsNouveauForm
.is_valid() and justificationsAutreForm
.is_valid():
181 dossier
= dossier_form
.save()
182 piecesForm
.instance
= dossier
184 justificationsNouveauForm
.instance
= dossier
185 justificationsNouveauForm
.save()
186 justificationsAutreForm
.instance
= dossier
187 justificationsAutreForm
.save()
188 if not dossier
.remuneration_set
.all():
189 # Pré-peuplement des entrées de la section "coût
190 # global", à l'exclusion de "Indemnité de fonction"
191 for type in type_remun
.all():
192 dae
.Remuneration(dossier
=dossier
, type=type,
193 devise
=dossier
.devise
).save()
196 # Sauvegarde du coût global
197 cg_lines
= defaultdict(dict)
198 for k
, v
in request
.POST
.items():
199 if k
.startswith('cg-'):
200 prefix
, field_name
, cg_id
= k
.split('-')
201 cg_lines
[int(cg_id
)][unicode(field_name
)] = v
203 for r
in dossier
.remuneration_set
.all():
204 print 'trying %r' % r
206 if cg_lines
[r
.id]['montant'] == '':
209 for k
, v
in cg_lines
[r
.id].items():
213 messages
.add_message(request
, messages
.SUCCESS
, "Le dossier %s a été sauvegardé." % dossier
)
214 return redirect('embauche_consulter', dossier_id
=dossier
.id)
216 messages
.add_message(request
, messages
.ERROR
, 'Il y a des erreurs dans le formulaire.')
219 dossier_form
= DossierForm(instance
=dossier
)
220 piecesForm
= DossierPieceForm(instance
=dossier
)
221 justificationsNouveauForm
= JustificationNouvelEmployeForm(instance
=dossier
)
222 justificationsAutreForm
= JustificationAutreEmployeForm(instance
=dossier
)
224 # Initialisation d'un formulaire vide
225 dossier_rh
= rh
.Dossier()
226 poste_rh
= poste
.id_rh
228 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier
)
229 employe
= dossier
.employe
230 data
= dict(employe
='dae-%s' % employe
.id)
231 employe_form
= EmployeForm(initial
=data
, instance
=employe
)
233 dossier
= pre_filled_dossier(dossier_rh
, 'new', poste_rh
)
234 employe_form
= EmployeForm()
236 dossier_form
= DossierForm(instance
=dossier
)
237 piecesForm
= DossierPieceForm(instance
=dossier
)
238 justificationsNouveauForm
= JustificationNouvelEmployeForm(instance
=dossier
)
239 justificationsAutreForm
= JustificationAutreEmployeForm(instance
=dossier
)
241 vars = dict(step
='employe',
242 type_remun
=type_remun
,
245 piecesForm
=piecesForm
,
246 justificationsNouveauForm
=justificationsNouveauForm
,
247 justificationsAutreForm
=justificationsAutreForm
,
248 comparaison_dossiers
=get_dossiers_connexes(poste
),
249 forms
=dict(employe
=employe_form
, dossier
=dossier_form
, )
253 return render_to_response('dae/embauche.html', vars,
254 RequestContext(request
))
256 def embauches_liste(request
):
257 """ Liste des embauches. """
259 vars['embauches'] = dae
.Dossier
.objects
.all().order_by('-date_creation')
260 return render_to_response('dae/embauches_liste.html', vars, RequestContext(request
))
262 def employe(request
, key
):
263 """ Récupération AJAX de l'employé pour la page d'embauche. """
264 data
= dict(employe
=key
)
268 employe
= dae
.Employe()
271 source
, id = key
.split('-')
274 employe
= get_object_or_404(dae
.Employe
, pk
=id)
276 e
= get_object_or_404(rh
.Employe
, id=id)
277 # Initialisation avec les valeurs de l'employé de rh_v1
278 employe
= dae
.Employe(id_rh
=e
)
279 for field
in ('prenom', 'nom', 'genre'):
280 setattr(employe
, field
, getattr(e
, field
))
282 return HttpResponse(EmployeForm(initial
=data
, instance
=employe
).as_table())
284 def dossier(request
, poste_key
, employe_key
):
285 """ Récupération AJAX du dossier pour la page d'embauche. """
288 poste_source
, poste_id
= poste_key
.split('-')
289 poste
= get_object_or_404(dae
.Poste
, pk
=poste_id
)
291 # Récupérer la devise de l'implantation lié au poste
292 implantation_devise
= poste
.get_default_devise()
293 data
.update({'devise' : implantation_devise
.id})
295 if poste
.id_rh_id
is not None:
296 poste_rh
= get_object_or_404(rh
.Poste
, pk
=poste
.id_rh_id
)
300 ##########################################################################################
302 ##########################################################################################
303 if employe_key
== '':
304 employe_source
= 'new'
306 dossier_rh
= rh
.Dossier()
307 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
309 ##########################################################################################
311 ##########################################################################################
312 if employe_key
.startswith('dae'):
313 employe_source
, employe_id
= employe_key
.split('-')
314 employe_dae
= get_object_or_404(dae
.Employe
, pk
=employe_id
)
316 # récupération de l'ancien dossier rh v1 pour l'employe DAE
318 dossier_rh
= rh
.Dossier
.objects
.get(employe
=employe_dae
.id_rh_id
, mandat_date_fin
=None)
319 except (rh
.Dossier
.DoesNotExist
):
320 dossier_rh
= rh
.Dossier()
322 # on tente de récupérer le dossier DAE, au pire on le contruit en le
323 # prépoluant avec son dossier rh v1.
325 dossier
= dae
.Dossier
.objects
.get(employe
=employe_dae
, poste
=poste
)
326 except (dae
.Dossier
.DoesNotExist
):
327 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
328 employe
= employe_dae
.id_rh
329 ##########################################################################################
331 ##########################################################################################
332 if employe_key
.startswith('rh'):
333 employe_source
, employe_id
= employe_key
.split('-')
334 employe_rh
= get_object_or_404(rh
.Employe
, pk
=employe_id
)
336 # récupération de l'ancien dossier rh v1 pour l'employe rh v1, s'il n'en a pas,
337 # on en fournit un nouveau qui servira uniquement un créer un nouveau dossier DAE.
339 dossier_rh
= rh
.Dossier
.objects
.get(employe
=employe_rh
, mandat_date_fin
=None)
340 except (rh
.Dossier
.DoesNotExist
):
341 dossier_rh
= rh
.Dossier()
342 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
345 dossier_form
= DossierForm(initial
=data
, instance
=dossier
)
346 vars = dict(form
=dossier_form
, poste
=poste
, employe
=employe
)
347 return render_to_response('dae/embauche-dossier.html', vars,
348 RequestContext(request
))
350 def salaire(request
, implantation
, devise
, classement
):
351 if not devise
or not classement
:
354 taux_impl
= rh
.TauxChange
.objects
.filter(implantation
=implantation
) \
356 taux
= rh
.TauxChange
.objects
.filter(devise
=devise
).order_by('-annee')
357 vp
= rh
.ValeurPoint
.objects
.filter(implantation
=implantation
) \
359 if vp
.count() * taux
.count() * taux_impl
.count() == 0:
362 classement
= get_object_or_404(rh
.Classement
, pk
=classement
)
363 taux
, taux_impl
, vp
= taux
[0].taux
, taux_impl
[0].taux
, vp
[0].valeur
365 salaire_euro
= round(vp
* classement
.coefficient
* taux_impl
, 2)
366 data
= dict(salaire_euro
=salaire_euro
, taux
=taux
,
367 salaire_devise
=round(salaire_euro
/ taux
, 2))
369 return HttpResponse(dumps(data
))
371 def pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
):
372 dossier
= dae
.Dossier()
374 if employe_source
!= 'new' and dossier_rh
.id:
375 dossier
.statut_anterieur
= dossier_rh
.statut
377 # Certains dossiers ont un classement à zéro
378 if dossier_rh
.classement_id
> 0:
379 dossier
.classement_anterieur
= dossier_rh
.classement
381 # Récupération du salaire de base
382 remun
= dossier_rh
.remuneration_set
.filter(type=1)
384 dossier
.salaire_anterieur
= remun
[0].montant
386 # Récupération du titulaire précédent
388 dossiers
= rh
.Dossier
.objects
.order_by('-mandat_date_fin')
389 dossiers
= dossiers
.filter(poste1
=poste_rh
) | dossiers
.filter(poste2
=poste_rh
)
391 # Ce bloc ignore toutes les erreurs, car les données de rh
392 # manquantes peuvent en générer
395 titulaire
= d
.employe
396 dossier
.employe_anterieur
= titulaire
397 dossier
.classement_titulaire_anterieur
= d
.classement
398 dossier
.statut_titulaire_anterieur
= d
.statut
399 dossier
.salaire_titulaire_anterieur
= \
400 d
.remuneration_set
.all()[0].montant
403 # TODO: afficher l'info, les champs ne sont pas dans le
404 # modèle dae.Dossier: nom, prenom, classement, salaire
407 except (rh
.Dossier
.DoesNotExist
):
408 dossier_rh
= rh
.Dossier()
412 def coefficient(request
):
417 method
= request
.method
418 params
= getattr(request
, method
, [])
420 if 'classement' in params
and params
.get('classement') is not u
"":
421 classement
= params
.get('classement')
422 classement
= rh
.Classement
.objects
.get(pk
=classement
)
423 data
['coefficient'] = classement
.coefficient
425 data
['coefficient'] = 0
426 return HttpResponse(dumps(data
))
429 def liste_valeurs_point(request
):
431 input : implantation_id
432 output : JSON liste de valeur point
434 method
= request
.method
435 params
= getattr(request
, method
, [])
437 annee_courante
= datetime
.datetime
.now().year
438 if 'implantation_id' in params
and params
.get('implantation_id') is not u
"":
439 implantation_id
= params
.get('implantation_id')
440 objects
= rh
.ValeurPoint
.objects
.filter(implantation
=implantation_id
, annee__in
=(annee_courante
-1, annee_courante
)).order_by("-annee")
442 objects
= rh
.ValeurPoint
.objects
.filter(annee__in
=(annee_courante
-1, annee_courante
)).order_by("-annee")
444 data
.append({'id' : o
.id, 'label' : o
.__unicode__(), })
445 return HttpResponse(dumps(data
))
447 def liste_postes(request
):
449 input : implantation_id
450 output : JSON liste de valeur point
452 method
= request
.method
453 params
= getattr(request
, method
, [])
456 # Voir le code de _poste_choices dans forms.py
457 dae_
= dae
.Poste
.objects
.filter(actif
=True, id_rh__isnull
=True)
458 copies
= dae
.Poste
.objects
.exclude(id_rh__isnull
=True)
459 rh_postes_actifs
= rh
.Poste
.objects
.filter(actif
=True)
461 if 'implantation_id' in params
and params
.get('implantation_id') is not u
"":
462 implantation_id
= params
.get('implantation_id')
463 dae_
= dae_
.filter(implantation__id
=implantation_id
)
464 copies
= copies
.filter(implantation__id
=implantation_id
)
465 rh_postes_actifs
= rh_postes_actifs
.filter(implantation__id
=implantation_id
)
467 id_copies
= [p
.id_rh_id
for p
in copies
.all()]
468 rhv1
= rh_postes_actifs
.exclude(id__in
=id_copies
)
469 rhv1
= rhv1
.select_related(depth
=1)
471 data
= [('', 'Nouveau poste')] + sorted([('dae-%s' % p
.id, label_poste_display(p
)) for p
in dae_ | copies
] + [('rh-%s' % p
.id, label_poste_display(p
)) for p
in rhv1
], key
=lambda t
: t
[1])
472 return HttpResponse(dumps(data
))
477 output : devise, devise_code, taux_euro
479 method
= request
.method
480 params
= getattr(request
, method
, [])
482 if 'valeur_point' in params
and params
.get('valeur_point') is not u
"":
483 valeur_point
= params
.get('valeur_point')
484 valeur_point
= rh
.ValeurPoint
.objects
.get(pk
=valeur_point
)
485 annee
= valeur_point
.annee
486 implantation
= valeur_point
.implantation
487 taux
= rh
.TauxChange
.objects
.get(annee
=annee
,
488 implantation
=implantation
)
489 data
['devise'] = taux
.devise
.id
490 data
['valeur'] = valeur_point
.valeur
491 data
['devise_code'] = taux
.devise
.code
492 data
['taux_euro'] = taux
.taux
494 return HttpResponseGone("Vous devez choisir une valeur de point")
495 return HttpResponse(dumps(data
))
497 def devise_code(request
):
500 output : devise_code, taux_euro
502 method
= request
.method
503 params
= getattr(request
, method
, [])
505 if 'devise' in params
:
506 devise
= params
.get('devise')
507 devise
= rh
.Devise
.objects
.get(pk
=devise
)
508 annee
= date
.today().year
509 taux
= rh
.TauxChange
.objects
.filter(annee
=annee
, devise
=devise
)
511 return HttpResponseGone("Le taux n'est pas disponible")
512 data
['devise_code'] = devise
.code
513 data
['taux_euro'] = taux
[0].taux
514 return HttpResponse(dumps(data
))
516 def add_remun(request
, dossier
, type_remun
):
517 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier
)
518 type_remun
= get_object_or_404(rh
.TypeRemuneration
, pk
=type_remun
)
519 dae
.Remuneration(dossier
=dossier
, devise
=dossier
.devise
,
520 type=type_remun
).save()
522 return render_to_response('dae/embauche-remun.html', dict(dossier
=dossier
),
523 RequestContext(request
))