icones apercus
[auf_rh_dae.git] / project / rh / admin.py
index 990f9b0..76adef5 100644 (file)
 # -*- encoding: utf-8 -*-
 
-from collections import defaultdict
 import datetime
 
-from django.db import models
-from django import forms
+from ajax_select import make_ajax_form
+from auf.django.metadata.admin import \
+        AUFMetadataAdminMixin, AUFMetadataInlineAdminMixin, \
+        AUF_METADATA_READONLY_FIELDS
 from django.core.urlresolvers import reverse
 from django.contrib import admin
-from django.contrib.admin.views.main import ChangeList as DjangoChangeList
 from django.conf import settings
-from django.db.models import Q
+from django.db.models import Q, Count
 from django.template.defaultfilters import date
-from ajax_select import make_ajax_form
-from auf.django.metadata.admin import AUFMetadataAdminMixin, AUFMetadataInlineAdminMixin, AUF_METADATA_READONLY_FIELDS
-from forms import ContratForm, AyantDroitForm, EmployeAdminForm, AjaxSelect
-from dae.utils import get_employe_from_user
-from groups import grp_drh
+
+import auf.django.references.models as ref
 import models as rh
-import filters
+from forms import \
+        ContratForm, AyantDroitForm, EmployeAdminForm, AjaxSelect, DossierForm
+from dae.utils import get_employe_from_user
+from change_list import ChangeList
+from groups import grp_correspondants_rh
+from decorators import in_drh_or_admin
 
-################################################################################
-# FILTRAGE PAR DATE 
-################################################################################
-class DateRangeMixin(object):
+
+class BaseAdmin(admin.ModelAdmin):
+
+    class Media:
+        css = {'screen': ('css/admin_custom.css',)}
+
+
+class ArchiveMixin(object):
     """
-    Mixin pour que le model admin utilise le changelist trafiqué permettant de filter par range
-    non strict.
-    Par défaut, le filtrage est configuré sur aujourd'hui, soit les actifs
+    Archive Mixin pour gérer le queryset et le display
+    NON COMPRIS : list_filter, et list_display, field à setter dans la classe.
     """
-    date_borne_gauche = 'date_debut'
-    date_borne_droite = 'date_fin'
-    def get_changelist(self, request, **kwargs):
-        if request.META.has_key('HTTP_REFERER'):
-            referer = request.META['HTTP_REFERER']
-            referer = "/".join(referer.split('/')[3:])
-            referer = "/%s" % referer.split('?')[0]
-            change_list_view = 'admin:%s_%s_changelist' % (self.model._meta.app_label, self.model.__name__.lower())
-            if referer != reverse(change_list_view):
-                params = request.GET.copy()
-                today = datetime.date.today()
-                params.update({'%s__gte' % self.date_borne_gauche : str(today), '%s__lte' % self.date_borne_droite : str(today) })
-                request.GET = params
-        return ChangeList
 
-class ChangeList(DjangoChangeList):
-    PERIODE_CHOICE = ('', 'actuelle', 'passee', 'future')
+    def queryset(self, request):
+        return self.model._base_manager
 
-    def __init__(self, *args, **kwargs):
-        self.annees = {'actuelle': 'actuelle', 'passee': 'passee', 'future': 'future'}
-        super(ChangeList, self).__init__(*args, **kwargs)
-    
-    def get_query_set(self):
-        old = self.params.copy()
-        periode = None
-        annee = None
-        date_debut = None
-        date_fin = None
-        today = datetime.date.today()
-        for k, v in self.params.items():
-            if 'periode' == k:
-                periode = self.params[k]
-                del self.params[k]
-            if 'annee' == k:
-                annee = self.params[k]
-                del self.params[k]
-            if 'date_debut' == k:
-                date_debut = self.params[k]
-                del self.params[k]
-            if 'date_fin' == k:
-                date_fin = self.params[k]
-                del self.params[k]
-
-        qs = super(ChangeList, self).get_query_set()
-        if periode == 'actuelle':
-            qs = qs.filter(date_fin__exact=today, date_debut__exact=today).distinct()
-        elif periode == 'passee':
-            qs = qs.filter(date_fin__lt=today)
-        elif periode == 'future':
-            qs = qs.filter(date_debut__gt=today)
-        elif annee:
-            date_debut = datetime.date(int(annee), 01, 01)
-            date_fin = datetime.date(int(annee), 12, 31)
-
-        if date_debut and date_fin:
-            prefix_debut = 'date_debut'
-            prefix_fin = 'date_fin'
-            q_left = (Q(**{'%s__isnull' % prefix_debut : True}) | Q(**{'%s__lte' % prefix_debut : date_debut})) & (Q(**{'%s__gte' % prefix_fin : date_debut}) & Q(**{'%s__lte' % prefix_fin : date_fin}))
-            q_right = (Q(**{'%s__isnull' % prefix_fin : True}) | Q(**{'%s__gte' % prefix_fin : date_fin})) & (Q(**{'%s__gte' % prefix_debut : date_debut}) & Q(**{'%s__lte' % prefix_debut : date_fin}))
-            q_both = Q(**{'%s__isnull' % prefix_fin : True}) | Q(**{'%s__lte' % prefix_fin : date_fin}) & (Q(**{'%s__isnull' % prefix_debut : True}) | Q(**{'%s__gte' % prefix_debut : date_debut}))
-            q_non_supprime = Q(**{'%s__exact' % prefix_debut.replace('date_debut', 'supprime') : False})
-            q = (q_left | q_right | q_both) & q_non_supprime
-            qs = qs.filter(q).distinct()
+    def _archive(self, obj):
+        if obj.archive:
+            return "oui"
+        else:
+            return "non"
+    _archive.short_description = u'Archivé'
+    _archive.admin_order_field = 'archive'
+
+
+class RegionProxy(ref.Region):
+    """ Proxy utilisé pour les organigrammes par région """
+    class Meta:
+        proxy = True
+        verbose_name = u"Organigramme par région"
+        verbose_name_plural = u"Organigramme par région"
+
+
+class ImplantationProxy(ref.Implantation):
+    """ Proxy utilisé pour les organigrammes par implantation """
+    class Meta:
+        proxy = True
+        verbose_name = u"Organigramme par implantations"
+        verbose_name_plural = u"Organigramme par implantations"
+
+
+class ServiceProxy(rh.Service):
+    """ Proxy utilisé pour les organigrammes opar service """
+
+    class Meta:
+        proxy = True
+        verbose_name = u"Organigramme par services"
+        verbose_name_plural = u"Organigramme par services"
+
+
+class EmployeProxy(rh.Employe):
+    """ Proxy utilisé pour les organigrammes des employés """
+    class Meta:
+        proxy = True
+        verbose_name = u"Organigramme des employés"
+        verbose_name_plural = u"Organigramme des employés"
 
