Merge branch 'release/1.7' into dev
authorBenoit C. Sirois <benoit.clennett-sirois@auf.org>
Thu, 14 Mar 2013 14:20:59 +0000 (10:20 -0400)
committerBenoit C. Sirois <benoit.clennett-sirois@auf.org>
Thu, 14 Mar 2013 14:20:59 +0000 (10:20 -0400)
27 files changed:
project/assets/css/dae.css
project/assets/css/print.css
project/assets/js/remun.js
project/dae/catalogues.py
project/dae/forms.py
project/dae/managers.py
project/dae/models.py
project/dae/templates/dae/embauche-dossier-consulter.html
project/dae/templates/dae/embauche-remun.html
project/dae/templates/dae/embauche_consulter.html
project/dae/templates/dae/poste.html
project/dae/templates/dae/poste_resume.html
project/dae/templates/dae/table_remuneration.html
project/dae/templatetags/dae.py
project/dae/views.py
project/dae/widgets.py
project/rh/admin.py
project/rh/catalogues.py
project/rh/forms.py
project/rh/migrations/0044_auto__add_field_changementpersonnel_date_creation.py [new file with mode: 0644]
project/rh/models.py
project/rh/templates/email/mouvement_employe.html [new file with mode: 0644]
project/rh/templates/rh/include/dossier.html
project/rh/templates/rh/include/employe.html
project/rh/templates/rh/include/remunerations.html
project/rh/views.py
project/settings.py

index a0da3f0..9e905cc 100644 (file)
@@ -19,4 +19,7 @@ h2.section {width:100%; background-color: #D0E8F8; text-align: center; color: #5
 .pagination { text-align: center; }
 table.listing { width: 100%; }
 .print-only { display: none; }
-.total-row th { background-color: #C7D1D8; }
\ No newline at end of file
+.total-row th, .total-row td { background-color: #C7D1D8; }
+tr td.spaced {
+    padding-left: 25px;
+}
\ No newline at end of file
index 0f22c3b..78ecb67 100644 (file)
@@ -27,3 +27,20 @@ label {font-weight: bold;}
 a.bouton-action, #header, #footer, #menu, form { display: none; }
 
 .print-only { display: block; }
+
+table#global-cost tr td.spaced {
+    padding-left: 25px;
+}
+
+table#global-cost tr td,
+table#global-cost tr th {
+    padding: 0px;
+}
+
+table#global-cost tr th {
+    font-size: 12px;
+}
+
+tr.gris-bkg {
+    background-color:#ccc; !important;
+}
\ No newline at end of file
index a73067c..c0fd635 100644 (file)
@@ -16,8 +16,7 @@ function remun_line(input) {
     //         return;
     // }
 
-    value = (montant_annuel.val());
-    value = roundNumber(value, 2)
+    value = montant_annuel.val();
 
     montant_annuel.val(roundNumber(value, 2));
 
@@ -55,6 +54,7 @@ function totalByIndex(selector, accessor) {
       aelector: the element where to display costs, and from which the index will be calculated.
       accessor: a function to get all items that will be part of the total.
     */
+    // $(selector).hide();
     $(selector).each(function(){
        var subtot = 0;
        var i = $(this).index();
index d52ad55..ba52e46 100644 (file)
@@ -96,7 +96,7 @@ class Dossier(object):
             q_filtre = q_recherche
         else:
             q_filtre = q_place & q_recherche
-        return rh.Dossier.objects.filter(q_filtre).distinct()
+        return rh.Dossier.objects.ma_region_ou_service(request.user).filter(q_filtre).distinct()
 
     def format_result(self, dossier):
         return dossier.__unicode__()
@@ -133,21 +133,25 @@ class Poste(object):
                     ))
               ))
 
-        if groups.is_user_dans_services_centraux(request.user):
-            q_place = Q(**{prefixe_implantation: employe.implantation})
-        else:
-            q_place = Q(**{
-                prefixe_implantation + '__zone_administrative':
-                employe.implantation.zone_administrative
-            })
+        # if groups.is_user_dans_services_centraux(request.user):
+        #     q_place = Q(**{prefixe_implantation: employe.implantation})
+        # else:
+        #     q_place = Q(**{
+        #         prefixe_implantation + '__zone_administrative':
+        #         employe.implantation.zone_administrative
+        #     })
 
-        user_groupes = [g.name for g in request.user.groups.all()]
-        if groups.DRH_NIVEAU_1 in user_groupes or \
-           groups.DRH_NIVEAU_2 in user_groupes:
-            q_filtre = q_recherche
-        else:
-            q_filtre = q_place & q_recherche
-        return rh.Dossier.objects.filter(q_filtre).order_by('-date_debut')
+
+        # user_groupes = [g.name for g in request.user.groups.all()]
+        # if groups.DRH_NIVEAU_1 in user_groupes or \
+        #    groups.DRH_NIVEAU_2 in user_groupes:
+        #     q_filtre = q_recherche
+        # else:
+        #     q_filtre = q_place & q_recherche
+
+        q_filtre = q_recherche
+
+        return rh.Dossier.objects.ma_region_ou_service(request.user).filter(q_filtre).order_by('-date_debut')
 
     def format_result(self, dossier):
         annee = dossier.date_debut.year
index 498f308..8856a18 100644 (file)
@@ -29,6 +29,20 @@ from .widgets import ReadOnlyChoiceWidget, ReadOnlyWidget
 from project.dae.workflow import POSTE_ETATS_BOUTONS, POSTE_ETAT_FINALISE
 
 
