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', 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', key
='dae-%s' % poste
.id,
217 messages
.add_message(request
, messages
.ERROR
, 'Il y a des erreurs dans le formulaire.')
220 dossier_form
= DossierForm(instance
=dossier
)
221 piecesForm
= DossierPieceForm(instance
=dossier
)
222 justificationsNouveauForm
= JustificationNouvelEmployeForm(instance
=dossier
)
223 justificationsAutreForm
= JustificationAutreEmployeForm(instance
=dossier
)
225 # Initialisation d'un formulaire vide
226 dossier_rh
= rh
.Dossier()
227 poste_rh
= poste
.id_rh
229 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier
)
230 employe
= dossier
.employe
231 data
= dict(employe
='dae-%s' % employe
.id)
232 employe_form
= EmployeForm(initial
=data
, instance
=employe
)
234 dossier
= pre_filled_dossier(dossier_rh
, 'new', poste_rh
)
235 employe_form
= EmployeForm()
237 dossier_form
= DossierForm(instance
=dossier
)
238 piecesForm
= DossierPieceForm(instance
=dossier
)
239 justificationsNouveauForm
= JustificationNouvelEmployeForm(instance
=dossier
)
240 justificationsAutreForm
= JustificationAutreEmployeForm(instance
=dossier
)
242 vars = dict(step
='employe',
243 type_remun
=type_remun
,
246 piecesForm
=piecesForm
,
247 justificationsNouveauForm
=justificationsNouveauForm
,
248 justificationsAutreForm
=justificationsAutreForm
,
249 comparaison_dossiers
=get_dossiers_connexes(poste
),
250 forms
=dict(employe
=employe_form
, dossier
=dossier_form
, )
254 return render_to_response('dae/embauche.html', vars,
255 RequestContext(request
))
257 def embauches_liste(request
):
258 """ Liste des embauches. """
260 vars['embauches'] = dae
.Dossier
.objects
.all().order_by('-date_creation')
261 return render_to_response('dae/embauches_liste.html', vars, RequestContext(request
))
263 def employe(request
, key
):
264 """ Récupération AJAX de l'employé pour la page d'embauche. """
265 data
= dict(employe
=key
)
269 employe
= dae
.Employe()
272 source
, id = key
.split('-')
275 employe
= get_object_or_404(dae
.Employe
, pk
=id)
277 e
= get_object_or_404(rh
.Employe
, id=id)
278 # Initialisation avec les valeurs de l'employé de rh_v1
279 employe
= dae
.Employe(id_rh
=e
)
280 for field
in ('prenom', 'nom', 'genre'):
281 setattr(employe
, field
, getattr(e
, field
))
283 return HttpResponse(EmployeForm(initial
=data
, instance
=employe
).as_table())
285 def dossier(request
, poste_key
, employe_key
):
286 """ Récupération AJAX du dossier pour la page d'embauche. """
289 poste_source
, poste_id
= poste_key
.split('-')
290 poste
= get_object_or_404(dae
.Poste
, pk
=poste_id
)
292 # Récupérer la devise de l'implantation lié au poste
293 implantation_devise
= poste
.get_default_devise()
294 data
.update({'devise' : implantation_devise
.id})
296 if poste
.id_rh_id
is not None:
297 poste_rh
= get_object_or_404(rh
.Poste
, pk
=poste
.id_rh_id
)
301 ##########################################################################################
303 ##########################################################################################
304 if employe_key
== '':
305 employe_source
= 'new'
307 dossier_rh
= rh
.Dossier()
308 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
310 ##########################################################################################
312 ##########################################################################################
313 if employe_key
.startswith('dae'):
314 employe_source
, employe_id
= employe_key
.split('-')
315 employe_dae
= get_object_or_404(dae
.Employe
, pk
=employe_id
)
317 # récupération de l'ancien dossier rh v1 pour l'employe DAE
319 dossier_rh
= rh
.Dossier
.objects
.get(employe
=employe_dae
.id_rh_id
, mandat_date_fin
=None)
320 except (rh
.Dossier
.DoesNotExist
):
321 dossier_rh
= rh
.Dossier()
323 # on tente de récupérer le dossier DAE, au pire on le contruit en le
324 # prépoluant avec son dossier rh v1.
326 dossier
= dae
.Dossier
.objects
.get(employe
=employe_dae
, poste
=poste
)
327 except (dae
.Dossier
.DoesNotExist
):
328 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
329 employe
= employe_dae
.id_rh
330 ##########################################################################################
332 ##########################################################################################
333 if employe_key
.startswith('rh'):
334 employe_source
, employe_id
= employe_key
.split('-')
335 employe_rh
= get_object_or_404(rh
.Employe
, pk
=employe_id
)
337 # récupération de l'ancien dossier rh v1 pour l'employe rh v1, s'il n'en a pas,
338 # on en fournit un nouveau qui servira uniquement un créer un nouveau dossier DAE.
340 dossier_rh
= rh
.Dossier
.objects
.get(employe
=employe_rh
, mandat_date_fin
=None)
341 except (rh
.Dossier
.DoesNotExist
):
342 dossier_rh
= rh
.Dossier()
343 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
346 dossier_form
= DossierForm(initial
=data
, instance
=dossier
)
347 vars = dict(form
=dossier_form
, poste
=poste
, employe
=employe
)
348 return render_to_response('dae/embauche-dossier.html', vars,
349 RequestContext(request
))
351 def salaire(request
, implantation
, devise
, classement
):
352 if not devise
or not classement
:
355 taux_impl
= rh
.TauxChange
.objects
.filter(implantation
=implantation
) \
357 taux
= rh
.TauxChange
.objects
.filter(devise
=devise
).order_by('-annee')
358 vp
= rh
.ValeurPoint
.objects
.filter(implantation
=implantation
) \
360 if vp
.count() * taux
.count() * taux_impl
.count() == 0:
363 classement
= get_object_or_404(rh
.Classement
, pk
=classement
)
364 taux
, taux_impl
, vp
= taux
[0].taux
, taux_impl
[0].taux
, vp
[0].valeur
366 salaire_euro
= round(vp
* classement
.coefficient
* taux_impl
, 2)
367 data
= dict(salaire_euro
=salaire_euro
, taux
=taux
,
368 salaire_devise
=round(salaire_euro
/ taux
, 2))
370 return HttpResponse(dumps(data
))
372 def pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
):
373 dossier
= dae
.Dossier()
375 if employe_source
!= 'new' and dossier_rh
.id:
376 dossier
.statut_anterieur
= dossier_rh
.statut
378 # Certains dossiers ont un classement à zéro
379 if dossier_rh
.classement_id
> 0:
380 dossier
.classement_anterieur
= dossier_rh
.classement
382 # Récupération du salaire de base
383 remun
= dossier_rh
.remuneration_set
.filter(type=1)
385 dossier
.salaire_anterieur
= remun
[0].montant
387 # Récupération du titulaire précédent
389 dossiers
= rh
.Dossier
.objects
.order_by('-mandat_date_fin')
390 dossiers
= dossiers
.filter(poste1
=poste_rh
) | dossiers
.filter(poste2
=poste_rh
)
392 # Ce bloc ignore toutes les erreurs, car les données de rh
393 # manquantes peuvent en générer
396 titulaire
= d
.employe
397 dossier
.employe_anterieur
= titulaire
398 dossier
.classement_titulaire_anterieur
= d
.classement
399 dossier
.statut_titulaire_anterieur
= d
.statut
400 dossier
.salaire_titulaire_anterieur
= \
401 d
.remuneration_set
.all()[0].montant
404 # TODO: afficher l'info, les champs ne sont pas dans le
405 # modèle dae.Dossier: nom, prenom, classement, salaire
408 except (rh
.Dossier
.DoesNotExist
):
409 dossier_rh
= rh
.Dossier()
413 def coefficient(request
):
418 method
= request
.method
419 params
= getattr(request
, method
, [])
421 if 'classement' in params
and params
.get('classement') is not u
"":
422 classement
= params
.get('classement')
423 classement
= rh
.Classement
.objects
.get(pk
=classement
)
424 data
['coefficient'] = classement
.coefficient
426 data
['coefficient'] = 0
427 return HttpResponse(dumps(data
))
430 def liste_valeurs_point(request
):
432 input : implantation_id
433 output : JSON liste de valeur point
435 method
= request
.method
436 params
= getattr(request
, method
, [])
438 annee_courante
= datetime
.datetime
.now().year
439 if 'implantation_id' in params
and params
.get('implantation_id') is not u
"":
440 implantation_id
= params
.get('implantation_id')
441 objects
= rh
.ValeurPoint
.objects
.filter(implantation
=implantation_id
, annee__in
=(annee_courante
-1, annee_courante
)).order_by("-annee")
443 objects
= rh
.ValeurPoint
.objects
.filter(annee__in
=(annee_courante
-1, annee_courante
)).order_by("-annee")
445 data
.append({'id' : o
.id, 'label' : o
.__unicode__(), })
446 return HttpResponse(dumps(data
))
448 def liste_postes(request
):
450 input : implantation_id
451 output : JSON liste de valeur point
453 method
= request
.method
454 params
= getattr(request
, method
, [])
457 # Voir le code de _poste_choices dans forms.py
458 dae_
= dae
.Poste
.objects
.filter(actif
=True, id_rh__isnull
=True)
459 copies
= dae
.Poste
.objects
.exclude(id_rh__isnull
=True)
460 rh_postes_actifs
= rh
.Poste
.objects
.filter(actif
=True)
462 if 'implantation_id' in params
and params
.get('implantation_id') is not u
"":
463 implantation_id
= params
.get('implantation_id')
464 dae_
= dae_
.filter(implantation__id
=implantation_id
)
465 copies
= copies
.filter(implantation__id
=implantation_id
)
466 rh_postes_actifs
= rh_postes_actifs
.filter(implantation__id
=implantation_id
)
468 id_copies
= [p
.id_rh_id
for p
in copies
.all()]
469 rhv1
= rh_postes_actifs
.exclude(id__in
=id_copies
)
470 rhv1
= rhv1
.select_related(depth
=1)
472 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])
473 return HttpResponse(dumps(data
))
478 output : devise, devise_code, taux_euro
480 method
= request
.method
481 params
= getattr(request
, method
, [])
483 if 'valeur_point' in params
and params
.get('valeur_point') is not u
"":
484 valeur_point
= params
.get('valeur_point')
485 valeur_point
= rh
.ValeurPoint
.objects
.get(pk
=valeur_point
)
486 annee
= valeur_point
.annee
487 implantation
= valeur_point
.implantation
488 taux
= rh
.TauxChange
.objects
.get(annee
=annee
,
489 implantation
=implantation
)
490 data
['devise'] = taux
.devise
.id
491 data
['valeur'] = valeur_point
.valeur
492 data
['devise_code'] = taux
.devise
.code
493 data
['taux_euro'] = taux
.taux
495 return HttpResponseGone("Vous devez choisir une valeur de point")
496 return HttpResponse(dumps(data
))
498 def devise_code(request
):
501 output : devise_code, taux_euro
503 method
= request
.method
504 params
= getattr(request
, method
, [])
506 if 'devise' in params
:
507 devise
= params
.get('devise')
508 devise
= rh
.Devise
.objects
.get(pk
=devise
)
509 annee
= date
.today().year
510 taux
= rh
.TauxChange
.objects
.filter(annee
=annee
, devise
=devise
)
512 return HttpResponseGone("Le taux n'est pas disponible")
513 data
['devise_code'] = devise
.code
514 data
['taux_euro'] = taux
[0].taux
515 return HttpResponse(dumps(data
))
517 def add_remun(request
, dossier
, type_remun
):
518 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier
)
519 type_remun
= get_object_or_404(rh
.TypeRemuneration
, pk
=type_remun
)
520 dae
.Remuneration(dossier
=dossier
, devise
=dossier
.devise
,
521 type=type_remun
).save()
523 return render_to_response('dae/embauche-remun.html', dict(dossier
=dossier
),
524 RequestContext(request
))