-        self.params = old
-        return qs
 
-################################################################################
+class DateRangeMixin(object):
+    prefixe_recherche_temporelle = ""
+
+    def get_changelist(self, request, **kwargs):
+        if 'HTTP_REFERER' in request.META.keys():
+                    referer = request.META['HTTP_REFERER']
+                    referer = "/".join(referer.split('/')[3:])
+                    referer = "/%s" % referer.split('?')[0]
+                    change_list_view = 'admin:%s_%s_changelist' % (
+                            self.model._meta.app_label,
+                            self.model.__name__.lower(),)
+                    if referer != reverse(change_list_view):
+                        params = request.GET.copy()
+                        params.update({'statut': 'Actif'})
+                        request.GET = params
+        return ChangeList
+
 
 # Override of the InlineModelAdmin to support the link in the tabular inline
 class LinkedInline(admin.options.InlineModelAdmin):
@@ -111,29 +111,31 @@ class LinkedInline(admin.options.InlineModelAdmin):
 class ProtectRegionMixin(object):
 
     def queryset(self, request):
-        from dae.workflow import grp_drh, grp_correspondants_rh
         qs = super(ProtectRegionMixin, self).queryset(request)
 
-        if request.user.is_superuser:
-            return qs
-
         user_groups = request.user.groups.all()
-
-        if grp_drh in user_groups:
+        if in_drh_or_admin(request.user):
             return qs
 
         if grp_correspondants_rh in user_groups:
             employe = get_employe_from_user(request.user)
-            q = Q(**{self.model.prefix_implantation: employe.implantation.region})
+            q = Q(**{self.model.prefix_implantation: \
+                    employe.implantation.region})
             qs = qs.filter(q).distinct()
             return qs
         return qs.none()
 
+    def has_add_permission(self, request):
+        if not in_drh_or_admin(request.user):
+            return False
+        else:
+            return True
+
     def has_change_permission(self, request, obj=None):
         user_groups = request.user.groups.all()
 
         # Lock pour autoriser uniquement les DRH à utiliser RH
-        if not request.user.is_superuser and not grp_drh in user_groups:
+        if not in_drh_or_admin(request.user):
             return False
 
         if len(user_groups) == 0 and not request.user.is_superuser:
@@ -148,8 +150,10 @@ class ProtectRegionMixin(object):
 # 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]
+        return [f.name for f in self.model._meta.fields \
+                if f.name not in AUF_METADATA_READONLY_FIELDS]
 
 
 class AyantDroitInline(AUFMetadataInlineAdminMixin, admin.StackedInline):
@@ -159,12 +163,18 @@ class AyantDroitInline(AUFMetadataInlineAdminMixin, admin.StackedInline):
 
     fieldsets = (
         (None, {
-            'fields': (('nom', 'prenom'), ('nom_affichage', 'genre'), 'nationalite', 'date_naissance', 'lien_parente', )
-        }),
+            'fields': (
+                ('nom', 'prenom'),
+                ('nom_affichage', 'genre'),
+                'nationalite',
+                'date_naissance',
+                'lien_parente',
+                )}),
     )
 
 
-class AyantDroitCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
+class AyantDroitCommentaireInline(AUFMetadataInlineAdminMixin, \
+        admin.TabularInline):
     readonly_fields = ('owner', )
     model = rh.AyantDroitCommentaire
     extra = 1
@@ -193,7 +203,8 @@ class DossierROInline(ReadOnlyInlineMixin, LinkedInline):
         return False
 
 
-class DossierCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
+class DossierCommentaireInline(AUFMetadataInlineAdminMixin, \
+        admin.TabularInline):
     readonly_fields = ('owner', )
     model = rh.DossierCommentaire
     extra = 1
@@ -207,7 +218,9 @@ class DossierPieceInline(admin.TabularInline):
 class EmployeInline(admin.TabularInline):
     model = rh.Employe
 
-class EmployeCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
+
+class EmployeCommentaireInline(AUFMetadataInlineAdminMixin, \
+        admin.TabularInline):
     readonly_fields = ('owner', )
     model = rh.EmployeCommentaire
     extra = 1
@@ -249,12 +262,11 @@ class PosteComparaisonInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
     model = rh.PosteComparaison
 
 
-class ClassementAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+class ClassementAdmin(AUFMetadataAdminMixin, BaseAdmin):
     list_display = ('_classement', '_date_modification', 'user_modification', )
     fieldsets = AUFMetadataAdminMixin.fieldsets + (
         (None, {
-            'fields': ('type', 'echelon', 'degre', 'coefficient',  )
-        }),
+            'fields': ('type', 'echelon', 'degre', 'coefficient',)}),
     )
 
     def _classement(self, obj):
@@ -262,16 +274,20 @@ class ClassementAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
     _classement.short_description = u"Classement"
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
-class CommentaireAdmin(admin.ModelAdmin):
-    pass
-
 
