fix
[auf_rh_dae.git] / project / dae / views.py
index c5cdb69..7277d8b 100644 (file)
@@ -1,43 +1,52 @@
 # -*- 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 dateutil.relativedelta import relativedelta
 
-from django.core.urlresolvers import reverse
-from django.core.paginator import Paginator, InvalidPage
-from django.http import Http404, HttpResponse, HttpResponseGone
-from django.shortcuts import redirect, render_to_response, get_object_or_404
-from django.views.static import serve
-from django.template import Context, RequestContext
-from django.template.loader import get_template
+from auf.django.permissions.decorators import get_object
+from auf.django.references import models as ref
 from django.contrib import messages
-from django.conf import settings
-from django.contrib.auth.decorators import login_required
-
-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.paginator import Paginator, InvalidPage
+from django.db.models import Q, Count
+from django.http import Http404, HttpResponse, HttpResponseNotFound
+from django.shortcuts import redirect, render, get_object_or_404
 from sendfile import sendfile
+from simplejson import dumps
 
-from dae import models as dae
-from dae.forms import *
-from dae.workflow import POSTE_ETAT_DRH_FINALISATION, ETATS_VALIDE, \
-        DOSSIER_ETAT_FINALISE, DOSSIER_ETAT_REGION_FINALISATION, \
-        DOSSIER_ETAT_DRH_FINALISATION
-from dae.decorators import redirect_interdiction, dae_groupe_requis, \
+from project.dae import models as dae
+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 dae.mail import send_drh_finalisation_mail
-from rh_v1 import models as rh
+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, \
+        remun_formset_factory, ReadOnlyRemunFormSet
+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,\
+        in_one_of_group
+from project.rh import models as rh
+from project import groups
 
+# Helpers
 
 def devises():
     liste = []
@@ -49,35 +58,14 @@ def devises():
             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
@@ -89,34 +77,54 @@ def poste_consulter(request, key):
     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)
 
-    comparaisons_internes = poste.comparaisons_internes.ma_region_ou_service(request.user)
-
-    vars = {
+    comparaisons_internes = \
+            poste.dae_comparaisons_internes.ma_region_ou_service(request.user)
+    return render(request, 'dae/poste_consulter.html', {
+        'devises': devises(),
         'poste': poste,
         'validationForm': validationForm,
-        'comparaisons_internes': comparaisons_internes
-    }
+        'comparaisons_internes': comparaisons_internes,
+        'importer': request.user.is_superuser,
+    })
 
-    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))
+
+@user_passes_test(lambda u: u.is_superuser)
+@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
 @poste_dans_ma_region_ou_service
 @poste_est_modifiable
+@in_one_of_group((groups.CORRESPONDANT_RH,
+    groups.ADMINISTRATEURS,
+    groups.DIRECTEUR_DE_BUREAU,
+    groups.DRH_NIVEAU_1,
+    groups.DRH_NIVEAU_2))
 def poste(request, key=None):
     """ Formulaire pour un poste.
 
@@ -124,76 +132,221 @@ def poste(request, key=None):
     il est automatiquement copié dans dae.
 
     """
+    if 'creer_dossier_dae' in request.GET:
+        creer_dossier_dae = True
+    else:
+        creer_dossier_dae = False
+
+    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']
+    if creer_dossier_dae:
+        data['type_intervention'] = request.GET['creer_dossier_dae']
+
+    # 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() and postesComparaisonsForm.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()
+            saved_cmps = [x.id for x in comparaisons]
+
+            for cmp_f in comparaisons_formset.forms:
+                comparaison = (cmp_f.instance, cmp_f)
+
+                cmp_dossier_id = comparaison[1].cleaned_data.get(
+                    'cmp_poste', None)
+                if (not cmp_dossier_id or
+                    comparaison[0].id not in saved_cmps):
+                    continue
+                cmp_dossier_qs = rh.Dossier.objects.filter(id=cmp_dossier_id)
+                if not cmp_dossier_qs.count() > 0:
+                    continue
+                dossier = rh.Dossier.objects.get(id=cmp_dossier_qs.get().id)
+
+                # Get all remunerations for a period of 1 year,
+                # going back from either: today (if dossier has not
+                # yet ended), or from dossier's date_fin.
+                cmp_date = min(dossier.date_fin or date.today(), date.today())
+                for remuneration in _filter_remunerations(
+                    dossier.remunerations().order_by('-date_debut'),
+                    only_traitement=False,
+                    ):
+                    dae.PosteComparaisonRemuneration.objects.create(
+                        poste_comparaison = comparaison[0],
+                        type=remuneration.type,
+                        type_revalorisation=remuneration.type_revalorisation,
+                        montant=remuneration.montant,
+                        devise=remuneration.devise,
+                        commentaire=remuneration.commentaire,
+                        date_debut=remuneration.date_debut,
+                        date_fin=remuneration.date_fin,
+                        )
+
+            # 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 creer_dossier_dae:
+                return redirect('embauche', key='dae-%s' % poste.id)
+
+            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)
+
+
+    # Modify queryset so that it is limited to users' rights:
+    imp_qs = dae.ProxyImplantation.dae_manager.ma_region_ou_service(
+        request.user)
+        
+    for cmp_form in comparaisons_formset.forms:
+        cmp_form.fields['implantation'].queryset = imp_qs
 