+def filtered_archived_fields_form_factory(*fields):
+    """
+    Retourne un model form 
+    """
+    class FilterArchivedFields(object):
+        def __init__(self, *a, **kw):
+            super(FilterArchivedFields, self).__init__(*a, **kw)
+            for f in fields:
+                self.fields[f].queryset = (
+                    self.fields[f]._queryset.filter(archive=False)
+                    )
+    return FilterArchivedFields
+
+
 class BaseInlineFormSetWithInitial(BaseInlineFormSet):
     """
     Cette classe permet de fournir l'option initial aux inlineformsets.
@@ -212,7 +226,11 @@ FinancementFormSet = inlineformset_factory(
 )
 
 
-class DossierComparaisonForm(forms.ModelForm):
+class DossierComparaisonForm(
+    filtered_archived_fields_form_factory(
+        'classement',
+        ),
+    forms.ModelForm):
 
     recherche = AutoCompleteSelectField('dossiers', required=False)
     poste = forms.CharField(
@@ -232,7 +250,9 @@ DossierComparaisonFormSet = modelformset_factory(
 )
 
 
-class PosteComparaisonForm(forms.ModelForm):
+class PosteComparaisonForm(
+    filtered_archived_fields_form_factory('classement'),
+    forms.ModelForm):
 
     recherche = AutoCompleteSelectField('dae_postes', required=False)
 
@@ -264,7 +284,11 @@ PosteComparaisonFormSet = inlineformset_factory(
 )
 
 
-class FlexibleRemunForm(forms.ModelForm):
+class FlexibleRemunForm(
+    filtered_archived_fields_form_factory(
+        'type',
+        ),
+    forms.ModelForm):
     # Utilisé dans templats.
     montant_mensuel = forms.DecimalField(required=False)
     montant = forms.DecimalField(required=True, label='Montant annuel')
@@ -370,7 +394,9 @@ class GroupedInlineFormset(BaseInlineFormSet):
 
         for g in self.groups:
             for i in xrange(self.extra):
-                self.groups[g]['forms'].append(tmp_extras.pop())
+                tmp_form = tmp_extras.pop()
+                self.groups[g]['forms'].append(tmp_form)
+                self.forms.append(tmp_form)
             
 
         # Override form choices with the data provided in
@@ -477,7 +503,11 @@ def remun_formset_factory(parent_model,
     return FormSet
 
 
-def remun_formset_factory_factory(read_only=False, parent_model=dae.Dossier, model=dae.Remuneration):
+def remun_formset_factory_factory(
+    read_only=False,
+    parent_model=dae.Dossier,
+    model=dae.Remuneration,
+    exclude_archived=False):
     """
     Don't we love factory factories?
     """
@@ -487,6 +517,13 @@ def remun_formset_factory_factory(read_only=False, parent_model=dae.Dossier, mod
     can_delete = False if read_only else True
     form_class = ReadOnlyRemunForm if read_only else FlexibleRemunForm
 
+    choice_override_extra_q = {}
+
+    if exclude_archived:
+        choice_override_extra_q.update({
+            'archive': False
+            })
+    
     return remun_formset_factory(
         parent_model,
         model,
@@ -494,56 +531,56 @@ def remun_formset_factory_factory(read_only=False, parent_model=dae.Dossier, mod
         extra=extras,
         can_delete=can_delete,
         read_only=read_only,
-        groups = [
-            (u'Traitement', u'Traitement',),
-            (u'Indemnité', u'Indemnité',),
-            (u'Charges', u'Charges',),
-            (u'Accessoire', u'Accessoire',),
-            (u'RAS', u'Rémunération autre source',),
-            ],
+        groups = rh.NATURE_REMUNERATION_CHOICES,
         choice_overrides = {
             u'Traitement': {
                 'type': [null_choice] + list(
                     rh.TypeRemuneration.objects.filter(
-                        nature_remuneration=u'Traitement').values_list(
+                        nature_remuneration=u'Traitement',
+                        **choice_override_extra_q).values_list(
                         'id', 'nom')
                     )
                 },
             u'Indemnité': {
                 'type': [null_choice] + list(
                     rh.TypeRemuneration.objects.filter(
-                        nature_remuneration=u'Indemnité').values_list(
+                        nature_remuneration=u'Indemnité',
+                        **choice_override_extra_q).values_list(
                         'id', 'nom')
                     )
                 },
             u'Charges': {
                 'type': [null_choice] + list(
                     rh.TypeRemuneration.objects.filter(
-                        nature_remuneration=u'Charges').values_list(
+                        nature_remuneration=u'Charges',
+                        **choice_override_extra_q).values_list(
                         'id', 'nom')
                     )
                 },
             u'Accessoire': {
                 'type': [null_choice] + list(
                     rh.TypeRemuneration.objects.filter(
-                        nature_remuneration=u'Accessoire').values_list(
+                        nature_remuneration=u'Accessoire',
+                        **choice_override_extra_q).values_list(
                         'id', 'nom')
                     )
                 },
             u'RAS': {
                 'type': [null_choice] + list(
                     rh.TypeRemuneration.objects.filter(
-                        nature_remuneration=u'RAS').values_list(
+                        nature_remuneration=u'RAS',
+                        **choice_override_extra_q).values_list(
                         'id', 'nom')
                     )
                 },
-            }
+            },
         )
 
 RemunForm = remun_formset_factory_factory(
     read_only=False,
     parent_model=dae.Dossier,
     model=dae.Remuneration,
+    exclude_archived=True,
 )
 
 ReadOnlyRemunFormSet = remun_formset_factory_factory(
@@ -565,7 +602,10 @@ DossierCompReadOnlyRemunFormSet = remun_formset_factory_factory(
     )
 
 
-class PosteForm(forms.ModelForm):
+class PosteForm(filtered_archived_fields_form_factory(
+        'classement_min',
+        'classement_max',),
+                forms.ModelForm):
     """ Formulaire des postes. """
 
     # On ne propose que les services actifs
@@ -747,7 +787,13 @@ class EmployeForm(forms.ModelForm):
         self.fields['employe'].choices = _employe_choices(self, request)
 
 
-class DossierForm(forms.ModelForm):
+class DossierForm(
+    filtered_archived_fields_form_factory(
+        'classement',
+        'classement_anterieur',
+        'classement_titulaire_anterieur',
+        ),
+    forms.ModelForm):
     """ Formulaire des dossiers. """
     class Meta:
         exclude = ('etat', 'employe', 'poste', 'date_debut',)
index f712815..544d906 100644 (file)
@@ -7,10 +7,15 @@ from project.rh.managers import \
         DossierManager as RHDossierManager, \
         PosteManager as RHPosteManager, \
         PosteComparaisonManager as RHPosteComparaisonManager, \
-        DossierComparaisonManager as RHDossierComparaisonManager
+        DossierComparaisonManager as RHDossierComparaisonManager, \
+        SecurityManager
 from project.dae.workflow import MAP_GROUPE_ETATS_A_FAIRE
 
 
+class ImplantationManager(SecurityManager):
+    use_for_related_fields = True
+    prefixe_implantation = "zone_administrative"
+
 class TodoManagerMixin(object):
 
     def mes_choses_a_faire(self, user):
index 0a0bb0c..fbb8f7a 100644 (file)
@@ -11,7 +11,10 @@ from django.db.models import Q
 
 import reversion
 
-from project.dae.managers import PosteManager, DossierManager
+from auf.django.references import models as ref
+
+from project.dae.managers import (
+    PosteManager, DossierManager, ImplantationManager)
 from project.dae.workflow import PosteWorkflow, DossierWorkflow
 from project.dae.workflow import \
         DOSSIER_ETAT_DRH_FINALISATION, DOSSIER_ETAT_REGION_FINALISATION, \
@@ -664,6 +667,7 @@ class Dossier(DossierWorkflow, rh.Dossier_):
         dossier_rh.statut_residence = self.statut_residence
         dossier_rh.classement = self.classement
         dossier_rh.regime_travail = self.regime_travail
+        dossier_rh.est_cadre = self.est_cadre
         dossier_rh.regime_travail_nb_heure_semaine = \
                 self.regime_travail_nb_heure_semaine
         dossier_rh.date_debut = self.contrat_date_debut
@@ -840,3 +844,12 @@ class ProxyPosteStatut(Poste):
         proxy = True
         verbose_name = "Statut du poste"
         verbose_name_plural = "Statut des postes"
+
+
+class ProxyImplantation(ref.Implantation):
+
+    # Ajout d'un manager pour ref.Implantation
+    dae_manager = ImplantationManager()
+    
+    class Meta:
+        proxy = True
index 520c44a..9ae9a1d 100644 (file)
         <td>{%if dossier.remplacement %}oui{% else %}non{%endif %}</td>
     </tr>
     <tr>
+        <th>Est un cadre?</th>
+        <td>{%if dossier.est_cadre %}oui{% else %}non{%endif %}</td>
+    </tr>
+    <tr>
         <th>Durée</th>
         <td> du {{ dossier.contrat_date_debut }} au {{ dossier.contrat_date_fin }}</td>
     </tr>
index 52b7ee8..4214d98 100644 (file)
@@ -1,3 +1,6 @@
+{% load l10n %}
+{% load dae %}
+
 {% for f in remunForm.management_form %}
     {{ f }}
 {% endfor %}
@@ -6,8 +9,11 @@
 <tr>
   <th>Type</th>
   <th>Devise locale</th>
-  <th>Annuel</th>
-  <th>Annuel Euros</th>
+  <th>Annuel<br/>(visé)</th>
+  <th>Annuel Euros<br/>(visé)</th>
+  {% if remunForm.read_only %}
+  <th>Annuel Euros<br/>(ajusté par période)</th>
+  {% endif %}
   <th>Précision</th>
   {% if not remunForm.read_only %}
   <th>Supprimer</th>
 {% for f in group.forms %}
 <tr class="calculable remunform">
     {{ f.id }}
-    <td>{{ f.type.errors }} {{ f.type }}</td>
+    <td class="spaced">{{ f.type.errors }} {{ f.type }}
+      {% if f.instance.date_debut or f.instance.date_fin %}
+      {% if f.instance.date_debut or f.instance.date_fin %}({% endif %}
+      {% if f.instance.date_debut %}{{f.instance.date_debut}}{% endif %}
+      -
+      {% if f.instance.date_fin %}{{f.instance.date_fin}}{% endif %}
+      {% if f.instance.date_debut or f.instance.date_fin %}){% endif %}
+      {% endif %}
+    </td>
     <td>{{ f.devise.errors }} {{ f.devise }}</td>
     <td class="monnaie cumulable">{{ f.montant.errors }} {{ f.montant }}</td>
     <td class="euro cumulable" id="id_{{ f.prefix }}-montant_annuel_euros"></td>
+    <!-- <td class="euro-ajuste cumulable" id="id_{{ f.prefix }}-montant_annuel_euros_ajuste">{{ f.instance.montant_ajuste_euros|stringformat:".2f" }}</td> -->
+    {% if remunForm.read_only %}
+    <td class="euro-ajuste cumulable" id="id_{{ f.prefix }}-montant_annuel_euros_ajuste">
+      {% remun_ajuste f.instance annee_remun %}
+    </td>
+    {% endif %}
     <td>{{ f.commentaire.errors }} {{ f.commentaire }}</td>
     {% if not remunForm.read_only %}
     <td>{{ f.DELETE }}</td>
@@ -32,7 +52,7 @@
 </tr>
 {% endfor %}
 <tr class="sous-totaux">
-    <td>Sous-total{% if not remunForm.read_only %} - 
+    <td class="spaced">Sous-total{% if not remunForm.read_only %} - 
       <a class="addlink" href="#">
        [<span class="icon">Ajouter une ligne</span>]
       </a>
@@ -41,6 +61,9 @@
     <td><!-- Laisser ce td pour que le javascript fonctionne bien. --></td>
     <td class="sous-total"></td>
     <td class="sous-total"></td>
+    {% if remunForm.read_only %}
+    <td class="sous-total"></td>
+    {% endif %}
     <td>&nbsp;</td>
     {% if not remunForm.read_only %}
     <td>&nbsp;</td>
@@ -53,6 +76,9 @@
     <th><!-- Laisser ce td pour que le javascript fonctionne bien. --></th>
     <th class="total"></th>
     <th class="total"></th>
+    {% if remunForm.read_only %}
+    <th class="total"></th>
+    {% endif %}
     <th>&nbsp;</th>
     {% if not remunForm.read_only %}
     <th>&nbsp;</th>
@@ -63,6 +89,9 @@
     <th><!-- Laisser ce td pour que le javascript fonctionne bien. --></th>
     <th></th>
     <th></th>
+    {% if remunForm.read_only %}
+    <th></th>
+    {% endif %}
     <th>&nbsp;</th>
     {% if not remunForm.read_only %}
     <th>&nbsp;</th>
 {% for f in remunForm.groups.RAS.forms %}
 <tr class="calculable remunform">
     {{ f.id }}
-    <td>{{ f.type.errors }} {{ f.type }}</td>
+    <td class="spaced">{{ f.type.errors }} {{ f.type }}</td>
     <td>{{ f.devise.errors }} {{ f.devise }}</td>
     <td class="monnaie cumulable">{{ f.montant.errors }} {{ f.montant }}</td>
     <td class="euro cumulable" id="id_{{ f.prefix }}-montant_annuel_euros"></td>
+    {% if remunForm.read_only %}
+    <td class="euro-ajuste cumulable" id="id_{{ f.prefix }}-montant_annuel_euros_ajuste">    
+      {% remun_ajuste f.instance annee_remun %}
+    </td>
+    {% endif %}
     <td>{{ f.commentaire.errors }} {{ f.commentaire }}</td>
     {% if not remunForm.read_only %}
     <td>{{ f.DELETE }}</td>
 </tr>
 {% endfor %}
 <tr class="sous-totaux">
-    <td>Sous-total{% if not remunForm.read_only %} - 
+    <td class="spaced">Sous-total{% if not remunForm.read_only %} - 
       <a class="addlink" href="#">
        [<span class="icon">Ajouter une ligne</span>]
       </a>
     <td><!-- Laisser ce td pour que le javascript fonctionne bien. --></td>
     <td class="sous-total"></td>
     <td class="sous-total"></td>
+    {% if remunForm.read_only %}
+    <td class="sous-total"></td>
+    {% endif %}
     <td>&nbsp;</td>
     {% if not remunForm.read_only %}
     <td>&nbsp;</td>
index a8d9210..a8b585a 100644 (file)
@@ -81,7 +81,7 @@
           <th>Salaire EUR</th>
       </tr>
       {% for dc in comparaisons %}
-      <tr>
+      <tr class="gris-bkg">
           <td>{{ dc.classement|default:"" }}</td>
           <td>{{ dc.statut|default:"" }}</td>
           <td>{{ dc.implantation }}</td>
index 182f556..aeffe37 100644 (file)
@@ -357,7 +357,7 @@ Demande d'autorisation d'engagement
     </fieldset>
 
     {% if creer_dossier_dae %}
-        <input type="submit" name="save" value="Créer ce poste et une embauche associée" />
+        <input type="submit" name="save" value="Créer ou renouveler ce poste et une embauche associée" />
     {% else %}
         <input type="submit" name="continue" value="Sauvegarder (et ajouter des lignes)" />
         <input type="submit" name="save" value="Sauvegarder" />
index 44e5ec7..0b5387e 100644 (file)
   <thead>
     <tr>
       <th></th>
-      <th>Min.</th>
-      <th>Max.</th>
+      <th>Min. annuel ({{ poste.devise_min.code }})</th>
+      <th>Min. annuel (€, taux: {{ poste.show_taux_minimum }})</th>
+      <th>Max. annuel ({{ poste.devise_max.code }})</th>
+      <th>Max. annuel (€, taux: {{ poste.show_taux_maximum }})</th>
     </tr>
   </thead>
   <tbody>
     <tr>
       <th>Échelon AUF</th>
-      <td>{{ poste.classement_min }}</td>
-      <td>{{ poste.classement_max }}</td>
+      <td colspan="2">{{ poste.classement_min }}</td>
+      <td colspan="2">{{ poste.classement_max }}</td>
     </tr>
     <tr>
-      <th>Salaire de base</th>
+      <td class="spaced" >Salaire de base</td>
       <td class="montant">
-        {{ poste.salaire_min|floatformat:0 }} {{ poste.devise_min.code }}
+        {{ poste.salaire_min|floatformat:0 }}
       </td>
       <td class="montant">
-        {{ poste.salaire_max|floatformat:0 }} {{ poste.devise_max.code }}
+        {{ poste.salaire_min|euros:poste.devise_min|floatformat:0 }}
+      </td>
+      <td class="montant">
+        {{ poste.salaire_max|floatformat:0 }}
+      </td>
+      <td class="montant">
+        {{ poste.salaire_max|euros:poste.devise_max|floatformat:0 }}
       </td>
     </tr>
     <tr>
-      <th>Indem. d'expatriation</th>
-      <td class="montant">{{ poste.indemn_expat_min|floatformat:0 }} {{ poste.devise_min.code }}</td>
-      <td class="montant">{{ poste.indemn_expat_max|floatformat:0 }} {{ poste.devise_max.code }}</td>
+      <td class="spaced">Indem. d'expatriation</td>
+      <td class="montant">{{ poste.indemn_expat_min|floatformat:0 }}</td>
+      <td class="montant">{{ poste.indemn_expat_min|euros:poste.devise_min|floatformat:0 }}</td>
+      <td class="montant">{{ poste.indemn_expat_max|floatformat:0 }}</td>
+      <td class="montant">{{ poste.indemn_expat_max|euros:poste.devise_max|floatformat:0 }}</td>
     </tr>
     <tr>
-      <th>Indem. de fonction</th>
-      <td class="montant">{{ poste.indemn_fct_min|floatformat:0 }} {{ poste.devise_min.code }}</td>
-      <td class="montant">{{ poste.indemn_fct_max|floatformat:0 }} {{ poste.devise_max.code }}</td>
+      <td class="spaced">Indem. de fonction</td>
+      <td class="montant">{{ poste.indemn_fct_min|floatformat:0 }}</td>
+      <td class="montant">{{ poste.indemn_fct_min|euros:poste.devise_min|floatformat:0 }}</td>
+      <td class="montant">{{ poste.indemn_fct_max|floatformat:0 }}</td>
+      <td class="montant">{{ poste.indemn_fct_max|euros:poste.devise_max|floatformat:0 }}</td>
     </tr>
     <tr>
-      <th>Charges patronales</th>
-      <td class="montant">{{ poste.charges_patronales_min|floatformat:0 }} {{ poste.devise_min.code }}</td>
-      <td class="montant">{{ poste.charges_patronales_max|floatformat:0 }} {{ poste.devise_max.code }}</td>
+      <td class="spaced">Charges patronales</td>
+      <td class="montant">{{ poste.charges_patronales_min|floatformat:0 }}</td>
+      <td class="montant">{{ poste.charges_patronales_min|euros:poste.devise_min|floatformat:0 }}</td>
+      <td class="montant">{{ poste.charges_patronales_max|floatformat:0 }}</td>
+      <td class="montant">{{ poste.charges_patronales_max|euros:poste.devise_max|floatformat:0 }}</td>
     </tr>
     <tr>
-      <th>Autres</th>
-      <td class="montant">{{ poste.autre_min|floatformat:0 }} {{ poste.devise_min.code }}</td>
-      <td class="montant">{{ poste.autre_max|floatformat:0 }} {{ poste.devise_max.code }}</td>
+      <td class="spaced">Autres</td>
+      <td class="montant">{{ poste.autre_min|floatformat:0 }}</td>
+      <td class="montant">{{ poste.autre_min|euros:poste.devise_min|floatformat:0 }}</td>
+      <td class="montant">{{ poste.autre_max|floatformat:0 }}</td>
+      <td class="montant">{{ poste.autre_max|euros:poste.devise_max|floatformat:0 }}</td>
     </tr>
-    <tr>
+    <tr class="total-row" >
       <th>TOTAL</th>
-      <td class="montant">{{ poste.get_couts_minimum|floatformat:0 }} {{ poste.devise_min.code }}</td>
-      <td class="montant">{{ poste.get_couts_maximum|floatformat:0 }} {{ poste.devise_max.code }}</td>
+      <td class="montant">{{ poste.get_couts_minimum|floatformat:0 }}</td>
+      <td class="montant">{{ poste.get_couts_minimum_euros|floatformat:0 }}</td>
+      <td class="montant">{{ poste.get_couts_maximum|floatformat:0 }}</td>
+      <td class="montant">{{ poste.get_couts_maximum_euros|floatformat:0 }}</td>
     </tr>
-    <tr>
+    <tr class="total-row" >
       <th>TOTAL sans charges patronales</th>
-      <td class="montant">{{ poste.get_salaire_minimum|floatformat:0 }} {{ poste.devise_min.code }}</td>
-      <td class="montant">{{ poste.get_salaire_maximum|floatformat:0 }} {{ poste.devise_max.code }}</td>
-    </tr>
-    <tr>
-      <th>Taux&nbsp;&gt;&nbsp;€</th>
-      <td>{{ poste.show_taux_minimum }}</td>
-      <td>{{ poste.show_taux_maximum }}</td>
-    </tr>
-    <tr>
-      <th>TOTAL (EUR)</th>
-      <td class="montant">{{ poste.show_couts_minimum_euros|floatformat:0 }} €</td>
-      <td class="montant">{{ poste.show_couts_maximum_euros|floatformat:0 }} €</td>
-    </tr>
-    <tr>
-      <th>TOTAL (EUR) sans charges patronales</th>
-      <td class="montant">{{ poste.show_salaire_minimum_euros|floatformat:0 }} €</td>
-      <td class="montant">{{ poste.show_salaire_maximum_euros|floatformat:0 }} €</td>
+      <td class="montant">{{ poste.get_salaire_minimum|floatformat:0 }}</td>
+      <td class="montant">{{ poste.get_salaire_minimum_euros|floatformat:0 }}</td>
+      <td class="montant">{{ poste.get_salaire_maximum|floatformat:0 }}</td>
+      <td class="montant">{{ poste.get_salaire_maximum_euros|floatformat:0 }}</td>
     </tr>
   </tbody>
 </table>
index 39fb195..d351d6f 100644 (file)
@@ -1,3 +1 @@
-<table cellspacing="0" id="global-cost">
-  {% include 'dae/embauche-remun.html' %}
-</table>
+{% include 'dae/embauche-remun.html' %}
index dd87a5d..08088b3 100644 (file)
@@ -1,8 +1,11 @@
 # -*- encoding: utf-8 -*-
 
 import os
+import datetime
+from decimal import Decimal
 
 from django import template
+from django.db.models import Q
 # -*- coding: utf-8 -*-
 
 from project import groups
@@ -98,6 +101,7 @@ def pagination(context, page):
 def remun_form(context, dossier):
 
     return {
+        'annee_remun': None,
         'remunForm': ReadOnlyRemunFormSet(instance=dossier)
         }
 
@@ -106,6 +110,7 @@ def remun_form(context, dossier):
 def rh_remun_form(context, dossier):
 
     return {
+        'annee_remun': None,
         'remunForm': RHReadOnlyRemunFormSet(instance=dossier)
         }
 
@@ -113,6 +118,7 @@ def rh_remun_form(context, dossier):
 @register.inclusion_tag('dae/embauche-remun.html', takes_context=True)
 def poste_cmp_remun_form(context, poste_cmp):
     return {
+        'annee_remun': None,
         'remunForm': PosteCompReadOnlyRemunFormSet(instance=poste_cmp)
         }
 
@@ -120,6 +126,7 @@ def poste_cmp_remun_form(context, poste_cmp):
 @register.inclusion_tag('dae/embauche-remun.html', takes_context=True)
 def dossier_cmp_remun_form(context, dossier_cmp):
     return {
+        'annee_remun': None,
         'remunForm': DossierCompReadOnlyRemunFormSet(instance=dossier_cmp)
         }
 
@@ -134,15 +141,43 @@ def rh_remun_form_for_year(context, dossier, year):
         )
 
     def _get_qs(inst):
-        return inst.model.objects.filter(
-            dossier=inst.instance,
-            date_debut__year=year,
-            )
+        year_start = datetime.date(year, 1, 1)
+        year_end = datetime.date(year, 12, 31)
+        qs = inst.model.objects.filter(
+            Q(dossier=inst.instance) & (
+                Q(date_debut__lte=year_end, date_fin__gte=year_start) |
+                Q(date_debut__lte=year_end, date_fin__isnull=True) |
+                Q(date_debut__isnull=True, date_fin__gte=year_start) |
+                Q(date_debut__isnull=True, date_fin__isnull=True)
+                ))
+        return qs
         
     fs.get_queryset = _get_qs
 
     return {
+        'annee_remun': year,
         'remunForm': fs(instance=dossier)
         }
 
 
+@register.simple_tag
+def remun_ajuste(remun, annee=None):
+    return '%.2f' % remun.montant_ajuste_euros(annee)
+
+
+@register.filter
+def euros(montant, devise):
+    """
+    Template tag pour convertir en euros.
+    """
+    taux = 1
+    if devise.code != 'EUR':
+        liste_taux = devise.tauxchange_set.order_by('-annee')
+        if liste_taux.count() == 0:
+            taux = 0
+        else:
+            taux = liste_taux[0].taux
+
+    return montant * Decimal(str(taux))
+    
+    
index d8118c0..aebd7d6 100644 (file)
@@ -4,6 +4,7 @@ from datetime import date, datetime
 from dateutil.relativedelta import relativedelta
 
 from auf.django.permissions.decorators import get_object
+from auf.django.references import models as ref
 from django.contrib import messages
 from django.contrib.auth.decorators import login_required, user_passes_test
 from django.contrib.contenttypes.models import ContentType
@@ -44,7 +45,7 @@ from project.decorators import redirect_interdiction,\
 from project.rh import models as rh
 from project import groups
 
-
 # Helpers
 
 def devises():
@@ -288,6 +289,14 @@ def poste(request, key=None):
             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,
@@ -345,7 +354,7 @@ def filtered_type_remun():
 
 @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
 
@@ -491,15 +500,15 @@ def embauche(request, key=None, dossier_id=None):
             for comparaison in zip(
                 comparaisons,
                 comparaisons_formset.forms):
-                dossier = rh.Dossier.objects.get(
+                rhdossier = rh.Dossier.objects.get(
                     id=comparaison[1].cleaned_data['cmp_dossier'])
 
                 # 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())
+                # 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(
-                    dossier.remunerations().order_by('-date_debut'),
+                    rhdossier.remunerations().order_by('-date_debut'),
                     only_traitement=False,
                     ):
                     dae.DossierComparaisonRemuneration.objects.create(
@@ -560,6 +569,15 @@ def embauche(request, key=None, dossier_id=None):
                 )
     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
+
+
     c = {
         'type_remun': filtered_type_remun(),
         'devises': devises(),
index a9ffd7a..bba6f81 100644 (file)
@@ -13,7 +13,7 @@ class ReadOnlyChoiceWidget(TextInput):
         if isinstance(self.choices, QuerySet) and value:
             display = self.choices.get(id=value)
         elif value:
-            display = dict(self.choices)[value]
+            display = dict(self.choices)[int(value)]
         else:
             display = ''
         return mark_safe(
index 6176750..24159ed 100644 (file)
@@ -5,7 +5,7 @@ import reversion
 import itertools
 from ajax_select import make_ajax_form
 from auf.django.references import models as ref
-from django.core.mail import send_mail
+from django.core.mail import send_mail, EmailMessage
 from django.contrib.auth.admin import UserAdmin
 from django.contrib.auth.models import User
 from django import forms
@@ -15,6 +15,7 @@ from django.contrib.contenttypes.models import ContentType
 from django.conf import settings
 from django.db.models import Q, Count
 from django.template.defaultfilters import date
+from django.template import Context, loader
 from django.utils.formats import date_format
 
 from project import groups
@@ -27,7 +28,9 @@ from project.permissions import user_gere_obj_de_sa_region, \
         user_can_delete_obj
 
 from project.rh.forms import ContratForm, AyantDroitForm, EmployeAdminForm, \
-        AjaxSelect, DossierForm, ResponsableInlineForm
+        AjaxSelect, DossierForm, ResponsableInlineForm, \
+        ClassementHistoriqueForm
+
 from project.rh.change_list import ChangeList
 
 
@@ -298,6 +301,7 @@ class DossierClassementRecordInline(admin.TabularInline):
         return (super(DossierClassementRecordInline, self)
                 .queryset(request).order_by('-date_debut', '-id'))
     model = rh.RHDossierClassementRecord
+    form = ClassementHistoriqueForm
     extra = 0
 
 
@@ -383,7 +387,7 @@ class DeviseAdmin(reversion.VersionAdmin, ArchivableAdmin,
                   DerniereModificationAdmin, BaseAdmin):
     ignore_duplicate_revisions = True
     list_display = (
-        'code', 'nom', '_archive', 'derniere_modification',
+        'code', 'nom', 'derniere_modification', '_archive',
     )
     list_filter = ('archive', )
     fieldsets = (
@@ -1137,7 +1141,7 @@ class ResponsableImplantationAdmin(BaseAdmin):
 
 
 class ServiceAdminBase(ArchivableAdmin, DerniereModificationAdmin, BaseAdmin):
-    list_display = ('nom', '_archive', 'derniere_modification')
+    list_display = ('nom', 'derniere_modification', '_archive')
     list_filter = ('archive', )
     fieldsets = (
         (None, {'fields': ('nom', 'archive')}),
@@ -1244,8 +1248,8 @@ class TypeRemunerationAdmin(reversion.VersionAdmin, ArchivableAdmin,
                             DerniereModificationAdmin, BaseAdmin):
     ignore_duplicate_revisions = True
     list_display = (
-        'nom', 'type_paiement', 'nature_remuneration', '_archive',
-        'derniere_modification'
+        'nom', 'type_paiement', 'nature_remuneration',
+        'derniere_modification', '_archive'
     )
     list_filter = ('archive', )
     fieldsets = (
@@ -1384,42 +1388,60 @@ def _communique(modaladmin, req, qs):
         changement_notifications__in=
         rh.ChangementPersonnelNotifications.objects.all()).distinct()
 
+    thead_colors = {
+        'NO': 'ff99ff',
+        'MO': 'ccccff',
+        'DE': 'ff99ff',
+        }
+
 
     for comb in combs:
-        # qf c'est pour trouver les recipients.
-        qf = reduce(
-            lambda x, y: x & y,
-            [Q(**{'changement_notifications__type': t}) for t in comb]
-            )
-        recipients = recipient_list.filter(qf)
+
+        recipients = ref.Employe.objects.none()
+        for t in comb:
+            recipients = recipient_list.filter(changement_notifications__type=t)
 
         recipient_list = recipient_list.exclude(
             id__in=recipients.values_list('id', flat=True))
 
         types_dict = dict(rh.TYPES_CHANGEMENT)
 
+        
         if len(recipients):
-            sujet = '[SGRH] Rapport des employés de type: %s' % (
-                ', '.join(
-                    [types_dict[c].lower() for c in
-                     comb]))
-            message = u''
+            ctx = {
+                'types': [
+                    ]
+                }
+
             for t in comb:
-                message += u'%s: \n' % (types_dict[t].decode('utf8'))
-                message += '\n'.join([u'\t%s %s, %s' % (
-                            x.dossier.employe.prenom,
-                            x.dossier.employe.nom,
-                            url_prefix + reverse(
-                                'admin:rh_dossier_change', args=[x.dossier.id]))
-                            for x in qs.filter(type__in=[t])])
-            send_mail(
+                changements = []
+                ctx['types'].append({
+                        'bgcolor': thead_colors[t],
+                        'name': types_dict[t],
+                        'changements': changements,
+                        })
+
+                for ch in qs.filter(type__in=[t]):
+                    changements.append(ch)
+                    
+            template = loader.get_template('email/mouvement_employe.html')
+            content = template.render(Context(ctx))
+
+            sujet = '[SGRH] ARRIVÉES - DÉPARTS - MOBILITÉS'
+
+            msg = EmailMessage(
                 sujet,
-                message,
+                content,
                 settings.SERVER_EMAIL,
                 [x.courriel for x in recipients],
-                fail_silently=False)
+                )
+            msg.content_subtype = "html"
+            msg.send()
         
-    qs.update(communique=True)
+    qs.update(
+        communique=True,
+        date_communication=datetime.datetime.now()
+        )
 
 _communique.short_description = u'Envoyer aux desinataires prévus.'
 
@@ -1431,8 +1453,12 @@ class ChangementPersonnelAdmin(admin.ModelAdmin):
         _communique,
         )
 
+    def _dossier(obj):
+        return obj.dossier.__unicode__()
+    _dossier.short_description = u'Dossier'
+
     list_display = (
-        'type', 'dossier', 'valide', 'communique', 'date_communication'
+        'type', _dossier, 'valide', 'communique', 'date_communication'
         )
 
     list_filter = (
index efb8a03..90f0204 100644 (file)
@@ -145,7 +145,7 @@ class Employe(object):
 class Dossier(object):
 
     def get_query(self, q, request):
-        dossiers = rh.Dossier.objects.filter(
+        return rh.Dossier.objects.ma_region_ou_service(request.user).filter(
             (Q(poste__nom=q) | Q(poste__type_poste__nom=q) |
              Q(employe__nom__icontains=q) | Q(employe__prenom__icontains=q) |
              Q(employe__nom_affichage__icontains=q)) &
index afab3db..5f68066 100644 (file)
@@ -11,6 +11,12 @@ from project.groups import get_employe_from_user, is_user_dans_region
 from project.rh import models as rh
 
 
+class ClassementHistoriqueForm(forms.ModelForm):
+
+    class Meta:
+        model = rh.RHDossierClassementRecord
+
+
 class AjaxSelect(object):
 
     class Media:
diff --git a/project/rh/migrations/0044_auto__add_field_changementpersonnel_date_creation.py b/project/rh/migrations/0044_auto__add_field_changementpersonnel_date_creation.py
new file mode 100644 (file)
index 0000000..2e910c5
--- /dev/null
@@ -0,0 +1,528 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'ChangementPersonnel.date_creation'
+        db.add_column('rh_changementpersonnel', 'date_creation',
+                      self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 3, 6, 0, 0), blank=True),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'ChangementPersonnel.date_creation'
+        db.delete_column('rh_changementpersonnel', 'date_creation')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'references.bureau': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'Bureau', 'db_table': "u'ref_bureau'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Implantation']", 'db_column': "'implantation'"}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_court': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'nom_long': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'region': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Region']", 'db_column': "'region'"})
+        },
+        'references.employe': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'Employe', 'db_table': "u'ref_employe'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'courriel': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'date_entree': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'fonction': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'genre': ('django.db.models.fields.CharField', [], {'max_length': '3'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'lieu_travail_theorique_de'", 'db_column': "'implantation'", 'to': "orm['references.Implantation']"}),
+            'implantation_physique': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'lieu_travail_reel_de'", 'db_column': "'implantation_physique'", 'to': "orm['references.Implantation']"}),
+            'mandat_debut': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'mandat_fin': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'poste_type_1': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'poste_type_1'", 'null': 'True', 'db_column': "'poste_type_1'", 'to': "orm['references.PosteType']"}),
+            'poste_type_2': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'poste_type_2'", 'null': 'True', 'db_column': "'poste_type_2'", 'to': "orm['references.PosteType']"}),
+            'prenom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'responsable': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'responsable_de'", 'null': 'True', 'db_column': "'responsable'", 'to': "orm['references.Employe']"}),
+            'service': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Service']", 'db_column': "'service'"}),
+            'telephone_ip': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'telephone_ip_nomade': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'telephone_poste': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
+        },
+        'references.implantation': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'Implantation', 'db_table': "u'ref_implantation'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'adresse_physique_bureau': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_code_postal': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'adresse_physique_code_postal_avant_ville': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+            'adresse_physique_no': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'adresse_physique_pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'impl_adresse_physique'", 'to_field': "'code'", 'db_column': "'adresse_physique_pays'", 'to': "orm['references.Pays']"}),
+            'adresse_physique_precision': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_precision_avant': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_region': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_rue': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_ville': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'adresse_postale_boite_postale': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_bureau': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_code_postal': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_code_postal_avant_ville': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+            'adresse_postale_no': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'impl_adresse_postale'", 'to_field': "'code'", 'db_column': "'adresse_postale_pays'", 'to': "orm['references.Pays']"}),
+            'adresse_postale_precision': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_precision_avant': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_region': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_rue': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_ville': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'bureau_rattachement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Implantation']", 'db_column': "'bureau_rattachement'"}),
+            'code_meteo': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'commentaire': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'courriel': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'courriel_interne': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'date_extension': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'date_fermeture': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'date_inauguration': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'date_ouverture': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'fax': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'fax_interne': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'fuseau_horaire': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'hebergement_convention': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+            'hebergement_convention_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'hebergement_etablissement': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modif_date': ('django.db.models.fields.DateField', [], {}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_court': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'nom_long': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'region': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Region']", 'db_column': "'region'"}),
+            'remarque': ('django.db.models.fields.TextField', [], {}),
+            'responsable_implantation': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'statut': ('django.db.models.fields.IntegerField', [], {}),
+            'telephone': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'telephone_interne': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '255', 'blank': 'True'}),
+            'zone_administrative': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.ZoneAdministrative']"})
+        },
+        'references.pays': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'Pays', 'db_table': "u'ref_pays'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2'}),
+            'code_bureau': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Bureau']", 'to_field': "'code'", 'null': 'True', 'db_column': "'code_bureau'", 'blank': 'True'}),
+            'code_iso3': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '3'}),
+            'developpement': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'monnaie': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nord_sud': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'region': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Region']", 'db_column': "'region'"})
+        },
+        'references.postetype': {
+            'Meta': {'object_name': 'PosteType', 'db_table': "u'ref_poste_type'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'references.region': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'Region', 'db_table': "u'ref_region'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation_bureau': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'gere_region'", 'null': 'True', 'db_column': "'implantation_bureau'", 'to': "orm['references.Implantation']"}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
+        },
+        'references.service': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'Service', 'db_table': "u'ref_service'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'references.zoneadministrative': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'ZoneAdministrative', 'db_table': "'ref_zoneadministrative'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'max_length': '4', 'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'reversion.revision': {
+            'Meta': {'object_name': 'Revision'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'manager_slug': ('django.db.models.fields.CharField', [], {'default': "'default'", 'max_length': '200', 'db_index': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'rh.ayantdroit': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'AyantDroit'},
+            'date_naissance': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'employe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ayantdroits'", 'db_column': "'employe'", 'to': "orm['rh.Employe']"}),
+            'genre': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'lien_parente': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'nationalite': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ayantdroits_nationalite'", 'db_column': "'nationalite'", 'to_field': "'code'", 'to': "orm['references.Pays']", 'blank': 'True', 'null': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_affichage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'prenom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.ayantdroitcommentaire': {
+            'Meta': {'ordering': "['-date_creation']", 'object_name': 'AyantDroitCommentaire'},
+            'ayant_droit': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'commentaires'", 'db_column': "'ayant_droit'", 'to': "orm['rh.AyantDroit']"}),
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'owner'", 'to': "orm['auth.User']"}),
+            'texte': ('django.db.models.fields.TextField', [], {})
+        },
+        'rh.categorieemploi': {
+            'Meta': {'ordering': "('nom',)", 'object_name': 'CategorieEmploi'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.changementpersonnel': {
+            'Meta': {'object_name': 'ChangementPersonnel'},
+            'communique': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'date_communication': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'mouvements'", 'to': "orm['rh.Dossier']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
+            'valide': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
+        },
+        'rh.changementpersonnelnotifications': {
+            'Meta': {'object_name': 'ChangementPersonnelNotifications'},
+            'destinataires': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'changement_notifications'", 'symmetrical': 'False', 'to': "orm['references.Employe']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2'})
+        },
+        'rh.classement': {
+            'Meta': {'ordering': "['type', 'echelon', 'degre', 'coefficient']", 'object_name': 'Classement'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'coefficient': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
+            'commentaire': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'degre': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
+            'echelon': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
+        },
+        'rh.contrat': {
+            'Meta': {'ordering': "['dossier__employe__nom']", 'object_name': 'Contrat'},
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_contrats'", 'db_column': "'dossier'", 'to': "orm['rh.Dossier']"}),
+            'fichier': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type_contrat': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'type_contrat'", 'to': "orm['rh.TypeContrat']"})
+        },
+        'rh.devise': {
+            'Meta': {'ordering': "['code']", 'object_name': 'Devise'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '10'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.dossier': {
+            'Meta': {'ordering': "['employe__nom']", 'object_name': 'Dossier'},
+            'classement': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'classement'", 'to': "orm['rh.Classement']"}),
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_modification': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
+            'employe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_dossiers'", 'db_column': "'employe'", 'to': "orm['rh.Employe']"}),
+            'est_cadre': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'organisme_bstg': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'organisme_bstg'", 'to': "orm['rh.OrganismeBstg']"}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_dossiers'", 'db_column': "'poste'", 'to': "orm['rh.Poste']"}),
+            'principal': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'regime_travail': ('django.db.models.fields.DecimalField', [], {'default': "'100.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'regime_travail_nb_heure_semaine': ('django.db.models.fields.DecimalField', [], {'default': "'35.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'remplacement': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'remplacement_de': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Dossier']"}),
+            'statut': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Statut']"}),
+            'statut_residence': ('django.db.models.fields.CharField', [], {'default': "'local'", 'max_length': '10', 'null': 'True'})
+        },
+        'rh.dossiercommentaire': {
+            'Meta': {'ordering': "['-date_creation']", 'object_name': 'DossierCommentaire'},
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'commentaires'", 'db_column': "'dossier'", 'to': "orm['rh.Dossier']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'owner'", 'to': "orm['auth.User']"}),
+            'texte': ('django.db.models.fields.TextField', [], {})
+        },
+        'rh.dossiercomparaison': {
+            'Meta': {'object_name': 'DossierComparaison'},
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Devise']"}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_comparaisons'", 'to': "orm['rh.Dossier']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['references.Implantation']"}),
+            'montant': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'personne': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'poste': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
+        },
+        'rh.dossierpiece': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'DossierPiece'},
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_dossierpieces'", 'db_column': "'dossier'", 'to': "orm['rh.Dossier']"}),
+            'fichier': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.employe': {
+            'Meta': {'ordering': "['nom', 'prenom']", 'object_name': 'Employe'},
+            'adresse': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'code_postal': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'courriel_perso': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'date_entree': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'date_naissance': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'genre': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nationalite': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'employes_nationalite'", 'db_column': "'nationalite'", 'to_field': "'code'", 'to': "orm['references.Pays']", 'blank': 'True', 'null': 'True'}),
+            'nb_postes': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_affichage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'employes'", 'db_column': "'pays'", 'to_field': "'code'", 'to': "orm['references.Pays']", 'blank': 'True', 'null': 'True'}),
+            'prenom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'province': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'situation_famille': ('django.db.models.fields.CharField', [], {'max_length': '1', 'null': 'True', 'blank': 'True'}),
+            'tel_cellulaire': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'tel_domicile': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'ville': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
+        },
+        'rh.employecommentaire': {
+            'Meta': {'object_name': 'EmployeCommentaire'},
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'employe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'commentaires'", 'db_column': "'employe'", 'to': "orm['rh.Employe']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'owner'", 'to': "orm['auth.User']"}),
+            'texte': ('django.db.models.fields.TextField', [], {})
+        },
+        'rh.employepiece': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'EmployePiece'},
+            'employe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pieces'", 'db_column': "'employe'", 'to': "orm['rh.Employe']"}),
+            'fichier': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.familleprofessionnelle': {
+            'Meta': {'ordering': "('nom',)", 'object_name': 'FamilleProfessionnelle'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'rh.modificationtraite': {
+            'Meta': {'object_name': 'ModificationTraite'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'revision': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reversion.Revision']"})
+        },
+        'rh.organismebstg': {
+            'Meta': {'ordering': "['type', 'nom']", 'object_name': 'OrganismeBstg'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'organismes_bstg'", 'db_column': "'pays'", 'to_field': "'code'", 'to': "orm['references.Pays']", 'blank': 'True', 'null': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
+        },
+        'rh.poste': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'Poste'},
+            'appel': ('django.db.models.fields.CharField', [], {'default': "'interne'", 'max_length': '10', 'null': 'True'}),
+            'autre_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'autre_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'classement_max': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'classement_max'", 'to': "orm['rh.Classement']"}),
+            'classement_min': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'classement_min'", 'to': "orm['rh.Classement']"}),
+            'comp_autre_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_autre_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_fonctionpub_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_fonctionpub_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_locale_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_locale_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_ong_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_ong_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_universite_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_universite_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_modification': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
+            'devise_comparaison': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'devise_comparaison'", 'to': "orm['rh.Devise']"}),
+            'devise_max': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'devise_max'", 'to': "orm['rh.Devise']"}),
+            'devise_min': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'devise_min'", 'to': "orm['rh.Devise']"}),
+            'expatrie': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'implantation'", 'to': "orm['references.Implantation']"}),
+            'indemn_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'indemn_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'justification': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'local': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}),
+            'mise_a_disposition': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_feminin': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
+            'regime_travail': ('django.db.models.fields.DecimalField', [], {'default': "'100.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'regime_travail_nb_heure_semaine': ('django.db.models.fields.DecimalField', [], {'default': "'35.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'responsable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'responsable'", 'to': "orm['rh.Poste']"}),
+            'salaire_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'salaire_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'service': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_postes'", 'null': 'True', 'db_column': "'service'", 'to': "orm['rh.Service']"}),
+            'type_poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'type_poste'", 'to': "orm['rh.TypePoste']"}),
+            'vacant': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+            'valeur_point_max': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'valeur_point_max'", 'to': "orm['rh.ValeurPoint']"}),
+            'valeur_point_min': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'valeur_point_min'", 'to': "orm['rh.ValeurPoint']"})
+        },
+        'rh.postecommentaire': {
+            'Meta': {'ordering': "['-date_creation']", 'object_name': 'PosteCommentaire'},
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'owner'", 'to': "orm['auth.User']"}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'commentaires'", 'db_column': "'poste'", 'to': "orm['rh.Poste']"}),
+            'texte': ('django.db.models.fields.TextField', [], {})
+        },
+        'rh.postecomparaison': {
+            'Meta': {'object_name': 'PosteComparaison'},
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Devise']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['references.Implantation']"}),
+            'montant': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_comparaisons_internes'", 'to': "orm['rh.Poste']"})
+        },
+        'rh.postefinancement': {
+            'Meta': {'ordering': "['type']", 'object_name': 'PosteFinancement'},
+            'commentaire': ('django.db.models.fields.TextField', [], {}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_financements'", 'db_column': "'poste'", 'to': "orm['rh.Poste']"}),
+            'pourcentage': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '1'})
+        },
+        'rh.postepiece': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'PostePiece'},
+            'fichier': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_pieces'", 'db_column': "'poste'", 'to': "orm['rh.Poste']"})
+        },
+        'rh.remuneration': {
+            'Meta': {'object_name': 'Remuneration'},
+            'commentaire': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'devise'", 'to': "orm['rh.Devise']"}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_remunerations'", 'db_column': "'dossier'", 'to': "orm['rh.Dossier']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'montant': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'type'", 'to': "orm['rh.TypeRemuneration']"}),
+            'type_revalorisation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'type_revalorisation'", 'to': "orm['rh.TypeRevalorisation']"})
+        },
+        'rh.responsableimplantation': {
+            'Meta': {'ordering': "['implantation__nom']", 'object_name': 'ResponsableImplantation'},
+            'employe': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'employe'", 'to': "orm['rh.Employe']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'responsable'", 'unique': 'True', 'db_column': "'implantation'", 'to': "orm['references.Implantation']"})
+        },
+        'rh.rhdossierclassementrecord': {
+            'Meta': {'object_name': 'RHDossierClassementRecord'},
+            'classement': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'classement_records'", 'to': "orm['rh.Classement']"}),
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'classement_records'", 'to': "orm['rh.Dossier']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'rh.service': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'Service'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.statut': {
+            'Meta': {'ordering': "['code']", 'object_name': 'Statut'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '25'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.tauxchange': {
+            'Meta': {'ordering': "['-annee', 'devise__code']", 'unique_together': "(('devise', 'annee'),)", 'object_name': 'TauxChange'},
+            'annee': ('django.db.models.fields.IntegerField', [], {}),
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rh.Devise']", 'db_column': "'devise'"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'taux': ('django.db.models.fields.FloatField', [], {})
+        },
+        'rh.typecontrat': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'TypeContrat'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_long': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.typeposte': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'TypePoste'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'categorie_emploi': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'categorie_emploi'", 'to': "orm['rh.CategorieEmploi']"}),
+            'famille_professionnelle': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'types_de_poste'", 'null': 'True', 'to': "orm['rh.FamilleProfessionnelle']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_responsable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_feminin': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.typeremuneration': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'TypeRemuneration'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nature_remuneration': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'type_paiement': ('django.db.models.fields.CharField', [], {'max_length': '30'})
+        },
+        'rh.typerevalorisation': {
+            'Meta': {'ordering': "['nom']", 'object_name': 'TypeRevalorisation'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.userprofile': {
+            'Meta': {'object_name': 'UserProfile'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"}),
+            'zones_administratives': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'profiles'", 'symmetrical': 'False', 'to': "orm['references.ZoneAdministrative']"})
+        },
+        'rh.valeurpoint': {
+            'Meta': {'ordering': "['-annee', 'implantation__nom']", 'unique_together': "(('implantation', 'annee'),)", 'object_name': 'ValeurPoint'},
+            'annee': ('django.db.models.fields.IntegerField', [], {}),
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'devise'", 'to': "orm['rh.Devise']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_valeur_point'", 'db_column': "'implantation'", 'to': "orm['references.Implantation']"}),
+            'valeur': ('django.db.models.fields.FloatField', [], {'null': 'True'})
+        }
+    }
+
+    complete_apps = ['rh']
\ No newline at end of file
index f7c67e0..b57d9b6 100644 (file)
@@ -31,6 +31,8 @@ from project.rh.managers import (
     )
 
 
+TWOPLACES = Decimal('0.01')
+
 from project.rh.validators import validate_date_passee
 
 # import pour relocaliser le modèle selon la convention (models.py pour
@@ -124,14 +126,17 @@ class DevisableMixin(object):
                 .order_by('-annee')
         return taux[0].taux
 
-    def montant_euros(self):
+    def montant_euros_float(self):
         try:
             taux = self.taux_devise()
         except Exception, e:
             return e
         if not taux:
             return None
-        return int(round(float(self.montant) * float(taux), 2))
+        return float(self.montant) * float(taux)
+
+    def montant_euros(self):
+        return int(round(self.montant_euros_float(), 2))
 
 
 class Commentaire(models.Model):
@@ -586,17 +591,50 @@ class Employe(models.Model):
         q = search.get_q_temporel(self.rh_dossiers)
         return self.rh_dossiers.filter(q)
 
-    def dossier_principal(self):
+    def dossier_principal_pour_annee(self):
+        return self.dossier_principal(pour_annee=True)
+
+    def dossier_principal(self, pour_annee=False):
         """
         Retourne le dossier principal (ou le plus ancien si il y en a
         plusieurs)
