harmonize and fix fucked data
[auf_rh_dae.git] / project / rh / models.py
index 06eb382..77a201d 100644 (file)
@@ -1,5 +1,6 @@
 # -=- encoding: utf-8 -=-
 
+import datetime
 from datetime import date
 
 from django.core.files.storage import FileSystemStorage
@@ -12,11 +13,20 @@ import auf.django.references.models as ref
 from validators import validate_date_passee
 from managers import PosteManager, DossierManager, DossierComparaisonManager, PosteComparaisonManager
 
+
+
+# Gruick hack pour déterminer d'ou provient l'instanciation d'une classe pour l'héritage.
+# Cela permet de faire du dynamic loading par app sans avoir à redéfinir dans DAE la FK
+def app_context():
+    import inspect;
+    models_stack = [s[1].split('/')[-2] for s in inspect.stack() if s[1].endswith('models.py')]
+    return models_stack[-1]
+
+
 # Constantes
 REGIME_TRAVAIL_DEFAULT = 100.00
 REGIME_TRAVAIL_NB_HEURE_SEMAINE_DEFAULT = 35.00
 
-
 # Upload de fichiers
 storage_prive = FileSystemStorage(settings.PRIVE_MEDIA_ROOT, 
                             base_url=settings.PRIVE_MEDIA_URL)
@@ -219,6 +229,7 @@ class PosteFinancement_(models.Model):
     """Pour un Poste, structure d'informations décrivant comment on prévoit
     financer ce Poste.
     """
+    poste = models.ForeignKey('%s.Poste' % app_context(), db_column='poste', related_name='%(app_label)s_financements')
     type = models.CharField(max_length=1, choices=POSTE_FINANCEMENT_CHOICES)
     pourcentage = models.DecimalField(max_digits=12, decimal_places=2,
             help_text="ex.: 33.33 % (décimale avec point)")
@@ -234,13 +245,14 @@ class PosteFinancement_(models.Model):
 
 
 class PosteFinancement(PosteFinancement_):
-    poste = models.ForeignKey('Poste', db_column='poste', related_name='%(app_label)s_financements')
+    pass
 
 
 class PostePiece_(models.Model):
     """Documents relatifs au Poste.
     Ex.: Description de poste
     """