-    vars.update(dict(form=form, poste=poste, poste_key=key, piecesForm=piecesForm, financementForm=financementForm, postesComparaisonsForm=postesComparaisonsForm))
+    vars.update(dict(
+        form=form, poste=poste, poste_key=key, piecesForm=piecesForm,
+        financementForm=financementForm,
+        comparaisons_formset=comparaisons_formset,
+        poste_rh=poste_rh,
+        creer_dossier_dae=creer_dossier_dae,
+    ))
+
+    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')
+    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) \
+            .annotate(num_dae=Count('dae_dossiers')) \
+            .filter(num_dae=0) \
+            .extra(select=extra_select).order_by('-id')
+    postes_en_cours = dae.Poste.objects.ma_region_ou_service(request.user) \
+            .annotate(num_dae=Count('dae_dossiers')) \
+            .filter(num_dae=0) \
+            .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,
+    })
 
-    return render_to_response('dae/postes_liste.html', vars, RequestContext(request))
 
 @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():
+    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)
@@ -202,45 +355,81 @@ def poste_piece(request, id, filename):
 ### 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):
+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:
+               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,
+        'devises': devises(),
+        'validationForm': validationForm,
+        'comparaisons_internes': comparaisons_internes,
+        'comparaisons': comparaisons,
+        'importer': request.user.is_superuser,
+    })
+
+
+@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)
 
-    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
 def embauche_choisir_poste(request):
-    return render_to_response('dae/embauche-choisir-poste.html', {
-        'form': ChoosePosteForm(request=request)
-    }, RequestContext(request))
+    if request.POST:
+        form = ChoosePosteForm(data=request.POST, request=request)
+        if form.is_valid():
+            return form.redirect()
+    else:
+        form = ChoosePosteForm(request=request)
+    c = {
+        'form': form,
+    }
+    return render(request, 'dae/embauche-choisir-poste.html', c)
+
 
 @dae_groupe_requis
 @dossier_dans_ma_region_ou_service
@@ -271,7 +460,9 @@ def embauche(request, key=None, dossier_id=None):
             else:
                 raise Http404
 
-        employe_form = EmployeForm(request.POST, instance=employe, request=request)
+        employe_form = EmployeForm(
+            request.POST, instance=employe, request=request
+        )
 
         if employe_form.is_valid():
             data = dict(request.POST.items())
@@ -283,28 +474,87 @@ def embauche(request, key=None, dossier_id=None):
             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)