+
+        Si pour_annee == True, retourne le ou les dossiers principaux
+        pour l'annee en cours, sinon, le ou les dossiers principaux
+        pour la journee en cours.
+
+        TODO: (Refactoring possible): Utiliser meme logique dans
+        dae/templatetags/dae.py
         """
-        try:
-            dossier = self.rh_dossiers \
-                    .filter(principal=True).order_by('date_debut')[0]
-        except IndexError, Dossier.DoesNotExist:
-            dossier = None
-        return dossier
+        
+        today = date.today()
+        if pour_annee:
+            year = today.year
+            year_start = date(year, 1, 1)
+            year_end = date(year, 12, 31)
+            
+            try:
+                dossier = self.rh_dossiers.filter(
+                    (Q(date_debut__lte=year_end, date_fin__isnull=True) |
+                     Q(date_debut__isnull=True, date_fin__gte=year_start) |
+                     Q(date_debut__lte=year_end, date_fin__gte=year_start) |
+                     Q(date_debut__isnull=True, date_fin__isnull=True)) &
+                    Q(principal=True)).order_by('date_debut')[0]
+            except IndexError, Dossier.DoesNotExist:
+                dossier = None
+            return dossier
+        else:
+            try:
+                dossier = self.rh_dossiers.filter(
+                    (Q(date_debut__lte=today, date_fin__isnull=True) |
+                     Q(date_debut__isnull=True, date_fin__gte=today) |
+                     Q(date_debut__lte=today, date_fin__gte=today) |
+                     Q(date_debut__isnull=True, date_fin__isnull=True)) &
+                    Q(principal=True)).order_by('date_debut')[0]
+            except IndexError, Dossier.DoesNotExist:
+                dossier = None
+            return dossier
+                
 
     def postes_encours(self):
         postes_encours = set()
@@ -812,7 +850,7 @@ class Dossier_(DateActiviteMixin, models.Model, DevisableMixin,):
 
     # Meta-data:
     est_cadre = models.BooleanField(
-        u"Est un câdre?",
+        u"Est un cadre?",
         default=False,
         )
 
@@ -1114,56 +1152,69 @@ class RHDossierClassementRecord(models.Model):
                           using,
                           **kw):
 
-        # Attempt to pull previous classement from history.
+        today = date.today()
+        previous_record = None
         previous_classement = None
         has_changed = False
 
-        if not created:
-            has_changed = (
-                instance.classement.id !=
-                instance.before_save.classement.id
-                )
-            try:
-                previous_record = cls.objects.get(
+        # Premièrement, pour les nouvelles instances:
+        if created:
+            if not instance.classement:
+                return
+            else:
+                cls.objects.create(
+                    date_debut=instance.date_debut,
+                    classement=instance.classement,
                     dossier=instance,
-                    classement=instance.before_save.classement,
-                    date_fin=None,
                     )
-            except cls.DoesNotExist:
-                previous_record = None
-            else:
-                previous_classement = previous_record.classement
+                return
 
+        # Deuxièmement, pour les instances existantes:
 
-        if created or (not created and not previous_classement):
-            cls.objects.create(
-                date_debut=instance.date_debut,
-                classement=instance.classement,
-                dossier=instance,
-                )
-        elif has_changed and previous_classement:
-            change_date = datetime.date.today()
-            previous_record.date_fin = change_date
-            previous_record.save()
-            cls.objects.create(
-                date_debut=change_date,
-                classement=instance.classement,
+        # Détermine si:
+        # 1. Est-ce que le classement a changé?
+        # 2. Est-ce qu'une historique de classement existe déjà
+        try:
+            previous_record = cls.objects.get(
                 dossier=instance,
+                classement=instance.before_save.classement,
+                date_fin=None,
                 )
-            
-        # elif not created:
-        #     cmp_inst = self.before_save
+        except cls.DoesNotExist:
+            if instance.before_save.classement:
+                # Il était censé avoir une historique de classement
+                # donc on le créé.
+                previous_record = cls.objects.create(
+                    date_debut=instance.before_save.date_debut,
+                    classement=instance.before_save.classement,
+                    dossier=instance,
+                    )
+                previous_classement = instance.before_save.classement
 
-        #     # Classement has changed!
-        #     if (cmp_inst.classement.id !=
-        #         instance.classement.id):
+        else:
+            previous_classement = previous_record.classement
 
+        has_changed = (
+            instance.classement !=
+            previous_classement
+            )
+
+        # Cas aucun changement:
+        if not has_changed:
+            return
+
+        else:
+            # Classement a changé
+            if previous_record:
+                previous_record.date_fin = today
+                previous_record.save()
                 
-                
-                
-            
-            
-        
+            if instance.classement:
+                cls.objects.create(
+                    date_debut=today,
+                    classement=instance.classement,
+                    dossier=instance,
+                    )
 
 
 class DossierPiece_(models.Model):
@@ -1276,6 +1327,64 @@ class Remuneration_(RemunerationMixin, DevisableMixin):
     """
     objects = RemunerationManager()
 