-class DeviseAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
-    list_display = ('code', 'nom', '_date_modification', 'user_modification',)
+class DeviseAdmin(AUFMetadataAdminMixin, BaseAdmin, ArchiveMixin):
+    list_display = (
+            'code',
+            'nom',
+            '_archive',
+            '_date_modification',
+            'user_modification',
+            )
     list_filter = ('archive', )
     fieldsets = AUFMetadataAdminMixin.fieldsets + (
         (None, {
@@ -280,13 +296,25 @@ class DeviseAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
     )
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
-class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
+
+class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin,
+                   ProtectRegionMixin, BaseAdmin, AjaxSelect):
     alphabet_filter = 'employe__nom'
-    search_fields = ('employe__nom', 'employe__prenom', 'poste__nom', 'poste__nom_feminin')
+    search_fields = (
+        'id',
+        'employe__id',
+        'poste__id',
+        'employe__nom',
+        'employe__prenom',
+        'poste__nom',
+        'poste__nom_feminin',
+        'poste__implantation__nom',
+    )
     list_display = (
         '_id',
         '_apercu',
@@ -297,16 +325,16 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, ad
         '_date_fin',
         '_date_modification',
         'user_modification',
+        '_dae',
     )
     list_display_links = ('_nom',)
     list_filter = (
         'poste__implantation__region',
         'poste__implantation',
-        'poste__type_poste__famille_emploi',
+        'poste__type_poste__categorie_emploi',
         'poste__type_poste',
         'rh_contrats__type_contrat',
-        'date_debut',
-        'date_fin',
+        'principal',
     )
     inlines = (DossierPieceInline, ContratInline,
                RemunerationInline,
@@ -314,23 +342,30 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, ad
               )
     fieldsets = AUFMetadataAdminMixin.fieldsets + (
         (None, {
-            'fields': ('employe', 'poste', 'statut', 'organisme_bstg',)
-        }),
+            'fields': (
+                'employe',
+                'poste',
+                'principal',
+                'statut',
+                'organisme_bstg',)}),
         ('Recrutement', {
-            'fields': ('statut_residence', 'remplacement', 'remplacement_de', )
-        }),
+            'fields': (
+                'statut_residence',
+                'remplacement',
+                'remplacement_de', )}),
         ('Rémunération', {
-            'fields': ('classement', ('regime_travail', 'regime_travail_nb_heure_semaine'),)
-        }),
+            'fields': (
+                'classement',
+                ('regime_travail', 'regime_travail_nb_heure_semaine'),)}),
         ('Occupation du Poste par cet Employe', {
-            'fields': (('date_debut', 'date_fin'), )
-        }),
+            'fields': (('date_debut', 'date_fin'), )}
+            ),
     )
-    form =  make_ajax_form(rh.Dossier, {
-        'employe' : 'employes',
-        'poste' : 'postes',
-        'remplacement_de' : 'dossiers',
-    })
+    form = make_ajax_form(rh.Dossier, {
+        'employe': 'employes',
+        'poste': 'postes',
+        'remplacement_de': 'dossiers',
+    }, superclass=DossierForm)
 
     def lookup_allowed(self, key, value):
         if key in (
@@ -338,12 +373,10 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, ad
             'poste__implantation__region__id__exact',
             'poste__implantation__id__exact',
             'poste__type_poste__id__exact',
-            'poste__type_poste__famille_emploi__id__exact',
+            'poste__type_poste__categorie_emploi__id__exact',
             'rh_contrats__type_contrat__id__exact',
-            'date_debut__gte',
-            'date_debut__isnull',
-            'date_fin__lte',
-            'date_fin__isnull',
+            'principal__exact',
+            'principal__isnull',
             ):
             return True
 
@@ -353,21 +386,42 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, ad
     _id.admin_order_field = "id"
 
     def _nom(self, obj):
-        return "%d : %s %s" % \
-                (obj.date_debut.year, obj.employe.nom.upper(), obj.employe.prenom)
+        return "%d : %s %s" % (
+                        obj.date_debut.year,
+                        obj.employe.nom.upper(),
+                        obj.employe.prenom)
     _nom.allow_tags = True
     _nom.short_description = u"Dossier"
 
-
     def _apercu(self, d):
-        apercu_link = u"""<a title="Aperçu du dossier" onclick="return showAddAnotherPopup(this);" href='%s'><img src="%simg/loupe.png" /></a>""" % \
+        apercu_link = u"""<a title="Aperçu du dossier"
+                             onclick="return showAddAnotherPopup(this);"
+                             href='%s'>
+                             <img src="%simg/dossier-apercu.png" />
+                             </a>""" % \
                 (reverse('dossier_apercu', args=(d.id,)),
                  settings.STATIC_URL,
                  )
         return apercu_link
     _apercu.allow_tags = True
     _apercu.short_description = u""
-    
+
+    def _dae(self, d):
+        apercu_link = ""
+        dossiers_dae = d.dossiers_dae.all()
+        if len(dossiers_dae) > 0:
+            dossier_dae = dossiers_dae[0]
+            apercu_link = u"""<a title="Aperçu du dossier"
+                                 onclick="return showAddAnotherPopup(this);"
+                                 href='%s'>
+                                 <img src="%simg/loupe.png" />
+                                 </a>""" % \
+                    (reverse('embauche_consulter', args=(dossier_dae.id,)),
+                     settings.STATIC_URL,
+                     )
+        return apercu_link
+    _dae.allow_tags = True
+    _dae.short_description = u"DAE"
 
     def _date_debut(self, obj):
         return date(obj.date_debut)
@@ -380,14 +434,18 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, ad
     _date_fin.short_description = u'Occupation fin'
     _date_fin.admin_order_field = 'date_fin'
 
-
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
     def _poste(self, dossier):
-        link = u"""<a title="Aperçu du poste" onclick="return showAddAnotherPopup(this);" href='%s'><img src="%simg/loupe.png" /></a> <a href="%s" title="Modifier le poste">%s</a>""" % \
+        link = u"""<a title="Aperçu du poste"
+                      onclick="return showAddAnotherPopup(this);"
+                      href='%s'><img src="%simg/poste-apercu.png" />
+                    </a>
+                    <a href="%s" title="Modifier le poste">%s</a>""" % \
                 (reverse('poste_apercu', args=(dossier.poste.id,)),
                  settings.STATIC_URL,
                  reverse('admin:rh_poste_change', args=(dossier.poste.id,)),
@@ -404,13 +462,17 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, ad
         edit_link = reverse('admin:rh_employe_change', args=(employe.id,))
 
         style = ""
-        view = u"""<a href="%s" title="Aperçu l'employé" onclick="return showAddAnotherPopup(this);"><img src="%simg/loupe.png" /></a>""" % (view_link, settings.STATIC_URL,)
+        view = u"""<a href="%s"
+                      title="Aperçu l'employé"
+                      onclick="return showAddAnotherPopup(this);">
+                      <img src="%simg/employe-apercu.png" />
+                    </a>""" % (view_link, settings.STATIC_URL,)
         return u"""%s<a href='%s' style="%s;">%s</a>""" % \
         (view, edit_link, style, employe)
     _employe.allow_tags = True
     _employe.short_description = u"Employé"
     _employe.admin_order_field = "employe__nom"
-   
+
     def save_formset(self, request, form, formset, change):
         instances = formset.save(commit=False)
         for instance in instances:
@@ -420,44 +482,67 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, ad
             instance.save()
 
 
-class DossierPieceAdmin(admin.ModelAdmin):
-    pass
-
-
-class DossierCommentaireAdmin(admin.ModelAdmin):
-    pass
-
-
-class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin,):
+class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin,
+                   ProtectRegionMixin, BaseAdmin):
+    prefixe_recherche_temporelle = "rh_dossiers__"
     alphabet_filter = 'nom'
     DEFAULT_ALPHABET = u'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-    search_fields = ('id', 'nom', 'prenom', 'nom_affichage', )