-        dossiersComparaisonsForm = DossierComparaisonForm(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 dossier_form.is_valid() and \
+        if employe_form.is_valid() and \
+           dossier_form.is_valid() and \
            piecesForm.is_valid() and \
-           dossiersComparaisonsForm.is_valid() and \
+           comparaisons_formset.is_valid() and \
            remunForm.is_valid():
             employe.save()
+            dossier_form.save()
             piecesForm.save()
-            dossiersComparaisonsForm.save()
             remunForm.save()
-            messages.success(request, "Le dossier %s a été sauvegardé." % dossier)
-            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.dossier = dossier
+                comparaison.save()
+            saved_cmps = [x.id for x in comparaisons]
+
+            for cmp_f in comparaisons_formset.forms:
+                comparaison = (cmp_f.instance, cmp_f)
+
+                cmp_dossier_id = comparaison[1].cleaned_data.get(
+                    'cmp_dossier', None)
+                if (not cmp_dossier_id or
+                    comparaison[0].id not in saved_cmps):
+                    continue
+                cmp_dossier_qs = rh.Dossier.objects.filter(id=cmp_dossier_id)
+                if not cmp_dossier_qs.count() > 0:
+                    continue
+                rhdossier = rh.Dossier.objects.get(id=cmp_dossier_qs.get().id)
+
+
+                # Get all remunerations for a period of 1 year,
+                # going back from either: today (if cdossier has not
+                # yet ended), or from cdossier's date_fin.
+                cmp_date = min(rhdossier.date_fin or date.today(), date.today())
+                for remuneration in _filter_remunerations(
+                    rhdossier.remunerations().order_by('-date_debut'),
+                    only_traitement=False,
+                    ):
+                    dae.DossierComparaisonRemuneration.objects.create(
+                        dossier_comparaison = comparaison[0],
+                        type=remuneration.type,
+                        type_revalorisation=remuneration.type_revalorisation,
+                        montant=remuneration.montant,
+                        devise=remuneration.devise,
+                        commentaire=remuneration.commentaire,
+                        date_debut=remuneration.date_debut,
+                        date_fin=remuneration.date_fin,
+                        )
+
+            messages.success(
+                request, "Le dossier %s a été sauvegardé." % dossier
+            )
+            if 'save' in request.POST:
                 return redirect('embauche_consulter', dossier_id=dossier.id)
             else:
-                return redirect('embauche', key=dossier.poste.key, dossier_id=dossier.id)
+                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.')
+            messages.add_message(
+                request, messages.ERROR,
+                'Il y a des erreurs dans le formulaire.'
+            )
 
     else:
         # Initialisation d'un formulaire vide
@@ -312,7 +562,9 @@ def embauche(request, key=None, dossier_id=None):
             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)
+            employe_form = EmployeForm(
+                initial=data, instance=employe, request=request
+            )
         else:
             dossier_rh = rh.Dossier()
             poste_rh = poste.id_rh
@@ -321,35 +573,120 @@ def embauche(request, key=None, dossier_id=None):
 
         dossier_form = DossierForm(instance=dossier)
         piecesForm = DossierPieceForm(instance=dossier)
-        dossiersComparaisonsForm = DossierComparaisonForm(instance=dossier)
+        comparaisons_formset = DossierComparaisonFormSet(
+            queryset=dossier.dae_comparaisons.ma_region_ou_service(
+                request.user
+            )
+        )
         remunForm = RemunForm(instance=dossier)
 
-    return render_to_response('dae/embauche.html', {
+    try:
+        comparaisons_internes = \
+                dossier.poste.dae_comparaisons_internes.ma_region_ou_service(
+                    request.user
+                )
+    except dae.Poste.DoesNotExist:
+        comparaisons_internes = []
+
+    # Modify queryset so that it is limited to users' rights:
+    imp_qs = dae.ProxyImplantation.dae_manager.ma_region_ou_service(
+        request.user)
+        
+    for cmp_form in comparaisons_formset.forms:
+        cmp_form.fields['implantation'].queryset = imp_qs
+
+    # Comment out for now.
+    # if dossier and dossier.poste:
+    #     dossier_form.fields['employe_anterieur'].queryset = (
+    #         dossier_form.fields['employe_anterieur'].queryset.filter(
+    #             rh_dossiers__poste=dossier.poste,
+    #             ).distinct()
+    #         )
+
+    c = {
         'type_remun': filtered_type_remun(),
         'devises': devises(),
         'poste': poste,
         'dossier': dossier,
         'piecesForm': piecesForm,
         'remunForm': remunForm,
-        'dossiersComparaisonsForm': dossiersComparaisonsForm,
-        'forms': dict(employe=employe_form, dossier=dossier_form, )
-    }, RequestContext(request))
+        'comparaisons_formset': comparaisons_formset,
+        'forms': dict(employe=employe_form, dossier=dossier_form, ),
+        'comparaisons_internes': comparaisons_internes,
+    }
+    return render(request, 'dae/embauche.html', c)
+
 
 @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).order_by('-date_creation').exclude(etat=DOSSIER_ETAT_FINALISE)
