plug metadata module #1544
authorOlivier Larchevêque <olivier.larcheveque@auf.org>
Fri, 8 Jul 2011 15:12:44 +0000 (11:12 -0400)
committerOlivier Larchevêque <olivier.larcheveque@auf.org>
Fri, 8 Jul 2011 15:12:44 +0000 (11:12 -0400)
buildout.cfg
project/rh/lib.py
project/rh/models.py

index 888d3e7..55d7aaa 100644 (file)
@@ -9,6 +9,7 @@ find-links = http://pypi.auf.org/simple/auf.recipe.django/
     http://pypi.auf.org/simple/auf.django.auth/
     http://pypi.auf.org/simple/auf.django.workflow/
     http://pypi.auf.org/simple/auf.django.admingroup/
+    http://pypi.auf.org/simple/auf.django.metadata/
 
 eggs =
     django
@@ -22,6 +23,8 @@ eggs =
     django-reversion
     simplejson
     django-ajax-selects
+    auf.django.metadata
+
 # LA PROD ne dispose que de reportlab 2.1, incompatible avec
 # les versions de pisa assez évoluées pour un bon rendu.
 #    reportlab
index 61c32e6..fc351c8 100644 (file)
@@ -1,80 +1,44 @@
 # -*- encoding: utf-8 -*-
 
-import datetime
 from django.db import models
 from django.contrib import admin
-
+from auf.django.metadata.admin import AUFMetadataAdminMixin, AUFMetadataInlineAdminMixin, AUF_METADATA_READONLY_FIELDS
 from project.rh import models as rh
 
-# MetaData
-METADATA_READONLY_FIELDS = ('supprime',
-                       'date_creation',
-                       'user_creation',
-                       'date_modification',
-                       'user_modification',
-                       'date_activation',
-                       'user_activation',
-                       'date_desactivation',
-                       'user_desactivation', )
-
-METADATA_FIELDSET_FIELDS = ('actif', 'date_creation', 'user_creation',
-                       'date_modification', 'user_modification',
-                       'date_activation', 'user_activation',
-                       'date_desactivation', 'user_desactivation',)
-
-class MetadataAdminMixin(object):
-    """
-    Surcharge l'admin de base, pour setter automatiquement les metadata
-    """
-    def save_model(self, request, obj, form, change):
-        if change is False:
-            obj.user_creation = request.user
-            obj.date_creation = datetime.datetime.now()
-        obj.user_modification = request.user
-        obj.date_modification = datetime.datetime.now()
-        if form.initial['actif'] is True and obj.actif is False:
-            obj.user_desactivation = request.user
-            obj.date_desactivation = datetime.datetime.now()
-        if form.initial['actif'] is False and obj.actif is True:
-            obj.user_activation = request.user
-            obj.date_activation = datetime.datetime.now()
-        obj.save()
-
-class ReadonlyInlineMixin(object):
-    def get_readonly_fields(self, request, obj=None):
-        return [f.name for f in self.model._meta.fields if f.name not in METADATA_READONLY_FIELDS]
+# Inlines
 
+class ReadOnlyInlineMixin(object):
+    def get_readonly_fields(self, request, obj=None):
+        return [f.name for f in self.model._meta.fields if f.name not in AUF_METADATA_READONLY_FIELDS]
 
-# Inlines
 
-class AyantDroitInline(admin.TabularInline):
-    exclude = METADATA_READONLY_FIELDS + ('actif', )
+class AyantDroitInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
     model = models.Model  # à remplacer dans admin.py
     extra = 1
 
-class AyantDroitCommentaireInline(admin.TabularInline):
-    exclude = METADATA_READONLY_FIELDS + ('actif', )
+
+class AyantDroitCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
     readonly_fields = ('owner', )
     model = models.Model  # à remplacer dans admin.py
     extra = 1
 
 
-class ContratInline(admin.TabularInline):
+class ContratInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
     model = models.Model  # à remplacer dans admin.py