+    search_fields = (
+        'id', 'nom', 'prenom', 'nom_affichage',
+        'rh_dossiers__poste__nom',
+        'rh_dossiers__poste__nom_feminin'
+    )
     ordering = ('nom', )
     form = EmployeAdminForm
-    list_display = ('_id', '_apercu', '_nom', '_dossiers_postes', '_date_modification',  'user_modification', )
+    list_display = (
+            '_id',
+            '_apercu',
+            '_nom',
+            '_dossiers_postes',
+            'date_entree',
+            '_date_modification',
+            'user_modification',
+            )
     list_display_links = ('_nom',)
-    list_filter = ('rh_dossiers__poste__implantation__region',  'rh_dossiers__poste__implantation', 'nb_postes', 'rh_dossiers__date_debut', 'rh_dossiers__date_fin')
-    date_borne_gauche = 'rh_dossiers__date_debut'
-    date_borne_droite = 'rh_dossiers__date_fin'
+    list_filter = (
+            'rh_dossiers__poste__implantation__region',
+            'rh_dossiers__poste__implantation',
+            'nb_postes',
+            )
     inlines = (AyantDroitInline,
                DossierROInline,
                EmployePieceInline,
                EmployeCommentaireInline)
     fieldsets = AUFMetadataAdminMixin.fieldsets + (
         ('Identification', {
-            'fields': (('nom', 'prenom'), ('nom_affichage', 'genre'), 'nationalite', 'date_naissance', )
-        }),
+            'fields': (
+                ('nom', 'prenom'),
+                ('nom_affichage', 'genre'),
+                'nationalite',
+                'date_naissance',
+                )}
+            ),
         ('Informations personnelles', {
-            'fields': ('situation_famille', 'date_entree', )
-        }),
-        ('Coordonnées', {
-            'fields': (('tel_domicile', 'tel_cellulaire'), ('adresse', 'ville'), ('code_postal', 'province'), 'pays', )
-        }),
+            'fields': ('situation_famille', 'date_entree', )}
+            ),
+        ('Coordonnées personnelles', {
+            'fields': (
+                ('tel_domicile', 'tel_cellulaire'),
+                ('adresse', 'ville'),
+                ('code_postal', 'province'),
+                'pays',
+                'courriel_perso'
+                )}
+            ),
         )
 
     def _apercu(self, obj):
-        return u"""<a title="Aperçu de l'employé" onclick="return showAddAnotherPopup(this);" href='%s'><img src="%simg/loupe.png" /></a>""" % \
-                (reverse('employe_apercu', args=(obj.id,)), settings.STATIC_URL)
+        return u"""<a title="Aperçu de l'employé"
+                      onclick="return showAddAnotherPopup(this);"
+                      href='%s'>
+                      <img src="%simg/employe-apercu.png" />
+                    </a>""" % \
+            (reverse('employe_apercu', args=(obj.id,)), settings.STATIC_URL)
     _apercu.allow_tags = True
     _apercu.short_description = u""
 
@@ -475,24 +560,37 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, ad
     _id.admin_order_field = "id"
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
     def _dossiers_postes(self, obj):
         l = []
         for d in obj.rh_dossiers.all().order_by('-date_debut'):
-            dossier = u"""<a title="Aperçu du dossier" href="%s" onclick="return showAddAnotherPopup(this);" title="Aperçu du dossier"><img src="%simg/loupe.png" /></a><a href="%s">Dossier</a>&nbsp;""" % \
-                                (  reverse('dossier_apercu', args=(d.id,)),
-                                settings.STATIC_URL,
-                                reverse('admin:rh_dossier_change', args=(d.id,))
-                                )
-
-            poste = u"""<a title="Aperçu du poste" href="%s" onclick="return showAddAnotherPopup(this);" title="Aperçu du poste"><img src="%simg/loupe.png" /></a><a href="%s">Poste</a>&nbsp;""" % \
-                                 (  reverse('poste_apercu', args=(d.poste.id,)),
-                                    settings.STATIC_URL,
-                                    reverse('admin:rh_poste_change', args=(d.poste.id,))
-                                 )
+            dossier = u"""<a title="Aperçu du dossier"
+                             href="%s"
+                             onclick="return showAddAnotherPopup(this);"
+                             title="Aperçu du dossier">
+                             <img src="%simg/dossier-apercu.png" />
+                          </a>
+                          <a href="%s">Dossier</a>
+                          &nbsp;""" % \
+                (reverse('dossier_apercu', args=(d.id,)),
+                 settings.STATIC_URL,
+                 reverse('admin:rh_dossier_change', args=(d.id,)))
+
+            poste = u"""<a title="Aperçu du poste"
+                           href="%s"
+                           onclick="return showAddAnotherPopup(this);"
+                           title="Aperçu du poste">
+                           <img src="%simg/poste-apercu.png" />
+                        </a>
+                        <a href="%s">Poste</a>
+                        &nbsp;""" % \
+                (reverse('poste_apercu', args=(d.poste.id,)),
+                 settings.STATIC_URL,
+                 reverse('admin:rh_poste_change', args=(d.poste.id,)))
             link = u"""<li>%s %s - %s : [%s] %s</li>""" % \
                 (dossier, poste,
                  d.date_debut.year,
@@ -501,7 +599,7 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, ad
                  )
 
             # Dossier terminé en gris non cliquable