-    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__zone_administrative__nom__icontains':
+                    word
+                }) |
+                Q(poste__implantation__zone_administrative__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('-'):
@@ -358,7 +695,9 @@ def embauches_finalisees(request):
     else:
         dir = ''
     if tri == 'region':
-        embauches = embauches.order_by(dir + 'poste__implantation__region__nom')
+        embauches = embauches.order_by(
+            dir + 'poste__implantation__zone_administrative__nom'
+        )
     elif tri == 'implantation':
         embauches = embauches.order_by(dir + 'poste__implantation__nom')
     elif tri == 'poste':
@@ -378,9 +717,12 @@ def embauches_finalisees(request):
     except InvalidPage:
         page = paginator.page(1)
 
-    return render_to_response('dae/embauches_finalisees.html', {
-        'embauches': page
-    }, RequestContext(request))
+    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. """
@@ -402,7 +744,10 @@ def employe(request, key):
             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
 
@@ -411,6 +756,7 @@ def employe(request, key):
 def contrat(request, contrat, filename):
     return sendfile(request, contrat.fichier.path)
 
+
 @dae_groupe_requis
 @get_contrat
 def contrat_supprimer(request, contrat):
@@ -418,9 +764,11 @@ def contrat_supprimer(request, contrat):
         if 'oui' in request.POST:
             contrat.delete()
         return redirect('embauche_consulter', dossier_id=contrat.dossier.id)
-    return render_to_response('dae/contrat-supprimer.html', {
-        'contrat': contrat
-    }, RequestContext(request))
+    c = {
+        'contrat': contrat,
+    }
+    return render(request, 'dae/contrat-supprimer.html', c)
+
 
 @dae_groupe_requis
 @dossier_dans_ma_region_ou_service
@@ -431,17 +779,54 @@ def embauche_ajouter_contrat(request, dossier_id=None):
         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()
-    return render_to_response('dae/embauche-ajouter-contrat.html', {
-        'form': form
-    }, RequestContext(request))
 
-################################################################################
+    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):
@@ -453,64 +838,64 @@ 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()
 
@@ -522,16 +907,17 @@ def pre_filled_dossier(dossier_rh, employe_source, poste_rh):
             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_debut')
+        dossiers = rh.Dossier.objects.order_by('-date_debut')
         if poste_rh:
-            dossiers = dossiers.filter(poste1=poste_rh) | dossiers.filter(poste2=poste_rh)
+            dossiers = dossiers.filter(poste=poste_rh)
         else:
             dossiers = rh.Dossier.objects.none()
         if len(dossiers):
@@ -543,7 +929,8 @@ def pre_filled_dossier(dossier_rh, employe_source, poste_rh):
                 dossier.employe_anterieur = titulaire
                 dossier.classement_titulaire_anterieur = d.classement
                 dossier.statut_titulaire_anterieur = d.statut
-                remun = d.remuneration_set.filter(type=1).order_by('-date_effective')[0]
+                remun = d.remunerations().filter(type=1) \
+                        .order_by('-date_debut')[0]
                 dossier.salaire_titulaire_anterieur = remun.montant
                 dossier.devise_titulaire_anterieur = remun.devise
             except:
@@ -557,30 +944,71 @@ def pre_filled_dossier(dossier_rh, employe_source, poste_rh):
 
     return dossier
 
+
+def _filter_remunerations(remun_qs, only_traitement=True):
+    """
+    Type de remun traitement derniers commencant a la meme date
+    """
+    # Toutes les rémunérations d'un dossier
+    remunerations = remun_qs
+
+    if only_traitement:
+        remunerations = [
+            r for r in remun_qs
+            if r.type.nature_remuneration == "Traitement"
+            ]
+    
+    # On prend les dernières avec le postulat que les rémun à la même date
+    # constituent le dernier salaire
+    if len(remunerations) > 0:
+        date_debut = remunerations[0].date_debut
+
+    return [r for r in remunerations if r.date_debut == date_debut]
+    
+
+
+def _get_salaire_traitement(dossier):
+    data = {}
+
+    remunerations = _filter_remunerations(dossier.remunerations().order_by('-date_debut'))
+    
+    montant = 0.0
+    montant_euros = 0.0
+    devise = None
+
+    # Les remun sont sensées être dans la même devise
+    for r in remunerations:
+        montant += float(r.montant)
+        montant_euros += r.montant_euros()
+        devise = r.devise.id
+
+    data['devise'] = devise
+    data['montant'] = montant
+    data['montant_euros'] = montant_euros
+    return data
+
+
 @dae_groupe_requis
 @vieux_dossier_dans_ma_region_ou_service
 def dossier_resume(request, dossier_id=None):
     try:
         dossier = rh.Dossier.objects.get(id=dossier_id)
     except:
-        return HttpResponseGone("Ce dossier n'est pas accessible")
+        return HttpResponseNotFound("Ce dossier n'est pas accessible")
 
     data = {}
     data['personne'] = unicode(dossier.employe)
-    data['classement'] = dossier.classement.id
-    data['statut'] = dossier.statut.id
-    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()
-    if salaire is not None:
-        data['devise'] = salaire.devise.id
-        data['montant_euros'] = salaire.en_euros()
-    else:
-        data['devise'] = None
-        data['montant_euros'] = 0
+    if dossier.classement is not None:
+        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
+    data['d_id'] = dossier.id
+    data.update(_get_salaire_traitement(dossier))
     return HttpResponse(dumps(data))
 
+
 @dae_groupe_requis
 @vieux_dossier_dans_ma_region_ou_service
 def poste_resume(request, dossier_id=None):
@@ -591,21 +1019,19 @@ def poste_resume(request, dossier_id=None):
     try:
         dossier = rh.Dossier.objects.get(id=dossier_id)
     except:
-        return HttpResponseGone("Ce dossier n'est pas accessible")
+        return HttpResponseNotFound("Ce dossier n'est pas accessible")
 
     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()
-    if salaire is not None:
-        data['devise'] = salaire.devise.id
-        data['montant_euros'] = salaire.en_euros()
-    else:
-        data['devise'] = None
-        data['montant_euros'] = 0
+    data['implantation'] = dossier.poste.implantation.id
+    data['poste'] = dossier.poste.nom
+    data['statut'] = dossier.statut_id
+    data['classement'] = dossier.classement_id
+    data['d_id'] = dossier.id
+    data.update(_get_salaire_traitement(dossier))
+
     return HttpResponse(dumps(data))
 
+
 def liste_postes(request):
     """ Appel AJAX :
     input : implantation_id
@@ -615,37 +1041,36 @@ def liste_postes(request):
     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)
