models plutôt complets
authordavin baragiotta <davin.baragiotta@u-db.(none)>
Thu, 5 May 2011 00:49:26 +0000 (20:49 -0400)
committerDavin BARAGIOTTA <davin.baragiotta@auf.org>
Thu, 5 May 2011 00:49:26 +0000 (20:49 -0400)
project/dae/models.py
project/rh/models.py

index a392a55..faa212e 100644 (file)
@@ -217,7 +217,8 @@ class Poste(PosteWorkflow, models.Model):
         (EUR autrement)
         """
         try:
-            implantation_devise = rh.TauxChange.objects.filter(implantation=self.implantation)[0].devise
+            implantation_devise = rh.TauxChange.objects \
+                            .filter(implantation=self.implantation)[0].devise
         except:
             implantation_devise = 5 # EUR
         return implantation_devise
index 380e3df..7cccc07 100644 (file)
@@ -10,9 +10,9 @@ import datamaster_modeles.models as ref
 
 
 # Constantes
-HELP_TEXT_DATE = "format: aaaa-mm-jj"
-REGIME_TRAVAIL_DEFAULT=100.00
-REGIME_TRAVAIL_NB_HEURE_SEMAINE_DEFAULT=35.00
+HELP_TEXT_DATE = u"format: aaaa-mm-jj"
+REGIME_TRAVAIL_DEFAULT = 100.00
+REGIME_TRAVAIL_NB_HEURE_SEMAINE_DEFAULT = 35.00
 
 
 # Upload de fichiers
@@ -30,24 +30,36 @@ def dossier_piece_dispatch(instance, filename):
 # Abstracts
 class Metadata(models.Model):
     """Méta-données AUF.
