icones apercus
[auf_rh_dae.git] / project / rh / admin.py
index 336e05a..76adef5 100644 (file)
@@ -2,24 +2,69 @@
 
 import datetime
 
+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.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
+
+import auf.django.references.models as ref
+import models as rh
+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_drh
-import models as rh
+from groups import grp_correspondants_rh
+from decorators import in_drh_or_admin
+
+
+class BaseAdmin(admin.ModelAdmin):
+
+    class Media:
+        css = {'screen': ('css/admin_custom.css',)}
+
+
+class ArchiveMixin(object):
+    """
+    Archive Mixin pour gérer le queryset et le display
+    NON COMPRIS : list_filter, et list_display, field à setter dans la classe.
+    """
+
+    def queryset(self, request):
+        return self.model._base_manager
+
+    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"
@@ -66,15 +111,10 @@ 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:
@@ -85,11 +125,17 @@ class ProtectRegionMixin(object):
             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:
@@ -216,7 +262,7 @@ 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, {
@@ -234,11 +280,7 @@ class ClassementAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
     _date_modification.admin_order_field = 'date_modification'
 
 
-class CommentaireAdmin(admin.ModelAdmin):
-    pass
-
-
-class DeviseAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+class DeviseAdmin(AUFMetadataAdminMixin, BaseAdmin, ArchiveMixin):
     list_display = (
             'code',
             'nom',
@@ -253,16 +295,6 @@ class DeviseAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
         }),
     )
 
-    def queryset(self, request):
-        return self.model._base_manager
-
-    def _archive(self, obj):
-        if obj.archive:
-            return "oui"
-        else:
-            return "non"
-    _archive.short_description = u'Archivé'
-
     def _date_modification(self, obj):
         return date(obj.date_modification) \
                 if obj.date_modification is not None else "(aucune)"
@@ -270,14 +302,19 @@ class DeviseAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
     _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')
+        'id',
+        'employe__id',
+        'poste__id',
+        'employe__nom',
+        'employe__prenom',
+        'poste__nom',
+        'poste__nom_feminin',
+        'poste__implantation__nom',
+    )
     list_display = (
         '_id',
         '_apercu',
@@ -288,14 +325,16 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
         '_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',
+        'principal',
     )
     inlines = (DossierPieceInline, ContratInline,
                RemunerationInline,
@@ -306,6 +345,7 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
             'fields': (
                 'employe',
                 'poste',
+                'principal',
                 'statut',
                 'organisme_bstg',)}),
         ('Recrutement', {
@@ -325,7 +365,7 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
         'employe': 'employes',
         'poste': 'postes',
         'remplacement_de': 'dossiers',
-    })
+    }, superclass=DossierForm)
 
     def lookup_allowed(self, key, value):
         if key in (
@@ -333,8 +373,10 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
             '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',
+            'principal__exact',
+            'principal__isnull',
             ):
             return True
 
@@ -355,7 +397,7 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
         apercu_link = u"""<a title="Aperçu du dossier"
                              onclick="return showAddAnotherPopup(this);"
                              href='%s'>
-                             <img src="%simg/loupe.png" />
+                             <img src="%simg/dossier-apercu.png" />
                              </a>""" % \
                 (reverse('dossier_apercu', args=(d.id,)),
                  settings.STATIC_URL,
@@ -364,6 +406,23 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
     _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)
 
@@ -384,7 +443,7 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
     def _poste(self, dossier):
         link = u"""<a title="Aperçu du poste"
                       onclick="return showAddAnotherPopup(this);"
-                      href='%s'><img src="%simg/loupe.png" />
+                      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,)),
@@ -406,7 +465,7 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
         view = u"""<a href="%s"
                       title="Aperçu l'employé"
                       onclick="return showAddAnotherPopup(this);">
-                      <img src="%simg/loupe.png" />
+                      <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)
@@ -423,20 +482,16 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
             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 = (
@@ -444,6 +499,7 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
             '_apercu',
             '_nom',
             '_dossiers_postes',
+            'date_entree',
             '_date_modification',
             'user_modification',
             )
@@ -469,12 +525,13 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
         ('Informations personnelles', {
             'fields': ('situation_famille', 'date_entree', )}
             ),