+    @staticmethod
+    def find_yearly_range(from_date, to_date, year):
+        today = date.today()
+        year = year or date.today().year
+        year_start = date(year, 1, 1)
+        year_end = date(year, 12, 31)
+
+        def constrain_to_year(*dates):
+            """
+            S'assure que les dates soient dans le range year_start a
+            year_end
+            """
+            return [min(max(year_start, d), year_end)
+                    for d in dates]
+
+        start_date = max(
+                from_date or year_start, year_start)
+        end_date = min(
+                to_date or year_end, year_end)
+        
+        start_date, end_date = constrain_to_year(start_date, end_date)
+
+        jours_annee = (year_end - year_start).days
+        jours_dates = (end_date - start_date).days
+        factor = Decimal(str(jours_dates)) / Decimal(str(jours_annee))
+        
+        return start_date, end_date, factor
+        
+
+    def montant_ajuste_euros(self, annee=None):
+        """
+        Le montant ajusté représente le montant annuel, ajusté sur la
+        période de temps travaillée, multipliée par le ratio de temps
+        travaillé (en rapport au temps plein).
+        """
+        date_debut, date_fin, factor = self.find_yearly_range(
+            self.date_debut,
+            self.date_fin,
+            annee,
+            )
+
+        montant_euros = Decimal(str(self.montant_euros_float()) or '0')
+        
+        if self.type.nature_remuneration != u'Accessoire':
+            dossier = getattr(self, 'dossier', None)
+            if not dossier:
+                """
+                Dans le cas d'un DossierComparaisonRemuneration, il
+                n'y a plus de reference au dossier.
+                """
+                regime_travail = REGIME_TRAVAIL_DEFAULT
+            else:
+                regime_travail = self.dossier.regime_travail
+            return (montant_euros * factor *
+                    regime_travail / 100)
+        else:
+            return montant_euros
+        
     def montant_mois(self):
         return round(self.montant / 12, 2)
 