+    poste = models.ForeignKey('%s.Poste' % app_context(), db_column='poste', related_name='%(app_label)s_pieces')
     nom = models.CharField(verbose_name = u"Nom", max_length=255)
     fichier = models.FileField(verbose_name = u"Fichier", 
                             upload_to=poste_piece_dispatch, 
@@ -254,12 +266,13 @@ class PostePiece_(models.Model):
         return u'%s' % (self.nom)
 
 class PostePiece(PostePiece_):
-    poste = models.ForeignKey('Poste', db_column='poste', related_name='%(app_label)s_pieces')
+    pass
 
 class PosteComparaison_(models.Model):
     """
     De la même manière qu'un dossier, un poste peut-être comparé à un autre poste.
     """
+    poste = models.ForeignKey('%s.Poste' % app_context(), related_name='%(app_label)s_comparaisons_internes')
     objects = PosteComparaisonManager()
 
     implantation = models.ForeignKey(ref.Implantation, null=True, blank=True, related_name="+")
@@ -271,20 +284,24 @@ class PosteComparaison_(models.Model):
         abstract = True
 
     def taux_devise(self):
-        liste_taux = self.devise.tauxchange_set.order_by('-annee').filter(implantation=self.implantation)
-        if len(liste_taux) == 0:
-            raise Exception(u"La devise %s n'a pas de taux pour l'implantation %s" % (self.devise, self.implantation))
+        if self.devise.code == "EUR":
+            return 1
+        annee = self.poste.date_debut.year
+        taux = [tc.taux for tc in TauxChange.objects.filter(devise=self.devise, annee=annee)]
+        taux = set(taux)
+        if len(taux) != 1:
+            raise Exception(u"Le taux de la devise %s n'a pas n'existe pas pour %s ou il existe plusieurs taux pour la même année" % (self.devise.id, annee))
         else:
-            return liste_taux[0].taux
+            return list(taux)[0]
 
     def montant_euros(self):
         return round(float(self.montant) * float(self.taux_devise()), 2)
 
 class PosteComparaison(PosteComparaison_):
-    poste = models.ForeignKey('Poste', related_name='%(app_label)s_comparaisons_internes')
+    pass
 
 class PosteCommentaire_(Commentaire):
-    poste = models.ForeignKey('Poste', db_column='poste', related_name='+')
+    poste = models.ForeignKey('%s.Poste' % app_context(), db_column='poste', related_name='+')
 
     class Meta:
         abstract = True
@@ -612,7 +629,7 @@ class Dossier_(AUFMetadata):
 
 
     def remunerations(self):
-        return self.rh_remuneration_remunerations.all().order_by('date_debut')
+        return self.rh_remunerations.all().order_by('date_debut')
 
     def get_salaire(self):
         try:
@@ -622,7 +639,7 @@ class Dossier_(AUFMetadata):
 
 class Dossier(Dossier_):
     __doc__ = Dossier_.__doc__
-    poste = models.ForeignKey('Poste', db_column='poste', related_name='%(app_label)s_dossiers')
+    poste = models.ForeignKey('%s.Poste' % app_context(), db_column='poste', related_name='%(app_label)s_dossiers')
     employe = models.ForeignKey('Employe', db_column='employe', 
                             related_name='%(app_label)s_dossiers',
                             verbose_name=u"Employé")
@@ -632,6 +649,7 @@ class DossierPiece_(models.Model):
     """Documents relatifs au Dossier (à l'occupation de ce poste par employé).
     Ex.: Lettre de motivation.
     """
+    dossier = models.ForeignKey('%s.Dossier' % app_context(), db_column='dossier', related_name='+')
     nom = models.CharField(verbose_name = u"Nom", max_length=255)
     fichier = models.FileField(verbose_name = u"Fichier", 
                             upload_to=dossier_piece_dispatch, 
@@ -645,22 +663,21 @@ class DossierPiece_(models.Model):
         return u'%s' % (self.nom)
 
 class DossierPiece(DossierPiece_):
-    dossier = models.ForeignKey('Dossier', db_column='dossier', related_name='+')
-    
+    pass
 
 class DossierCommentaire_(Commentaire):
+    dossier = models.ForeignKey('%s.Dossier' % app_context(), db_column='dossier', related_name='+')
     class Meta:
         abstract = True
 
 class DossierCommentaire(DossierCommentaire_):
-    dossier = models.ForeignKey('Dossier', db_column='dossier', related_name='+')
-
+    pass
 
 class DossierComparaison_(models.Model):
     """
     Photo d'une comparaison salariale au moment de l'embauche.
     """
-
+    dossier = models.ForeignKey('%s.Dossier' % app_context(), related_name='%(app_label)s_comparaisons')
     objects = DossierComparaisonManager()
 
     implantation = models.ForeignKey(ref.Implantation, related_name="+", null=True, blank=True)
@@ -673,24 +690,25 @@ class DossierComparaison_(models.Model):
         abstract = True
 
     def taux_devise(self):
-        liste_taux = self.devise.tauxchange_set.order_by('-annee').filter(implantation=self.dossier.poste.implantation)
-        if len(liste_taux) == 0:
-            raise Exception(u"La devise %s n'a pas de taux pour l'implantation %s" % (self.devise, self.dossier.poste.implantation))
+        annee = self.dossier.poste.date_debut.year
+        taux = [tc.taux for tc in TauxChange.objects.filter(devise=self.devise, annee=annee)]
+        taux = set(taux)
+        if len(taux) != 1:
+            raise Exception(u"Le taux de la devise %s n'a pas n'existe pas pour %s ou il existe plusieurs taux pour la même année" % (self.devise.id, annee))
         else:
-            return liste_taux[0].taux
+            return list(taux)[0]
 
     def montant_euros(self):
         return round(float(self.montant) * float(self.taux_devise()), 2)
 
 class DossierComparaison(DossierComparaison_):
-    dossier = models.ForeignKey('Dossier', related_name='comparaisons')
+    pass
 
 ### RÉMUNÉRATION
     
 class RemunerationMixin(AUFMetadata):
+    dossier = models.ForeignKey('%s.Dossier' % app_context(), db_column='dossier', related_name='%(app_label)s_remunerations')
     # Identification
-    dossier = models.ForeignKey('Dossier', db_column='dossier',
-                        related_name='%(app_label)s_%(class)s_remunerations')
     type = models.ForeignKey('TypeRemuneration', db_column='type', 
                             related_name='+',
                             verbose_name = u"Type de rémunération")
@@ -702,9 +720,7 @@ class RemunerationMixin(AUFMetadata):
     montant = models.FloatField(null=True, blank=True,
                             default=0)
                             # Annuel (12 mois, 52 semaines, 364 jours?)
-    devise = models.ForeignKey('Devise', to_field='id',
-                            db_column='devise', related_name='+',
-                            default=5)
+    devise = models.ForeignKey('Devise', db_column='devise', related_name='+', default=5)
     # commentaire = precision
     commentaire = models.CharField(max_length=255, null=True, blank=True)
     # date_debut = anciennement date_effectif
@@ -730,10 +746,24 @@ class Remuneration_(RemunerationMixin):
         return round(self.montant / 12, 2)
 
     def taux_devise(self):
-        return self.devise.tauxchange_set.order_by('-annee').all()[0].taux
+        if self.devise.code == "EUR":
+            return 1
+
+        annee = datetime.datetime.now().year
+        if self.date_debut is not None:
+            annee = self.date_debut.year
+        if self.dossier.poste.date_debut is not None:
+            annee = self.dossier.poste.date_debut
+
+        taux = [tc.taux for tc in TauxChange.objects.filter(devise=self.devise_id, annee=annee)]
+        taux = set(taux)
+        if len(taux) != 1:
+            raise Exception(u"Le taux de la devise %s n'a pas n'existe pas pour %s ou il existe plusieurs taux pour la même année" % (self.devise.id, annee))
+        else:
+            return list(taux)[0]
 
     def montant_euro(self):
-        return round(float(self.montant) / float(self.taux_devise()), 2)
+        return round(float(self.montant) * float(self.taux_devise()), 2)
 
     def montant_euro_mois(self):
         return round(self.montant_euro() / 12, 2)
@@ -752,7 +782,7 @@ class Remuneration_(RemunerationMixin):
 
 
 class Remuneration(Remuneration_):
-    __doc__ = Remuneration_.__doc__
+    pass
 
 
 ### CONTRATS
@@ -767,7 +797,7 @@ class Contrat_(AUFMetadata):
     pour un Poste particulier. Pour un Dossier (qui documente cette 
     relation de travail) plusieurs contrats peuvent être associés.
     """
-
+    dossier = models.ForeignKey('%s.Dossier' % app_context(), db_column='dossier', related_name='%(app_label)s_contrats')
     objects = ContratManager()
 
     type_contrat = models.ForeignKey('TypeContrat', db_column='type_contrat', 
@@ -787,71 +817,71 @@ class Contrat_(AUFMetadata):
         return u'%s - %s' % (self.dossier, self.id)
 
 class Contrat(Contrat_):
-    dossier = models.ForeignKey('Dossier', db_column='dossier', related_name='contrats')
+    pass
         
 
 ### ÉVÉNEMENTS
 
-class Evenement_(AUFMetadata):
-    """Un Evenement sert à déclarer une situation temporaire (exceptionnelle) 
-    d'un Dossier qui vient altérer des informations normales liées à un Dossier 
-    (ex.: la Remuneration).
-    
-    Ex.: congé de maternité, maladie...
-    
-    Lors de ces situations exceptionnelles, l'Employe a un régime de travail
-    différent et une rémunération en conséquence. On souhaite toutefois
-    conserver le Dossier intact afin d'éviter une re-saisie des données lors
-    du retour à la normale.
-    """
-    dossier = models.ForeignKey('Dossier', db_column='dossier', 
-                            related_name='+')
-    nom = models.CharField(max_length=255)
-    date_debut = models.DateField(verbose_name = u"Date de début")
-    date_fin = models.DateField(verbose_name = u"Date de fin",
-                            null=True, blank=True)
-
-    class Meta:
-        abstract = True
-        ordering = ['nom']
-        verbose_name = u"Évènement"
-        verbose_name_plural = u"Évènements"
-                            
-    def __unicode__(self):
-        return u'%s' % (self.nom)
-
-
-class Evenement(Evenement_):
-    __doc__ = Evenement_.__doc__
-
-    
-class EvenementRemuneration_(RemunerationMixin):
-    """Structure de rémunération liée à un Evenement qui remplace 
-    temporairement la Remuneration normale d'un Dossier, pour toute la durée
-    de l'Evenement.
-    """
-    evenement = models.ForeignKey("Evenement", db_column='evenement',
-                            related_name='+',
-                            verbose_name = u"Évènement")
-    # TODO : le champ dossier hérité de Remuneration doit être dérivé
-    # de l'Evenement associé
-
-    class Meta:
-        abstract = True
-        ordering = ['evenement', 'type__nom', '-date_fin']
-        verbose_name = u"Évènement - rémunération"
-        verbose_name_plural = u"Évènements - rémunérations"
-
-
-class EvenementRemuneration(EvenementRemuneration_):
-    __doc__ = EvenementRemuneration_.__doc__
-
-    class Meta:
-        abstract = True
-
-
-class EvenementRemuneration(EvenementRemuneration_):
-    __doc__ = EvenementRemuneration_.__doc__
+#class Evenement_(AUFMetadata):
+#    """Un Evenement sert à déclarer une situation temporaire (exceptionnelle) 
+#    d'un Dossier qui vient altérer des informations normales liées à un Dossier 
+#    (ex.: la Remuneration).
+#    
+#    Ex.: congé de maternité, maladie...
+#    
+#    Lors de ces situations exceptionnelles, l'Employe a un régime de travail
+#    différent et une rémunération en conséquence. On souhaite toutefois
+#    conserver le Dossier intact afin d'éviter une re-saisie des données lors
+#    du retour à la normale.
+#    """
+#    dossier = models.ForeignKey('%s.Dossier' % app_context(), db_column='dossier', 
+#                            related_name='+')
+#    nom = models.CharField(max_length=255)
+#    date_debut = models.DateField(verbose_name = u"Date de début")
+#    date_fin = models.DateField(verbose_name = u"Date de fin",
+#                            null=True, blank=True)
+#
+#    class Meta:
+#        abstract = True
+#        ordering = ['nom']
+#        verbose_name = u"Évènement"
+#        verbose_name_plural = u"Évènements"
+#                            
+#    def __unicode__(self):
+#        return u'%s' % (self.nom)
+#
+#
+#class Evenement(Evenement_):
+#    __doc__ = Evenement_.__doc__
+#
+#    
+#class EvenementRemuneration_(RemunerationMixin):
+#    """Structure de rémunération liée à un Evenement qui remplace 
+#    temporairement la Remuneration normale d'un Dossier, pour toute la durée
+#    de l'Evenement.
+#    """
+#    evenement = models.ForeignKey("Evenement", db_column='evenement',
+#                            related_name='+',
+#                            verbose_name = u"Évènement")
+#    # TODO : le champ dossier hérité de Remuneration doit être dérivé
+#    # de l'Evenement associé
+#
+#    class Meta:
+#        abstract = True
+#        ordering = ['evenement', 'type__nom', '-date_fin']
+#        verbose_name = u"Évènement - rémunération"
+#        verbose_name_plural = u"Évènements - rémunérations"
+#
+#
+#class EvenementRemuneration(EvenementRemuneration_):
+#    __doc__ = EvenementRemuneration_.__doc__
+#
+#    class Meta:
+#        abstract = True
+#
+#
+#class EvenementRemuneration(EvenementRemuneration_):
+#    __doc__ = EvenementRemuneration_.__doc__
 
 
 ### RÉFÉRENCES RH