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