-            if d.date_fin is not None:
+            if d.date_fin is not None and d.date_fin < datetime.date.today():
                 link = u"""<li style="color: grey">%s : [%s] %s</li>""" % \
                     (d.date_debut.year,
                      d.poste.id,
@@ -514,7 +612,7 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, ad
     _dossiers_postes.short_description = u"Dossiers et postes"
 
     def queryset(self, request):
-        qs = super(EmployeAdmin, self).queryset(request) 
+        qs = super(EmployeAdmin, self).queryset(request)
         return qs.select_related(depth=1).order_by('nom')
 
     def save_formset(self, request, form, formset, change):
@@ -526,117 +624,172 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, ad
             instance.save()
 
 
+class EmployeProxyAdmin(EmployeAdmin):
+    list_display = ('_id', '_apercu', '_nom', '_organigramme')
+    actions = None
 
-class EmployeCommentaireAdmin(admin.ModelAdmin):
-    pass
+    def __init__(self, *args, **kwargs):
+        super(EmployeProxyAdmin, self).__init__(*args, **kwargs)
+        self.list_display_links = (None, )
 
+    def has_add_permission(self, obj):
+        return False
 
-class EmployePieceAdmin(admin.ModelAdmin):
-    pass
+    def _organigramme(self, obj):
+        l = []
+        for d in rh.Dossier.objects.filter(
+            Q(date_fin__gt=datetime.date.today()) | Q(date_fin=None),
+            Q(date_debut__lt=datetime.date.today()) | Q(date_debut=None),
+            employe=obj.id
+        ):
+            organigramme = \
+                    u'Organigramme, niveau: ' \
+                    u'<input type="text" id="level_%s" ' \
+                    u'style="width:30px;height:15px;" /> ' \
+                    u'<input type="button" value="Générer" ' \
+                    u"""onclick="window.location='%s' + """ \
+                    u"""document.getElementById('level_%s').value" />""" % (
+                        d.poste.id,
+                        reverse('rho_employe_sans_niveau', args=(d.poste.id,)),
+                        d.poste.id
+                    )
+            link = u"""<li>%s - [%s] %s : %s</li>""" % (
+                    d.date_debut.year,
+                    d.poste.id,
+                    d.poste.nom,
+                    organigramme
+            )
+            l.append(link)
+        return "<ul>%s</ul>" % "\n".join(l)
+
+    _organigramme.allow_tags = True
+    _organigramme.short_description = "Organigramme"
 
 
-class FamilleEmploiAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+class CategorieEmploiAdmin(AUFMetadataAdminMixin, BaseAdmin):
     list_display = ('nom', '_date_modification', 'user_modification', )
     inlines = (TypePosteInline,)
-    fieldsets = AUFMetadataAdminMixin.fieldsets + ( 
-        (None, {
-            'fields': ('nom', )
-        }),
-        )
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
+        (None, {'fields': ('nom', )}),)
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
-class OrganismeBstgAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+
+class OrganismeBstgAdmin(AUFMetadataAdminMixin, BaseAdmin):
     search_fields = ('nom',)
-    list_display = ('nom', 'type', 'pays', '_date_modification', 'user_modification', )
+    list_display = (
+            'nom',
+            'type',
+            'pays',
+            '_date_modification',
+            'user_modification',
+            )
     list_filter = ('type', )
     inlines = (DossierROInline,)
-    fieldsets = AUFMetadataAdminMixin.fieldsets + ( 
-        (None, {
-            'fields': ('nom', 'type', 'pays', )
-        }),
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
+        (None, {'fields': ('nom', 'type', 'pays',)}),
         )
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
 
-class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
-    form =  make_ajax_form(rh.Poste, {
-        'implantation' : 'implantations',
-        'type_poste' : 'typepostes',
-        'responsable' : 'postes',
-        'valeur_point_min' : 'valeurpoints',
-        'valeur_point_max' : 'valeurpoints',
+class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin,
+                 ProtectRegionMixin, BaseAdmin, AjaxSelect):
+    form = make_ajax_form(rh.Poste, {
+        'implantation': 'implantations',
+        'type_poste': 'typepostes',
+        'responsable': 'postes',
+        'valeur_point_min': 'valeurpoints',
+        'valeur_point_max': 'valeurpoints',
     })
     alphabet_filter = 'nom'
-    search_fields = ('nom', 
-        'implantation__code', 
-        'implantation__nom', 
-        'implantation__region__code', 
-        'implantation__region__nom',
-        'rh_dossiers__employe__nom',
-        'rh_dossiers__employe__prenom',
-        )
+    search_fields = (
+            'id',
+            'nom',
+            'implantation__nom',
+            'implantation__region__code',
+            'implantation__region__nom',
+            'rh_dossiers__employe__nom',
+            'rh_dossiers__employe__prenom',
+            )
     list_display = (
         '_id',
         '_apercu',
-        '_nom', 
+        '_nom',
         '_occupe_par',
-        'implantation', 
-        '_service', 
+        '_implantation',
+        '_service',
         '_responsable',
-        'date_debut', 
+        'date_debut',
         'date_fin',
         '_date_modification',
         'user_modification',
+        '_dae',
         )
     list_filter = (
-        'implantation__region', 
+        'implantation__region',
         'implantation',
-        'service', 
+        'service',
         'type_poste',
-        'type_poste__famille_emploi',
-        'date_debut',
-        'date_fin',
+        'type_poste__categorie_emploi',
+        'type_poste__famille_professionnelle',
         'vacant',
         )
     list_display_links = ('_nom',)
     fieldsets = AUFMetadataAdminMixin.fieldsets + (
-        (None, {
-            'fields': (('nom', 'nom_feminin'), 'implantation', 'type_poste',
-                       'service', 'responsable')
-        }),
+        (None, {'fields': (
+                ('nom', 'nom_feminin'),
+                'implantation',
+                'type_poste',
+                'service',
+                'responsable',
+                )}
+                ),
         ('Contrat', {
-            'fields': (('regime_travail', 'regime_travail_nb_heure_semaine'), )
-        }),
+            'fields': ((
+                'regime_travail',
+                'regime_travail_nb_heure_semaine'),
+                )}
+            ),
         ('Recrutement', {
-            'fields': (('local', 'expatrie', 'mise_a_disposition', 'appel'),)
-        }),
+            'fields': (('local', 'expatrie', 'mise_a_disposition', 'appel'),)}
+            ),
         ('Rémunération', {
-            'fields': (('classement_min', 'valeur_point_min', 'devise_min', 'salaire_min', 'indemn_min', 'autre_min', ),
-                       ('classement_max', 'valeur_point_max' ,'devise_max', 'salaire_max', 'indemn_max', 'autre_max', ),
-                        )
-        }),
+            'fields': (('classement_min',
+                        'valeur_point_min',
+                        'devise_min',
+                        'salaire_min',
+                        'indemn_min',
+                        'autre_min',),
+                       ('classement_max',
+                        'valeur_point_max',
+                        'devise_max',
+                        'salaire_max',
+                        'indemn_max',
+                        'autre_max',),
+                        )}),
         ('Comparatifs de rémunération', {
             'fields': ('devise_comparaison',
                        ('comp_locale_min', 'comp_locale_max'),
                        ('comp_universite_min', 'comp_universite_max'),
                        ('comp_fonctionpub_min', 'comp_fonctionpub_max'),
                        ('comp_ong_min', 'comp_ong_max'),
-                       ('comp_autre_min', 'comp_autre_max'))
-        }),
+                       ('comp_autre_min', 'comp_autre_max'))}
+            ),
         ('Justification', {
-            'fields': ('justification',)
-        }),
+            'fields': ('justification',)}
+            ),
         ('Autres Méta-données', {
-            'fields': ('date_debut', 'date_fin')
-        }),
+            'fields': ('date_debut', 'date_fin')}
+            ),
     )
 
     inlines = (PosteFinancementInline,
@@ -645,78 +798,103 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admi
                PosteComparaisonInline,
                PosteCommentaireInline, )
 
