# -*- encoding: utf-8 -*-
-import os
-import datetime
-import StringIO
-from collections import defaultdict
-from datetime import date
-from simplejson import dumps
-import warnings
+from datetime import date, datetime
-from django.core.urlresolvers import reverse
-from django.http import Http404, HttpResponse, HttpResponseGone
-from django.shortcuts import redirect, render_to_response, get_object_or_404
-from django.template import Context, RequestContext
-from django.template.loader import get_template
+from auf.django.permissions.decorators import get_object
from django.contrib import messages
-from django.conf import settings
-
-from reversion.models import Version
+from django.contrib.auth.decorators import login_required, user_passes_test
+from django.contrib.contenttypes.models import ContentType
+from django.core.exceptions import MultipleObjectsReturned
+from django.core.paginator import Paginator, InvalidPage
+from django.db.models import Q
+from django.http import Http404, HttpResponse, HttpResponseGone
+from django.shortcuts import redirect, render, get_object_or_404
+from sendfile import sendfile
+from simplejson import dumps
from project.dae import models as dae
-from project.rh_v1 import models as rh
-
-from decorators import dae_groupe_requis, \
- poste_dans_ma_region_ou_service, \
- dossier_dans_ma_region_ou_service, \
- vieux_dossier_dans_ma_region_ou_service, \
- employe_dans_ma_region_ou_service, \
- dossier_est_modifiable, \
- poste_est_modifiable
-from forms import *
-from workflow import POSTE_ETAT_DRH_FINALISATION, DOSSIER_ETAT_REFUSE
+from project.dae.decorators import \
+ dae_groupe_requis, \
+ poste_dans_ma_region_ou_service, \
+ dossier_dans_ma_region_ou_service, \
+ vieux_dossier_dans_ma_region_ou_service, \
+ employe_dans_ma_region_ou_service, \
+ dossier_est_modifiable, \
+ poste_est_modifiable, get_contrat
+from project.dae.forms import FinancementFormSet, FinancementFormSetInitial
+from project.dae.forms import PosteComparaisonFormSet, PosteComparaisonFormSetInitial
+from project.dae.forms import \
+ PosteWorkflowForm, PosteForm, PostePieceFormSet, \
+ DossierWorkflowForm, ChoosePosteForm, \
+ EmployeForm, DossierForm, DossierPieceForm, \
+ DossierComparaisonFormSet, RemunForm, ContratForm, DAENumeriseeForm, \
+ label_poste_display, DAEFinaliseesSearchForm
+from project.dae.mail import send_drh_finalisation_mail
+from project.dae.workflow import \
+ DOSSIER_ETAT_FINALISE, DOSSIER_ETAT_REGION_FINALISATION, \
+ DOSSIER_ETAT_DRH_FINALISATION, POSTE_ETAT_FINALISE
+from project.decorators import \
+ redirect_interdiction, drh_or_admin_required, in_drh_or_admin
+from project.rh import models as rh
+
+
+# Helpers
def devises():
liste = []
data['taux_euro'] = 0
else:
data['taux_euro'] = taux[0].taux
- data['devise_code'] = d.code
+ data['devise_code'] = d.id
liste.append(data)
return liste
-def reponse_pdf(template_src, context_dict):
- """
- Générer une réponse HTTP avec un PDF
- """
- import ho.pisa as pisa
- pisa.showLogging()
- css = ""
- for f in ('css/pdf.css', 'css/dae.css'):
- css_file = os.path.join(settings.MEDIA_ROOT, f)
- css += open(css_file, 'r').read()
- context_dict['css'] = css
-
- template = get_template(template_src)
- context = Context(context_dict)
- html = template.render(context)
- result = StringIO.StringIO()
- pdf = pisa.pisaDocument(html, result, encoding='UTF-8')
- if not pdf.err:
- return HttpResponse(result.getvalue(), mimetype='application/pdf')
- return HttpResponse("impossible de générer le pdf! %s" % html)
-
@dae_groupe_requis
def index(request):
- return render_to_response('dae/index.html', {}, RequestContext(request))
+ return render(request, 'dae/index.html', {})
+
+
+### POSTE
@dae_groupe_requis
@poste_dans_ma_region_ou_service
def poste_consulter(request, key):
source, id = key.split('-')
poste = get_object_or_404(dae.Poste, pk=id)
-
+
if request.POST:
- validationForm = PosteWorkflowForm(request.POST, instance=poste, request=request)
+ validationForm = PosteWorkflowForm(
+ request.POST, instance=poste, request=request
+ )
if validationForm.is_valid():
- validationForm.save()
- messages.add_message(request, messages.SUCCESS, "La validation a été enregistrée.")
+ messages.add_message(
+ request, messages.SUCCESS, "La validation a été enregistrée."
+ )
return redirect('dae_postes_liste')
else:
validationForm = PosteWorkflowForm(instance=poste, request=request)
-
- vars = {'poste' : poste, 'validationForm' : validationForm, }
+ comparaisons_internes = \
+ poste.dae_comparaisons_internes.ma_region_ou_service(request.user)
+ return render(request, 'dae/poste_consulter.html', {
+ 'poste': poste,
+ 'validationForm': validationForm,
+ 'comparaisons_internes': comparaisons_internes,
+ 'importer': in_drh_or_admin(request.user)
+ })
- mode = request.GET.get('mode', None)
- if mode is None:
- return render_to_response('dae/poste_consulter.html', vars, RequestContext(request))
- if mode == 'pdf':
- return reponse_pdf('dae/poste_pdf.html', vars)
- if mode == 'vpdf':
- return render_to_response('dae/poste_pdf.html', vars, RequestContext(request))
+
+
+@drh_or_admin_required
+def poste_importer(request, id):
+ poste_dae = get_object_or_404(dae.Poste, id=id)
+ if request.method == 'POST':
+ if 'confirmer' in request.POST:
+ poste_rh = poste_dae.importer_dans_rh()
+ return redirect('admin:rh_poste_change', poste_rh.id)
+ else:
+ return redirect('poste_consulter', 'dae-' + id)
+ else:
+ c = {
+ 'poste': poste_dae,
+ }
+ return render(request, 'dae/poste_importer.html', c)
@dae_groupe_requis
il est automatiquement copié dans dae.
"""
+
+ def _dupliquer_poste(poste_dae, poste_rh):
+ """
+ Recopie les fields d'un poste RH dans un poste DAE
+ avec ceux-ci précédemment crées
+ """
+ exclus = ('id', 'supprime', 'date_creation',
+ 'user_creation', 'date_modification',
+ 'user_modification', )
+ fields = [f for f in poste_rh._meta.fields if f.name not in exclus]
+ for field in fields:
+ setattr(poste_dae, field.name, getattr(poste_rh, field.name))
+ return poste_dae
+
poste, data, vars = None, dict(), dict()
- if key:
- # Poste existant
- data['poste'] = key
+ # Sans key, c'est un nouveau poste
+ if key is None:
+ new = True
+ else:
+ new = False
+
+ # Type intervention
+ if 'type_intervention' in request.GET:
+ data['type_intervention'] = request.GET['type_intervention']
+
+ # Poste existant
+ poste_rh = None
+ if not new:
source, id = key.split('-')
if source == 'dae':
poste = get_object_or_404(dae.Poste, pk=id)
+ data['poste'] = key
elif source == 'rh':
- p = get_object_or_404(rh.Poste, pk=id)
+ poste_rh = get_object_or_404(rh.Poste, pk=id)
+ poste = dae.Poste(id_rh=poste_rh)
# Initialisation avec les valeurs du poste de rh_v1
- poste = dae.Poste(id_rh=p, nom=p.type_poste.nom)
- for field in ('implantation', 'type_poste', 'actif'):
- setattr(poste, field, getattr(p, field))
+ poste = _dupliquer_poste(poste, poste_rh)
+ data['poste'] = 'rh-' + str(poste.id_rh_id)
+
+ # prépopuler pour la modification de poste
+ if poste_rh is not None:
+ FinancementForm = FinancementFormSetInitial
+ PosteComparaisonForm = PosteComparaisonFormSetInitial
+
+ qs_financements = poste_rh.rh_financements.all()
+ qs_comparaisons = poste_rh.rh_comparaisons_internes.all()
+ financements = [{'type': f.type, 'pourcentage': f.pourcentage,
+ 'commentaire': f.commentaire} for f in qs_financements]
+ comparaisons = [{'implantation': c.implantation, 'nom': c.nom,
+ 'montant': c.montant, 'devise': c.devise} for c in qs_comparaisons]
+ # formulaires normaux, avec modifications des objects FK
else:
- # Nouveau poste
- vars['new'] = True
+ FinancementForm = FinancementFormSet
+ PosteComparaisonForm = PosteComparaisonFormSet
+ financements = []
+ comparaisons = []
+
if request.POST:
data.update(dict(request.POST.items()))
form = PosteForm(data, instance=poste, request=request)
- financementForm = FinancementForm(request.POST, instance=poste)
- piecesForm = PostePieceForm(request.POST, request.FILES, instance=poste)
- postesComparaisonsForm = PosteComparaisonForm(request.POST, instance=poste)
- if form.is_valid() and piecesForm.is_valid() and financementForm.is_valid():
+ financementForm = FinancementForm(request.POST, instance=poste, )
+ piecesForm = PostePieceFormSet(request.POST, request.FILES, instance=poste, )
+ comparaisons_formset = PosteComparaisonForm(
+ request.POST,
+ instance=poste,
+ )
+ if form.is_valid() and piecesForm.is_valid() and \
+ financementForm.is_valid() and comparaisons_formset.is_valid():
poste = form.save()
piecesForm.instance = poste
piecesForm.save()
financementForm.instance = poste
financementForm.save()
- postesComparaisonsForm.instance = poste
- postesComparaisonsForm.save()
- messages.add_message(request, messages.SUCCESS, "Le poste %s a été sauvegardé." % poste)
- if request.POST.has_key('save'):
+
+ # Ne remplacer que les comparaisons de ma région
+ comparaisons = comparaisons_formset.save(commit=False)
+ for comparaison in comparaisons:
+ comparaison.poste = poste
+ comparaison.save()
+
+ # dans le cas d'une modification de poste de RH, on recopie les PJ
+ if poste_rh is not None:
+ for piece in poste_rh.rh_pieces.all():
+ dae.PostePiece(poste=poste, nom=piece.nom,
+ fichier=piece.fichier).save()
+ messages.add_message(
+ request, messages.SUCCESS,
+ "Le poste %s a été sauvegardé." % poste
+ )
+ if 'save' in request.POST:
return redirect('poste_consulter', key='dae-%s' % poste.id)
else:
return redirect('poste', key='dae-%s' % poste.id)
-
+
else:
- messages.add_message(request, messages.ERROR, 'Il y a des erreurs dans le formulaire.')
-
+ messages.add_message(
+ request, messages.ERROR,
+ 'Il y a des erreurs dans le formulaire.'
+ )
+
else:
# 'initial' évite la validation prémature lors d'une copie de poste de
# rh_v1 vers dae.
form = PosteForm(initial=data, instance=poste, request=request)
- piecesForm = PostePieceForm(instance=poste)
- financementForm = FinancementForm(instance=poste)
- postesComparaisonsForm = PosteComparaisonForm(instance=poste)
+ piecesForm = PostePieceFormSet(instance=poste)
+
+ if poste_rh is not None:
+ financementForm = FinancementForm(initial=financements, instance=poste)
+ comparaisons_formset = PosteComparaisonForm(
+ initial=comparaisons,
+ instance=poste,
+ )
+ # cas de la création d'un nouveau poste
+ else:
+ financementForm = FinancementForm(instance=poste)
+ comparaisons_formset = PosteComparaisonForm(instance=poste)
+
+ vars.update(dict(
+ form=form, poste=poste, poste_key=key, piecesForm=piecesForm,
+ financementForm=financementForm,
+ comparaisons_formset=comparaisons_formset,
+ poste_rh=poste_rh,
+ ))
- vars.update(dict(form=form, poste=poste, poste_key=key, piecesForm=piecesForm, financementForm=financementForm, postesComparaisonsForm=postesComparaisonsForm))
+ return render(request, 'dae/poste.html', vars)
- return render_to_response('dae/poste.html', vars, RequestContext(request))
@dae_groupe_requis
def postes_liste(request):
""" Liste des postes. """
- vars = dict()
- vars['postes_a_traiter'] = dae.Poste.objects.mes_choses_a_faire(request.user).all().order_by('-date_creation')
- vars['postes_non_valides'] = dae.Poste.objects.ma_region_ou_service(request.user).filter(~Q(etat=POSTE_ETAT_DRH_FINALISATION)).order_by('-date_creation')
- vars['postes_valides'] = dae.Poste.objects.ma_region_ou_service(request.user).filter(etat=POSTE_ETAT_DRH_FINALISATION).order_by('-date_creation')
- return render_to_response('dae/postes_liste.html', vars, RequestContext(request))
+ content_type = ContentType.objects.get_for_model(dae.Poste)
+ extra_select = {'derniere_validation': (
+ "SELECT MAX(date) FROM workflow_workflowcommentaire "
+ "WHERE content_type_id = '%s' AND object_id = dae_poste.id" %
+ content_type.id
+ )}
+ postes_a_traiter = dae.Poste.objects.mes_choses_a_faire(request.user) \
+ .extra(select=extra_select).order_by('-id')
+ postes_en_cours = dae.Poste.objects.ma_region_ou_service(request.user) \
+ .extra(select=extra_select) \
+ .filter(~Q(etat=POSTE_ETAT_FINALISE)) \
+ .order_by('-id')
+ return render(request, 'dae/postes_liste.html', {
+ 'postes_a_traiter': postes_a_traiter,
+ 'postes_en_cours': postes_en_cours,
+ })
+
+
+@login_required
+def poste_piece(request, id, filename):
+ """Téléchargement d'une pièce jointe à un poste."""
+ piece = get_object_or_404(dae.PostePiece, pk=id)
+ if dae.Poste.objects.ma_region_ou_service(request.user) \
+ .filter(id=piece.poste_id).exists():
+ return sendfile(request, piece.fichier.path)
+ else:
+ return redirect_interdiction(request)
+
+
+### DOSSIER
def filtered_type_remun():
- defaut = (2, 3, 8, 17) # salaire de base, indemnité de fonction, charges patronales
+ defaut = (2, 3, 8, 17) # salaire de base, indemnité de fonction,
+ # charges patronales
return rh.TypeRemuneration.objects.filter(pk__in=defaut)
+
@dae_groupe_requis
@dossier_dans_ma_region_ou_service
def embauche_consulter(request, dossier_id):
dossier = get_object_or_404(dae.Dossier, pk=dossier_id)
+ etat_precedent = dossier.etat
if request.POST:
- validationForm = DossierWorkflowForm(request.POST, instance=dossier, request=request)
+ validationForm = DossierWorkflowForm(
+ request.POST, instance=dossier, request=request
+ )
if validationForm.is_valid():
+ if etat_precedent == DOSSIER_ETAT_REGION_FINALISATION and \
+ validationForm.cleaned_data['etat'] == \
+ DOSSIER_ETAT_DRH_FINALISATION:
+ send_drh_finalisation_mail(request, dossier)
validationForm.save()
- messages.add_message(request, messages.SUCCESS, "La validation a été enregistrée.")
+ messages.add_message(
+ request, messages.SUCCESS, "La validation a été enregistrée."
+ )
return redirect('dae_embauches_liste')
else:
validationForm = DossierWorkflowForm(instance=dossier, request=request)
-
- vars = {
- 'dossier' : dossier,
- 'validationForm' : validationForm,
+
+ comparaisons_internes = \
+ dossier.poste.dae_comparaisons_internes.ma_region_ou_service(
+ request.user
+ )
+ comparaisons = dossier.dae_comparaisons.ma_region_ou_service(request.user)
+ return render(request, 'dae/embauche_consulter.html', {
+ 'dossier': dossier,
+ 'validationForm': validationForm,
+ 'comparaisons_internes': comparaisons_internes,
+ 'comparaisons': comparaisons,
+ 'importer': in_drh_or_admin(request.user)
+ })
+
+@user_passes_test(lambda u: u.is_superuser)
+@dae_groupe_requis
+@dossier_dans_ma_region_ou_service
+def embauche_importer(request, dossier_id=None):
+ dossier_dae = get_object_or_404(dae.Dossier, id=dossier_id)
+ if request.method == 'POST':
+ if 'confirmer' in request.POST:
+ dossier_rh = dossier_dae.importer_dans_rh()
+ return redirect('admin:rh_dossier_change', dossier_rh.id)
+ else:
+ return redirect('embauches_finalisees')
+ else:
+ c = {
+ 'dossier': dossier_dae,
}
+ return render(request, 'dae/embauche_importer.html', c)
+
+
+@dae_groupe_requis
+def embauche_choisir_poste(request):
+ c = {
+ 'form': ChoosePosteForm(request=request),
+ }
+ return render(request, 'dae/embauche-choisir-poste.html', c)
- mode = request.GET.get('mode', None)
- if mode is None:
- return render_to_response('dae/embauche_consulter.html', vars, RequestContext(request))
- if mode == 'pdf':
- return reponse_pdf('dae/embauche_pdf.html', vars)
- if mode == 'vpdf':
- return render_to_response('dae/embauche_pdf.html', vars, RequestContext(request))
@dae_groupe_requis
@dossier_dans_ma_region_ou_service
@dossier_est_modifiable
def embauche(request, key=None, dossier_id=None):
""" Formulaire d'autorisation d'embauche. """
- if not key:
- vars = dict(step='poste', form=ChoosePosteForm(request=request))
- else:
- type_remun = filtered_type_remun()
- vars = dict(type_remun=type_remun)
- source, id = key.split('-')
- if source != 'dae':
- return Http404
- poste = get_object_or_404(dae.Poste, pk=id)
- if not dossier_id:
- vars['new'] = True
- if request.POST:
- if request.POST['employe'] == '':
- # Nouvel employé
- employe = dae.Employe()
+ # Récupérer ou créer un poste et un dossier
+ source, id = key.split('-')
+ if source != 'dae':
+ return Http404
+ poste = get_object_or_404(dae.Poste, pk=id)
+
+ if request.POST:
+ if request.POST['employe'] == '':
+ # Nouvel employé
+ employe = dae.Employe()
+ else:
+ employe_source, id = request.POST['employe'].split('-')
+ if employe_source == 'dae':
+ # Employé DAE
+ employe = get_object_or_404(dae.Employe, pk=id)
+ elif employe_source == 'rh':
+ # Employé RH, on le copie dans DAE
+ e = get_object_or_404(rh.Employe, pk=id)
+ employe = dae.Employe(id_rh=e, prenom=e.prenom, nom=e.nom,
+ genre=e.genre)
else:
- employe_source, id = request.POST['employe'].split('-')
- if employe_source == 'dae':
- # Employé DAE
- employe = get_object_or_404(dae.Employe, pk=id)
- elif employe_source == 'rh':
- # Employé RH, on le copie dans DAE
- e = get_object_or_404(rh.Employe, pk=id)
- employe = dae.Employe(id_rh=e, prenom=e.prenom, nom=e.nom,
- genre=e.genre)
- else:
- raise Http404
-
- employe_form = EmployeForm(request.POST, instance=employe, request=request)
-
- if request.POST:
- if employe_form.is_valid():
- data = dict(request.POST.items())
- #with warnings.catch_warnings():
- # warnings.simplefilter('ignore')
- employe = employe_form.save()
- data['employe'] = 'dae-%s' % employe.id
- employe_form = EmployeForm(data, instance=employe, request=request)
-
- if not dossier_id:
- dossier = dae.Dossier(poste=poste, employe=employe)
- else:
- dossier = get_object_or_404(dae.Dossier, pk=dossier_id)
- dossier_form = DossierForm(request.POST, instance=dossier)
- piecesForm = DossierPieceForm(request.POST, request.FILES, instance=dossier)
- dossiersComparaisonsForm = DossierComparaisonForm(request.POST, instance=dossier)
- remunForm = RemunForm(request.POST, instance=dossier)
- if dossier_form.is_valid() and \
- piecesForm.is_valid() and \
- dossiersComparaisonsForm.is_valid() and \
- remunForm.is_valid():
-
- dossier = dossier_form.save()
- piecesForm.instance = dossier
- piecesForm.save()
- dossiersComparaisonsForm.instance = dossier
- dossiersComparaisonsForm.save()
- remunForm.instance = dossier
- remunForm.save()
-
- #if not dossier.remuneration_set.all():
- # # Pré-peuplement des entrées de la section "coût
- # # global", à l'exclusion de "Indemnité de fonction"
- # for type in type_remun.all():
- # dae.Remuneration(dossier=dossier, type=type,
- # devise=dossier.devise).save()
-
- #else:
- # # Sauvegarde du coût global
- # cg_lines = defaultdict(dict)
- # for k, v in request.POST.items():
- # if k.startswith('cg-'):
- # prefix, field_name, cg_id = k.split('-')
- # cg_lines[int(cg_id)][unicode(field_name)] = v
-
- # for r in dossier.remuneration_set.all():
- # print 'trying %r' % r
- # if r.id in cg_lines:
- # if cg_lines[r.id]['montant'] == '':
- # r.delete()
- # else:
- # for k, v in cg_lines[r.id].items():
- # setattr(r, k, v)
- # r.save()
-
- messages.add_message(request, messages.SUCCESS, "Le dossier %s a été sauvegardé." % dossier)
- if request.POST.has_key('save'):
- return redirect('embauche_consulter', dossier_id=dossier.id)
- else:
- return redirect('embauche', key=dossier.poste.key, dossier_id=dossier.id)
-
- else:
- messages.add_message(request, messages.ERROR, 'Il y a des erreurs dans le formulaire.')
-
+ raise Http404
+
+ employe_form = EmployeForm(
+ request.POST, instance=employe, request=request
+ )
+
+ if employe_form.is_valid():
+ data = dict(request.POST.items())
+ employe = employe_form.save()
+ data['employe'] = 'dae-%s' % employe.id
+ employe_form = EmployeForm(data, instance=employe, request=request)
+
+ if not dossier_id:
+ dossier = dae.Dossier(poste=poste, employe=employe)
+ else:
+ dossier = get_object_or_404(dae.Dossier, pk=dossier_id)
+ dossier.employe = employe_form.instance
+
+ dossier_form = DossierForm(request.POST, instance=dossier)
+ piecesForm = DossierPieceForm(
+ request.POST, request.FILES, instance=dossier
+ )
+ comparaisons_formset = DossierComparaisonFormSet(
+ request.POST,
+ queryset=dossier.dae_comparaisons.ma_region_ou_service(
+ request.user
+ )
+ )
+ remunForm = RemunForm(request.POST, instance=dossier)
+
+ if employe_form.is_valid() and \
+ dossier_form.is_valid() and \
+ piecesForm.is_valid() and \
+ comparaisons_formset.is_valid() and \
+ remunForm.is_valid():
+ employe.save()
+ dossier_form.save()
+ piecesForm.save()
+ remunForm.save()
+
+ # Ne remplacer que les comparaisons de ma région
+ comparaisons = comparaisons_formset.save(commit=False)
+ for comparaison in comparaisons:
+ comparaison.dossier = dossier
+ comparaison.save()
+
+ messages.success(
+ request, "Le dossier %s a été sauvegardé." % dossier
+ )
+ if 'save' in request.POST:
+ return redirect('embauche_consulter', dossier_id=dossier.id)
else:
- dossier_form = DossierForm(instance=dossier)
- piecesForm = DossierPieceForm(instance=dossier)
- dossiersComparaisonsForm = DossierComparaisonForm(instance=dossier)
- remunForm = RemunForm(instance=dossier)
+ return redirect(
+ 'embauche', key=dossier.poste.key, dossier_id=dossier.id
+ )
+
+ else:
+ messages.add_message(
+ request, messages.ERROR,
+ 'Il y a des erreurs dans le formulaire.'
+ )
+
+ else:
+ # Initialisation d'un formulaire vide
+ if dossier_id:
+ dossier = get_object_or_404(dae.Dossier, pk=dossier_id)
+ employe = dossier.employe
+ data = dict(employe='dae-%s' % employe.id)
+ employe_form = EmployeForm(
+ initial=data, instance=employe, request=request
+ )
else:
- # Initialisation d'un formulaire vide
dossier_rh = rh.Dossier()
poste_rh = poste.id_rh
- if dossier_id:
- dossier = get_object_or_404(dae.Dossier, pk=dossier_id)
- employe = dossier.employe
- data = dict(employe='dae-%s' % employe.id)
- employe_form = EmployeForm(initial=data, instance=employe, request=request)
- else:
- dossier = pre_filled_dossier(dossier_rh, 'new', poste_rh)
- employe_form = EmployeForm(request=request)
-
- dossier_form = DossierForm(instance=dossier)
- piecesForm = DossierPieceForm(instance=dossier)
- dossiersComparaisonsForm = DossierComparaisonForm(instance=dossier)
- remunForm = RemunForm(instance=dossier)
-
- vars = dict(step='employe',
- type_remun=type_remun,
- devises=devises(),
- poste=poste,
- dossier=dossier,
- piecesForm=piecesForm,
- remunForm=remunForm,
- dossiersComparaisonsForm=dossiersComparaisonsForm,
- forms=dict(employe=employe_form, dossier=dossier_form, )
+ dossier = pre_filled_dossier(dossier_rh, 'new', poste_rh)
+ employe_form = EmployeForm(request=request)
+
+ dossier_form = DossierForm(instance=dossier)
+ piecesForm = DossierPieceForm(instance=dossier)
+ comparaisons_formset = DossierComparaisonFormSet(
+ queryset=dossier.dae_comparaisons.ma_region_ou_service(
+ request.user
+ )
+ )
+ remunForm = RemunForm(instance=dossier)
+
+ try:
+ comparaisons_internes = \
+ dossier.poste.dae_comparaisons_internes.ma_region_ou_service(
+ request.user
)
-
+ except dae.Poste.DoesNotExist:
+ comparaisons_internes = []
+ c = {
+ 'type_remun': filtered_type_remun(),
+ 'devises': devises(),
+ 'poste': poste,
+ 'dossier': dossier,
+ 'piecesForm': piecesForm,
+ 'remunForm': remunForm,
+ 'comparaisons_formset': comparaisons_formset,
+ 'forms': dict(employe=employe_form, dossier=dossier_form, ),
+ 'comparaisons_internes': comparaisons_internes,
+ }
+ return render(request, 'dae/embauche.html', c)
+
- return render_to_response('dae/embauche.html', vars,
- RequestContext(request))
@dae_groupe_requis
@dossier_dans_ma_region_ou_service
def embauches_liste(request):
""" Liste des embauches. """
- vars = dict()
- vars['embauches_a_traiter'] = dae.Dossier.objects.mes_choses_a_faire(request.user).all().order_by('-date_creation')
- vars['embauches_en_cours'] = dae.Dossier.objects.ma_region_ou_service(request.user).filter(~Q(etat=DOSSIER_ETAT_REFUSE)).order_by('-date_creation')
- vars['embauches_non_retenues'] = dae.Dossier.objects.ma_region_ou_service(request.user).filter(etat=DOSSIER_ETAT_REFUSE).order_by('-date_creation')
- return render_to_response('dae/embauches_liste.html', vars, RequestContext(request))
+ content_type = ContentType.objects.get_for_model(dae.Dossier)
+ extra_select = {'derniere_validation': (
+ "SELECT MAX(date) FROM workflow_workflowcommentaire "
+ "WHERE content_type_id = '%s' AND object_id = dae_dossier.id" %
+ content_type.id
+ )}
+ embauches_a_traiter = dae.Dossier.objects \
+ .mes_choses_a_faire(request.user) \
+ .extra(select=extra_select).order_by('-id')
+ embauches_en_cours = dae.Dossier.objects \
+ .ma_region_ou_service(request.user) \
+ .extra(select=extra_select) \
+ .order_by('-id') \
+ .exclude(etat=DOSSIER_ETAT_FINALISE)
+ c = {
+ 'embauches_a_traiter': embauches_a_traiter,
+ 'embauches_en_cours': embauches_en_cours,
+ }
+ return render(request, 'dae/embauches_liste.html', c)
+
+
+@dae_groupe_requis
+def embauches_finalisees(request):
+ """Liste des embauches finalisées."""
+
+ ### POST
+
+ if request.method == 'POST':
+ if 'supprimer' in request.POST:
+ ids = request.POST.getlist('ids')
+ dossiers = dae.Dossier.objects.filter(id__in=ids)
+ count = dossiers.count()
+ if count > 0:
+ dossiers.delete()
+ messages.success(request, u'%d dossiers supprimés' % count)
+ return redirect(request.get_full_path())
+
+ ### GET
+
+ embauches = dae.Dossier.objects.ma_region_ou_service(request.user) \
+ .filter(etat=DOSSIER_ETAT_FINALISE)
+
+ # Recherche
+ search_form = DAEFinaliseesSearchForm(request.GET)
+ if search_form.is_valid():
+ q = search_form.cleaned_data.get('q').strip()
+ importees = search_form.cleaned_data.get('importees')
+ if q:
+ criteria = [
+ Q(poste__implantation__region__nom__icontains=word) |
+ Q(poste__implantation__region__code=word) |
+ Q(poste__implantation__nom__icontains=word) |
+ Q(poste__nom__icontains=word) |
+ Q(employe__nom__icontains=word) |
+ Q(employe__prenom__icontains=word)
+ for word in q.split()
+ ]
+ embauches = embauches.filter(*criteria)
+ if importees == 'oui':
+ embauches = embauches.exclude(dossier_rh=None)
+ elif importees == 'non':
+ embauches = embauches.filter(dossier_rh=None)
+
+ # Tri
+ tri = request.GET.get('tri', None)
+ if tri and tri.startswith('-'):
+ dir = '-'
+ tri = tri[1:]
+ else:
+ dir = ''
+ if tri == 'region':
+ embauches = embauches.order_by(
+ dir + 'poste__implantation__region__nom'
+ )
+ elif tri == 'implantation':
+ embauches = embauches.order_by(dir + 'poste__implantation__nom')
+ elif tri == 'poste':
+ embauches = embauches.order_by(dir + 'poste__nom')
+ elif tri == 'personne':
+ embauches = embauches.order_by(dir + 'employe__nom',
+ dir + 'employe__prenom')
+ elif tri == 'date_debut':
+ embauches = embauches.order_by(dir + 'debut_contrat')
+ elif tri == 'date_fin':
+ embauches = embauches.order_by(dir + 'fin_contrat')
+
+ # Pagination
+ paginator = Paginator(embauches, 20)
+ try:
+ page = paginator.page(request.GET.get('page', 1))
+ except InvalidPage:
+ page = paginator.page(1)
+
+ return render(request, 'dae/embauches_finalisees.html', {
+ 'embauches': page,
+ 'search_form': search_form,
+ 'importer': in_drh_or_admin(request.user)
+ })
+
def employe(request, key):
""" Récupération AJAX de l'employé pour la page d'embauche. """
for field in ('prenom', 'nom', 'genre'):
setattr(employe, field, getattr(e, field))
- return HttpResponse(EmployeForm(initial=data, instance=employe, request=request).as_table())
+ return HttpResponse(
+ EmployeForm(initial=data, instance=employe, request=request).as_table()
+ )
+
+
+### CONTRATS
+
+@dae_groupe_requis
+@get_contrat
+def contrat(request, contrat, filename):
+ return sendfile(request, contrat.fichier.path)
+
+
+@dae_groupe_requis
+@get_contrat
+def contrat_supprimer(request, contrat):
+ if request.method == 'POST':
+ if 'oui' in request.POST:
+ contrat.delete()
+ return redirect('embauche_consulter', dossier_id=contrat.dossier.id)
+ c = {
+ 'contrat': contrat,
+ }
+ return render(request, 'dae/contrat-supprimer.html', c)
+
+
+@dae_groupe_requis
+@dossier_dans_ma_region_ou_service
+def embauche_ajouter_contrat(request, dossier_id=None):
+ dossier = get_object_or_404(dae.Dossier, pk=dossier_id)
+ if request.method == 'POST':
+ form = ContratForm(request.POST, request.FILES)
+ if form.is_valid():
+ contrat = form.save(commit=False)
+ contrat.dossier = dossier
+ contrat.date_debut = dossier.contrat_date_debut
+ contrat.date_fin = dossier.contrat_date_fin
+ contrat.save()
+ return redirect('embauche_consulter', dossier_id=dossier.id)
+ else:
+ form = ContratForm()
+
+ c = {
+ 'form': form,
+ }
+ return render(request, 'dae/embauche-ajouter-contrat.html', c)
+
+
+### DAE NUMERISEE
+
+@get_object(dae.Dossier, 'consulter')
+def dae_numerisee(request, dossier):
+ return sendfile(request, dossier.dae_numerisee.path)
+
+
+@get_object(dae.Dossier, 'modifier_dae_numerisee')
+def dae_numerisee_modifier(request, dossier):
+ if request.method == 'POST':
+ form = DAENumeriseeForm(request.POST, request.FILES, instance=dossier)
+ if form.is_valid():
+ form.save()
+ return redirect('embauche_consulter', dossier_id=dossier.id)
+ else:
+ form = DAENumeriseeForm(instance=dossier)
+
+ c = {
+ 'form': form,
+ }
+ return render(request, 'dae/dae_numerisee_modifier.html', c)
+
+
+@get_object(dae.Dossier, 'modifier_dae_numerisee')
+def dae_numerisee_supprimer(request, dossier):
+ if request.method == 'POST':
+ if 'oui' in request.POST:
+ dossier.dae_numerisee = None
+ dossier.save()
+ return redirect('embauche_consulter', dossier_id=dossier.id)
+ return render(request, 'dae/dae_numerisee_supprimer.html', {})
+
-################################################################################
# AJAX SECURISE
-################################################################################
+
@dae_groupe_requis
@employe_dans_ma_region_ou_service
def dossier(request, poste_key, employe_key):
# Récupérer la devise de l'implantation lié au poste
implantation_devise = poste.get_default_devise()
- data.update({'devise' : implantation_devise.id})
-
+ data.update({'devise': implantation_devise})
+
if poste.id_rh_id is not None:
poste_rh = get_object_or_404(rh.Poste, pk=poste.id_rh_id)
else:
poste_rh = None
- ##########################################################################################
# NOUVEL EMPLOYE
- ##########################################################################################
if employe_key == '':
employe_source = 'new'
employe = None
dossier_rh = rh.Dossier()
dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
- ##########################################################################################
# EMPLOYE DAE
- ##########################################################################################
if employe_key.startswith('dae'):
- employe_source, employe_id = employe_key.split('-')
- employe_dae = get_object_or_404(dae.Employe, pk=employe_id)
-
- # récupération de l'ancien dossier rh v1 pour l'employe DAE
- try:
- dossier_rh = rh.Dossier.objects.get(employe=employe_dae.id_rh_id, mandat_date_fin=None)
- except (rh.Dossier.DoesNotExist):
- dossier_rh = rh.Dossier()
-
- # on tente de récupérer le dossier DAE, au pire on le contruit en le
- # prépoluant avec son dossier rh v1.
- try:
- dossier = dae.Dossier.objects.get(employe=employe_dae, poste=poste)
- except (dae.Dossier.DoesNotExist):
- dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
- employe = employe_dae.id_rh
- ##########################################################################################
+ employe_source, employe_id = employe_key.split('-')
+ employe_dae = get_object_or_404(dae.Employe, pk=employe_id)
+
+ # récupération de l'ancien dossier rh v1 pour l'employe DAE
+ try:
+ dossier_rh = rh.Dossier.objects.get(
+ employe=employe_dae.id_rh_id, date_fin=None
+ )
+ except (rh.Dossier.DoesNotExist):
+ dossier_rh = rh.Dossier()
+
+ # on tente de récupérer le dossier DAE, au pire on le contruit en le
+ # prépoluant avec son dossier rh v1.
+ try:
+ dossier = dae.Dossier.objects.get(employe=employe_dae, poste=poste)
+ except (dae.Dossier.DoesNotExist):
+ dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
+ employe = employe_dae.id_rh
+
# EMPLOYE RH v1
- ##########################################################################################
if employe_key.startswith('rh'):
- employe_source, employe_id = employe_key.split('-')
- employe_rh = get_object_or_404(rh.Employe, pk=employe_id)
-
- # récupération de l'ancien dossier rh v1 pour l'employe rh v1, s'il n'en a pas,
- # on en fournit un nouveau qui servira uniquement un créer un nouveau dossier DAE.
- try:
- dossier_rh = rh.Dossier.objects.get(employe=employe_rh, mandat_date_fin=None)
- except (rh.Dossier.DoesNotExist):
- dossier_rh = rh.Dossier()
- dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
- employe = employe_rh
+ employe_source, employe_id = employe_key.split('-')
+ employe_rh = get_object_or_404(rh.Employe, pk=employe_id)
+
+ # récupération de l'ancien dossier rh v1 pour l'employe rh v1, s'il
+ # n'en a pas, on en fournit un nouveau qui servira uniquement un
+ # créer un nouveau dossier DAE.
+ try:
+ dossier_rh = rh.Dossier.objects.get(
+ employe=employe_rh, date_fin=None
+ )
+ except (rh.Dossier.DoesNotExist):
+ dossier_rh = rh.Dossier()
+ dossier = pre_filled_dossier(dossier_rh, employe_source, poste_rh)
+ employe = employe_rh
dossier_form = DossierForm(initial=data, instance=dossier)
vars = dict(form=dossier_form, poste=poste, employe=employe)
- return render_to_response('dae/embauche-dossier.html', vars,
- RequestContext(request))
+ return render(request, 'dae/embauche-dossier.html', vars)
+
-# @Cette fonction est appelée à partir de fonctions déjà sécurisée
+# Cette fonction est appelée à partir de fonctions déjà sécurisée
def pre_filled_dossier(dossier_rh, employe_source, poste_rh):
dossier = dae.Dossier()
dossier.classement_anterieur = dossier_rh.classement
# Récupération du salaire de base
- remun = dossier_rh.remuneration_set.filter(type=1).order_by('-date_effective')
+ remun = dossier_rh.remunerations() \
+ .filter(type=1).order_by('-date_debut')
if remun:
dossier.salaire_anterieur = remun[0].montant
+ dossier.devise_anterieur = remun[0].devise
# Récupération du titulaire précédent
try:
- dossiers = rh.Dossier.objects.order_by('-mandat_date_fin')
- dossiers = dossiers.filter(poste1=poste_rh) | dossiers.filter(poste2=poste_rh)
+ dossiers = rh.Dossier.objects.order_by('-date_debut')
+ if poste_rh:
+ dossiers = dossiers.filter(poste=poste_rh)
+ else:
+ dossiers = rh.Dossier.objects.none()
if len(dossiers):
# Ce bloc ignore toutes les erreurs, car les données de rh
# manquantes peuvent en générer
dossier.employe_anterieur = titulaire
dossier.classement_titulaire_anterieur = d.classement
dossier.statut_titulaire_anterieur = d.statut
- dossier.salaire_titulaire_anterieur = d.remuneration_set.filter(type=1).order_by('-date_effective')[0].montant
+ remun = d.remunerations().filter(type=1) \
+ .order_by('-date_debut')[0]
+ dossier.salaire_titulaire_anterieur = remun.montant
+ dossier.devise_titulaire_anterieur = remun.devise
except:
pass
# TODO: afficher l'info, les champs ne sont pas dans le
return dossier
+
@dae_groupe_requis
@vieux_dossier_dans_ma_region_ou_service
def dossier_resume(request, dossier_id=None):
data = {}
data['personne'] = unicode(dossier.employe)
- data['implantation'] = dossier.implantation1.id
- data['poste'] = u"%s %s" % (dossier.poste1.type_poste.nom, dossier.complement1)
- data['montant'] = dossier.get_salaire()
- salaire = dossier.get_dernier_salaire_remun()
+ data['classement'] = dossier.classement.id
+ if dossier.statut is not None:
+ data['statut'] = dossier.statut.id
+ data['implantation'] = dossier.poste.implantation.id
+ data['poste'] = dossier.poste.nom
+ salaire = dossier.get_salaire()
if salaire is not None:
+ data['montant'] = float(salaire.montant)
+ else:
+ data['montant'] = None
+ if salaire is not None and salaire.devise is not None:
data['devise'] = salaire.devise.id
- data['montant_euros'] = salaire.en_euros()
+ data['montant_euros'] = salaire.montant_euros()
else:
data['devise'] = None
data['montant_euros'] = 0
return HttpResponse(dumps(data))
+
@dae_groupe_requis
@vieux_dossier_dans_ma_region_ou_service
def poste_resume(request, dossier_id=None):
except:
return HttpResponseGone("Ce dossier n'est pas accessible")
+ salaire = dossier.get_salaire()
data = {}
- data['implantation'] = dossier.implantation1.id
- data['poste'] = u"%s %s" % (dossier.poste1.type_poste.nom, dossier.complement1)
- data['montant'] = dossier.get_salaire()
- salaire = dossier.get_dernier_salaire_remun()
+ data['implantation'] = dossier.poste.implantation.id
+ data['poste'] = dossier.poste.nom
if salaire is not None:
data['devise'] = salaire.devise.id
- data['montant_euros'] = salaire.en_euros()
+ data['montant'] = float(salaire.montant)
+ data['montant_euros'] = salaire.montant_euros()
else:
data['devise'] = None
- data['montant_euros'] = 0
+ data['montant'] = ""
+ data['montant_euros'] = ""
+ data['statut'] = dossier.statut_id
+ data['classement'] = dossier.classement_id
return HttpResponse(dumps(data))
+
def liste_postes(request):
- """ Appel AJAX :
+ """ Appel AJAX :
input : implantation_id
output : JSON liste de valeur point
"""
params = getattr(request, method, [])
data = []
- # Voir le code de _poste_choices dans forms.py
- dae_ = dae.Poste.objects.filter(actif=True, id_rh__isnull=True)
- copies = dae.Poste.objects.exclude(id_rh__isnull=True)
- rh_postes_actifs = rh.Poste.objects.filter(actif=True)
-
- if 'implantation_id' in params and params.get('implantation_id') is not u"":
+ if 'implantation_id' in params \
+ and params.get('implantation_id') is not u"":
implantation_id = params.get('implantation_id')
- dae_ = dae_.filter(implantation__id=implantation_id)
- copies = copies.filter(implantation__id=implantation_id)
- rh_postes_actifs = rh_postes_actifs.filter(implantation__id=implantation_id)
-
- id_copies = [p.id_rh_id for p in copies.all()]
- rhv1 = rh_postes_actifs.exclude(id__in=id_copies)
- rhv1 = rhv1.select_related(depth=1)
-
- data = [('', 'Nouveau poste')] + sorted([('dae-%s' % p.id, label_poste_display(p)) for p in dae_ | copies] + [('rh-%s' % p.id, label_poste_display(p)) for p in rhv1], key=lambda t: t[1])
+ q = Q(implantation__id=implantation_id)
+ else:
+ q = Q()
+
+ postes_rh = rh.Poste.objects.ma_region_ou_service(request.user).filter(q)
+ postes_rh = postes_rh.select_related(depth=1)
+
+ data = [('', 'Nouveau poste')] + \
+ sorted([('rh-%s' % p.id, label_poste_display(p)) for p in
+ postes_rh],
+ key=lambda t: t[1])
return HttpResponse(dumps(data))
-################################################################################
+@login_required
+def dossier_piece(request, id, filename):
+ """Téléchargement d'une pièce jointe à un poste."""
+ piece = get_object_or_404(dae.DossierPiece, pk=id)
+ if dae.Dossier.objects.ma_region_ou_service(request.user) \
+ .filter(id=piece.dossier_id).exists():
+ return sendfile(request, piece.fichier.path)
+ else:
+ return redirect_interdiction(request)
+
+
# AJAX SECURITE non nécessaire
-################################################################################
+
def coefficient(request):
- """ Appel AJAX :
+ """ Appel AJAX :
input : classement
output : coefficient
"""
def devise(request):
- """ Appel AJAX :
+ """ Appel AJAX :
input : valeur_point
output : devise, devise_code, taux_euro
"""
method = request.method
params = getattr(request, method, [])
data = dict()
- if 'valeur_point' in params and params.get('valeur_point') is not u"":
+ if 'valeur_point' in params and params.get('valeur_point') is not u"":
valeur_point = params.get('valeur_point')
valeur_point = rh.ValeurPoint.objects.get(pk=valeur_point)
annee = valeur_point.annee
- implantation = valeur_point.implantation
- taux = rh.TauxChange.objects.get(annee=annee,
- implantation=implantation)
+ try:
+ taux = rh.TauxChange.objects.get(
+ annee=annee, devise=valeur_point.devise
+ )
+ except MultipleObjectsReturned:
+ return HttpResponseGone(
+ u"Il existe plusieurs taux pour la devise %s "
+ u"cette année-là : %s" % (valeur_point.devise.code, annee)
+ )
+
data['devise'] = taux.devise.id
data['valeur'] = valeur_point.valeur
data['devise_code'] = taux.devise.code
else:
return HttpResponseGone("Vous devez choisir une valeur de point")
return HttpResponse(dumps(data))
-
+
+
def devise_code(request):
- """ Appel AJAX :
+ """ Appel AJAX :
input : devise
output : devise_code, taux_euro
"""
data['taux_euro'] = taux[0].taux
return HttpResponse(dumps(data))
+
def add_remun(request, dossier, type_remun):
dossier = get_object_or_404(dae.Dossier, pk=dossier)
type_remun = get_object_or_404(rh.TypeRemuneration, pk=type_remun)
dae.Remuneration(dossier=dossier, devise=dossier.devise,
type=type_remun).save()
- return render_to_response('dae/embauche-remun.html', dict(dossier=dossier),
- RequestContext(request))
+ c = {
+ 'dossier': dossier,
+ }
+ return render(request, 'dae/embauche-remun.html', c)
+
def salaire(request, implantation, devise, classement):
if not devise or not classement:
raise Http404
- taux_impl = rh.TauxChange.objects.filter(implantation=implantation) \
- .order_by('-annee')
taux = rh.TauxChange.objects.filter(devise=devise).order_by('-annee')
- vp = rh.ValeurPoint.objects.filter(implantation=implantation) \
- .order_by('-annee')
- if vp.count() * taux.count() * taux_impl.count() == 0:
- raise Http404
+ vp = rh.ValeurPoint.objects \
+ .filter(implantation=implantation, devise=devise) \
+ .order_by('-annee')
+
+ if vp.count() == 0:
+ raise Exception(u"pas de valeur de point pour le couple\
+ implantation/devise (%s/%s)" % (implantation, devise))
+
+ if taux.count() == 0:
+ raise Exception(u"Pas de taux pour la devise %s" % devise)
classement = get_object_or_404(rh.Classement, pk=classement)
- taux, taux_impl, vp = taux[0].taux, taux_impl[0].taux, vp[0].valeur
+ if classement.coefficient is None:
+ raise Http404
+ taux, vp = taux[0].taux, vp[0].valeur
- salaire_euro = round(vp * classement.coefficient * taux_impl, 2)
+ salaire_euro = round(vp * classement.coefficient * taux, 2)
data = dict(salaire_euro=salaire_euro, taux=taux,
salaire_devise=round(salaire_euro / taux, 2))
return HttpResponse(dumps(data))
+
def liste_valeurs_point(request):
- """ Appel AJAX :
+ """ Appel AJAX :
input : implantation_id
output : JSON liste de valeur point
"""
method = request.method
params = getattr(request, method, [])
data = []
- annee_courante = datetime.datetime.now().year
- if 'implantation_id' in params and params.get('implantation_id') is not u"":
+ annee_courante = datetime.now().year
+ if 'implantation_id' in params \
+ and params.get('implantation_id') is not u"":
implantation_id = params.get('implantation_id')
- objects = rh.ValeurPoint.objects.filter(implantation=implantation_id, annee__in=(annee_courante-1, annee_courante)).order_by("-annee")
+ preselectionne = rh.ValeurPoint.objects \
+ .filter(implantation=implantation_id, annee=annee_courante) \
+ .order_by("-annee")
+ for o in preselectionne:
+ data.append({
+ 'id': o.id,
+ 'label': o.__unicode__(),
+ 'devise': o.devise_id,
+ 'suggestion': True
+ })
else:
- objects = rh.ValeurPoint.objects.filter(annee__in=(annee_courante-1, annee_courante)).order_by("-annee")
- for o in objects:
- data.append({'id' : o.id, 'label' : o.__unicode__(), })
- return HttpResponse(dumps(data))
-
+ preselectionne = rh.ValeurPoint.objects.none()
+
+ liste_complete = rh.ValeurPoint.objects \
+ .filter(annee__in=(annee_courante,)) \
+ .order_by("-annee")
+ for o in liste_complete.exclude(id__in=[p.id for p in preselectionne]):
+ data.append({
+ 'id': o.id,
+ 'label': o.__unicode__(),
+ 'devise': o.devise_id,
+ 'suggestion': False
+ })
+ return HttpResponse(dumps(data, indent=4))