+    Metadata.actif = flag remplaçant la suppression.
+    actif == False : objet réputé supprimé.
     """
     actif = models.BooleanField(default=True)
     date_creation = models.DateField(auto_now_add=True)
-    user_creation = models.ForeignKey("auth.User")
+    user_creation = models.ForeignKey('auth.User', 
+                            db_column='user_creation', related_name='+',
+                            null=True, blank=True, default=True)
     date_modification = models.DateField(auto_now=True)
-    user_modification = models.ForeignKey("auth.User")
-    date_desactivation = models.DateField()
-    user_desactivation = models.ForeignKey("auth.User")
+    user_modification = models.ForeignKey('auth.User', 
+                            db_column='user_modification', related_name='+',
+                            null=True, blank=True, default=True)
+    date_desactivation = models.DateField(null=True, blank=True, default=True)
+    user_desactivation = models.ForeignKey('auth.User', 
+                            db_column='user_desactivation', related_name='+',
+                            null=True, blank=True, default=True)
     
     class Meta:
         abstract = True
 
 class Commentaire(Metadata):
     texte = models.TextField()
-    owner = models.ForeignKey("auth.User")
+    owner = models.ForeignKey('auth.User', db_column='owner', related_name='+')
     
     class Meta:
         abstract = True
+        ordering = ['-date_creation']
+        
+    def __unicode__(self):
+        return u'%s' % (self.texte)
 
 
 ### POSTE
@@ -58,99 +70,126 @@ POSTE_APPEL_CHOICES = (
 )
 
 class Poste(Metadata):
+    """Un Poste est un emploi (job) à combler dans une implantation. 
+    Un Poste peut être comblé par un Employe, auquel cas un Dossier est créé.
+    Si on veut recruter 2 jardiniers, 2 Postes distincts existent.
+    """
     # Identification
-    id = models.IntegerField(primary_key=True)
     nom = models.CharField(max_length=255, 
-                            verbose_name="Titre du poste", )
+                            verbose_name=u"Titre du poste", )
     nom_feminin = models.CharField(max_length=255,
-                            verbose_name="Titre du poste (au féminin)")
-    implantation = models.ForeignKey(ref.Implantation)
-    type_poste = models.ForeignKey('TypePoste', null=True, related_name='+')
-    service = models.ForeignKey('Service', related_name='+',
-                            verbose_name=u"Direction/Service/Pôle support")
-    responsable = models.ForeignKey('Poste', related_name='+',
-                            verbose_name="Poste du responsable")
+                            verbose_name=u"Titre du poste (au féminin)"
+                            null=True)
+    implantation = models.ForeignKey(ref.Implantation, 
+                            db_column='implantation', related_name='+')
+    type_poste = models.ForeignKey('TypePoste', db_column='type_poste',
+                            related_name='+',
+                            null=True)
+    service = models.ForeignKey('Service', db_column='service', 
+                            related_name='+',
+                            verbose_name=u"Direction/Service/Pôle support",
+                            default=1)  # default = Rectorat
+    responsable = models.ForeignKey('Poste', db_column='responsable', 
+                            related_name='+',
+                            verbose_name=u"Poste du responsable",
+                            default=149)    # default = Recteur
                                 
     # Contrat
     regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
                             default=REGIME_TRAVAIL_DEFAULT, 
-                            verbose_name="Temps de travail", 
-                            help_text="% du temps complet")
+                            verbose_name=u"Temps de travail", 
+                            help_text=u"% du temps complet")
     regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
                             decimal_places=2,
                             default=REGIME_TRAVAIL_NB_HEURE_SEMAINE_DEFAULT,
-                            verbose_name="Nb. heures par semaine")
+                            verbose_name=u"Nb. heures par semaine")
 
     # Recrutement
-    local = models.BooleanField(verbose_name="Local", default=True, blank=True)
-    expatrie = models.BooleanField(verbose_name="Expatrié", default=False, 
+    local = models.BooleanField(verbose_name=u"Local", default=True, 
+                            blank=True)
+    expatrie = models.BooleanField(verbose_name=u"Expatrié", default=False, 
                             blank=True)
-    mise_a_disposition = models.BooleanField(verbose_name="Mise à disposition")
-    appel = models.CharField(max_length=10, default='interne',
-                            verbose_name="Appel à candidature",
-                            choices=POSTE_APPEL_CHOICES)
+    mise_a_disposition = models.BooleanField(
+                            verbose_name=u"Mise à disposition",
+                            default=False)
+    appel = models.CharField(max_length=10, 
+                            verbose_name=u"Appel à candidature",
+                            choices=POSTE_APPEL_CHOICES,
+                            default='interne')
 
     # Rémunération
-    classement_min = models.ForeignKey('Classement', related_name='+',
-                            blank=True, null=True)
-    classement_max = models.ForeignKey('Classement', related_name='+',
-                            blank=True, null=True)
-    valeur_point_min = models.ForeignKey('ValeurPoint', related_name='+', 
-                            blank=True, null=True)
-    valeur_point_max = models.ForeignKey('ValeurPoint', related_name='+', 
-                            blank=True, null=True)
-    devise_min = models.ForeignKey('Devise', default=5, related_name='+')
-    devise_max = models.ForeignKey('Devise', default=5, related_name='+')
+    classement_min = models.ForeignKey('Classement', 
+                            db_column='classement_min', related_name='+',
+                            null=True, blank=True)
+    classement_max = models.ForeignKey('Classement', 
+                            db_column='classement_max', related_name='+',
+                            null=True, blank=True)
+    valeur_point_min = models.ForeignKey('ValeurPoint', 
+                            db_column='valeur_point_min', related_name='+', 
+                            null=True, blank=True)
+    valeur_point_max = models.ForeignKey('ValeurPoint', 
+                            db_column='valeur_point_max', related_name='+', 
+                            null=True, blank=True)
+    devise_min = models.ForeignKey('Devise', db_column='devise_min', 
+                            related_name='+', default=5)
+    devise_max = models.ForeignKey('Devise', db_column='devise_max', 
+                            related_name='+', default=5)
     salaire_min = models.DecimalField(max_digits=12, decimal_places=2,
-                                      default=0)
+                            default=0)
     salaire_max = models.DecimalField(max_digits=12, decimal_places=2,
-                                      default=0)
+                            default=0)
     indemn_min = models.DecimalField(max_digits=12, decimal_places=2,
-                                      default=0)
+                            default=0)
     indemn_max = models.DecimalField(max_digits=12, decimal_places=2,
-                                      default=0)
+                            default=0)
     autre_min = models.DecimalField(max_digits=12, decimal_places=2,
-                                      default=0)
+                            default=0)
     autre_max = models.DecimalField(max_digits=12, decimal_places=2,
-                                      default=0)
+                            default=0)
 
     # Comparatifs de rémunération
-    devise_comparaison = models.ForeignKey('Devise', related_name='+',
-                                           default=5)
+    devise_comparaison = models.ForeignKey('Devise', 
+                            db_column='devise_comparaison', 
+                            related_name='+',
+                            default=5)
     comp_locale_min = models.DecimalField(max_digits=12, decimal_places=2,
-                                          null=True, blank=True)
+                            null=True, blank=True)
     comp_locale_max = models.DecimalField(max_digits=12, decimal_places=2,
-                                          null=True, blank=True)
+                            null=True, blank=True)
     comp_universite_min = models.DecimalField(max_digits=12, decimal_places=2,
-                                              null=True, blank=True)
+                            null=True, blank=True)
     comp_universite_max = models.DecimalField(max_digits=12, decimal_places=2,
-                                              null=True, blank=True)
+                            null=True, blank=True)
     comp_fonctionpub_min = models.DecimalField(max_digits=12, decimal_places=2,
-                                               null=True, blank=True)
+                            null=True, blank=True)
     comp_fonctionpub_max = models.DecimalField(max_digits=12, decimal_places=2,
-                                               null=True, blank=True)
+                            null=True, blank=True)
     comp_ong_min = models.DecimalField(max_digits=12, decimal_places=2,
-                                       null=True, blank=True)
+                            null=True, blank=True)
     comp_ong_max = models.DecimalField(max_digits=12, decimal_places=2,
-                                       null=True, blank=True)
+                            null=True, blank=True)
     comp_autre_min = models.DecimalField(max_digits=12, decimal_places=2,
-                                         null=True, blank=True)
+                            null=True, blank=True)
     comp_autre_max = models.DecimalField(max_digits=12, decimal_places=2,
-                                         null=True, blank=True)
+                            null=True, blank=True)
 
     # Justification
-    justification = models.TextField()
+    justification = models.TextField(null=True, blank=True)
 
     # Autres Metadata
     date_validation = models.DateTimeField(null=True, blank=True)   # de dae
-    date_debut = models.DateField(verbose_name="Date de début",
-                                    help_text=HELP_TEXT_DATE)
-    date_fin = models.DateField(null=True, blank=True,
-                                    verbose_name="Date de fin",
-                                    help_text=HELP_TEXT_DATE)
-            
+    date_debut = models.DateField(verbose_name=u"Date de début",
+                            help_text=HELP_TEXT_DATE)
+    date_fin = models.DateField(verbose_name=u"Date de fin",
+                            help_text=HELP_TEXT_DATE,
+                            null=True, blank=True)
+
+    class Meta:
+        ordering = ['implantation__nom', 'nom']
+
     def __unicode__(self):
         # TODO : gérer si poste est vacant ou non dans affichage
+        # TODO : gérer le nom_feminin (autre méthode appelée par __unicode__ ?)
         return u'%s - %s [%s]' % (self.implantation, self.nom, self.id)
 
 
@@ -161,28 +200,42 @@ POSTE_FINANCEMENT_CHOICES = (
 )
 
 class PosteFinancement(models.Model):
-    poste = models.ForeignKey('Poste', related_name='financements')
+    """Pour un Poste, structure d'informations décrivant comment on prévoit
+    financer ce Poste.
+    """
+    poste = models.ForeignKey('Poste', db_column='poste', 
+                            related_name='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)")
+            help_text=u"ex.: 33.33 % (décimale avec point)")
     commentaire = models.TextField(
-            help_text="Spécifiez la source de financement.")
+            help_text=u"Spécifiez la source de financement.")
 
     class Meta:
         ordering = ['type']
+        
+    def __unicode__(self):
+        return u'%s : %s %' % (self.type, self.pourcentage)
 
 class PostePiece(models.Model):
-    """Documents relatifs au Poste
+    """Documents relatifs au Poste.
     Ex.: Description de poste
     """