-
     def lookup_allowed(self, key, value):
-        if key in (
-            'date_debut__gte',
-            'date_debut__isnull',
-            'date_fin__lte',
-            'date_fin__isnull',
-            'implantation__region__id__exact',
-            'implantation__id__exact',
-            'type_poste__id__exact',
-            'type_poste__famille_emploi__id__exact',
-            'service__id__exact',
-            'service__isnull',
-            'vacant__exact',
-            ):
-            return True
+        return key in (
+            'date_debut__gte', 'date_debut__isnull', 'date_fin__lte',
+            'date_fin__isnull', 'implantation__region__id__exact',
+            'implantation__id__exact', 'type_poste__id__exact',
+            'type_poste__categorie_emploi__id__exact', 'service__id__exact',
+            'service__isnull', 'vacant__exact', 'vacant__isnull',
+        ) or super(PosteAdmin, self).lookup_allowed(key, value)
 
-    
     def _apercu(self, poste):
-        view_link = u"""<a onclick="return showAddAnotherPopup(this);" title="Aperçu du poste" href='%s'><img src="%simg/loupe.png" /></a>""" % \
+        view_link = u"""<a onclick="return showAddAnotherPopup(this);"
+                           title="Aperçu du poste"
+                           href='%s'>
+                        <img src="%simg/poste-apercu.png" />
+                        </a>""" % \
                 (reverse('poste_apercu', args=(poste.id,)),
-                 settings.STATIC_URL,
-                 )
-        return view_link 
+                 settings.STATIC_URL,)
+        return view_link
     _apercu.allow_tags = True
     _apercu.short_description = ''
 
+    def _dae(self, poste):
+        apercu_link = ""
+        postes_dae = poste.postes_dae.all()
+        if len(postes_dae) > 0:
+            poste_dae = postes_dae[0]
+            apercu_link = \
+                    u'<a title="Aperçu du dossier" href="%s" ' \
+                    u'onclick="return showAddAnotherPopup(this);">' \
+                    u'<img src="%simg/loupe.png" /></a>' % (reverse(
+                        'poste_consulter', args=("dae-%s" % poste_dae.id,)
+                    ), settings.STATIC_URL)
+        return apercu_link
+    _dae.allow_tags = True
+    _dae.short_description = u"DAE"
+
     def _id(self, obj):
         return "%s" % obj.id
     _id.short_description = '#'
     _id.admin_order_field = 'id'
 
     def _service(self, obj):
-        return obj.service
+        if obj.service.supprime:
+            return """<span style="color:red">%s</span>""" % obj.service
+        else:
+            return obj.service
     _service.short_description = 'Service'
+    _service.allow_tags = True
 
     def _responsable(self, obj):
         try:
-            responsable = u"""<a href="%s" onclick="return showAddAnotherPopup(this)"><img src="%simg/loupe.png" title="Aperçu du poste"></a> <a href="%s">%s</a><br />""" % \
-                    (
-                            reverse('poste_apercu', args=(obj.responsable.id,)),
-                            settings.STATIC_URL,
-                            reverse('admin:rh_poste_change', args=(obj.responsable.id,)),
-                            obj.responsable.nom
-                    )
+            responsable = u"""<a href="%s"
+                                 onclick="return showAddAnotherPopup(this)">
+                                <img src="%simg/poste-apercu.png"
+                                     title="Aperçu du poste" />
+                              </a>
+                              <a href="%s">%s</a>
+                              <br />""" % \
+                (reverse('poste_apercu', args=(obj.responsable.id,)),
+                settings.STATIC_URL,
+                reverse('admin:rh_poste_change', args=(obj.responsable.id,)),
+                obj.responsable.nom)
         except:
             responsable = ''
 
         try:
-            employeposte_change = "%s %s" % (obj.responsable.rh_dossiers.all()[0].employe.nom.upper(), obj.responsable.rh_dossiers.all()[0].employe.prenom)
-            employe_id = obj.responsable.rh_dossiers.all()[0].id
-            employe = u"""<br /><a href="%s" onclick="return showAddAnotherPopup(this)"><img src="%simg/loupe.png" title="Aperçu de l'employé"></a> <a href="%s">%s</a>""" % \
-                    (
-                            reverse('employe_apercu', args=(employe_id,)),
-                            settings.STATIC_URL,
-                            reverse('admin:rh_employe_change', args=(employe_id,)),
-                            employe
-                    )
+            dossier = obj.responsable.rh_dossiers.all().order_by('-date_debut')[0]
+            employe_id = dossier.employe.id
+            employe_html = u"""<br />
+                    <a href="%s"
+                       onclick="return showAddAnotherPopup(this)">
+                       <img src="%simg/employe-apercu.png"
+                            title="Aperçu de l'employé">
+                    </a>
+                    <a href="%s">%s</a>""" % \
+                    (reverse('employe_apercu', args=(employe_id,)),
+                     settings.STATIC_URL,
+                     reverse('admin:rh_employe_change', args=(employe_id,)),
+                     dossier.employe)
         except:
-            employe = ""
+            employe_html = ""
 
-        return "%s %s" % (responsable, employe)
+        return "%s %s" % (responsable, employe_html)
     _responsable.short_description = 'Responsable'
     _responsable.allow_tags = True
 
+    def _implantation(self, poste):
+        return poste.implantation.nom
+    _implantation.short_description = 'Implantation'
+    _implantation.admin_order_field = 'implantation'
+
     def _nom(self, poste):
         return """<a href="%s">%s</a>""" % \
                 (reverse('admin:rh_poste_change', args=(poste.id,)),
-                poste.nom
-                )
+                poste.nom)
     _nom.allow_tags = True