+        q = Q(implantation__id=implantation_id)
+    else:
+        q = Q()
 
-    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)
+    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([('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])
+    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():
+    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 :
     input : classement
@@ -675,17 +1100,30 @@ def devise(request):
         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 rh.TauxChange.DoesNotExist:
+            return HttpResponseNotFound(
+                u"Taux de change introuvable pour la devise %s "
+                u"pour l'année %d" % (valeur_point.devise.code, annee)
+            )
+        except rh.TauxChange.MultipleObjectsReturned:
+            return HttpResponseNotFound(
+                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
         data['taux_euro'] = taux.taux
     else:
-        return HttpResponseGone("Vous devez choisir une valeur de point")
+        return HttpResponseNotFound("Vous devez choisir une valeur de point")
     return HttpResponse(dumps(data))
 
+
 def devise_code(request):
     """ Appel AJAX :
     input : devise
@@ -700,41 +1138,55 @@ def devise_code(request):
         annee = date.today().year
         taux = rh.TauxChange.objects.filter(annee=annee, devise=devise)
         if len(taux) == 0:
-            return HttpResponseGone("Le taux n'est pas disponible")
+            return HttpResponseNotFound("Le taux n'est pas disponible")
         data['devise_code'] = devise.code
         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:
+        status = u"pas de valeur de point pour le couple \
+implantation/devise (%s/%s)" % (implantation, devise)
+        return HttpResponse(dumps(dict(status=status)))
+
+    if taux.count() == 0:
+        status = u"Pas de taux pour la devise %s" % devise
+        return HttpResponse(dumps(dict(status=status)))
 
     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)
-    data = dict(salaire_euro=salaire_euro, taux=taux,
+    salaire_euro = round(vp * classement.coefficient * taux, 2)
+    data = dict(status='OK',
+                salaire_euro=salaire_euro, taux=taux,
                 salaire_devise=round(salaire_euro / taux, 2))
 
     return HttpResponse(dumps(data))
 
+
 def liste_valeurs_point(request):
     """ Appel AJAX :
     input : implantation_id
@@ -743,16 +1195,31 @@ def liste_valeurs_point(request):
     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')
-        preselectionne = rh.ValeurPoint.objects.filter(implantation=implantation_id, annee__in=(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.get_tauxchange_courant().devise.id, 'suggestion' : True})
+            data.append({
+                'id': o.id,
+                'label': o.__unicode__(),
+                'devise': o.devise_id,
+                'suggestion': True
+            })
     else:
         preselectionne = rh.ValeurPoint.objects.none()
 
-    liste_complete = rh.ValeurPoint.objects.filter(annee__in=(annee_courante,)).order_by("-annee")
+    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.get_tauxchange_courant().devise.id, 'suggestion' : False})
-    return HttpResponse(dumps(data))
+        data.append({
+            'id': o.id,
+            'label': o.__unicode__(),
+            'devise': o.devise_id,
+            'suggestion': False
+        })
+    return HttpResponse(dumps(data, indent=4))