-    poste = models.ForeignKey("Poste")
-    nom = models.CharField(verbose_name="Nom", max_length=255)
-    fichier = models.FileField(verbose_name="Fichier", 
+    poste = models.ForeignKey("Poste", db_column='poste', 
+                            related_name='pieces')
+    nom = models.CharField(verbose_name=u"Nom", max_length=255)
+    fichier = models.FileField(verbose_name=u"Fichier", 
                             upload_to=poste_piece_dispatch, 
                             storage=storage_prive)
 
+    class Meta:
+        ordering = ['nom']
+        
+    def __unicode__(self):
+        return u'%s' % (self.nom)
+
 class PosteCommentaire(Commentaire):
-    poste = models.ForeignKey("Poste")
+    poste = models.ForeignKey("Poste", db_column='poste', related_name='+')
 
 
 ### EMPLOYÉ/PERSONNE
@@ -198,49 +251,72 @@ SITUATION_CHOICES = (
 )
 
 class Employe(Metadata):
+    """Personne occupant ou ayant occupé un Poste. Un Employe aura autant de 
+    Dossiers qu'il occupe ou a occupé de Postes.
+    
+    Cette classe aurait pu avantageusement s'appeler Personne car la notion 
+    d'employé n'a pas de sens si aucun Dossier n'existe pour une personne.
+    """
     # Identification
-    id = models.IntegerField(primary_key=True)
     nom = models.CharField(max_length=255)
-    prenom = models.CharField(max_length=255, verbose_name='Prénom')
+    prenom = models.CharField(max_length=255, verbose_name=u"Prénom")
+    # TODO : nom_affichage doit être obligatoire, pas nom et prenom
+    nom_affichage = models.CharField(max_length=255, 
+                            verbose_name=u"Nom d'affichage",
+                            null=True, blank=True)
     nationalite = models.ForeignKey(ref.Pays, to_field='code', 
-                            related_name='employes_nationalite', 
-                            db_column='nationalite')
-    date_naissance = models.DateField(null=True, blank=True)
+                            db_column='nationalite',
+                            related_name='employes_nationalite')
+    date_naissance = models.DateField(help_text=HELP_TEXT_DATE,
+                            null=True, blank=True)
     genre = models.CharField(max_length=1, choices=GENRE_CHOICES)
     
     # Infos personnelles