-    _nom.short_description = u'Nom'
+    _nom.short_description = u'Poste'
     _nom.admin_order_field = 'nom'
 
     def _date_modification(self, obj):
@@ -727,23 +905,27 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admi
     def _occupe_par(self, obj):
         """Formatte la méthode Poste.occupe_par() pour l'admin"""
         output = u"Vacant"
-        if obj.date_fin is not None and obj.date_fin < datetime.date.now():
+        if obj.date_fin is not None and obj.date_fin < datetime.date.today():
             return u"s/o"
         employes = obj.occupe_par()
         if employes:
             l = []
             for e in employes:
-                link = "<a href='%s' title='Aperçu de l\'employer' onclick='return showAddAnotherPopup(this)'><img src='%simg/loupe.png' /></a> <a href='%s'>%s</a>" % \
+                link = u"""<a href='%s'
+                              title='Aperçu de l\'employé'
+                              onclick='return showAddAnotherPopup(this)'>
+                              <img src='%simg/employe-apercu.png' />
+                            </a>
+                            <a href='%s'>%s</a>""" % \
                      (reverse('employe_apercu', args=(e.id,)),
                      settings.STATIC_URL,
                      reverse('admin:rh_employe_change', args=(e.id,)),
-                     e
-                     )
+                     e)
                 l.append(link)
             output = "\n<br />".join(l)
         return output
     _occupe_par.allow_tags = True
-    _occupe_par.short_description = "Occupé par"   
+    _occupe_par.short_description = "Occupé par"
 
     def save_formset(self, request, form, formset, change):
         instances = formset.save(commit=False)
@@ -755,140 +937,243 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admi
         formset.save_m2m()
 
 
-class PosteCommentaireAdmin(admin.ModelAdmin):
-    pass
-
-
-class PosteFinancementAdmin(admin.ModelAdmin):
-    pass
+class ResponsableInline(admin.TabularInline):
+    model = rh.ResponsableImplantation
+    extra = 0
+    fk_name = "implantation"
 
 
-class PostePieceAdmin(admin.ModelAdmin):
-    fk_name = 'poste'
+class ResponsableImplantationAdmin(BaseAdmin):
+    actions = None
+    list_filter = ('region', 'statut', )
+    list_display = ('_region', '_nom', 'statut', '_responsable', )
+    readonly_fields = ('nom', )
+    fields = ('nom', )
+    inlines = (ResponsableInline, )
+    
+    def _region(self, obj):
+        return obj.region.code
+    _region.short_description = u"Région"
+    _region.admin_order_field = 'region__code'
+    
+    def _nom(self, obj):
+        return obj.nom
+    _nom.short_description = u"Implantation"
+    _nom.admin_order_field = 'nom'
+    
+    def _responsable(self, obj):
+        try:
+            employe = obj.responsable.employe
+            dossiers = employe.dossiers_encours()
+            if len(dossiers) == 0:
+                return u"<span style='color: red;'>%s %s </span>" % (
+                    employe, u"sans dossier actif")
+            else:
+                return employe
+        except Exception:
+            if obj.statut in (1, 2):  # ouverte, ouverture imminente
+                css = "style='color: red;'"
+            else:
+                css = ""
+            return u"<span %s>Pas de responsable</span>" % css
+    _responsable.allow_tags = True
+    _responsable.short_description = u"Responsable"
 
+    def has_add_permission(self, request=None):
+        return False
 
-class RemunerationAdmin(admin.ModelAdmin):
-    pass
+    def has_change_permission(self, request, obj=None):
+        return in_drh_or_admin(request.user)
 
+    def has_delete_permission(self, request, obj=None):
+        return False
 
-class ResponsableImplantationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
-    fieldsets = AUFMetadataAdminMixin.fieldsets + ( 
-        (None, {
-            'fields': ('employe', 'implantation', ),
-        }),
-        )
-    
 
-class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
-    list_display = ('nom', '_date_modification', 'user_modification', )
-    fieldsets = AUFMetadataAdminMixin.fieldsets + ( 
+class ServiceAdmin(AUFMetadataAdminMixin, BaseAdmin, ArchiveMixin):
+    list_display = (
+            'nom',
+            '_archive',
+            '_date_modification',
+            'user_modification',
+            )
+    list_filter = ('archive', )
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
         (None, {
-            'fields': ('nom', ),
+            'fields': ('nom', 'archive', ),
         }),
         )
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
 
-class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+class ServiceProxyAdmin(ServiceAdmin):
+    list_display = ('nom', '_organigramme', '_archive', )
+    actions = None
+
+    def __init__(self, *args, **kwargs):
+        super(ServiceProxyAdmin, self).__init__(*args, **kwargs)
+        self.list_display_links = (None, )
+
+    def queryset(self, request):
+        return super(ServiceProxyAdmin, self).queryset(request) \
+                .annotate(num_postes=Count('rh_postes')) \
+                .filter(num_postes__gt=0)
+
+    def has_add_permission(self, obj):
+        return False
+
+    def has_change_permission(self, request, obj=None):
+        return in_drh_or_admin(request.user)
+
+    def _organigramme(self, obj):
+        return """<a href="%s"><strong>Organigramme</strong></a>""" % \
+                (reverse('rho_service', args=(obj.id,)))
+    _organigramme.allow_tags = True
+    _organigramme.short_description = "Organigramme"
+
+
+class StatutAdmin(AUFMetadataAdminMixin, BaseAdmin):
     list_display = ('code', 'nom', '_date_modification', 'user_modification', )
-    fieldsets = AUFMetadataAdminMixin.fieldsets + ( 
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
         (None, {
             'fields': ('code', 'nom', ),
         }),
         )
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
-class TauxChangeAdmin(admin.ModelAdmin):
-    list_display = ('taux', 'devise', 'annee', '_date_modification', 'user_modification', )
+
+class TauxChangeAdmin(BaseAdmin):
+    list_display = (
+            'taux',
+            'devise',
+            'annee',
+            '_date_modification',
+            'user_modification',
+            )
     list_filter = ('devise', )
-    fieldsets = AUFMetadataAdminMixin.fieldsets + ( 
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
         (None, {
             'fields': ('taux', 'devise', 'annee', ),
         }),
         )
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
-class TypeContratAdmin(admin.ModelAdmin):
-    list_display = ('nom', 'nom_long', '_date_modification', 'user_modification', )
-    fieldsets = AUFMetadataAdminMixin.fieldsets + ( 
+
+class TypeContratAdmin(BaseAdmin):
+    list_display = (
+            'nom',
+            'nom_long',
+            '_date_modification',
+            'user_modification',
+            )
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
         (None, {
             'fields': ('nom', 'nom_long', ),
         }),
         )
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
 