-        ('Coordonnées', {
+        ('Coordonnées personnelles', {
             'fields': (
                 ('tel_domicile', 'tel_cellulaire'),
                 ('adresse', 'ville'),
                 ('code_postal', 'province'),
                 'pays',
+                'courriel_perso'
                 )}
             ),
         )
@@ -483,7 +540,7 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
         return u"""<a title="Aperçu de l'employé"
                       onclick="return showAddAnotherPopup(this);"
                       href='%s'>
-                      <img src="%simg/loupe.png" />
+                      <img src="%simg/employe-apercu.png" />
                     </a>""" % \
             (reverse('employe_apercu', args=(obj.id,)), settings.STATIC_URL)
     _apercu.allow_tags = True
@@ -515,7 +572,7 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
                              href="%s"
                              onclick="return showAddAnotherPopup(this);"
                              title="Aperçu du dossier">
-                             <img src="%simg/loupe.png" />
+                             <img src="%simg/dossier-apercu.png" />
                           </a>
                           <a href="%s">Dossier</a>
                           &nbsp;""" % \
@@ -527,7 +584,7 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
                            href="%s"
                            onclick="return showAddAnotherPopup(this);"
                            title="Aperçu du poste">
-                           <img src="%simg/loupe.png" />
+                           <img src="%simg/poste-apercu.png" />
                         </a>
                         <a href="%s">Poste</a>
                         &nbsp;""" % \
@@ -569,33 +626,39 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
 
 class EmployeProxyAdmin(EmployeAdmin):
     list_display = ('_id', '_apercu', '_nom', '_organigramme')
-    list_display_links = ('_nom',)
+    actions = None
+
+    def __init__(self, *args, **kwargs):
+        super(EmployeProxyAdmin, self).__init__(*args, **kwargs)
+        self.list_display_links = (None, )
 
     def has_add_permission(self, obj):
         return False
 
     def _organigramme(self, obj):
         l = []
-        for d in obj.rh_dossiers.all().order_by('-date_debut'):
-            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,)))
-            organigramme = u"""<a href="%s">Organigramme</a>""" % \
-                    (reverse('rho_employe', args=(d.poste.id,)))
-            link = u"""<li>%s - %s - %s : [%s] %s</li>""" % \
-                (poste, organigramme,
-                 d.date_debut.year,
-                 d.poste.id,
-                 d.poste.nom,
-                 )
+        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)
 
@@ -603,15 +666,7 @@ class EmployeProxyAdmin(EmployeAdmin):
     _organigramme.short_description = "Organigramme"
 
 