-    situation_famille = models.CharField(max_length=1, null=True, blank=True,
-                            choices=SITUATION_CHOICES)
-    date_entree = models.DateField(verbose_name="Date d'entrée à l'AUF", 
+    situation_famille = models.CharField(max_length=1, 
+                            choices=SITUATION_CHOICES,
+                            null=True, blank=True)
+    date_entree = models.DateField(verbose_name=u"Date d'entrée à l'AUF",
+                            help_text=HELP_TEXT_DATE, 
                             null=True, blank=True)
     
     # Coordonnées
     tel_domicile = models.CharField(max_length=255, null=True, blank=True)
     tel_cellulaire = models.CharField(max_length=255, null=True, blank=True)
     adresse = models.CharField(max_length=255, null=True, blank=True)
-    no_rue = models.CharField(max_length=255, null=True, blank=True)
     ville = models.CharField(max_length=255, null=True, blank=True)
     province = models.CharField(max_length=255, null=True, blank=True)
     code_postal = models.CharField(max_length=255, null=True, blank=True)
-    pays = models.ForeignKey(ref.Pays, to_field='code', 
-                            null=True, blank=True, 
-                            related_name='employes', db_column='pays')
+    pays = models.ForeignKey(ref.Pays, to_field='code', db_column='pays',
+                            related_name='employes', 
+                            null=True, blank=True)
 
+    class Meta:
+        ordering = ['nom_affichage']
+        
     def __unicode__(self):
-        return u'%s %s' % (self.prenom, self.nom.upper())
+        # TODO : gérer nom d'affichage
+        return u'%s' % (self.nom_affichage)
 
 class EmployePiece(models.Model):
-    """Documents relatifs à l'employé
+    """Documents relatifs à un employé.
     Ex.: CV...
     """
-    employe = models.ForeignKey("Employe")
-    nom = models.CharField(verbose_name="Nom", max_length=255)
-    fichier = models.FileField(verbose_name="Fichier", 
+    employe = models.ForeignKey("Employe", db_column='employe', 
+                            related_name='+')
+    nom = models.CharField(verbose_name=u"Nom", max_length=255)
+    fichier = models.FileField(verbose_name=u"Fichier", 
                             upload_to=dossier_piece_dispatch, 
                             storage=storage_prive)
 
+    class Meta:
+        ordering = ['nom']
+        
+    def __unicode__(self):
+        return u'%s' % (self.nom)
+
 class EmployeCommentaire(Commentaire):
-    employe = models.ForeignKey("Employe")
+    employe = models.ForeignKey("Employe", db_column='employe',
+                            related_name='+')
 
 
 LIEN_PARENTE_CHOICES = (
@@ -251,24 +327,38 @@ LIEN_PARENTE_CHOICES = (
 )
 
 class AyantDroit(Metadata):
+    """Personne en relation avec un Employe.
+    """
     # Identification
-    id = models.IntegerField(primary_key=True)
     nom = models.CharField(max_length=255)
     prenom = models.CharField(max_length=255)
+    # TODO : nom_affichage doit être obligatoire, pas nom et prenom
+    nom_affichage = models.CharField(max_length=255, 
+                            verbose_name=u"Nom d'affichage",
+                            null=True, blank=True)
     nationalite = models.ForeignKey(ref.Pays, to_field='code', 
-                            related_name='ayantdroits_nationalite', 
-                            db_column='nationalite')
-    date_naissance = models.DateField(null=True, blank=True)
+                            db_column='nationalite',
+                            related_name='ayantdroits_nationalite')
+    date_naissance = models.DateField(help_text=HELP_TEXT_DATE,
+                            null=True, blank=True)
     genre = models.CharField(max_length=1, choices=GENRE_CHOICES)
     
     # Relation
     employe = models.ForeignKey('Employe', db_column='employe', 
-                            related_name='ayants_droit')
-    lien_parente = models.CharField(max_length=10, null=True, blank=True, 
-                            choices=LIEN_PARENTE_CHOICES)
+                            related_name='ayantdroits')
+    lien_parente = models.CharField(max_length=10, 
+                            choices=LIEN_PARENTE_CHOICES,
+                            null=True, blank=True)
+
+    class Meta:
+        ordering = ['nom_affichage']
+    def __unicode__(self):
+        # TODO : gérer nom d'affichage
+        return u'%s %s' % (self.prenom, self.nom.upper())
 
 class AyantDroitCommentaire(Commentaire):
-    ayant_droit = models.ForeignKey("AyantDroit")
+    ayant_droit = models.ForeignKey("AyantDroit", db_column='ayant_droit',
+                            related_name='+')
 
 
 ### DOSSIER
@@ -285,49 +375,64 @@ COMPTE_COMPTA_CHOICES = (
 )
 
 class Dossier(Metadata):
+    """Le Dossier regroupe les informations relatives à l'occupation
+    d'un Poste par un Employe. Un seul Dossier existe par Poste occupé
+    par un Employe.
+    
+    Plusieurs Contrats peuvent être associés au Dossier.
+    Une structure de Remuneration est rattachée au Dossier. Un Poste pour
+    lequel aucun Dossier n'existe est un poste vacant.
+    """
     # Identification
-    id = models.IntegerField(primary_key=True)
-    employe = models.ForeignKey('Employe', db_column='employe')
-    poste = models.ForeignKey('Poste', related_name='+', editable=False)
-    statut = models.ForeignKey('Statut', related_name='+')
+    employe = models.ForeignKey('Employe', db_column='employe', 
+                            related_name='+')
+    poste = models.ForeignKey('Poste', db_column='poste', 
+                            related_name='+', editable=False)
+    statut = models.ForeignKey('Statut', related_name='+', default=3)
     organisme_bstg = models.ForeignKey('OrganismeBstg', 
-            null=True, blank=True,
-            verbose_name="Organisme", 
-            help_text="Si détaché (DET) ou mis à disposition (MAD), \
-                    préciser l'organisme.",
-            related_name='+')
-        
+                            db_column='organisme_bstg',
+                            related_name='+',
+                            verbose_name=u"Organisme", 
+                            help_text=u"Si détaché (DET) ou \
+                                    mis à disposition (MAD), \
+                                    préciser l'organisme.",
+                            null=True, blank=True)
+                          
     # Recrutement
     remplacement = models.BooleanField(default=False)
     statut_residence = models.CharField(max_length=10, default='local', 
-                            verbose_name="Statut",
+                            verbose_name=u"Statut",
                             choices=STATUT_RESIDENCE_CHOICES)
    
     # Rémunération
-    classement = models.ForeignKey('Classement', related_name='+',
-                          null=True, blank=True)
+    classement = models.ForeignKey('Classement', db_column='classement', 
+                            related_name='+',
+                            null=True, blank=True)
     regime_travail = models.DecimalField(max_digits=12, 
                             decimal_places=2,
                             default=REGIME_TRAVAIL_DEFAULT,
-                            verbose_name="Régime de travail",
-                            help_text="% du temps complet")
+                            verbose_name=u"Régime de travail",
+                            help_text=u"% du temps complet")
     regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
                             decimal_places=2, 
                             default=REGIME_TRAVAIL_NB_HEURE_SEMAINE_DEFAULT,
-                            verbose_name="Nb. heures par semaine")
+                            verbose_name=u"Nb. heures par semaine")
 
     # Occupation du Poste par cet Employe (anciennement "mandat")
-    date_debut = models.DateField(help_text=HELP_TEXT_DATE,
-                            verbose_name="Date de début d'occupation de poste")
-    date_fin = models.DateField(null=True, blank=True,
+    date_debut = models.DateField(verbose_name=u"Date de début d'occupation \
+                            de poste",
+                            help_text=HELP_TEXT_DATE)
+    date_fin = models.DateField(verbose_name=u"Date de fin d'occupation \
+                            de poste",
                             help_text=HELP_TEXT_DATE,
-                            verbose_name="Date de fin d'occupation de poste")
-    # Contrat
-    # TODO : m2m Contrat
+                            null=True, blank=True)
     
     # Comptes
     # TODO?
     
+    class Meta:
+        ordering = ['poste__nom', 'employe__nom_affichage']
+        
     def __unicode__(self):
         return u'%s - %s' % (self.poste.nom, self.employe)
 
@@ -335,40 +440,56 @@ class DossierPiece(models.Model):
     """Documents relatifs au Dossier (à l'occupation de ce poste par employé).
     Ex.: Lettre de motivation.
     """
-    dossier = models.ForeignKey("Dossier")
-    nom = models.CharField(verbose_name="Nom", max_length=255)
-    fichier = models.FileField(verbose_name="Fichier", 
+    dossier = models.ForeignKey("Dossier", 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, 
                             storage=storage_prive)
 
+    class Meta:
+        ordering = ['nom']
+        
+    def __unicode__(self):
+        return u'%s' % (self.nom)
+
 class DossierCommentaire(Commentaire):
-    dossier = models.ForeignKey("Dossier")
+    dossier = models.ForeignKey("Dossier", db_column='dossier', 
+                            related_name='+')
 
 
 ### RÉMUNÉRATION
     
 class RemunerationMixin(Metadata):
     # Identification
-    id = models.IntegerField(primary_key=True)
     dossier = models.ForeignKey('Dossier', db_column='dossier')
     type = models.ForeignKey('TypeRemuneration', db_column='type', 
                             related_name='+')
     type_revalorisation = models.ForeignKey('TypeRevalorisation', 
                             db_column='type_revalorisation', 
+                            related_name='+',
                             null=True, blank=True)
     montant = models.FloatField(max_digits=12, decimal_places=2, 
-                            null=True, blank=True)
+                            null=True, blank=True,
+                            default=0)
                             # Annuel (12 mois, 52 semaines, 364 jours?)
     devise = models.ForeignKey('Devise', to_field='code',
-                               db_column='devise', related_name='+')
+                            db_column='devise', related_name='+',
+                            default=5)
     # commentaire = precision
     commentaire = models.CharField(max_length=255, null=True, blank=True)
     # date_debut = anciennement date_effectif
-    date_debut = models.DateField(null=True, blank=True)
-    date_fin = models.DateField(null=True, blank=True)
+    date_debut = models.DateField(help_text=HELP_TEXT_DATE, 
+                            null=True, blank=True)
+    date_fin = models.DateField(help_text=HELP_TEXT_DATE,
+                            null=True, blank=True)
     
     class Meta: 
         abstract = True
+        ordering = ['type__nom', '-date_fin']
+        
+    def __unicode__(self):
+        return u'%s %s (%s)' % (self.montant, self.devise.code, self.type.nom)
     
 class Remuneration(RemunerationMixin):
     """Structure de rémunération (données budgétaires) en situation normale
@@ -403,50 +524,86 @@ class Contrat(Metadata):
     pour un Poste particulier. Pour un Dossier (qui documente cette 
     relation de travail) plusieurs contrats peuvent être associés.
     """
-    dossier = models.ForeignKey("Dossier")
-    type_contrat = models.ForeignKey('TypeContrat', related_name='+')
+    dossier = models.ForeignKey('Dossier', db_column='dossier', 
+                            related_name='+')
+    type_contrat = models.ForeignKey('TypeContrat', db_column='type_contrat', 
+                            related_name='+')
     date_debut = models.DateField(help_text=HELP_TEXT_DATE)
-    date_fin = models.DateField(null=True, blank=True,
-                                        help_text=HELP_TEXT_DATE)
+    date_fin = models.DateField(help_text=HELP_TEXT_DATE,
+                            null=True, blank=True)
+
+    class Meta:
+        ordering = ['dossier__employe__nom_affichage']
+        
+    def __unicode__(self):
+        return u'%s - %s' % (self.dossier.employe.nom_affichage, self.id)
+        
+# TODO? class ContratPiece(models.Model):
     
 
 ### ÉVÉNEMENTS
 
-class Evenement(models.Models):
-    pass
-    # nom
-    # date_debut
-    # date_fin
+class Evenement(Metadata):
+    """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(help_text=HELP_TEXT_DATE)
+    date_fin = models.DateField(help_text=HELP_TEXT_DATE, 
+                            null=True, blank=True)
+    class Meta:
+        ordering = ['nom']
+                            
+    def __unicode__(self):
+        return u'%s' % (self.nom)
     
 class EvenementRemuneration(RemunerationMixin):
-    pass
-    # evenement
+    """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='+')
 
 
 ### RÉFÉRENCES RH 
 
-class FamilleEmploi(models.Model):
-    # Identification
-    id = models.IntegerField(primary_key=True)
+class FamilleEmploi(Metadata):
+    """Catégorie utilisée dans la gestion des Postes.
+    Catégorie supérieure à TypePoste.
+    """
     nom = models.CharField(max_length=255)
-    # Méta
-    actif = models.BooleanField()
+    
+    def __unicode__(self):
+        return u'%s' % (self.nom)
 
-class TypePoste(models.Model):
-    # Identification
-    id = models.IntegerField(primary_key=True)
+class TypePoste(Metadata):
+    """Catégorie de Poste.
+    """
     nom = models.CharField(max_length=255)
     nom_feminin = models.CharField(max_length=255)
-    #description = models.CharField(max_length=255)
-    is_responsable = models.BooleanField()
+    
+    is_responsable = models.BooleanField(default=False)
     famille_emploi = models.ForeignKey('FamilleEmploi', 
-                            db_column='famille_emploi')
-    # Méta
-    date_modification = models.DateField(auto_now=True)
-    actif = models.BooleanField()
+                            db_column='famille_emploi',
+                            related_name='+')
 
+    class Meta:
+        ordering = ['nom']
+        
     def __unicode__(self):
-        return u'%s' % self.nom
+        # TODO : gérer nom féminin
+        return u'%s' % (self.nom)
 
 
 TYPE_PAIEMENT_CHOICES = (
@@ -462,137 +619,153 @@ NATURE_REMUNERATION_CHOICES = (
     ('Traitement', 'Traitement'),
 )
 
-class TypeRemuneration(models.Model):
-    # Identification
-    id = models.IntegerField(primary_key=True)
+class TypeRemuneration(Metadata):
+    """Catégorie de Remuneration.
+    """
     nom = models.CharField(max_length=255)
     type_paiement = models.CharField(max_length=30, 
                             choices=TYPE_PAIEMENT_CHOICES)
     nature_remuneration = models.CharField(max_length=30, 
                             choices=NATURE_REMUNERATION_CHOICES)
-    # Méta
-    actif = models.BooleanField()
 
     def __unicode__(self):
-        return u'%s' % self.nom
+        return u'%s' % (self.nom)
         
-class TypeRevalorisation(models.Model):
+class TypeRevalorisation(Metadata):
     """Justification du changement de la Remuneration.
-    (Actuellement utilisé dans aucun traitement informatique)
+    (Actuellement utilisé dans aucun traitement informatique.)
     """
-    # Identification
-    id = models.IntegerField(primary_key=True)
     nom = models.CharField(max_length=255)
-    # Méta
-    actif = models.BooleanField()
-    
-class Service(models.Model):
-    # Identification
-    id = models.IntegerField(primary_key=True)
-    nom = models.CharField(max_length=255)
-    # Méta
-    actif = models.BooleanField()
 
     def __unicode__(self):
-        return u'%s' % self.nom
+        return u'%s' % (self.nom)
+    
+class Service(Metadata):
+    """Unité administrative où les Postes sont rattachés.
+    """
+    nom = models.CharField(max_length=255)
         
     class Meta:
         ordering = ['nom']
 
+    def __unicode__(self):
+        return u'%s' % (self.nom)
+
 
 TYPE_ORGANISME_CHOICES = (
     ('MAD', 'Mise à disposition'),
     ('DET', 'Détachement'),
 )
 
-class OrganismeBstg(models.Model):
-    # Identification
-    id = models.IntegerField(primary_key=True)
+class OrganismeBstg(Metadata):
+    """Organisation d'où provient un Employe mis à disposition (MAD) de 
+    ou détaché (DET) à l'AUF à titre gratuit.
+    
+    (BSTG = bien et service à titre gratuit.)
+    """
     nom = models.CharField(max_length=255)
     type = models.CharField(max_length=10, choices=TYPE_ORGANISME_CHOICES)
-    # pays
-    
-    # Méta
-    actif = models.BooleanField()
-
-    def __unicode__(self):
-        return u'%s (%s)' % (self.nom, self.type)
+    pays = models.ForeignKey(ref.Pays, to_field='code', 
+                            db_column='pays',
+                            related_name='organismes_bstg',
+                            null=True, blank=True)
 
     class Meta:
         ordering = ['type', 'nom']
 
+    def __unicode__(self):
+        return u'%s (%s)' % (self.nom, self.type)
 
-CONTRAT_CATEGORIE_CHOICES= (
-    ('A', 'A'),
-    ('C', 'C'),
-)
-
-class Statut(models.Model):
+class Statut(Metadata):
+    """Statut de l'Employe dans le cadre d'un Dossier particulier.
+    """
     # Identification
-    id = models.IntegerField(primary_key=True)
     code = models.CharField(max_length=25, unique=True)
     nom = models.CharField(max_length=255)
-    type_contrat_categorie = models.CharField(max_length=10, 
-                            choices=CONTRAT_CATEGORIE_CHOICES)
-    #CHOICES A, C (veut dire quoi?) voir TypeContrat.categorie
-    # A = AUF, C = Contractuel ???
-    # Méta
-    actif = models.BooleanField()
 
+    class Meta:
+        ordering = ['code']
+        
     def __unicode__(self):
         return u'%s : %s' % (self.code, self.nom)
 
 
 TYPE_CLASSEMENT_CHOICES = (
-    ('S', 'S'),
-    ('T', 'T'),
+    ('S', 'S -Soutien'),
+    ('T', 'T - Technicien'),
+    ('P', 'P - Professionel'),
+    ('C', 'C - Cadre'),
+    ('D', 'D - Direction'),
+    ('SO', 'SO - Sans objet [expatriés]'),
+    ('HG', 'HG - Hors grille [direction]'),
 )
 
-class Classement(models.Model):
+class Classement(Metadata):
+    """Éléments de classement de la 
+    "Grille générique de classement hiérarchique".
+    
+    Utile pour connaître, pour un Dossier, le salaire de base théorique lié au 
+    classement dans la grille. Le classement donne le coefficient utilisé dans:
+
+    salaire de base = coefficient * valeur du point de l'Implantation du Poste
+    """
     # Identification
-    id = models.IntegerField(primary_key=True)
     type = models.CharField(max_length=10, choices=TYPE_CLASSEMENT_CHOICES)
     echelon = models.IntegerField()
     degre = models.IntegerField()
-    coefficient = models.FloatField(null=True)
-    # annee # au lieu de date_debut et date_fin
+    coefficient = models.FloatField(default=0)
     # Méta
-    commentaire = models.TextField(null=True, blank=True) 
-    date_modification = models.DateField(auto_now=True)
-    actif = models.BooleanField()
+    # annee # au lieu de date_debut et date_fin
+    commentaire = models.TextField(null=True, blank=True)
+    
+    class Meta:
+        ordering = ['type','echelon','degre','coefficient']
 
     def __unicode__(self):
         return u'%s.%s.%s (%s)' % (self.type, self.echelon, self.degre,
                                    self.coefficient)
-    class Meta:
-        ordering = ['type','echelon','degre','coefficient']
 
-class TauxChange(models.Model):
+class TauxChange(Metadata):
     """Taux de change de la devise vers l'euro (EUR) 
-    pour cette année budgétaire.
+    pour chaque année budgétaire.
     """
     # Identification
-    id = models.IntegerField(primary_key=True)
-    devise = models.ForeignKey('Devise', to_field='code', db_column='devise')
+    devise = models.ForeignKey('Devise', to_field='code', db_column='devise',
+                            related_name='+')
     annee = models.IntegerField()
     taux = models.FloatField()
+    
+    class Meta:
+        ordering = ['annee', 'devise__code']
+    
+    def __unicode__(self):
+        return u'%s : %s €' % (self.devise.code, self.taux)
 
-class ValeurPoint(models.Model):
-    # Identification
-    id = models.IntegerField(primary_key=True)
+class ValeurPoint(Metadata):
+    """Utile pour connaître, pour un Dossier, le salaire de base théorique lié 
+    au classement dans la grille. La ValeurPoint s'obtient par l'implantation 
+    du POste de ce Dossier : dossier.poste.implantation (pseudo code).
+
+    salaire de base = coefficient * valeur du point de l'Implantation du Poste
+    """
     valeur = models.FloatField()
-    # devise
+    devise = models.ForeignKey('Devise', db_column='devise', 
+                            related_name='+', default=5)
     implantation = models.ForeignKey(ref.Implantation, 
                             db_column='implantation', 
-                            related_name='valeurs_point')
+                            related_name='valeur_point')
     # Méta
     annee = models.IntegerField()
 
     # Stockage de tous les taux de change 
     # pour optimiser la recherche de la devise associée
     annee_courante = datetime.datetime.now().year
-    tauxchange = TauxChange.objects.select_related('devise').filter(annee=annee_courante)
+    tauxchange = TauxChange.objects.select_related('devise')    \
+                            .filter(annee=annee_courante)
 
+    class Meta:
+        ordering = ['annee', 'implantation__nom']
+        
     def __unicode__(self):
         tx = self.get_tauxchange_courant()
         if tx:
@@ -605,23 +778,23 @@ class ValeurPoint(models.Model):
     class Meta:
         ordering = ['valeur']
 
-class Devise(models.Model):
-    id = models.IntegerField(primary_key=True)
+class Devise(Metadata):
+    """Devise monétaire.
+    """
     code =  models.CharField(max_length=10, unique=True)
     nom = models.CharField(max_length=255)
 
+    class Meta:
+        ordering = ['code']
+        
     def __unicode__(self):
         return u'%s - %s' % (self.code, self.nom)
 
-class TypeContrat(models.Model):
-    # Identification
-    id = models.IntegerField(primary_key=True)
+class TypeContrat(Metadata):
+    """Type de contrat.
+    """
     nom = models.CharField(max_length=255)
-    nom_long = models.CharField(max_length=255) # description
-    categorie = models.CharField(max_length=10, 
-                            choices=CONTRAT_CATEGORIE_CHOICES) # A, C?
-    # Méta
-    actif = models.BooleanField()
+    nom_long = models.CharField(max_length=255)
 
     def __unicode__(self):
         return u'%s' % (self.nom)
@@ -629,12 +802,16 @@ class TypeContrat(models.Model):
         
 ### AUTRES
 
-class ResponsableImplantation(models.Model):
+class ResponsableImplantation(Metadata):
     """Le responsable d'une implantation. 
     Anciennement géré sur le Dossier du responsable.
     """
-    employe = models.ForeignKey('Employe', null=True, blank=True)
-    implantation = models.ForeignKey(ref.Implantation, unique=True)
+    employe = models.ForeignKey('Employe', db_column='employe', 
+                            related_name='+',
+                            null=True, blank=True)
+    implantation = models.ForeignKey(ref.Implantation, 
+                            db_column='implantation', related_name='+', 
+                            unique=True)
 
     def __unicode__(self):
         return u'%s : %s' % (self.implantation, self.employe)