-class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+class TypePosteAdmin(AUFMetadataAdminMixin, BaseAdmin):
     search_fields = ('nom', 'nom_feminin', )
-    list_display = ('nom', 'famille_emploi', '_date_modification', 'user_modification', )
-    list_filter = ('famille_emploi', )
-    fieldsets = AUFMetadataAdminMixin.fieldsets + ( 
+    list_display = (
+            'nom',
+            'categorie_emploi',
+            '_date_modification',
+            'user_modification',
+            )
+    list_filter = ('categorie_emploi', 'famille_professionnelle')
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
         (None, {
-            'fields': ('nom', 'nom_feminin', 'is_responsable', 'famille_emploi',  )
-        }),
+            'fields': (
+                'nom',
+                'nom_feminin',
+                'is_responsable',
+                'categorie_emploi',
+                'famille_professionnelle',
+                )}
+            ),
         )
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
 
-class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
-    list_display = ('nom', 'type_paiement', 'nature_remuneration', '_date_modification', 'user_modification', )
-    fieldsets = AUFMetadataAdminMixin.fieldsets + ( 
-        (None, {
-            'fields': ('nom', 'type_paiement', 'nature_remuneration', )
-        }),
+class TypeRemunerationAdmin(AUFMetadataAdminMixin, BaseAdmin,
+                            ArchiveMixin):
+    list_display = (
+            'nom',
+            'type_paiement',
+            'nature_remuneration',
+            '_archive',
+            '_date_modification',
+            'user_modification',)
+    list_filter = ('archive', )
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
+        (None, {'fields': ('nom', 'type_paiement', 'nature_remuneration',
+        'archive')}),
         )
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
 
-class TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+class TypeRevalorisationAdmin(AUFMetadataAdminMixin, BaseAdmin):
     list_display = ('nom', '_date_modification', 'user_modification', )
-    fieldsets = AUFMetadataAdminMixin.fieldsets + ( 
-        (None, {
-            'fields': ('nom', )
-        }),
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
+        (None, {'fields': ('nom', )}),
         )
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
 
-class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
-    list_display = ('_devise_code', '_devise_nom', 'annee', 'valeur',  '_date_modification', 'user_modification', )
-    list_filter = ('annee', 'devise', )
-    fieldsets = AUFMetadataAdminMixin.fieldsets + ( 
-        (None, {
-            'fields': ('valeur', 'devise', 'implantation', 'annee', )
-        }),
+class ValeurPointAdmin(AUFMetadataAdminMixin, BaseAdmin):
+    list_display = (
+            '_devise_code',
+            '_devise_nom',
+            'annee',
+            'implantation',
+            'valeur',
+            '_date_modification',
+            'user_modification',
+            )
+    list_filter = ('annee', 'devise', 'implantation__region', )
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
+        (None, {'fields': ('valeur', 'devise', 'implantation', 'annee', )}),
         )
 
     def _date_modification(self, obj):
-        return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
+        return date(obj.date_modification) \
+                if obj.date_modification is not None else "(aucune)"
     _date_modification.short_description = u'date modification'
     _date_modification.admin_order_field = 'date_modification'
 
@@ -901,14 +1186,63 @@ class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
     _devise_nom.short_description = "Nom de la devise"
 
 
+class ImplantationProxyAdmin(BaseAdmin):
+    list_display = ('nom', '_organigramme')
+    actions = None
+
+    def __init__(self, *args, **kwargs):
+        super(ImplantationProxyAdmin, self).__init__(*args, **kwargs)
+        self.list_display_links = (None, )
+
+    def has_add_permission(self, obj):
+        return False
+
+    def has_change_permission(self, request, obj=None):
+        return in_drh_or_admin(request.user)
+
+    def _organigramme(self, obj):
+        return '<a href="%s"><strong>Organigramme</strong></a>' % (
+            reverse('rho_implantation', args=(obj.id,))
+        )
+    _organigramme.allow_tags = True
+    _organigramme.short_description = "Organigramme"
+
+
+class RegionProxyAdmin(BaseAdmin):
+    list_display = ('nom', '_organigramme')
+    actions = None
+
+    def __init__(self, *args, **kwargs):
+        super(RegionProxyAdmin, self).__init__(*args, **kwargs)
+        self.list_display_links = (None, )
+
+    def has_add_permission(self, obj):
+        return False
+
+    def has_change_permission(self, request, obj=None):
+        return in_drh_or_admin(request.user)
+
+    def _organigramme(self, obj):
+        return """<a href="%s"><strong>Organigramme</strong></a>""" % (
+            reverse('rho_region', args=(obj.id,))
+        )
+    _organigramme.allow_tags = True
+    _organigramme.short_description = "Organigramme"
+
+
 admin.site.register(rh.Classement, ClassementAdmin)
 admin.site.register(rh.Devise, DeviseAdmin)
 admin.site.register(rh.Dossier, DossierAdmin)
+admin.site.register(EmployeProxy, EmployeProxyAdmin)
+admin.site.register(ServiceProxy, ServiceProxyAdmin)
 admin.site.register(rh.Employe, EmployeAdmin)
-admin.site.register(rh.FamilleEmploi, FamilleEmploiAdmin)
+admin.site.register(rh.CategorieEmploi, CategorieEmploiAdmin)
+admin.site.register(rh.FamilleProfessionnelle)
 admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin)
 admin.site.register(rh.Poste, PosteAdmin)
-admin.site.register(rh.ResponsableImplantation, ResponsableImplantationAdmin)
+admin.site.register(
+    rh.ResponsableImplantationProxy, ResponsableImplantationAdmin
+)
 admin.site.register(rh.Service, ServiceAdmin)
 admin.site.register(rh.Statut, StatutAdmin)
 admin.site.register(rh.TauxChange, TauxChangeAdmin)
@@ -917,3 +1251,5 @@ admin.site.register(rh.TypePoste, TypePosteAdmin)
 admin.site.register(rh.TypeRemuneration, TypeRemunerationAdmin)
 admin.site.register(rh.TypeRevalorisation, TypeRevalorisationAdmin)
 admin.site.register(rh.ValeurPoint, ValeurPointAdmin)
+admin.site.register(ImplantationProxy, ImplantationProxyAdmin)
+admin.site.register(RegionProxy, RegionProxyAdmin)