@@ -1420,11 +1529,11 @@ TYPE_PAIEMENT_CHOICES = (
 )
 
 NATURE_REMUNERATION_CHOICES = (
-    (u'Accessoire', u'Traitement ponctuel'),
+    (u'Traitement', u'Traitements'),
+    (u'Indemnité', u'Indemnités autres'),
     (u'Charges', u'Charges patronales'),
-    (u'Indemnité', u'Indemnité'),
+    (u'Accessoire', u'Accessoires'),
     (u'RAS', u'Rémunération autre source'),
-    (u'Traitement', u'Traitement'),
 )
 
 
@@ -1433,6 +1542,9 @@ class TypeRemuneration(Archivable):
     Catégorie de Remuneration.
     """
 
+    objects = models.Manager()
+    sans_archives = ArchivableManager()
+
     nom = models.CharField(max_length=255)
     type_paiement = models.CharField(
         u"type de paiement", max_length=30, choices=TYPE_PAIEMENT_CHOICES
@@ -1558,12 +1670,12 @@ TYPE_CLASSEMENT_CHOICES = (
 )
 
 
-class ClassementManager(ArchivableManager):
+class ClassementManager(models.Manager):
     """
     Ordonner les spcéfiquement les classements.
     """
     def get_query_set(self):
-        qs = super(self.__class__, self).get_query_set()
+        qs = super(ClassementManager, self).get_query_set()
         qs = qs.extra(select={
             'ponderation': 'FIND_IN_SET(type,"SO,HG,S,T,P,C,D")'
         })
@@ -1571,6 +1683,11 @@ class ClassementManager(ArchivableManager):
         return qs.all()
 
 
+class ClassementArchivableManager(ClassementManager,
+                                  ArchivableManager):
+    pass
+
+
 class Classement_(Archivable):
     """
     Éléments de classement de la