-class EmployeCommentaireAdmin(admin.ModelAdmin):
-    pass
-
-
-class EmployePieceAdmin(admin.ModelAdmin):
-    pass
-
-
-class FamilleEmploiAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+class CategorieEmploiAdmin(AUFMetadataAdminMixin, BaseAdmin):
     list_display = ('nom', '_date_modification', 'user_modification', )
     inlines = (TypePosteInline,)
     fieldsets = AUFMetadataAdminMixin.fieldsets + (
@@ -624,7 +679,7 @@ class FamilleEmploiAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
     _date_modification.admin_order_field = 'date_modification'
 
 
-class OrganismeBstgAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+class OrganismeBstgAdmin(AUFMetadataAdminMixin, BaseAdmin):
     search_fields = ('nom',)
     list_display = (
             'nom',
@@ -646,8 +701,8 @@ class OrganismeBstgAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
     _date_modification.admin_order_field = 'date_modification'
 
 
-class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
-        ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
+class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin,
+                 ProtectRegionMixin, BaseAdmin, AjaxSelect):
     form = make_ajax_form(rh.Poste, {
         'implantation': 'implantations',
         'type_poste': 'typepostes',
@@ -670,20 +725,22 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
         '_apercu',
         '_nom',
         '_occupe_par',
-        'implantation',
+        '_implantation',
         '_service',
         '_responsable',
         'date_debut',
         'date_fin',
         '_date_modification',
         'user_modification',
+        '_dae',
         )
     list_filter = (
         'implantation__region',
         'implantation',
         'service',
         'type_poste',
-        'type_poste__famille_emploi',
+        'type_poste__categorie_emploi',
+        'type_poste__famille_professionnelle',
         'vacant',
         )
     list_display_links = ('_nom',)
@@ -742,27 +799,19 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
                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',
-            'vacant__isnull',
-            ):
-            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" />
+                        <img src="%simg/poste-apercu.png" />
                         </a>""" % \
                 (reverse('poste_apercu', args=(poste.id,)),
                  settings.STATIC_URL,)
@@ -770,6 +819,21 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
     _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 = '#'
@@ -787,7 +851,7 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
         try:
             responsable = u"""<a href="%s"
                                  onclick="return showAddAnotherPopup(this)">
-                                <img src="%simg/loupe.png"
+                                <img src="%simg/poste-apercu.png"
                                      title="Aperçu du poste" />
                               </a>
                               <a href="%s">%s</a>
@@ -800,31 +864,37 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
             responsable = ''
 
         try:
-            employe_id = obj.responsable.rh_dossiers.all()[0].id
-            employe = u"""<br />
+            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/loupe.png"
+                       <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,)),
-                     employe)
+                     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)
     _nom.allow_tags = True
-    _nom.short_description = u'Nom'
+    _nom.short_description = u'Poste'
     _nom.admin_order_field = 'nom'
 
     def _date_modification(self, obj):
@@ -835,16 +905,16 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
     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 = u"""<a href='%s'
-                              title='Aperçu de l\'employer'
+                              title='Aperçu de l\'employé'
                               onclick='return showAddAnotherPopup(this)'>
-                              <img src='%simg/loupe.png' />
+                              <img src='%simg/employe-apercu.png' />
                             </a>
                             <a href='%s'>%s</a>""" % \
                      (reverse('employe_apercu', args=(e.id,)),
@@ -867,31 +937,59 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
         formset.save_m2m()
 
 
-class PosteCommentaireAdmin(admin.ModelAdmin):
-    pass
-
-
-class PosteFinancementAdmin(admin.ModelAdmin):
-    pass
-
-
-class PostePieceAdmin(admin.ModelAdmin):
-    fk_name = 'poste'
-
+class ResponsableInline(admin.TabularInline):
+    model = rh.ResponsableImplantation
+    extra = 0
+    fk_name = "implantation"
+
+
+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"
 
-class RemunerationAdmin(admin.ModelAdmin):
-    pass
+    def has_add_permission(self, request=None):
+        return False
 
+    def has_change_permission(self, request, obj=None):
+        return in_drh_or_admin(request.user)
 
-class ResponsableImplantationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
-    fieldsets = AUFMetadataAdminMixin.fieldsets + (
-        (None, {
-            'fields': ('employe', 'implantation', ),
-        }),
-        )
+    def has_delete_permission(self, request, obj=None):
+        return False
 
 
-class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+class ServiceAdmin(AUFMetadataAdminMixin, BaseAdmin, ArchiveMixin):
     list_display = (
             'nom',
             '_archive',
@@ -905,13 +1003,6 @@ class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
         }),
         )
 
-    def _archive(self, obj):
-        if obj.archive:
-            return "oui"
-        else:
-            return "non"
-    _archive.short_description = u'Archivé'
-
     def _date_modification(self, obj):
         return date(obj.date_modification) \
                 if obj.date_modification is not None else "(aucune)"
@@ -920,18 +1011,32 @@ class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
 
 
 class ServiceProxyAdmin(ServiceAdmin):
-    list_display = ('nom', '_organigramme')
-    list_display_links = ('nom',)
+    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">Organigramme</a>""" % (reverse('rho_service', args=(obj.id,)))
+        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, admin.ModelAdmin):
+
+class StatutAdmin(AUFMetadataAdminMixin, BaseAdmin):
     list_display = ('code', 'nom', '_date_modification', 'user_modification', )
     fieldsets = AUFMetadataAdminMixin.fieldsets + (
         (None, {
@@ -946,7 +1051,7 @@ class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
     _date_modification.admin_order_field = 'date_modification'
 
 
-class TauxChangeAdmin(admin.ModelAdmin):
+class TauxChangeAdmin(BaseAdmin):
     list_display = (
             'taux',
             'devise',
@@ -968,7 +1073,7 @@ class TauxChangeAdmin(admin.ModelAdmin):
     _date_modification.admin_order_field = 'date_modification'
 
 
-class TypeContratAdmin(admin.ModelAdmin):
+class TypeContratAdmin(BaseAdmin):
     list_display = (
             'nom',
             'nom_long',
@@ -988,22 +1093,23 @@ class TypeContratAdmin(admin.ModelAdmin):
     _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',
+            'categorie_emploi',
             '_date_modification',
             'user_modification',
             )
-    list_filter = ('famille_emploi', )
+    list_filter = ('categorie_emploi', 'famille_professionnelle')
     fieldsets = AUFMetadataAdminMixin.fieldsets + (
         (None, {
             'fields': (
                 'nom',
                 'nom_feminin',
                 'is_responsable',
-                'famille_emploi',
+                'categorie_emploi',
+                'famille_professionnelle',
                 )}
             ),
         )
@@ -1015,15 +1121,19 @@ class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
     _date_modification.admin_order_field = 'date_modification'
 
 
-class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+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',)}),
+        (None, {'fields': ('nom', 'type_paiement', 'nature_remuneration',
+        'archive')}),
         )
 
     def _date_modification(self, obj):
@@ -1033,7 +1143,7 @@ class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
     _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', )}),
@@ -1046,16 +1156,17 @@ class TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
     _date_modification.admin_order_field = 'date_modification'
 
 
-class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+class ValeurPointAdmin(AUFMetadataAdminMixin, BaseAdmin):
     list_display = (
             '_devise_code',
             '_devise_nom',
             'annee',
+            'implantation',
             'valeur',
             '_date_modification',
             'user_modification',
             )
-    list_filter = ('annee', 'devise', )
+    list_filter = ('annee', 'devise', 'implantation__region', )
     fieldsets = AUFMetadataAdminMixin.fieldsets + (
         (None, {'fields': ('valeur', 'devise', 'implantation', 'annee', )}),
         )
@@ -1075,16 +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)
@@ -1093,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)