-    exclude = METADATA_READONLY_FIELDS + ('actif', )
     extra = 1
 
 
-class DossierROInline(ReadonlyInlineMixin, admin.TabularInline):
+class DossierROInline(ReadOnlyInlineMixin, admin.TabularInline):
+    exclude = AUF_METADATA_READONLY_FIELDS
     model = models.Model  # à remplacer dans admin.py
-    exclude = METADATA_READONLY_FIELDS
 
-class DossierCommentaireInline(admin.TabularInline, MetadataAdminMixin):
-    exclude = METADATA_READONLY_FIELDS + ('actif', )
+
+class DossierCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
     readonly_fields = ('owner', )
     model = models.Model  # à remplacer dans admin.py
     extra = 1
 
+
 class DossierPieceInline(admin.TabularInline):
     model = models.Model  # à remplacer dans admin.py
 
@@ -82,9 +46,7 @@ class DossierPieceInline(admin.TabularInline):
 class EmployeInline(admin.TabularInline):
     model = models.Model  # à remplacer dans admin.py
 
-
-class EmployeCommentaireInline(admin.TabularInline):
-    exclude = METADATA_READONLY_FIELDS + ('actif', )
+class EmployeCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
     readonly_fields = ('owner', )
     model = models.Model  # à remplacer dans admin.py
     extra = 1
@@ -94,15 +56,13 @@ class EmployePieceInline(admin.TabularInline):
     model = models.Model  # à remplacer dans admin.py
 
 
-class EvenementInline(admin.TabularInline, MetadataAdminMixin):
+class EvenementInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
     model = models.Model  # à remplacer dans admin.py
-    exclude = METADATA_READONLY_FIELDS + ('actif', )
     extra = 1
 
 
-class EvenementRemunerationInline(admin.TabularInline, MetadataAdminMixin):
+class EvenementRemunerationInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
     model = models.Model  # à remplacer dans admin.py
-    exclude = METADATA_READONLY_FIELDS + ('actif', )
     extra = 1
 
 
@@ -110,8 +70,7 @@ class PosteInline(admin.TabularInline):
     model = models.Model  # à remplacer dans admin.py
 
 
-class PosteCommentaireInline(admin.TabularInline):
-    exclude = METADATA_READONLY_FIELDS + ('actif', )
+class PosteCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
     readonly_fields = ('owner', )
     model = models.Model  # à remplacer dans admin.py
     extra = 1
@@ -125,13 +84,12 @@ class PostePieceInline(admin.TabularInline):
     model = models.Model  # à remplacer dans admin.py
 
 
-class RemunerationInline(admin.TabularInline):
+class RemunerationInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
     model = models.Model  # à remplacer dans admin.py
-    exclude = METADATA_READONLY_FIELDS + ('actif', )
     extra = 1
 
 
-class RemunerationROInline(ReadonlyInlineMixin, RemunerationInline):
+class RemunerationROInline(ReadOnlyInlineMixin, RemunerationInline):
     pass
 
 
@@ -141,19 +99,15 @@ class TypePosteInline(admin.TabularInline):
 
 # Admins
 
-class AyantDroitAdmin(admin.ModelAdmin):
+class AyantDroitAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
     """
     L'ajout d'un nouvel ayantdroit se fait dans l'admin de l'employé.
     """
     search_fields = ('nom', 'prenom', 'employe__nom', 'employe__prenom', )
     list_display = ('_ayantdroit', '_employe', )
     inlines = (AyantDroitCommentaireInline,)
-    readonly_fields = METADATA_READONLY_FIELDS + ('employe',)
-    fieldsets = (
-        ('Metadata', {
-            'classes': ('collapse',),
-            'fields': METADATA_FIELDSET_FIELDS,
-        }),
+    readonly_fields = AUFMetadataAdminMixin.readonly_fields + ('employe',)
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
         ("Lien avec l'employé", {
             'fields': ('employe', 'lien_parente', )
         }),
@@ -164,6 +118,7 @@ class AyantDroitAdmin(admin.ModelAdmin):
     )
 
     def save_formset(self, request, form, formset, change):
