import DAE pour super user uniquement
[auf_rh_dae.git] / project / dae / views.py
CommitLineData
5d680e84 1# -*- encoding: utf-8 -*-
f87fe1a1 2
cea09938 3from datetime import date, datetime
139686f2 4
cea09938 5from auf.django.permissions.decorators import get_object
5a1f75cb 6from django.contrib import messages
7f432a0b 7from django.contrib.auth.decorators import login_required, user_passes_test
5a1f75cb 8from django.contrib.contenttypes.models import ContentType
3f5cbabe 9from django.core.exceptions import MultipleObjectsReturned
44055779 10from django.core.paginator import Paginator, InvalidPage
5a1f75cb 11from django.db.models import Q
86f1e48d 12from django.http import Http404, HttpResponse, HttpResponseGone
890b80e7 13from django.shortcuts import redirect, render, get_object_or_404
e3563bcf 14from sendfile import sendfile
cea09938 15from simplejson import dumps
75f0e87b 16
5a1f75cb
EMS
17from project.dae import models as dae
18from project.dae.decorators import \
acbc95a1 19 dae_groupe_requis, \
8684fcaa
EMS
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
874949f3
OL
26from project.dae.forms import FinancementFormSet, FinancementFormSetInitial
27from project.dae.forms import PosteComparaisonFormSet, PosteComparaisonFormSetInitial
5a1f75cb 28from project.dae.forms import \
874949f3
OL
29 PosteWorkflowForm, PosteForm, PostePieceFormSet, \
30 DossierWorkflowForm, ChoosePosteForm, \
5a1f75cb
EMS
31 EmployeForm, DossierForm, DossierPieceForm, \
32 DossierComparaisonFormSet, RemunForm, ContratForm, DAENumeriseeForm, \
cbfd7bd4 33 label_poste_display, DAEFinaliseesSearchForm
5a1f75cb
EMS
34from project.dae.mail import send_drh_finalisation_mail
35from project.dae.workflow import \
36 DOSSIER_ETAT_FINALISE, DOSSIER_ETAT_REGION_FINALISATION, \
37 DOSSIER_ETAT_DRH_FINALISATION, POSTE_ETAT_FINALISE
1b31de9f 38from project.decorators import redirect_interdiction
5a1f75cb 39from project.rh import models as rh
8684fcaa 40
ed1982f3 41
cea09938
EMS
42# Helpers
43
0a085c42
OL
44def 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
378ffe6c 54 data['devise_code'] = d.id
0a085c42
OL
55 liste.append(data)
56 return liste
57
5a1f75cb 58
5633fa41 59@dae_groupe_requis
5d680e84 60def index(request):
890b80e7 61 return render(request, 'dae/index.html', {})
5d680e84 62
e3563bcf
EMS
63
64### POSTE
65
5633fa41
OL
66@dae_groupe_requis
67@poste_dans_ma_region_ou_service
c0413a6f
OL
68def poste_consulter(request, key):
69 source, id = key.split('-')
70 poste = get_object_or_404(dae.Poste, pk=id)
8684fcaa 71
e6f52402 72 if request.POST:
5a1f75cb
EMS
73 validationForm = PosteWorkflowForm(
74 request.POST, instance=poste, request=request
75 )
e6f52402 76 if validationForm.is_valid():
5a1f75cb
EMS
77 messages.add_message(
78 request, messages.SUCCESS, "La validation a été enregistrée."
79 )
18c6d4c0 80 return redirect('dae_postes_liste')
e6f52402
OL
81 else:
82 validationForm = PosteWorkflowForm(instance=poste, request=request)
8684fcaa 83
5a1f75cb
EMS
84 comparaisons_internes = \
85 poste.dae_comparaisons_internes.ma_region_ou_service(request.user)
1de3da13
EMS
86 vars = {
87 'poste': poste,
88 'validationForm': validationForm,
89 'comparaisons_internes': comparaisons_internes
90 }
868a9322 91
890b80e7 92 return render(request, 'dae/poste_consulter.html', vars)
5a1f75cb 93
c0413a6f 94
6fcc7644
EMS
95def 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:
890b80e7
DB
104 c = {
105 'poste': poste_dae,
106 }
107 return render(request, 'dae/poste_importer.html', c)
6fcc7644
EMS
108
109
5633fa41 110@dae_groupe_requis
1b217058 111@poste_dans_ma_region_ou_service
6e80b20c 112@poste_est_modifiable
3ed49093 113def poste(request, key=None):
5d680e84
NC
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 """
874949f3
OL
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
5d680e84
NC
134 poste, data, vars = None, dict(), dict()
135
874949f3
OL
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:
139686f2 145 source, id = key.split('-')
5d680e84 146
139686f2 147 if source == 'dae':
5d680e84 148 poste = get_object_or_404(dae.Poste, pk=id)
874949f3 149 #data['poste'] = key
139686f2 150 elif source == 'rh':
2e672700 151 poste_rh = get_object_or_404(rh.Poste, pk=id)
2e672700 152 poste = dae.Poste(id_rh=poste_rh)
874949f3
OL
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)
5d680e84 156
2e672700 157 # prépopuler pour la modification de poste
874949f3
OL
158 if poste_rh is not None:
159 FinancementForm = FinancementFormSetInitial
160 PosteComparaisonForm = PosteComparaisonFormSetInitial
2e672700 161
2e672700
OL
162 qs_financements = poste_rh.rh_financements.all()
163 qs_comparaisons = poste_rh.rh_comparaisons_internes.all()
874949f3
OL
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 = []
2e672700
OL
174
175
5d680e84 176 if request.POST:
3ed49093 177 data.update(dict(request.POST.items()))
f258e4e7 178 form = PosteForm(data, instance=poste, request=request)
874949f3
OL
179 financementForm = FinancementForm(request.POST, instance=poste, )
180 piecesForm = PostePieceFormSet(request.POST, request.FILES, instance=poste, )
181 comparaisons_formset = PosteComparaisonForm(
c4bfc2a0 182 request.POST,
874949f3 183 instance=poste,
c4bfc2a0 184 )
5a1f75cb
EMS
185 if form.is_valid() and piecesForm.is_valid() and \
186 financementForm.is_valid() and comparaisons_formset.is_valid():
5d680e84 187 poste = form.save()
eb8c3edb
OL
188 piecesForm.instance = poste
189 piecesForm.save()
151e7bd0
OL
190 financementForm.instance = poste
191 financementForm.save()
320d7584
EMS
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
2e672700
OL
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()
5a1f75cb
EMS
204 messages.add_message(
205 request, messages.SUCCESS,
206 "Le poste %s a été sauvegardé." % poste
207 )
208 if 'save' in request.POST:
5bc760f9
OL
209 return redirect('poste_consulter', key='dae-%s' % poste.id)
210 else:
211 return redirect('poste', key='dae-%s' % poste.id)
8684fcaa 212
9cb4de55 213 else:
5a1f75cb
EMS
214 messages.add_message(
215 request, messages.ERROR,
216 'Il y a des erreurs dans le formulaire.'
217 )
8684fcaa 218
5d680e84
NC
219 else:
220 # 'initial' évite la validation prémature lors d'une copie de poste de
221 # rh_v1 vers dae.
f258e4e7 222 form = PosteForm(initial=data, instance=poste, request=request)
874949f3 223 piecesForm = PostePieceFormSet(instance=poste)
2e672700 224
874949f3
OL
225 if poste_rh is not None:
226 financementForm = FinancementForm(initial=financements, instance=poste)
227 comparaisons_formset = PosteComparaisonForm(
2e672700 228 initial=comparaisons,
874949f3 229 instance=poste,
829eb351 230 )
874949f3 231 # cas de la création d'un nouveau poste
829eb351 232 else:
874949f3
OL
233 financementForm = FinancementForm(instance=poste)
234 comparaisons_formset = PosteComparaisonForm(instance=poste)
5d680e84 235
320d7584
EMS
236 vars.update(dict(
237 form=form, poste=poste, poste_key=key, piecesForm=piecesForm,
238 financementForm=financementForm,
2e672700
OL
239 comparaisons_formset=comparaisons_formset,
240 poste_rh=poste_rh,
320d7584 241 ))
5d680e84 242
890b80e7 243 return render(request, 'dae/poste.html', vars)
3ed49093 244
5a1f75cb 245
5633fa41 246@dae_groupe_requis
498881f4 247def postes_liste(request):
0f23302a 248 """ Liste des postes. """
92741270
EMS
249 content_type = ContentType.objects.get_for_model(dae.Poste)
250 extra_select = {'derniere_validation': (
251 "SELECT MAX(date) FROM workflow_workflowcommentaire "
5a1f75cb
EMS
252 "WHERE content_type_id = '%s' AND object_id = dae_poste.id" %
253 content_type.id
92741270
EMS
254 )}
255 postes_a_traiter = dae.Poste.objects.mes_choses_a_faire(request.user) \
cea09938 256 .extra(select=extra_select).order_by('-id')
92741270 257 postes_en_cours = dae.Poste.objects.ma_region_ou_service(request.user) \
5a1f75cb
EMS
258 .extra(select=extra_select) \
259 .filter(~Q(etat=POSTE_ETAT_FINALISE)) \
cea09938
EMS
260 .order_by('-id')
261 return render(request, 'dae/postes_liste.html', {
92741270
EMS
262 'postes_a_traiter': postes_a_traiter,
263 'postes_en_cours': postes_en_cours,
cea09938 264 })
98d51b59 265
5a1f75cb 266
e3563bcf 267@login_required
67a94eaf 268def poste_piece(request, id, filename):
e3563bcf
EMS
269 """Téléchargement d'une pièce jointe à un poste."""
270 piece = get_object_or_404(dae.PostePiece, pk=id)
5a1f75cb
EMS
271 if dae.Poste.objects.ma_region_ou_service(request.user) \
272 .filter(id=piece.poste_id).exists():
67a94eaf 273 return sendfile(request, piece.fichier.path)
e3563bcf
EMS
274 else:
275 return redirect_interdiction(request)
276
277
278### DOSSIER
279
cb1d62b5 280def filtered_type_remun():
5a1f75cb
EMS
281 defaut = (2, 3, 8, 17) # salaire de base, indemnité de fonction,
282 # charges patronales
0a085c42 283 return rh.TypeRemuneration.objects.filter(pk__in=defaut)
cb1d62b5 284
5a1f75cb 285
5633fa41 286@dae_groupe_requis
62d3903d 287@dossier_dans_ma_region_ou_service
5d5a57a4
OL
288def embauche_consulter(request, dossier_id):
289 dossier = get_object_or_404(dae.Dossier, pk=dossier_id)
8684fcaa 290 etat_precedent = dossier.etat
e6f52402
OL
291
292 if request.POST:
5a1f75cb
EMS
293 validationForm = DossierWorkflowForm(
294 request.POST, instance=dossier, request=request
295 )
e6f52402 296 if validationForm.is_valid():
8684fcaa 297 if etat_precedent == DOSSIER_ETAT_REGION_FINALISATION and \
5a1f75cb
EMS
298 validationForm.cleaned_data['etat'] == \
299 DOSSIER_ETAT_DRH_FINALISATION:
8684fcaa 300 send_drh_finalisation_mail(request, dossier)
e6f52402 301 validationForm.save()
5a1f75cb
EMS
302 messages.add_message(
303 request, messages.SUCCESS, "La validation a été enregistrée."
304 )
18c6d4c0 305 return redirect('dae_embauches_liste')
e6f52402
OL
306 else:
307 validationForm = DossierWorkflowForm(instance=dossier, request=request)
9536ea21 308
5a1f75cb
EMS
309 comparaisons_internes = \
310 dossier.poste.dae_comparaisons_internes.ma_region_ou_service(
311 request.user
312 )
a4125771 313 comparaisons = dossier.dae_comparaisons.ma_region_ou_service(request.user)
5d5a57a4 314 vars = {
291bbfd9
EMS
315 'dossier': dossier,
316 'validationForm': validationForm,
320d7584
EMS
317 'comparaisons_internes': comparaisons_internes,
318 'comparaisons': comparaisons
319 }
890b80e7 320 return render(request, 'dae/embauche_consulter.html', vars)
5a1f75cb 321
7f432a0b 322@user_passes_test(lambda u: u.is_superuser)
5633fa41 323@dae_groupe_requis
fb0ed970
EMS
324@dossier_dans_ma_region_ou_service
325def embauche_importer(request, dossier_id=None):
326 dossier_dae = get_object_or_404(dae.Dossier, id=dossier_id)
47b60f16
EMS
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:
890b80e7
DB
334 c = {
335 'dossier': dossier_dae,
336 }
337 return render(request, 'dae/embauche_importer.html', c)
fb0ed970
EMS
338
339
340@dae_groupe_requis
577dcb77 341def embauche_choisir_poste(request):
890b80e7
DB
342 c = {
343 'form': ChoosePosteForm(request=request),
344 }
345 return render(request, 'dae/embauche-choisir-poste.html', c)
577dcb77 346
5a1f75cb 347
577dcb77 348@dae_groupe_requis
62d3903d 349@dossier_dans_ma_region_ou_service
62cfa562 350@dossier_est_modifiable
62d3903d 351def embauche(request, key=None, dossier_id=None):
139686f2 352 """ Formulaire d'autorisation d'embauche. """
139686f2 353
577dcb77
EMS
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)
139686f2 374 else:
577dcb77
EMS
375 raise Http404
376
5a1f75cb
EMS
377 employe_form = EmployeForm(
378 request.POST, instance=employe, request=request
379 )
577dcb77
EMS
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)
16b1454e 391 dossier.employe = employe_form.instance
577dcb77
EMS
392
393 dossier_form = DossierForm(request.POST, instance=dossier)
5a1f75cb
EMS
394 piecesForm = DossierPieceForm(
395 request.POST, request.FILES, instance=dossier
396 )
320d7584
EMS
397 comparaisons_formset = DossierComparaisonFormSet(
398 request.POST,
5a1f75cb
EMS
399 queryset=dossier.dae_comparaisons.ma_region_ou_service(
400 request.user
401 )
320d7584 402 )
577dcb77
EMS
403 remunForm = RemunForm(request.POST, instance=dossier)
404
55360d7d
EMS
405 if employe_form.is_valid() and \
406 dossier_form.is_valid() and \
577dcb77 407 piecesForm.is_valid() and \
320d7584 408 comparaisons_formset.is_valid() and \
577dcb77
EMS
409 remunForm.is_valid():
410 employe.save()
55360d7d 411 dossier_form.save()
577dcb77 412 piecesForm.save()
577dcb77 413 remunForm.save()
320d7584
EMS
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
5a1f75cb
EMS
421 messages.success(
422 request, "Le dossier %s a été sauvegardé." % dossier
423 )
424 if 'save' in request.POST:
577dcb77 425 return redirect('embauche_consulter', dossier_id=dossier.id)
768d7e1b 426 else:
5a1f75cb
EMS
427 return redirect(
428 'embauche', key=dossier.poste.key, dossier_id=dossier.id
429 )
9536ea21 430
577dcb77 431 else:
5a1f75cb
EMS
432 messages.add_message(
433 request, messages.ERROR,
434 'Il y a des erreurs dans le formulaire.'
435 )
9536ea21 436
577dcb77
EMS
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)
5a1f75cb
EMS
443 employe_form = EmployeForm(
444 initial=data, instance=employe, request=request
445 )
ed1982f3
NC
446 else:
447 dossier_rh = rh.Dossier()
448 poste_rh = poste.id_rh
577dcb77
EMS
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)
320d7584 454 comparaisons_formset = DossierComparaisonFormSet(
5a1f75cb
EMS
455 queryset=dossier.dae_comparaisons.ma_region_ou_service(
456 request.user
457 )
320d7584 458 )
577dcb77
EMS
459 remunForm = RemunForm(instance=dossier)
460
829eb351 461 try:
5a1f75cb
EMS
462 comparaisons_internes = \
463 dossier.poste.dae_comparaisons_internes.ma_region_ou_service(
464 request.user
465 )
829eb351
EMS
466 except dae.Poste.DoesNotExist:
467 comparaisons_internes = []
890b80e7 468 c = {
577dcb77
EMS
469 'type_remun': filtered_type_remun(),
470 'devises': devises(),
471 'poste': poste,
472 'dossier': dossier,
473 'piecesForm': piecesForm,
474 'remunForm': remunForm,
320d7584 475 'comparaisons_formset': comparaisons_formset,
291bbfd9 476 'forms': dict(employe=employe_form, dossier=dossier_form, ),
890b80e7
DB
477 'comparaisons_internes': comparaisons_internes,
478 }
479 return render(request, 'dae/embauche.html', c)
139686f2 480
5a1f75cb 481
5633fa41 482@dae_groupe_requis
62d3903d 483@dossier_dans_ma_region_ou_service
0140cbd2 484def embauches_liste(request):
485 """ Liste des embauches. """
92741270
EMS
486 content_type = ContentType.objects.get_for_model(dae.Dossier)
487 extra_select = {'derniere_validation': (
488 "SELECT MAX(date) FROM workflow_workflowcommentaire "
5a1f75cb
EMS
489 "WHERE content_type_id = '%s' AND object_id = dae_dossier.id" %
490 content_type.id
92741270 491 )}
5a1f75cb
EMS
492 embauches_a_traiter = dae.Dossier.objects \
493 .mes_choses_a_faire(request.user) \
cea09938 494 .extra(select=extra_select).order_by('-id')
5a1f75cb
EMS
495 embauches_en_cours = dae.Dossier.objects \
496 .ma_region_ou_service(request.user) \
497 .extra(select=extra_select) \
cea09938 498 .order_by('-id') \
5a1f75cb 499 .exclude(etat=DOSSIER_ETAT_FINALISE)
890b80e7 500 c = {
92741270
EMS
501 'embauches_a_traiter': embauches_a_traiter,
502 'embauches_en_cours': embauches_en_cours,
890b80e7
DB
503 }
504 return render(request, 'dae/embauches_liste.html', c)
355c80c8 505
5a1f75cb 506
44055779
EMS
507@dae_groupe_requis
508def embauches_finalisees(request):
509 """Liste des embauches finalisées."""
bed096fc
EMS
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
44055779
EMS
525 embauches = dae.Dossier.objects.ma_region_ou_service(request.user) \
526 .filter(etat=DOSSIER_ETAT_FINALISE)
527
cbfd7bd4
EMS
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
44055779
EMS
549 # Tri
550 tri = request.GET.get('tri', None)
7652a4c3 551 if tri and tri.startswith('-'):
44055779
EMS
552 dir = '-'
553 tri = tri[1:]
554 else:
555 dir = ''
556 if tri == 'region':
5a1f75cb
EMS
557 embauches = embauches.order_by(
558 dir + 'poste__implantation__region__nom'
559 )
44055779
EMS
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':
8684fcaa
EMS
565 embauches = embauches.order_by(dir + 'employe__nom',
566 dir + 'employe__prenom')
44055779
EMS
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)
1b31de9f 578
890b80e7 579 c = {
cbfd7bd4 580 'embauches': page,
890b80e7
DB
581 'search_form': search_form,
582 }
583 return render(request, 'dae/embauches_finalisees.html', c)
44055779 584
5a1f75cb 585
139686f2
NC
586def 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
5a1f75cb
EMS
606 return HttpResponse(
607 EmployeForm(initial=data, instance=employe, request=request).as_table()
608 )
609
139686f2 610
9536ea21
EMS
611### CONTRATS
612
613@dae_groupe_requis
614@get_contrat
67a94eaf
EMS
615def contrat(request, contrat, filename):
616 return sendfile(request, contrat.fichier.path)
9536ea21 617
5a1f75cb 618
9536ea21
EMS
619@dae_groupe_requis
620@get_contrat
621def 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)
890b80e7
DB
626 c = {
627 'contrat': contrat,
628 }
629 return render(request, 'dae/contrat-supprimer.html', c)
9536ea21 630
5a1f75cb 631
9536ea21
EMS
632@dae_groupe_requis
633@dossier_dans_ma_region_ou_service
634def 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
9dfa4296
OL
641 contrat.date_debut = dossier.contrat_date_debut
642 contrat.date_fin = dossier.contrat_date_fin
9536ea21
EMS
643 contrat.save()
644 return redirect('embauche_consulter', dossier_id=dossier.id)
645 else:
646 form = ContratForm()
1b31de9f 647
890b80e7
DB
648 c = {
649 'form': form,
650 }
651 return render(request, 'dae/embauche-ajouter-contrat.html', c)
9536ea21 652
5a1f75cb 653
c3f0b49f
EMS
654### DAE NUMERISEE
655
656@get_object(dae.Dossier, 'consulter')
657def dae_numerisee(request, dossier):
658 return sendfile(request, dossier.dae_numerisee.path)
659
5a1f75cb 660
c3f0b49f
EMS
661@get_object(dae.Dossier, 'modifier_dae_numerisee')
662def 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)
1b31de9f 670
890b80e7
DB
671 c = {
672 'form': form,
673 }
674 return render(request, 'dae/dae_numerisee_modifier.html', c)
c3f0b49f 675
5a1f75cb 676
c3f0b49f
EMS
677@get_object(dae.Dossier, 'modifier_dae_numerisee')
678def 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)
890b80e7 684 return render(request, 'dae/dae_numerisee_supprimer.html', {})
5a1f75cb 685
c3f0b49f 686
04380fba 687# AJAX SECURISE
5a1f75cb 688
04380fba
OL
689@dae_groupe_requis
690@employe_dans_ma_region_ou_service
139686f2
NC
691def 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)
179f6b49
OL
697
698 # Récupérer la devise de l'implantation lié au poste
699 implantation_devise = poste.get_default_devise()
5a1f75cb 700 data.update({'devise': implantation_devise})
9536ea21 701
e27db04c
OL
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
139686f2 706
eabaed81 707 # NOUVEL EMPLOYE
139686f2
NC
708 if employe_key == '':
709 employe_source = 'new'
eabaed81 710 employe = None
139686f2 711 dossier_rh = rh.Dossier()
ed1982f3 712 dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
139686f2 713
eabaed81 714 # EMPLOYE DAE
eabaed81 715 if employe_key.startswith('dae'):
5a1f75cb
EMS
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
eabaed81 735 # EMPLOYE RH v1
eabaed81 736 if employe_key.startswith('rh'):
5a1f75cb
EMS
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
da3ca955 751
eabaed81
OL
752 dossier_form = DossierForm(initial=data, instance=dossier)
753 vars = dict(form=dossier_form, poste=poste, employe=employe)
890b80e7 754 return render(request, 'dae/embauche-dossier.html', vars)
139686f2 755
5a1f75cb
EMS
756
757# Cette fonction est appelée à partir de fonctions déjà sécurisée
ed1982f3
NC
758def 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
5a1f75cb
EMS
769 remun = dossier_rh.remunerations() \
770 .filter(type=1).order_by('-date_debut')
ed1982f3
NC
771 if remun:
772 dossier.salaire_anterieur = remun[0].montant
80bcc96b 773 dossier.devise_anterieur = remun[0].devise
ed1982f3
NC
774
775 # Récupération du titulaire précédent
776 try:
09aa8374 777 dossiers = rh.Dossier.objects.order_by('-date_debut')
32f26ff3 778 if poste_rh:
09aa8374 779 dossiers = dossiers.filter(poste=poste_rh)
32f26ff3
AJ
780 else:
781 dossiers = rh.Dossier.objects.none()
ed1982f3
NC
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
5a1f75cb
EMS
791 remun = d.remunerations().filter(type=1) \
792 .order_by('-date_debut')[0]
80bcc96b
OL
793 dossier.salaire_titulaire_anterieur = remun.montant
794 dossier.devise_titulaire_anterieur = remun.devise
ed1982f3
NC
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
5a1f75cb 806
04380fba 807@dae_groupe_requis
c0492570 808@vieux_dossier_dans_ma_region_ou_service
04380fba 809def dossier_resume(request, dossier_id=None):
04380fba
OL
810 try:
811 dossier = rh.Dossier.objects.get(id=dossier_id)
812 except:
813 return HttpResponseGone("Ce dossier n'est pas accessible")
f87fe1a1 814
04380fba
OL
815 data = {}
816 data['personne'] = unicode(dossier.employe)
0ebb99b3 817 data['classement'] = dossier.classement.id
09aa8374
OL
818 if dossier.statut is not None:
819 data['statut'] = dossier.statut.id
820 data['implantation'] = dossier.poste.implantation.id
5a1f75cb
EMS
821 data['poste'] = u"%s %s" % (
822 dossier.poste.type_poste.nom, dossier.poste.nom
823 )
09aa8374 824 salaire = dossier.get_salaire()
a4125771 825 if salaire is not None:
5a64aab4 826 data['montant'] = float(salaire.montant)
a4125771
OL
827 else:
828 data['montant'] = None
829 if salaire is not None and salaire.devise is not None:
10b6780c 830 data['devise'] = salaire.devise.id
e84c8ef1 831 data['montant_euros'] = salaire.montant_euros()
f87fe1a1 832 else:
04380fba
OL
833 data['devise'] = None
834 data['montant_euros'] = 0
85668061 835 return HttpResponse(dumps(data))
f87fe1a1 836
5a1f75cb 837
068d1462
OL
838@dae_groupe_requis
839@vieux_dossier_dans_ma_region_ou_service
840def 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
3f5cbabe 850 salaire = dossier.get_salaire()
068d1462 851 data = {}
09aa8374 852 data['implantation'] = dossier.poste.implantation.id
5a1f75cb
EMS
853 data['poste'] = u"%s %s" % (
854 dossier.poste.type_poste.nom, dossier.poste.nom
855 )
068d1462
OL
856 if salaire is not None:
857 data['devise'] = salaire.devise.id
e503e64d 858 data['montant'] = float(salaire.montant)
e84c8ef1 859 data['montant_euros'] = salaire.montant_euros()
068d1462
OL
860 else:
861 data['devise'] = None
e503e64d
OL
862 data['montant'] = ""
863 data['montant_euros'] = ""
5d84008f
OL
864 data['statut'] = dossier.statut_id
865 data['classement'] = dossier.classement_id
068d1462
OL
866 return HttpResponse(dumps(data))
867
5a1f75cb 868
6d047148 869def liste_postes(request):
8684fcaa 870 """ Appel AJAX :
6d047148
OL
871 input : implantation_id
872 output : JSON liste de valeur point
873 """
874 method = request.method
875 params = getattr(request, method, [])
876 data = []
877
5a1f75cb
EMS
878 if 'implantation_id' in params \
879 and params.get('implantation_id') is not u"":
6d047148 880 implantation_id = params.get('implantation_id')
9c1ff333
OL
881 q = Q(implantation__id=implantation_id)
882 else:
883 q = Q()
9536ea21 884
9c1ff333
OL
885 postes_rh = rh.Poste.objects.ma_region_ou_service(request.user).filter(q)
886 postes_rh = postes_rh.select_related(depth=1)
4bce4d24 887
5a1f75cb 888 data = [('', 'Nouveau poste')] + \
9c1ff333
OL
889 sorted([('rh-%s' % p.id, label_poste_display(p)) for p in
890 postes_rh],
891 key=lambda t: t[1])
6d047148
OL
892 return HttpResponse(dumps(data))
893
5a1f75cb 894
e3563bcf 895@login_required
67a94eaf 896def dossier_piece(request, id, filename):
e3563bcf
EMS
897 """Téléchargement d'une pièce jointe à un poste."""
898 piece = get_object_or_404(dae.DossierPiece, pk=id)
5a1f75cb
EMS
899 if dae.Dossier.objects.ma_region_ou_service(request.user) \
900 .filter(id=piece.dossier_id).exists():
67a94eaf 901 return sendfile(request, piece.fichier.path)
e3563bcf
EMS
902 else:
903 return redirect_interdiction(request)
904
5a1f75cb 905
04380fba 906# AJAX SECURITE non nécessaire
5a1f75cb 907
04380fba 908def coefficient(request):
9536ea21 909 """ Appel AJAX :
04380fba
OL
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
3d627bfd 925def devise(request):
8684fcaa 926 """ Appel AJAX :
3d627bfd 927 input : valeur_point
8e30e17f 928 output : devise, devise_code, taux_euro
3d627bfd 929 """
f87fe1a1
OL
930 method = request.method
931 params = getattr(request, method, [])
3d627bfd 932 data = dict()
8684fcaa 933 if 'valeur_point' in params and params.get('valeur_point') is not u"":
f87fe1a1 934 valeur_point = params.get('valeur_point')
3d627bfd 935 valeur_point = rh.ValeurPoint.objects.get(pk=valeur_point)
936 annee = valeur_point.annee
3f5cbabe 937 try:
5a1f75cb
EMS
938 taux = rh.TauxChange.objects.get(
939 annee=annee, devise=valeur_point.devise
940 )
3f5cbabe 941 except MultipleObjectsReturned:
5a1f75cb
EMS
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 )
3f5cbabe 946
3d627bfd 947 data['devise'] = taux.devise.id
f87fe1a1 948 data['valeur'] = valeur_point.valeur
3d627bfd 949 data['devise_code'] = taux.devise.code
8e30e17f 950 data['taux_euro'] = taux.taux
be3c51e9
OL
951 else:
952 return HttpResponseGone("Vous devez choisir une valeur de point")
3d627bfd 953 return HttpResponse(dumps(data))
9536ea21 954
5a1f75cb 955
3d627bfd 956def devise_code(request):
8684fcaa 957 """ Appel AJAX :
3d627bfd 958 input : devise
8e30e17f 959 output : devise_code, taux_euro
3d627bfd 960 """
f87fe1a1
OL
961 method = request.method
962 params = getattr(request, method, [])
3d627bfd 963 data = dict()
f87fe1a1
OL
964 if 'devise' in params:
965 devise = params.get('devise')
3d627bfd 966 devise = rh.Devise.objects.get(pk=devise)
8e30e17f 967 annee = date.today().year
968 taux = rh.TauxChange.objects.filter(annee=annee, devise=devise)
86f1e48d
OL
969 if len(taux) == 0:
970 return HttpResponseGone("Le taux n'est pas disponible")
3d627bfd 971 data['devise_code'] = devise.code
8e30e17f 972 data['taux_euro'] = taux[0].taux
3d627bfd 973 return HttpResponse(dumps(data))
85668061 974
5a1f75cb 975
cb1d62b5
NC
976def 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
890b80e7
DB
982 c = {
983 'dossier': dossier,
984 }
985 return render(request, 'dae/embauche-remun.html', c)
03b395db 986
5a1f75cb 987
04380fba
OL
988def salaire(request, implantation, devise, classement):
989 if not devise or not classement:
990 raise Http404
991
04380fba 992 taux = rh.TauxChange.objects.filter(devise=devise).order_by('-annee')
5a1f75cb
EMS
993 vp = rh.ValeurPoint.objects \
994 .filter(implantation=implantation, devise=devise) \
995 .order_by('-annee')
aa512122
OL
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)
04380fba
OL
1003
1004 classement = get_object_or_404(rh.Classement, pk=classement)
e2968ebb
EMS
1005 if classement.coefficient is None:
1006 raise Http404
90716392 1007 taux, vp = taux[0].taux, vp[0].valeur
04380fba 1008
90716392 1009 salaire_euro = round(vp * classement.coefficient * taux, 2)
04380fba
OL
1010 data = dict(salaire_euro=salaire_euro, taux=taux,
1011 salaire_devise=round(salaire_euro / taux, 2))
1012
1013 return HttpResponse(dumps(data))
1014
5a1f75cb 1015
04380fba 1016def liste_valeurs_point(request):
8684fcaa 1017 """ Appel AJAX :
04380fba
OL
1018 input : implantation_id
1019 output : JSON liste de valeur point
03b395db 1020 """
04380fba
OL
1021 method = request.method
1022 params = getattr(request, method, [])
1023 data = []
cea09938 1024 annee_courante = datetime.now().year
5a1f75cb
EMS
1025 if 'implantation_id' in params \
1026 and params.get('implantation_id') is not u"":
04380fba 1027 implantation_id = params.get('implantation_id')
5a1f75cb
EMS
1028 preselectionne = rh.ValeurPoint.objects \
1029 .filter(implantation=implantation_id, annee=annee_courante) \
1030 .order_by("-annee")
7ad0549c 1031 for o in preselectionne:
5a1f75cb
EMS
1032 data.append({
1033 'id': o.id,
1034 'label': o.__unicode__(),
1035 'devise': o.devise_id,
1036 'suggestion': True
1037 })
b1f7765e 1038 else:
7ad0549c
OL
1039 preselectionne = rh.ValeurPoint.objects.none()
1040
5a1f75cb
EMS
1041 liste_complete = rh.ValeurPoint.objects \
1042 .filter(annee__in=(annee_courante,)) \
1043 .order_by("-annee")
7ad0549c 1044 for o in liste_complete.exclude(id__in=[p.id for p in preselectionne]):
5a1f75cb
EMS
1045 data.append({
1046 'id': o.id,
1047 'label': o.__unicode__(),
1048 'devise': o.devise_id,
1049 'suggestion': False
1050 })
3f5cbabe 1051 return HttpResponse(dumps(data, indent=4))