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
)
162 justificationsNouveauForm
= JustificationNouvelEmployeForm(request
.POST
, instance
=dossier
)
163 justificationsAutreForm
= JustificationAutreEmployeForm(request
.POST
, instance
=dossier
)
165 if dossier_form
.is_valid() and piecesForm
.is_valid() and justificationsNouveauForm
.is_valid() and justificationsAutreForm
.is_valid():
166 dossier
= dossier_form
.save()
167 piecesForm
.instance
= dossier
169 justificationsNouveauForm
.instance
= dossier
170 justificationsNouveauForm
.save()
171 justificationsAutreForm
.instance
= dossier
172 justificationsAutreForm
.save()
173 if not dossier
.remuneration_set
.all():
174 # Pré-peuplement des entrées de la section "coût
175 # global", à l'exclusion de "Indemnité de fonction"
176 for type in type_remun
.all():
177 dae
.Remuneration(dossier
=dossier
, type=type,
178 devise
=dossier
.devise
).save()
181 # Sauvegarde du coût global
182 cg_lines
= defaultdict(dict)
183 for k
, v
in request
.POST
.items():
184 if k
.startswith('cg-'):
185 prefix
, field_name
, cg_id
= k
.split('-')
186 cg_lines
[int(cg_id
)][unicode(field_name
)] = v
188 for r
in dossier
.remuneration_set
.all():
189 print 'trying %r' % r
191 if cg_lines
[r
.id]['montant'] == '':
194 for k
, v
in cg_lines
[r
.id].items():
198 messages
.add_message(request
, messages
.SUCCESS
, "Le dossier %s a été sauvegardé." % dossier
)
199 return redirect('embauche', key
='dae-%s' % poste
.id,
202 messages
.add_message(request
, messages
.ERROR
, 'Il y a des erreurs dans le formulaire.')
205 dossier_form
= DossierForm(instance
=dossier
)
206 piecesForm
= DossierPieceForm(instance
=dossier
)
207 justificationsNouveauForm
= JustificationNouvelEmployeForm(instance
=dossier
)
208 justificationsAutreForm
= JustificationAutreEmployeForm(instance
=dossier
)
210 # Initialisation d'un formulaire vide
211 dossier_rh
= rh
.Dossier()
212 poste_rh
= poste
.id_rh
214 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier
)
215 employe
= dossier
.employe
216 data
= dict(employe
='dae-%s' % employe
.id)
217 employe_form
= EmployeForm(initial
=data
, instance
=employe
)
219 dossier
= pre_filled_dossier(dossier_rh
, 'new', poste_rh
)
220 employe_form
= EmployeForm()
222 dossier_form
= DossierForm(instance
=dossier
)
223 piecesForm
= DossierPieceForm(instance
=dossier
)
224 justificationsNouveauForm
= JustificationNouvelEmployeForm(instance
=dossier
)
225 justificationsAutreForm
= JustificationAutreEmployeForm(instance
=dossier
)
227 vars = dict(step
='employe',
230 piecesForm
=piecesForm
,
231 justificationsNouveauForm
=justificationsNouveauForm
,
232 justificationsAutreForm
=justificationsAutreForm
,
233 forms
=dict(employe
=employe_form
, dossier
=dossier_form
, )
236 return render_to_response('dae/embauche.html', vars,
237 RequestContext(request
))
239 def embauches_liste(request
):
240 """ Liste des embauches. """
242 vars['embauches'] = []
243 for d
in dae
.Dossier
.objects
.all().order_by('-date_creation'):
244 versions
= Version
.objects
.get_for_object(d
)
245 if len(versions
) > 0:
246 premiere_revision
= versions
[0].revision
248 premiere_revision
= None
249 vars['embauches'].append((d
, premiere_revision
))
250 return render_to_response('dae/embauches_liste.html', vars,
251 RequestContext(request
))
253 def employe(request
, key
):
254 """ Récupération AJAX de l'employé pour la page d'embauche. """
255 data
= dict(employe
=key
)
259 employe
= dae
.Employe()
262 source
, id = key
.split('-')
265 employe
= get_object_or_404(dae
.Employe
, pk
=id)
267 e
= get_object_or_404(rh
.Employe
, id=id)
268 # Initialisation avec les valeurs de l'employé de rh_v1
269 employe
= dae
.Employe(id_rh
=e
)
270 for field
in ('prenom', 'nom', 'genre'):
271 setattr(employe
, field
, getattr(e
, field
))
273 return HttpResponse(EmployeForm(initial
=data
, instance
=employe
).as_table())
275 def dossier(request
, poste_key
, employe_key
):
276 """ Récupération AJAX du dossier pour la page d'embauche. """
279 poste_source
, poste_id
= poste_key
.split('-')
280 poste
= get_object_or_404(dae
.Poste
, pk
=poste_id
)
282 # Récupérer la devise de l'implantation lié au poste
283 implantation_devise
= poste
.get_default_devise()
284 data
.update({'devise' : implantation_devise
.id})
286 if poste
.id_rh_id
is not None:
287 poste_rh
= get_object_or_404(rh
.Poste
, pk
=poste
.id_rh_id
)
291 ##########################################################################################
293 ##########################################################################################
294 if employe_key
== '':
295 employe_source
= 'new'
297 dossier_rh
= rh
.Dossier()
298 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
300 ##########################################################################################
302 ##########################################################################################
303 if employe_key
.startswith('dae'):
304 employe_source
, employe_id
= employe_key
.split('-')
305 employe_dae
= get_object_or_404(dae
.Employe
, pk
=employe_id
)
307 # récupération de l'ancien dossier rh v1 pour l'employe DAE
309 dossier_rh
= rh
.Dossier
.objects
.get(employe
=employe_dae
.id_rh_id
, mandat_date_fin
=None)
310 except (rh
.Dossier
.DoesNotExist
):
311 dossier_rh
= rh
.Dossier()
313 # on tente de récupérer le dossier DAE, au pire on le contruit en le
314 # prépoluant avec son dossier rh v1.
316 dossier
= dae
.Dossier
.objects
.get(employe
=employe_dae
, poste
=poste
)
317 except (dae
.Dossier
.DoesNotExist
):
318 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
319 employe
= employe_dae
.id_rh
320 ##########################################################################################
322 ##########################################################################################
323 if employe_key
.startswith('rh'):
324 employe_source
, employe_id
= employe_key
.split('-')
325 employe_rh
= get_object_or_404(rh
.Employe
, pk
=employe_id
)
327 # récupération de l'ancien dossier rh v1 pour l'employe rh v1, s'il n'en a pas,
328 # on en fournit un nouveau qui servira uniquement un créer un nouveau dossier DAE.
330 dossier_rh
= rh
.Dossier
.objects
.get(employe
=employe_rh
, mandat_date_fin
=None)
331 except (rh
.Dossier
.DoesNotExist
):
332 dossier_rh
= rh
.Dossier()
333 dossier
= pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
)
336 dossier_form
= DossierForm(initial
=data
, instance
=dossier
)
337 vars = dict(form
=dossier_form
, poste
=poste
, employe
=employe
)
338 return render_to_response('dae/embauche-dossier.html', vars,
339 RequestContext(request
))
341 def salaire(request
, implantation
, devise
, classement
):
342 if not devise
or not classement
:
345 taux_impl
= rh
.TauxChange
.objects
.filter(implantation
=implantation
) \
347 taux
= rh
.TauxChange
.objects
.filter(devise
=devise
).order_by('-annee')
348 vp
= rh
.ValeurPoint
.objects
.filter(implantation
=implantation
) \
350 if vp
.count() * taux
.count() * taux_impl
.count() == 0:
353 classement
= get_object_or_404(rh
.Classement
, pk
=classement
)
354 taux
, taux_impl
, vp
= taux
[0].taux
, taux_impl
[0].taux
, vp
[0].valeur
356 salaire_euro
= round(vp
* classement
.coefficient
* taux_impl
, 2)
357 data
= dict(salaire_euro
=salaire_euro
, taux
=taux
,
358 salaire_devise
=round(salaire_euro
/ taux
, 2))
360 return HttpResponse(dumps(data
))
362 def pre_filled_dossier(dossier_rh
, employe_source
, poste_rh
):
363 dossier
= dae
.Dossier()
365 if employe_source
!= 'new' and dossier_rh
.id:
366 dossier
.statut_anterieur
= dossier_rh
.statut
368 # Certains dossiers ont un classement à zéro
369 if dossier_rh
.classement_id
> 0:
370 dossier
.classement_anterieur
= dossier_rh
.classement
372 # Récupération du salaire de base
373 remun
= dossier_rh
.remuneration_set
.filter(type=1)
375 dossier
.salaire_anterieur
= remun
[0].montant
377 # Récupération du titulaire précédent
379 dossiers
= rh
.Dossier
.objects
.order_by('-mandat_date_fin')
380 dossiers
= dossiers
.filter(poste1
=poste_rh
) | dossiers
.filter(poste2
=poste_rh
)
382 # Ce bloc ignore toutes les erreurs, car les données de rh
383 # manquantes peuvent en générer
386 titulaire
= d
.employe
387 dossier
.employe_anterieur
= titulaire
388 dossier
.classement_titulaire_anterieur
= d
.classement
389 dossier
.statut_titulaire_anterieur
= d
.statut
390 dossier
.salaire_titulaire_anterieur
= \
391 d
.remuneration_set
.all()[0].montant
394 # TODO: afficher l'info, les champs ne sont pas dans le
395 # modèle dae.Dossier: nom, prenom, classement, salaire
398 except (rh
.Dossier
.DoesNotExist
):
399 dossier_rh
= rh
.Dossier()
403 def coefficient(request
):
408 method
= request
.method
409 params
= getattr(request
, method
, [])
411 if 'classement' in params
and params
.get('classement') is not u
"":
412 classement
= params
.get('classement')
413 classement
= rh
.Classement
.objects
.get(pk
=classement
)
414 data
['coefficient'] = classement
.coefficient
416 data
['coefficient'] = 0
417 return HttpResponse(dumps(data
))
420 def liste_valeurs_point(request
):
422 input : implantation_id
423 output : JSON liste de valeur point
425 method
= request
.method
426 params
= getattr(request
, method
, [])
428 annee_courante
= datetime
.datetime
.now().year
429 if 'implantation_id' in params
and params
.get('implantation_id') is not u
"":
430 implantation_id
= params
.get('implantation_id')
431 objects
= rh
.ValeurPoint
.objects
.filter(implantation
=implantation_id
, annee__in
=(annee_courante
-1, annee_courante
)).order_by("-annee")
433 objects
= rh
.ValeurPoint
.objects
.filter(annee__in
=(annee_courante
-1, annee_courante
)).order_by("-annee")
435 data
.append({'id' : o
.id, 'label' : o
.__unicode__(), })
436 return HttpResponse(dumps(data
))
441 output : devise, devise_code, taux_euro
443 method
= request
.method
444 params
= getattr(request
, method
, [])
446 if 'valeur_point' in params
and params
.get('valeur_point') is not u
"":
447 valeur_point
= params
.get('valeur_point')
448 valeur_point
= rh
.ValeurPoint
.objects
.get(pk
=valeur_point
)
449 annee
= valeur_point
.annee
450 implantation
= valeur_point
.implantation
451 taux
= rh
.TauxChange
.objects
.get(annee
=annee
,
452 implantation
=implantation
)
453 data
['devise'] = taux
.devise
.id
454 data
['valeur'] = valeur_point
.valeur
455 data
['devise_code'] = taux
.devise
.code
456 data
['taux_euro'] = taux
.taux
458 return HttpResponseGone("Vous devez choisir une valeur de point")
459 return HttpResponse(dumps(data
))
461 def devise_code(request
):
464 output : devise_code, taux_euro
466 method
= request
.method
467 params
= getattr(request
, method
, [])
469 if 'devise' in params
:
470 devise
= params
.get('devise')
471 devise
= rh
.Devise
.objects
.get(pk
=devise
)
472 annee
= date
.today().year
473 taux
= rh
.TauxChange
.objects
.filter(annee
=annee
, devise
=devise
)
475 return HttpResponseGone("Le taux n'est pas disponible")
476 data
['devise_code'] = devise
.code
477 data
['taux_euro'] = taux
[0].taux
478 return HttpResponse(dumps(data
))
480 def add_remun(request
, dossier
, type_remun
):
481 dossier
= get_object_or_404(dae
.Dossier
, pk
=dossier
)
482 type_remun
= get_object_or_404(rh
.TypeRemuneration
, pk
=type_remun
)
483 dae
.Remuneration(dossier
=dossier
, devise
=dossier
.devise
,
484 type=type_remun
).save()
486 return render_to_response('dae/embauche-remun.html', dict(dossier
=dossier
),
487 RequestContext(request
))