+        super(AyantDroitAdmin, self).save_formset(request, form, formset, change)
         instances = formset.save(commit=False)
         for instance in instances:
             if instance.__class__ == rh.AyantDroitCommentaire:
@@ -202,7 +157,7 @@ class DeviseAdmin(admin.ModelAdmin):
     pass
 
 
-class DossierAdmin(MetadataAdminMixin, admin.ModelAdmin,):
+class DossierAdmin(AUFMetadataAdminMixin, admin.ModelAdmin,):
     search_fields = ('employe__nom', 'employe__prenom', )
     list_display = ('_employe', '_poste', 'date_debut', 'date_fin', )
     inlines = (DossierPieceInline, ContratInline,
@@ -210,12 +165,7 @@ class DossierAdmin(MetadataAdminMixin, admin.ModelAdmin,):
                #EvenementInline,
                DossierCommentaireInline,
               )
-    readonly_fields = METADATA_READONLY_FIELDS
-    fieldsets = (
-        ('Metadata', {
-            'classes': ('collapse',),
-            'fields': METADATA_FIELDSET_FIELDS,
-        }),
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
         ('Identification', {
             'fields': ('employe', 'poste', 'statut', 'organisme_bstg',)
         }),
@@ -239,6 +189,7 @@ class DossierAdmin(MetadataAdminMixin, admin.ModelAdmin,):
     _employe.short_description = u'Employé'
     
     def save_formset(self, request, form, formset, change):
+        super(DossierAdmin, self).save_formset(request, form, formset, change)
         instances = formset.save(commit=False)
         for instance in instances:
             if instance.__class__ == rh.DossierCommentaire:
@@ -254,17 +205,13 @@ class DossierCommentaireAdmin(admin.ModelAdmin):
     pass
 
 
-class EmployeAdmin(MetadataAdminMixin, admin.ModelAdmin):
+class EmployeAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+    search_fields = ('id', 'nom', 'prenom', 'nom_affichage', )
     inlines = (AyantDroitInline,
                DossierROInline,
                EmployePieceInline,
                EmployeCommentaireInline)
-    readonly_fields = METADATA_READONLY_FIELDS
-    fieldsets = (
-        ('Metadata', {
-            'classes': ('collapse',),
-            'fields': METADATA_FIELDSET_FIELDS,
-        }),
+    fieldsets = AUFMetadataAdminMixin.fieldsets + ( 
         ('Identification', {
             'fields': ('nom', 'prenom', 'nom_affichage', 'nationalite', 'date_naissance', 'genre', )
         }),
@@ -277,6 +224,7 @@ class EmployeAdmin(MetadataAdminMixin, admin.ModelAdmin):
         )
 
     def save_formset(self, request, form, formset, change):
+        super(EmployeAdmin, self).save_formset(request, form, formset, change)
         instances = formset.save(commit=False)
         for instance in instances:
             if instance.__class__ == rh.EmployeCommentaire:
index 10a3470..a410f9b 100644 (file)
@@ -1,11 +1,10 @@
 # -=- encoding: utf-8 -=-
 
-import datetime
-
 from django.core.files.storage import FileSystemStorage
 from django.db import models
-import settings
-
+from django.conf import settings
+from auf.django.metadata.models import AUFMetadata
+from auf.django.metadata.managers import NoDeleteManager
 import datamaster_modeles.models as ref
 
 
@@ -28,47 +27,7 @@ def dossier_piece_dispatch(instance, filename):
     return path
 
 
-class RHManager(models.Manager):
-    def get_query_set(self):
-        return super(RHManager, self).get_query_set().filter(supprime=False)
-
-
-# Abstracts
-class Metadata(models.Model):
-    """Méta-données AUF.
-    Metadata.actif = flag remplaçant la suppression.
-    supprime == True : objet réputé supprimé.
-    """
-    supprime = models.BooleanField(default=False)
-    date_creation = models.DateField(null=True, blank=True)
-    user_creation = models.ForeignKey('auth.User', 
-                            db_column='user_creation', related_name='+',
-                            null=True, blank=True)
-    date_modification = models.DateField(null=True, blank=True)
-    user_modification = models.ForeignKey('auth.User', 
-                            db_column='user_modification', related_name='+',
-                            null=True, blank=True)
-    actif = models.BooleanField(default=True)
-    date_activation = models.DateField(null=True, blank=True)
-    user_activation = models.ForeignKey('auth.User', 
-                            db_column='user_activation', related_name='+',
-                            null=True, blank=True)
-    date_desactivation = models.DateField(null=True, blank=True)
-    user_desactivation = models.ForeignKey('auth.User', 
-                            db_column='user_desactivation', related_name='+',
-                            null=True, blank=True)
-
-    objects = RHManager()
-
-    class Meta:
-        abstract = True
-
-    def delete(self):
-        self.supprime = True
-        self.save()
-
-
-class Commentaire(Metadata):
+class Commentaire(AUFMetadata):
     texte = models.TextField()
     owner = models.ForeignKey('auth.User', db_column='owner', related_name='+')
     
@@ -87,12 +46,11 @@ POSTE_APPEL_CHOICES = (
     ('externe', 'Externe'),
 )
 
-
-class PosteManager(models.Manager):
+class PosteManager(NoDeleteManager):
     def get_query_set(self):
         return super(PosteManager, self).get_query_set().select_related('implantation')
 
-class Poste_(Metadata):
+class Poste_(AUFMetadata):
     """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.
@@ -313,7 +271,7 @@ SITUATION_CHOICES = (
     ('M', 'Marié'),
 )
 
-class Employe(Metadata):
+class Employe(AUFMetadata):
     """Personne occupant ou ayant occupé un Poste. Un Employe aura autant de 
     Dossiers qu'il occupe ou a occupé de Postes.
     
@@ -402,7 +360,7 @@ LIEN_PARENTE_CHOICES = (
     ('Fils', 'Fils'),
 )
 
-class AyantDroit(Metadata):
+class AyantDroit(AUFMetadata):
     """Personne en relation avec un Employe.
     """
     # Identification
@@ -462,7 +420,7 @@ COMPTE_COMPTA_CHOICES = (
     ('aucun', 'Aucun'),
 )
 
-class Dossier_(Metadata):
+class Dossier_(AUFMetadata):
     """Le Dossier regroupe les informations relatives à l'occupation
     d'un Poste par un Employe. Un seul Dossier existe par Poste occupé
     par un Employe.
@@ -565,7 +523,7 @@ class DossierCommentaire(Commentaire):
 
 ### RÉMUNÉRATION
     
-class RemunerationMixin(Metadata):
+class RemunerationMixin(AUFMetadata):
     # Identification
     dossier = models.ForeignKey('Dossier', db_column='dossier',
                         related_name='%(app_label)s_%(class)s_remunerations')
@@ -637,7 +595,7 @@ class Remuneration(Remuneration_):
 
 ### CONTRATS
         
-class Contrat(Metadata):
+class Contrat(AUFMetadata):
     """Document juridique qui encadre la relation de travail d'un Employe
     pour un Poste particulier. Pour un Dossier (qui documente cette 
     relation de travail) plusieurs contrats peuvent être associés.
@@ -666,7 +624,7 @@ class Contrat(Metadata):
 
 ### ÉVÉNEMENTS
 
-class Evenement_(Metadata):
+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).
@@ -732,7 +690,7 @@ class EvenementRemuneration(EvenementRemuneration_):
 
 ### RÉFÉRENCES RH 
 
-class FamilleEmploi(Metadata):
+class FamilleEmploi(AUFMetadata):
     """Catégorie utilisée dans la gestion des Postes.
     Catégorie supérieure à TypePoste.
     """
@@ -746,7 +704,7 @@ class FamilleEmploi(Metadata):
     def __unicode__(self):
         return u'%s' % (self.nom)
 
-class TypePoste(Metadata):
+class TypePoste(AUFMetadata):
     """Catégorie de Poste.
     """
     nom = models.CharField(max_length=255)
@@ -782,7 +740,7 @@ NATURE_REMUNERATION_CHOICES = (
     ('Traitement', 'Traitement'),
 )
 
-class TypeRemuneration(Metadata):
+class TypeRemuneration(AUFMetadata):
     """Catégorie de Remuneration.
     """
     nom = models.CharField(max_length=255)
@@ -801,7 +759,7 @@ class TypeRemuneration(Metadata):
     def __unicode__(self):
         return u'%s' % (self.nom)
         
-class TypeRevalorisation(Metadata):
+class TypeRevalorisation(AUFMetadata):
     """Justification du changement de la Remuneration.
     (Actuellement utilisé dans aucun traitement informatique.)
     """
@@ -815,7 +773,7 @@ class TypeRevalorisation(Metadata):
     def __unicode__(self):
         return u'%s' % (self.nom)
     
-class Service(Metadata):
+class Service(AUFMetadata):
     """Unité administrative où les Postes sont rattachés.
     """
     nom = models.CharField(max_length=255)
@@ -834,7 +792,7 @@ TYPE_ORGANISME_CHOICES = (
     ('DET', 'Détachement'),
 )
 
-class OrganismeBstg(Metadata):
+class OrganismeBstg(AUFMetadata):
     """Organisation d'où provient un Employe mis à disposition (MAD) de 
     ou détaché (DET) à l'AUF à titre gratuit.
     
@@ -855,7 +813,7 @@ class OrganismeBstg(Metadata):
     def __unicode__(self):
         return u'%s (%s)' % (self.nom, self.get_type_display())
 
-class Statut(Metadata):
+class Statut(AUFMetadata):
     """Statut de l'Employe dans le cadre d'un Dossier particulier.
     """
     # Identification
@@ -882,7 +840,7 @@ TYPE_CLASSEMENT_CHOICES = (
 )
 
 
-class Classement_(Metadata):
+class Classement_(AUFMetadata):
     """Éléments de classement de la 
     "Grille générique de classement hiérarchique".
     
@@ -915,7 +873,7 @@ class Classement(Classement_):
     __doc__ = Classement_.__doc__
 
 
-class TauxChange_(Metadata):
+class TauxChange_(AUFMetadata):
     """Taux de change de la devise vers l'euro (EUR) 
     pour chaque année budgétaire.
     """
@@ -939,7 +897,7 @@ class TauxChange(TauxChange_):
     __doc__ = TauxChange_.__doc__
 
 
-class ValeurPoint_(Metadata):
+class ValeurPoint_(AUFMetadata):
     """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).
@@ -983,7 +941,7 @@ class ValeurPoint(ValeurPoint_):
     __doc__ = ValeurPoint_.__doc__
 
 
-class Devise(Metadata):
+class Devise(AUFMetadata):
     """Devise monétaire.
     """
     code =  models.CharField(max_length=10, unique=True)
@@ -997,7 +955,7 @@ class Devise(Metadata):
     def __unicode__(self):
         return u'%s - %s' % (self.code, self.nom)
 
-class TypeContrat(Metadata):
+class TypeContrat(AUFMetadata):
     """Type de contrat.
     """
     nom = models.CharField(max_length=255)
@@ -1014,7 +972,7 @@ class TypeContrat(Metadata):
         
 ### AUTRES
 
-class ResponsableImplantation(Metadata):
+class ResponsableImplantation(AUFMetadata):
     """Le responsable d'une implantation. 
     Anciennement géré sur le Dossier du responsable.
     """