Merge branch 'reversion'
[auf_rh_dae.git] / project / dae / views.py
1 # -*- encoding: utf-8 -*-
2
3 from datetime import date, datetime
4
5 from auf.django.permissions.decorators import get_object
6 from django.contrib import messages
7 from django.contrib.auth.decorators import login_required
8 from django.contrib.contenttypes.models import ContentType
9 from django.core.exceptions import MultipleObjectsReturned
10 from django.core.paginator import Paginator, InvalidPage
11 from django.db.models import Q
12 from django.http import Http404, HttpResponse, HttpResponseGone
13 from django.shortcuts import redirect, render, get_object_or_404
14 from sendfile import sendfile
15 from simplejson import dumps
16
17 from project.dae import models as dae
18 from project.dae.decorators import \
19 dae_groupe_requis, \
20 poste_dans_ma_region_ou_service, \
21 dossier_dans_ma_region_ou_service, \
22 vieux_dossier_dans_ma_region_ou_service, \
23 employe_dans_ma_region_ou_service, \
24 dossier_est_modifiable, \
25 poste_est_modifiable, get_contrat
26 from project.dae.forms import FinancementFormSet, FinancementFormSetInitial
27 from project.dae.forms import PosteComparaisonFormSet, PosteComparaisonFormSetInitial
28 from project.dae.forms import \
29 PosteWorkflowForm, PosteForm, PostePieceFormSet, \
30 DossierWorkflowForm, ChoosePosteForm, \
31 EmployeForm, DossierForm, DossierPieceForm, \
32 DossierComparaisonFormSet, RemunForm, ContratForm, DAENumeriseeForm, \
33 label_poste_display, DAEFinaliseesSearchForm
34 from project.dae.mail import send_drh_finalisation_mail
35 from project.dae.workflow import \
36 DOSSIER_ETAT_FINALISE, DOSSIER_ETAT_REGION_FINALISATION, \
37 DOSSIER_ETAT_DRH_FINALISATION, POSTE_ETAT_FINALISE
38 from project.decorators import redirect_interdiction
39 from project.rh import models as rh
40
41
42 # Helpers
43
44 def devises():
45 liste = []
46 for d in rh.Devise.objects.all():
47 annee = date.today().year
48 taux = rh.TauxChange.objects.filter(annee=annee, devise=d)
49 data = {}
50 if len(taux) == 0:
51 data['taux_euro'] = 0
52 else:
53 data['taux_euro'] = taux[0].taux
54 data['devise_code'] = d.id
55 liste.append(data)
56 return liste
57
58
59 @dae_groupe_requis
60 def index(request):
61 return render(request, 'dae/index.html', {})
62
63
64 ### POSTE
65
66 @dae_groupe_requis
67 @poste_dans_ma_region_ou_service
68 def poste_consulter(request, key):
69 source, id = key.split('-')
70 poste = get_object_or_404(dae.Poste, pk=id)
71
72 if request.POST:
73 validationForm = PosteWorkflowForm(
74 request.POST, instance=poste, request=request
75 )
76 if validationForm.is_valid():
77 messages.add_message(
78 request, messages.SUCCESS, "La validation a été enregistrée."
79 )
80 return redirect('dae_postes_liste')
81 else:
82 validationForm = PosteWorkflowForm(instance=poste, request=request)
83
84 comparaisons_internes = \
85 poste.dae_comparaisons_internes.ma_region_ou_service(request.user)
86 vars = {
87 'poste': poste,
88 'validationForm': validationForm,
89 'comparaisons_internes': comparaisons_internes
90 }
91
92 return render(request, 'dae/poste_consulter.html', vars)
93
94
95 def poste_importer(request, id):
96 poste_dae = get_object_or_404(dae.Poste, id=id)
97 if request.method == 'POST':
98 if 'confirmer' in request.POST:
99 poste_rh = poste_dae.importer_dans_rh()
100 return redirect('admin:rh_poste_change', poste_rh.id)
101 else:
102 return redirect('poste_consulter', 'dae-' + id)
103 else:
104 c = {
105 'poste': poste_dae,
106 }
107 return render(request, 'dae/poste_importer.html', c)
108
109
110 @dae_groupe_requis
111 @poste_dans_ma_region_ou_service
112 @poste_est_modifiable
113 def poste(request, key=None):
114 """ Formulaire pour un poste.
115
116 Permet de créer ou modifier un poste. Si le poste n'existe que dans rh_v1
117 il est automatiquement copié dans dae.
118
119 """
120
121 def _dupliquer_poste(poste_dae, poste_rh):
122 """
123 Recopie les fields d'un poste RH dans un poste DAE
124 avec ceux-ci précédemment crées
125 """
126 exclus = ('id', 'supprime', 'date_creation',
127 'user_creation', 'date_modification',
128 'user_modification', )
129 fields = [f for f in poste_rh._meta.fields if f.name not in exclus]
130 for field in fields:
131 setattr(poste_dae, field.name, getattr(poste_rh, field.name))
132 return poste_dae
133
134 poste, data, vars = None, dict(), dict()
135
136 # Sans key, c'est un nouveau poste
137 if key is None:
138 new = True
139 else:
140 new = False
141
142 # Poste existant
143 poste_rh = None
144 if not new:
145 source, id = key.split('-')
146
147 if source == 'dae':
148 poste = get_object_or_404(dae.Poste, pk=id)
149 #data['poste'] = key
150 elif source == 'rh':
151 poste_rh = get_object_or_404(rh.Poste, pk=id)
152 poste = dae.Poste(id_rh=poste_rh)
153 # Initialisation avec les valeurs du poste de rh_v1
154 poste = _dupliquer_poste(poste, poste_rh)
155 #data['poste'] = 'rh-' + str(poste.id_rh_id)
156
157 # prépopuler pour la modification de poste
158 if poste_rh is not None:
159 FinancementForm = FinancementFormSetInitial
160 PosteComparaisonForm = PosteComparaisonFormSetInitial
161
162 qs_financements = poste_rh.rh_financements.all()
163 qs_comparaisons = poste_rh.rh_comparaisons_internes.all()
164 financements = [{'type': f.type, 'pourcentage': f.pourcentage,
165 'commentaire': f.commentaire} for f in qs_financements]
166 comparaisons = [{'implantation': c.implantation, 'nom': c.nom,
167 'montant': c.montant, 'devise': c.devise} for c in qs_comparaisons]
168 # formulaires normaux, avec modifications des objects FK
169 else:
170 FinancementForm = FinancementFormSet
171 PosteComparaisonForm = PosteComparaisonFormSet
172 financements = []
173 comparaisons = []
174
175
176 if request.POST:
177 data.update(dict(request.POST.items()))
178 form = PosteForm(data, instance=poste, request=request)
179 financementForm = FinancementForm(request.POST, instance=poste, )
180 piecesForm = PostePieceFormSet(request.POST, request.FILES, instance=poste, )
181 comparaisons_formset = PosteComparaisonForm(
182 request.POST,
183 instance=poste,
184 )
185 if form.is_valid() and piecesForm.is_valid() and \
186 financementForm.is_valid() and comparaisons_formset.is_valid():
187 poste = form.save()
188 piecesForm.instance = poste
189 piecesForm.save()
190 financementForm.instance = poste
191 financementForm.save()
192
193 # Ne remplacer que les comparaisons de ma région
194 comparaisons = comparaisons_formset.save(commit=False)
195 for comparaison in comparaisons:
196 comparaison.poste = poste
197 comparaison.save()
198
199 # dans le cas d'une modification de poste de RH, on recopie les PJ
200 if poste_rh is not None:
201 for piece in poste_rh.rh_pieces.all():
202 dae.PostePiece(poste=poste, nom=piece.nom,
203 fichier=piece.fichier).save()
204 messages.add_message(
205 request, messages.SUCCESS,
206 "Le poste %s a été sauvegardé." % poste
207 )
208 if 'save' in request.POST:
209 return redirect('poste_consulter', key='dae-%s' % poste.id)
210 else:
211 return redirect('poste', key='dae-%s' % poste.id)
212
213 else:
214 messages.add_message(
215 request, messages.ERROR,
216 'Il y a des erreurs dans le formulaire.'
217 )
218
219 else:
220 # 'initial' évite la validation prémature lors d'une copie de poste de
221 # rh_v1 vers dae.
222 form = PosteForm(initial=data, instance=poste, request=request)
223 piecesForm = PostePieceFormSet(instance=poste)
224
225 if poste_rh is not None:
226 financementForm = FinancementForm(initial=financements, instance=poste)
227 comparaisons_formset = PosteComparaisonForm(
228 initial=comparaisons,
229 instance=poste,
230 )
231 # cas de la création d'un nouveau poste
232 else:
233 financementForm = FinancementForm(instance=poste)
234 comparaisons_formset = PosteComparaisonForm(instance=poste)
235
236 vars.update(dict(
237 form=form, poste=poste, poste_key=key, piecesForm=piecesForm,
238 financementForm=financementForm,
239 comparaisons_formset=comparaisons_formset,
240 poste_rh=poste_rh,
241 ))
242
243 return render(request, 'dae/poste.html', vars)
244
245
246 @dae_groupe_requis
247 def postes_liste(request):
248 """ Liste des postes. """
249 content_type = ContentType.objects.get_for_model(dae.Poste)
250 extra_select = {'derniere_validation': (
251 "SELECT MAX(date) FROM workflow_workflowcommentaire "
252 "WHERE content_type_id = '%s' AND object_id = dae_poste.id" %
253 content_type.id
254 )}
255 postes_a_traiter = dae.Poste.objects.mes_choses_a_faire(request.user) \
256 .extra(select=extra_select).order_by('-id')
257 postes_en_cours = dae.Poste.objects.ma_region_ou_service(request.user) \
258 .extra(select=extra_select) \
259 .filter(~Q(etat=POSTE_ETAT_FINALISE)) \
260 .order_by('-id')
261 return render(request, 'dae/postes_liste.html', {
262 'postes_a_traiter': postes_a_traiter,
263 'postes_en_cours': postes_en_cours,
264 })
265
266
267 @login_required
268 def poste_piece(request, id, filename):
269 """Téléchargement d'une pièce jointe à un poste."""
270 piece = get_object_or_404(dae.PostePiece, pk=id)
271 if dae.Poste.objects.ma_region_ou_service(request.user) \
272 .filter(id=piece.poste_id).exists():
273 return sendfile(request, piece.fichier.path)
274 else:
275 return redirect_interdiction(request)
276
277
278 ### DOSSIER
279
280 def filtered_type_remun():
281 defaut = (2, 3, 8, 17) # salaire de base, indemnité de fonction,
282 # charges patronales
283 return rh.TypeRemuneration.objects.filter(pk__in=defaut)
284
285
286 @dae_groupe_requis
287 @dossier_dans_ma_region_ou_service
288 def embauche_consulter(request, dossier_id):
289 dossier = get_object_or_404(dae.Dossier, pk=dossier_id)
290 etat_precedent = dossier.etat
291
292 if request.POST:
293 validationForm = DossierWorkflowForm(
294 request.POST, instance=dossier, request=request
295 )
296 if validationForm.is_valid():
297 if etat_precedent == DOSSIER_ETAT_REGION_FINALISATION and \
298 validationForm.cleaned_data['etat'] == \
299 DOSSIER_ETAT_DRH_FINALISATION:
300 send_drh_finalisation_mail(request, dossier)
301 validationForm.save()
302 messages.add_message(
303 request, messages.SUCCESS, "La validation a été enregistrée."
304 )
305 return redirect('dae_embauches_liste')
306 else:
307 validationForm = DossierWorkflowForm(instance=dossier, request=request)
308
309 comparaisons_internes = \
310 dossier.poste.dae_comparaisons_internes.ma_region_ou_service(
311 request.user
312 )
313 comparaisons = dossier.dae_comparaisons.ma_region_ou_service(request.user)
314 vars = {
315 'dossier': dossier,
316 'validationForm': validationForm,
317 'comparaisons_internes': comparaisons_internes,
318 'comparaisons': comparaisons
319 }
320 return render(request, 'dae/embauche_consulter.html', vars)
321
322
323 @dae_groupe_requis
324 @dossier_dans_ma_region_ou_service
325 def embauche_importer(request, dossier_id=None):
326 dossier_dae = get_object_or_404(dae.Dossier, id=dossier_id)
327 if request.method == 'POST':
328 if 'confirmer' in request.POST:
329 dossier_rh = dossier_dae.importer_dans_rh()
330 return redirect('admin:rh_dossier_change', dossier_rh.id)
331 else:
332 return redirect('embauches_finalisees')
333 else:
334 c = {
335 'dossier': dossier_dae,
336 }
337 return render(request, 'dae/embauche_importer.html', c)
338
339
340 @dae_groupe_requis
341 def embauche_choisir_poste(request):
342 c = {
343 'form': ChoosePosteForm(request=request),
344 }
345 return render(request, 'dae/embauche-choisir-poste.html', c)
346
347
348 @dae_groupe_requis
349 @dossier_dans_ma_region_ou_service
350 @dossier_est_modifiable
351 def embauche(request, key=None, dossier_id=None):
352 """ Formulaire d'autorisation d'embauche. """
353
354 # Récupérer ou créer un poste et un dossier
355 source, id = key.split('-')
356 if source != 'dae':
357 return Http404
358 poste = get_object_or_404(dae.Poste, pk=id)
359
360 if request.POST:
361 if request.POST['employe'] == '':
362 # Nouvel employé
363 employe = dae.Employe()
364 else:
365 employe_source, id = request.POST['employe'].split('-')
366 if employe_source == 'dae':
367 # Employé DAE
368 employe = get_object_or_404(dae.Employe, pk=id)
369 elif employe_source == 'rh':
370 # Employé RH, on le copie dans DAE
371 e = get_object_or_404(rh.Employe, pk=id)
372 employe = dae.Employe(id_rh=e, prenom=e.prenom, nom=e.nom,
373 genre=e.genre)
374 else:
375 raise Http404
376
377 employe_form = EmployeForm(
378 request.POST, instance=employe, request=request
379 )
380
381 if employe_form.is_valid():
382 data = dict(request.POST.items())
383 employe = employe_form.save()
384 data['employe'] = 'dae-%s' % employe.id
385 employe_form = EmployeForm(data, instance=employe, request=request)
386
387 if not dossier_id:
388 dossier = dae.Dossier(poste=poste, employe=employe)
389 else:
390 dossier = get_object_or_404(dae.Dossier, pk=dossier_id)
391 dossier.employe = employe_form.instance
392
393 dossier_form = DossierForm(request.POST, instance=dossier)
394 piecesForm = DossierPieceForm(
395 request.POST, request.FILES, instance=dossier
396 )
397 comparaisons_formset = DossierComparaisonFormSet(
398 request.POST,
399 queryset=dossier.dae_comparaisons.ma_region_ou_service(
400 request.user
401 )
402 )
403 remunForm = RemunForm(request.POST, instance=dossier)
404
405 if employe_form.is_valid() and \
406 dossier_form.is_valid() and \
407 piecesForm.is_valid() and \
408 comparaisons_formset.is_valid() and \
409 remunForm.is_valid():
410 employe.save()
411 dossier_form.save()
412 piecesForm.save()
413 remunForm.save()
414
415 # Ne remplacer que les comparaisons de ma région
416 comparaisons = comparaisons_formset.save(commit=False)
417 for comparaison in comparaisons:
418 comparaison.dossier = dossier
419 comparaison.save()
420
421 messages.success(
422 request, "Le dossier %s a été sauvegardé." % dossier
423 )
424 if 'save' in request.POST:
425 return redirect('embauche_consulter', dossier_id=dossier.id)
426 else:
427 return redirect(
428 'embauche', key=dossier.poste.key, dossier_id=dossier.id
429 )
430
431 else:
432 messages.add_message(
433 request, messages.ERROR,
434 'Il y a des erreurs dans le formulaire.'
435 )
436
437 else:
438 # Initialisation d'un formulaire vide
439 if dossier_id:
440 dossier = get_object_or_404(dae.Dossier, pk=dossier_id)
441 employe = dossier.employe
442 data = dict(employe='dae-%s' % employe.id)
443 employe_form = EmployeForm(
444 initial=data, instance=employe, request=request
445 )
446 else:
447 dossier_rh = rh.Dossier()
448 poste_rh = poste.id_rh
449 dossier = pre_filled_dossier(dossier_rh, 'new', poste_rh)
450 employe_form = EmployeForm(request=request)
451
452 dossier_form = DossierForm(instance=dossier)
453 piecesForm = DossierPieceForm(instance=dossier)
454 comparaisons_formset = DossierComparaisonFormSet(
455 queryset=dossier.dae_comparaisons.ma_region_ou_service(
456 request.user
457 )
458 )
459 remunForm = RemunForm(instance=dossier)
460
461 try:
462 comparaisons_internes = \
463 dossier.poste.dae_comparaisons_internes.ma_region_ou_service(
464 request.user
465 )
466 except dae.Poste.DoesNotExist:
467 comparaisons_internes = []
468 c = {
469 'type_remun': filtered_type_remun(),
470 'devises': devises(),
471 'poste': poste,
472 'dossier': dossier,
473 'piecesForm': piecesForm,
474 'remunForm': remunForm,
475 'comparaisons_formset': comparaisons_formset,
476 'forms': dict(employe=employe_form, dossier=dossier_form, ),
477 'comparaisons_internes': comparaisons_internes,
478 }
479 return render(request, 'dae/embauche.html', c)
480
481
482 @dae_groupe_requis
483 @dossier_dans_ma_region_ou_service
484 def embauches_liste(request):
485 """ Liste des embauches. """
486 content_type = ContentType.objects.get_for_model(dae.Dossier)
487 extra_select = {'derniere_validation': (
488 "SELECT MAX(date) FROM workflow_workflowcommentaire "
489 "WHERE content_type_id = '%s' AND object_id = dae_dossier.id" %
490 content_type.id
491 )}
492 embauches_a_traiter = dae.Dossier.objects \
493 .mes_choses_a_faire(request.user) \
494 .extra(select=extra_select).order_by('-id')
495 embauches_en_cours = dae.Dossier.objects \
496 .ma_region_ou_service(request.user) \
497 .extra(select=extra_select) \
498 .order_by('-id') \
499 .exclude(etat=DOSSIER_ETAT_FINALISE)
500 c = {
501 'embauches_a_traiter': embauches_a_traiter,
502 'embauches_en_cours': embauches_en_cours,
503 }
504 return render(request, 'dae/embauches_liste.html', c)
505
506
507 @dae_groupe_requis
508 def embauches_finalisees(request):
509 """Liste des embauches finalisées."""
510
511 ### POST
512
513 if request.method == 'POST':
514 if 'supprimer' in request.POST:
515 ids = request.POST.getlist('ids')
516 dossiers = dae.Dossier.objects.filter(id__in=ids)
517 count = dossiers.count()
518 if count > 0:
519 dossiers.delete()
520 messages.success(request, u'%d dossiers supprimés' % count)
521 return redirect(request.get_full_path())
522
523 ### GET
524
525 embauches = dae.Dossier.objects.ma_region_ou_service(request.user) \
526 .filter(etat=DOSSIER_ETAT_FINALISE)
527
528 # Recherche
529 search_form = DAEFinaliseesSearchForm(request.GET)
530 if search_form.is_valid():
531 q = search_form.cleaned_data.get('q').strip()
532 importees = search_form.cleaned_data.get('importees')
533 if q:
534 criteria = [
535 Q(poste__implantation__region__nom__icontains=word) |
536 Q(poste__implantation__region__code=word) |
537 Q(poste__implantation__nom__icontains=word) |
538 Q(poste__nom__icontains=word) |
539 Q(employe__nom__icontains=word) |
540 Q(employe__prenom__icontains=word)
541 for word in q.split()
542 ]
543 embauches = embauches.filter(*criteria)
544 if importees == 'oui':
545 embauches = embauches.exclude(dossier_rh=None)
546 elif importees == 'non':
547 embauches = embauches.filter(dossier_rh=None)
548
549 # Tri
550 tri = request.GET.get('tri', None)
551 if tri and tri.startswith('-'):
552 dir = '-'
553 tri = tri[1:]
554 else:
555 dir = ''
556 if tri == 'region':
557 embauches = embauches.order_by(
558 dir + 'poste__implantation__region__nom'
559 )
560 elif tri == 'implantation':
561 embauches = embauches.order_by(dir + 'poste__implantation__nom')
562 elif tri == 'poste':
563 embauches = embauches.order_by(dir + 'poste__nom')
564 elif tri == 'personne':
565 embauches = embauches.order_by(dir + 'employe__nom',
566 dir + 'employe__prenom')
567 elif tri == 'date_debut':
568 embauches = embauches.order_by(dir + 'debut_contrat')
569 elif tri == 'date_fin':
570 embauches = embauches.order_by(dir + 'fin_contrat')
571
572 # Pagination
573 paginator = Paginator(embauches, 20)
574 try:
575 page = paginator.page(request.GET.get('page', 1))
576 except InvalidPage:
577 page = paginator.page(1)
578
579 c = {
580 'embauches': page,
581 'search_form': search_form,
582 }
583 return render(request, 'dae/embauches_finalisees.html', c)
584
585
586 def employe(request, key):
587 """ Récupération AJAX de l'employé pour la page d'embauche. """
588 data = dict(employe=key)
589
590 if key == '':
591 # Nouvel employé
592 employe = dae.Employe()
593 else:
594 # Employé existant
595 source, id = key.split('-')
596
597 if source == 'dae':
598 employe = get_object_or_404(dae.Employe, pk=id)
599 elif source == 'rh':
600 e = get_object_or_404(rh.Employe, id=id)
601 # Initialisation avec les valeurs de l'employé de rh_v1
602 employe = dae.Employe(id_rh=e)
603 for field in ('prenom', 'nom', 'genre'):
604 setattr(employe, field, getattr(e, field))
605
606 return HttpResponse(
607 EmployeForm(initial=data, instance=employe, request=request).as_table()
608 )
609
610
611 ### CONTRATS
612
613 @dae_groupe_requis
614 @get_contrat
615 def contrat(request, contrat, filename):
616 return sendfile(request, contrat.fichier.path)
617
618
619 @dae_groupe_requis
620 @get_contrat
621 def contrat_supprimer(request, contrat):
622 if request.method == 'POST':
623 if 'oui' in request.POST:
624 contrat.delete()
625 return redirect('embauche_consulter', dossier_id=contrat.dossier.id)
626 c = {
627 'contrat': contrat,
628 }
629 return render(request, 'dae/contrat-supprimer.html', c)
630
631
632 @dae_groupe_requis
633 @dossier_dans_ma_region_ou_service
634 def embauche_ajouter_contrat(request, dossier_id=None):
635 dossier = get_object_or_404(dae.Dossier, pk=dossier_id)
636 if request.method == 'POST':
637 form = ContratForm(request.POST, request.FILES)
638 if form.is_valid():
639 contrat = form.save(commit=False)
640 contrat.dossier = dossier
641 contrat.date_debut = dossier.contrat_date_debut
642 contrat.date_fin = dossier.contrat_date_fin
643 contrat.save()
644 return redirect('embauche_consulter', dossier_id=dossier.id)
645 else:
646 form = ContratForm()
647
648 c = {
649 'form': form,
650 }
651 return render(request, 'dae/embauche-ajouter-contrat.html', c)
652
653
654 ### DAE NUMERISEE
655
656 @get_object(dae.Dossier, 'consulter')
657 def dae_numerisee(request, dossier):
658 return sendfile(request, dossier.dae_numerisee.path)
659
660
661 @get_object(dae.Dossier, 'modifier_dae_numerisee')
662 def dae_numerisee_modifier(request, dossier):
663 if request.method == 'POST':
664 form = DAENumeriseeForm(request.POST, request.FILES, instance=dossier)
665 if form.is_valid():
666 form.save()
667 return redirect('embauche_consulter', dossier_id=dossier.id)
668 else:
669 form = DAENumeriseeForm(instance=dossier)
670
671 c = {
672 'form': form,
673 }
674 return render(request, 'dae/dae_numerisee_modifier.html', c)
675
676
677 @get_object(dae.Dossier, 'modifier_dae_numerisee')
678 def dae_numerisee_supprimer(request, dossier):
679 if request.method == 'POST':
680 if 'oui' in request.POST:
681 dossier.dae_numerisee = None
682 dossier.save()
683 return redirect('embauche_consulter', dossier_id=dossier.id)
684 return render(request, 'dae/dae_numerisee_supprimer.html', {})
685
686
687 # AJAX SECURISE
688
689 @dae_groupe_requis
690 @employe_dans_ma_region_ou_service
691 def dossier(request, poste_key, employe_key):
692 """ Récupération AJAX du dossier pour la page d'embauche. """
693 data = dict()
694
695 poste_source, poste_id = poste_key.split('-')
696 poste = get_object_or_404(dae.Poste, pk=poste_id)
697
698 # Récupérer la devise de l'implantation lié au poste
699 implantation_devise = poste.get_default_devise()
700 data.update({'devise': implantation_devise})
701
702 if poste.id_rh_id is not None:
703 poste_rh = get_object_or_404(rh.Poste, pk=poste.id_rh_id)
704 else:
705 poste_rh = None
706
707 # NOUVEL EMPLOYE
708 if employe_key == '':
709 employe_source = 'new'
710 employe = None
711 dossier_rh = rh.Dossier()
712 dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
713
714 # EMPLOYE DAE
715 if employe_key.startswith('dae'):
716 employe_source, employe_id = employe_key.split('-')
717 employe_dae = get_object_or_404(dae.Employe, pk=employe_id)
718
719 # récupération de l'ancien dossier rh v1 pour l'employe DAE
720 try:
721 dossier_rh = rh.Dossier.objects.get(
722 employe=employe_dae.id_rh_id, date_fin=None
723 )
724 except (rh.Dossier.DoesNotExist):
725 dossier_rh = rh.Dossier()
726
727 # on tente de récupérer le dossier DAE, au pire on le contruit en le
728 # prépoluant avec son dossier rh v1.
729 try:
730 dossier = dae.Dossier.objects.get(employe=employe_dae, poste=poste)
731 except (dae.Dossier.DoesNotExist):
732 dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
733 employe = employe_dae.id_rh
734
735 # EMPLOYE RH v1
736 if employe_key.startswith('rh'):
737 employe_source, employe_id = employe_key.split('-')
738 employe_rh = get_object_or_404(rh.Employe, pk=employe_id)
739
740 # récupération de l'ancien dossier rh v1 pour l'employe rh v1, s'il
741 # n'en a pas, on en fournit un nouveau qui servira uniquement un
742 # créer un nouveau dossier DAE.
743 try:
744 dossier_rh = rh.Dossier.objects.get(
745 employe=employe_rh, date_fin=None
746 )
747 except (rh.Dossier.DoesNotExist):
748 dossier_rh = rh.Dossier()
749 dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
750 employe = employe_rh
751
752 dossier_form = DossierForm(initial=data, instance=dossier)
753 vars = dict(form=dossier_form, poste=poste, employe=employe)
754 return render(request, 'dae/embauche-dossier.html', vars)
755
756
757 # Cette fonction est appelée à partir de fonctions déjà sécurisée
758 def pre_filled_dossier(dossier_rh, employe_source, poste_rh):
759 dossier = dae.Dossier()
760
761 if employe_source != 'new' and dossier_rh.id:
762 dossier.statut_anterieur = dossier_rh.statut
763
764 # Certains dossiers ont un classement à zéro
765 if dossier_rh.classement_id > 0:
766 dossier.classement_anterieur = dossier_rh.classement
767
768 # Récupération du salaire de base
769 remun = dossier_rh.remunerations() \
770 .filter(type=1).order_by('-date_debut')
771 if remun:
772 dossier.salaire_anterieur = remun[0].montant
773 dossier.devise_anterieur = remun[0].devise
774
775 # Récupération du titulaire précédent
776 try:
777 dossiers = rh.Dossier.objects.order_by('-date_debut')
778 if poste_rh:
779 dossiers = dossiers.filter(poste=poste_rh)
780 else:
781 dossiers = rh.Dossier.objects.none()
782 if len(dossiers):
783 # Ce bloc ignore toutes les erreurs, car les données de rh
784 # manquantes peuvent en générer
785 d = dossiers[0]
786 try:
787 titulaire = d.employe
788 dossier.employe_anterieur = titulaire
789 dossier.classement_titulaire_anterieur = d.classement
790 dossier.statut_titulaire_anterieur = d.statut
791 remun = d.remunerations().filter(type=1) \
792 .order_by('-date_debut')[0]
793 dossier.salaire_titulaire_anterieur = remun.montant
794 dossier.devise_titulaire_anterieur = remun.devise
795 except:
796 pass
797 # TODO: afficher l'info, les champs ne sont pas dans le
798 # modèle dae.Dossier: nom, prenom, classement, salaire
799 pass
800
801 except (rh.Dossier.DoesNotExist):
802 dossier_rh = rh.Dossier()
803
804 return dossier
805
806
807 @dae_groupe_requis
808 @vieux_dossier_dans_ma_region_ou_service
809 def dossier_resume(request, dossier_id=None):
810 try:
811 dossier = rh.Dossier.objects.get(id=dossier_id)
812 except:
813 return HttpResponseGone("Ce dossier n'est pas accessible")
814
815 data = {}
816 data['personne'] = unicode(dossier.employe)
817 data['classement'] = dossier.classement.id
818 if dossier.statut is not None:
819 data['statut'] = dossier.statut.id
820 data['implantation'] = dossier.poste.implantation.id
821 data['poste'] = u"%s %s" % (
822 dossier.poste.type_poste.nom, dossier.poste.nom
823 )
824 salaire = dossier.get_salaire()
825 if salaire is not None:
826 data['montant'] = float(salaire.montant)
827 else:
828 data['montant'] = None
829 if salaire is not None and salaire.devise is not None:
830 data['devise'] = salaire.devise.id
831 data['montant_euros'] = salaire.montant_euros()
832 else:
833 data['devise'] = None
834 data['montant_euros'] = 0
835 return HttpResponse(dumps(data))
836
837
838 @dae_groupe_requis
839 @vieux_dossier_dans_ma_region_ou_service
840 def poste_resume(request, dossier_id=None):
841 """
842 On travaille, en réalité sur le dossier mais on cache
843 l'identité de la personne.
844 """
845 try:
846 dossier = rh.Dossier.objects.get(id=dossier_id)
847 except:
848 return HttpResponseGone("Ce dossier n'est pas accessible")
849
850 salaire = dossier.get_salaire()
851 data = {}
852 data['implantation'] = dossier.poste.implantation.id
853 data['poste'] = u"%s %s" % (
854 dossier.poste.type_poste.nom, dossier.poste.nom
855 )
856 if salaire is not None:
857 data['devise'] = salaire.devise.id
858 data['montant'] = float(salaire.montant)
859 data['montant_euros'] = salaire.montant_euros()
860 else:
861 data['devise'] = None
862 data['montant'] = ""
863 data['montant_euros'] = ""
864 data['statut'] = dossier.statut_id
865 data['classement'] = dossier.classement_id
866 return HttpResponse(dumps(data))
867
868
869 def liste_postes(request):
870 """ Appel AJAX :
871 input : implantation_id
872 output : JSON liste de valeur point
873 """
874 method = request.method
875 params = getattr(request, method, [])
876 data = []
877
878 if 'implantation_id' in params \
879 and params.get('implantation_id') is not u"":
880 implantation_id = params.get('implantation_id')
881 q = Q(implantation__id=implantation_id)
882 else:
883 q = Q()
884
885 postes_rh = rh.Poste.objects.ma_region_ou_service(request.user).filter(q)
886 postes_rh = postes_rh.select_related(depth=1)
887
888 data = [('', 'Nouveau poste')] + \
889 sorted([('rh-%s' % p.id, label_poste_display(p)) for p in
890 postes_rh],
891 key=lambda t: t[1])
892 return HttpResponse(dumps(data))
893
894
895 @login_required
896 def dossier_piece(request, id, filename):
897 """Téléchargement d'une pièce jointe à un poste."""
898 piece = get_object_or_404(dae.DossierPiece, pk=id)
899 if dae.Dossier.objects.ma_region_ou_service(request.user) \
900 .filter(id=piece.dossier_id).exists():
901 return sendfile(request, piece.fichier.path)
902 else:
903 return redirect_interdiction(request)
904
905
906 # AJAX SECURITE non nécessaire
907
908 def coefficient(request):
909 """ Appel AJAX :
910 input : classement
911 output : coefficient
912 """
913 method = request.method
914 params = getattr(request, method, [])
915 data = dict()
916 if 'classement' in params and params.get('classement') is not u"":
917 classement = params.get('classement')
918 classement = rh.Classement.objects.get(pk=classement)
919 data['coefficient'] = classement.coefficient
920 else:
921 data['coefficient'] = 0
922 return HttpResponse(dumps(data))
923
924
925 def devise(request):
926 """ Appel AJAX :
927 input : valeur_point
928 output : devise, devise_code, taux_euro
929 """
930 method = request.method
931 params = getattr(request, method, [])
932 data = dict()
933 if 'valeur_point' in params and params.get('valeur_point') is not u"":
934 valeur_point = params.get('valeur_point')
935 valeur_point = rh.ValeurPoint.objects.get(pk=valeur_point)
936 annee = valeur_point.annee
937 try:
938 taux = rh.TauxChange.objects.get(
939 annee=annee, devise=valeur_point.devise
940 )
941 except MultipleObjectsReturned:
942 return HttpResponseGone(
943 u"Il existe plusieurs taux pour la devise %s "
944 u"cette année-là : %s" % (valeur_point.devise.code, annee)
945 )
946
947 data['devise'] = taux.devise.id
948 data['valeur'] = valeur_point.valeur
949 data['devise_code'] = taux.devise.code
950 data['taux_euro'] = taux.taux
951 else:
952 return HttpResponseGone("Vous devez choisir une valeur de point")
953 return HttpResponse(dumps(data))
954
955
956 def devise_code(request):
957 """ Appel AJAX :
958 input : devise
959 output : devise_code, taux_euro
960 """
961 method = request.method
962 params = getattr(request, method, [])
963 data = dict()
964 if 'devise' in params:
965 devise = params.get('devise')
966 devise = rh.Devise.objects.get(pk=devise)
967 annee = date.today().year
968 taux = rh.TauxChange.objects.filter(annee=annee, devise=devise)
969 if len(taux) == 0:
970 return HttpResponseGone("Le taux n'est pas disponible")
971 data['devise_code'] = devise.code
972 data['taux_euro'] = taux[0].taux
973 return HttpResponse(dumps(data))
974
975
976 def add_remun(request, dossier, type_remun):
977 dossier = get_object_or_404(dae.Dossier, pk=dossier)
978 type_remun = get_object_or_404(rh.TypeRemuneration, pk=type_remun)
979 dae.Remuneration(dossier=dossier, devise=dossier.devise,
980 type=type_remun).save()
981
982 c = {
983 'dossier': dossier,
984 }
985 return render(request, 'dae/embauche-remun.html', c)
986
987
988 def salaire(request, implantation, devise, classement):
989 if not devise or not classement:
990 raise Http404
991
992 taux = rh.TauxChange.objects.filter(devise=devise).order_by('-annee')
993 vp = rh.ValeurPoint.objects \
994 .filter(implantation=implantation, devise=devise) \
995 .order_by('-annee')
996
997 if vp.count() == 0:
998 raise Exception(u"pas de valeur de point pour le couple\
999 implantation/devise (%s/%s)" % (implantation, devise))
1000
1001 if taux.count() == 0:
1002 raise Exception(u"Pas de taux pour la devise %s" % devise)
1003
1004 classement = get_object_or_404(rh.Classement, pk=classement)
1005 if classement.coefficient is None:
1006 raise Http404
1007 taux, vp = taux[0].taux, vp[0].valeur
1008
1009 salaire_euro = round(vp * classement.coefficient * taux, 2)
1010 data = dict(salaire_euro=salaire_euro, taux=taux,
1011 salaire_devise=round(salaire_euro / taux, 2))
1012
1013 return HttpResponse(dumps(data))
1014
1015
1016 def liste_valeurs_point(request):
1017 """ Appel AJAX :
1018 input : implantation_id
1019 output : JSON liste de valeur point
1020 """
1021 method = request.method
1022 params = getattr(request, method, [])
1023 data = []
1024 annee_courante = datetime.now().year
1025 if 'implantation_id' in params \
1026 and params.get('implantation_id') is not u"":
1027 implantation_id = params.get('implantation_id')
1028 preselectionne = rh.ValeurPoint.objects \
1029 .filter(implantation=implantation_id, annee=annee_courante) \
1030 .order_by("-annee")
1031 for o in preselectionne:
1032 data.append({
1033 'id': o.id,
1034 'label': o.__unicode__(),
1035 'devise': o.devise_id,
1036 'suggestion': True
1037 })
1038 else:
1039 preselectionne = rh.ValeurPoint.objects.none()
1040
1041 liste_complete = rh.ValeurPoint.objects \
1042 .filter(annee__in=(annee_courante,)) \
1043 .order_by("-annee")
1044 for o in liste_complete.exclude(id__in=[p.id for p in preselectionne]):
1045 data.append({
1046 'id': o.id,
1047 'label': o.__unicode__(),
1048 'devise': o.devise_id,
1049 'suggestion': False
1050 })
1051 return HttpResponse(dumps(data, indent=4))