@@ -1582,6 +1699,7 @@ class Classement_(Archivable):
     salaire de base = coefficient * valeur du point de l'Implantation du Poste
     """
     objects = ClassementManager()
+    sans_archives = ClassementArchivableManager()
 
     # Identification
     type = models.CharField(max_length=10, choices=TYPE_CLASSEMENT_CHOICES)
@@ -1776,16 +1894,16 @@ reversion.register(UserProfile, format='xml')
 
 
 TYPES_CHANGEMENT = (
-    ('NO', 'Nouveau personnel'),
-    ('MO', 'Mouvement de personnel'),
-    ('DE', 'Départ de personnel'),
+    ('NO', 'Arrivée'),
+    ('MO', 'Mobilité'),
+    ('DE', 'Départ'),
     )
 
 
 class ChangementPersonnelNotifications(models.Model):
     class Meta:
-        verbose_name = u"Destinataire pour notices de changement de personnel"
-        verbose_name_plural = u"Destinataires pour notices de changement de personnel"
+        verbose_name = u"Destinataire pour notices de mouvement de personnel"
+        verbose_name_plural = u"Destinataires pour notices de mouvement de personnel"
 
     type = models.CharField(
         max_length=2,
@@ -1816,8 +1934,8 @@ class ChangementPersonnel(models.Model):
     """
 
     class Meta:
-        verbose_name = u"Notification de changement du personnel"
-        verbose_name_plural = u"Notifications de changement du personnel"
+        verbose_name = u"Mouvement de personnel"
+        verbose_name_plural = u"Mouvements de personnel"
 
     def __unicode__(self):
         return '%s: %s' % (self.dossier.__unicode__(),
@@ -1860,8 +1978,10 @@ class ChangementPersonnel(models.Model):
        
         # Here, verify differences between the instance, before and
         # after the save.
+        df_has_changed = False
+
         if created:
-            if instance.before_save.date_fin != None:
+            if df != None:
                 df_has_changed = True
         else:
             df_has_changed = (df != instance.before_save.date_fin and
@@ -1925,7 +2045,12 @@ class ChangementPersonnel(models.Model):
         )
 
     valide = models.BooleanField(default=True)
-    communique = models.BooleanField(default=False)
+    date_creation = models.DateTimeField(
+        auto_now_add=True)
+    communique = models.BooleanField(
+        u'Communiqué',
+        default=False,
+        )
     date_communication = models.DateTimeField(
                 null=True,
                 blank=True,
diff --git a/project/rh/templates/email/mouvement_employe.html b/project/rh/templates/email/mouvement_employe.html
new file mode 100644 (file)
index 0000000..98ad609
--- /dev/null
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <body>
+    Bonjour à tous,<br>
+    <br>
+    Tel qu'annoncé, merci de trouver ci-joint un récapitulatif des mouvements de personnels, je vous prie de bien vouloir vérifier que les actions inscrites ont bel et bien été effectuées. Veuillez également prendre note qu'il y a sûrement des répétitions, dans ce cas ne pas en tenir compte.<br>
+    <br>
+    {% for type in types %}
+    {% if type.changements %}
+    <table border="1" cellpadding="2" cellspacing="2" width="100%">
+      <tbody>
+       <tr>
+         <th bgcolor="#{{type.bgcolor}}" valign="top">
+           {{ type.name }}
+         </th>
+         <th bgcolor="#{{type.bgcolor}}" valign="top">
+           #Employé
+         </th>
+         <th bgcolor="#{{type.bgcolor}}" valign="top">
+           Date
+         </th>
+         <th bgcolor="#{{type.bgcolor}}" valign="top">
+           Titre
+         </th>
+         <th bgcolor="#{{type.bgcolor}}" valign="top">
+           Emplacement
+         </th>
+       </tr>
+       {% for changement in type.changements %}
+       <tr>
+         <td valign="top">
+           {{ changement.dossier.employe.nom|upper }} {{ changement.dossier.employe.prenom }}
+         </td>
+         <td valign="top">
+           {{ changement.dossier.employe.id }}
+         </td>
+         <td valign="top">
+           {{ changement.date_creation|date:"d-m-Y" }}
+         </td>
+         <td valign="top">
+           {{ changement.dossier.poste.nom }}
+         </td>
+         <td valign="top">
+           {{ changement.dossier.poste.implantation.nom }}
+         </td>
+       </tr>
+       {% endfor %}
+      </tbody>
+    </table>
+    <br>
+    {% endif %}
+    {% endfor %}
+    <br>
+    Je vous remercie de bien vouloir me signaler tout autre mouvement de personnel qui m'aurait échappé.<br>
+    <br>
+    En vous remerciant tous de votre attention,<br>
+    <br>
+    Bien cordialement<br>
+    <br>
+    Odette Tremblay
+  </body>
+</html>
index f81895c..af2ae35 100644 (file)
@@ -6,7 +6,7 @@
   <script type="text/javascript">
     var DEVISES = {};
     {% for d in devises %}
-    DEVISES['{{d.devise_code}}'] = {{d.taux_euro|stringformat:"f"}};
+    DEVISES['{{d.devise_code}}'] = {{d.taux_euro|stringformat:".10f"}};
     {% endfor %}
   </script>
   <script src="{{ STATIC_URL }}js/dae.js" type="text/javascript"></script>
@@ -29,7 +29,7 @@
     {% include "rh/form-row.html" with label="Régime de travail (Nb. heures par semaine)" value=dossier.regime_travail_nb_heure_semaine %}
     <div class="form-row">
       <div>
-        <label>Est un câdre :</label>
+        <label>Est un cadre :</label>
         <p>
          {% if dossier.est_cadre %}
          Oui
     {% endif %}
 </fieldset>
 
-{% if dossier.actif %}
 <fieldset class="module aligned page-break">
-    <h2>Rémunération en cours</h2>
     {% for annee in annees %}
-    <h2>Pour l'année {{ annee }}</h2>
+    <h2>Rémunérations pour l'année {{ annee }}</h2>
     {% rh_remun_form_for_year dossier annee %}
     {% endfor %}
 </fieldset>
-{% endif %}
 
 {% include "rh/include/pieces.html" %}
 
@@ -84,9 +81,4 @@
 </fieldset>
 {% endif %}
 
-<fieldset class="module aligned">
-    <h2>Historique de rémunération</h2>
-{% include "rh/include/remunerations.html" with remunerations=dossier.remunerations %}
-</fieldset>
-
 {% include "rh/include/commentaires.html" %}
index 3c1131c..0cd2249 100644 (file)
@@ -1,3 +1,19 @@
+{% load dae %}
+
+{% block extrahead %}
+  <script src="{{ STATIC_URL }}js/jquery-1.5.1.min.js"
+          type="text/javascript"></script>
+  <script type="text/javascript">
+    var DEVISES = {};
+    {% for d in devises %}
+    DEVISES['{{d.devise_code}}'] = {{d.taux_euro|stringformat:"f"}};
+    {% endfor %}
+  </script>
+  <script src="{{ STATIC_URL }}js/dae.js" type="text/javascript"></script>
+  <script src="{{ STATIC_URL }}js/remun.js" type="text/javascript"></script>
+{% endblock %}
+
+
 <fieldset class="module aligned">
     <h2>Identification</h2>
     {% include "rh/form-row.html" with label="Nom" value=employe.nom %}
     {% include "rh/form-row.html" with label="Adresse courriel personnelle" value=employe.courriel_perso %}
 </fieldset>
 
+{% if dossier_principal %}
+{% if annee %}
+<fieldset class="module aligned page-break">
+    <h2>Rémunérations pour l'année {{ annee }}, pour le dossier principal: {{ dossier_principal}}</h2>
+    {% rh_remun_form_for_year dossier_principal annee %}
+</fieldset>
+{% endif %}
+{% endif %}
+
 <fieldset class="module aligned">
     <h2>Ayants droit</h2>
     {% for ay in employe.ayantdroits.all %}
index 43ee896..f5b7cf7 100644 (file)
@@ -30,7 +30,7 @@ from project.rh.lib import get_lookup_params
 from project.rh.templatetags.rapports import SortHeaders
 from project.rh.historique import get_active_revisions, TodoForm
 
-TWOPLACES = Decimal('0.01')
+TWOPLACES = rh.TWOPLACES
 
 
 def devises():
@@ -45,6 +45,7 @@ def devises():
             data['taux_euro'] = taux[0].taux
         data['devise_code'] = d.id
         liste.append(data)
+        
     return liste
 
 
@@ -351,17 +352,20 @@ def rapports_masse_salariale(request):
                 taux_change = Decimal(1)
 
             remuns_par_type = defaultdict(lambda: 0)
+
             for remun in remuns:
-                if remun.type.nature_remuneration == u'Accessoire':
-                    remuns_par_type[remun.type_id] += montant_remun(remun)
+                montant_ajuste_euros = remun.montant_ajuste_euros(annee=annee)
+                if len(devises) == 1:
+                    devise = remuns[0].devise.code
+                    montant_ajuste = (
+                        montant_ajuste_euros /
+                        Decimal(str(remuns[0].taux_change))
+                        ).quantize(TWOPLACES)
                 else:
-                    remuns_par_type[remun.type_id] += (
-                        montant_remun(remun) * ((
-                            min(remun.date_fin or fin_annee, fin_annee) -
-                            max(remun.date_debut or debut_annee, debut_annee)
-                        ).days + 1) / jours_annee *
-                        dossier.regime_travail / 100
-                    ).quantize(TWOPLACES)
+                    montant_ajuste = montant_ajuste_euros.quantize(TWOPLACES)
+                    devise = 'EUR'
+                remuns_par_type[remun.type_id] += montant_ajuste
+
             traitements = [
                 remuns_par_type[type.id]
                 for type in types_remun_par_nature[u'Traitement']
@@ -713,12 +717,17 @@ def employe_apercu(request, employe_id):
 
     dossiers = rh.Dossier.objects.filter(q).order_by('-date_debut')
 
+    dossier_principal = employe.dossier_principal()
+
     c = {
         'title': u"Employe %s" % (employe, ),
         'is_popup': request.GET.get('_popup', False),
         'employe': employe,
         'dossiers': dossiers,
+        'dossier_principal': dossier_principal,
         'media_url': settings.PRIVE_MEDIA_URL,
+        'annee': date.today().year,
+        'devises': devises(),
     }
     return render(request, 'admin/rh/employe/apercu.html', c)
 
index bd4769b..912a13c 100644 (file)
@@ -130,7 +130,7 @@ ADMIN_TOOLS_MENU = 'project.menu.CustomMenu'
 
 AJAX_LOOKUP_CHANNELS = {
     'responsables': ('project.dae.catalogues', 'Responsable'),
-    'dossiers': ('project.dae.catalogues', 'Dossier'),
+    'dae_dossiers': ('project.dae.catalogues', 'Dossier'),
     'dae_postes': ('project.dae.catalogues', 'Poste'),
     'pays': ('project.rh.catalogues', 'Pays'),
     'implantations': ('project.rh.catalogues', 'Implantation'),