Création à la volée des évaluations à chaque fois qu'on affiche la liste
[auf_rh_dae.git] / project / recrutement / admin.py
index dfcaf2e..c2b14aa 100644 (file)
@@ -2,6 +2,8 @@
 
 import textwrap
 
+from auf.django.emploi.models import CandidatPiece, Candidat, OffreEmploi
+from auf.django.references.models import Region, Bureau, Implantation
 from django.conf import settings
 from django.contrib import admin
 from django.core.urlresolvers import reverse
@@ -9,31 +11,23 @@ from django.db.models import Avg
 from django.shortcuts import render_to_response
 from django.template import RequestContext
 
+from auf.django.export.admin import ExportAdmin
 from auf.django.emploi.models import STATUT_CHOICES
 from django.forms.models import BaseInlineFormSet
 from django.http import HttpResponseRedirect
 from django.shortcuts import redirect
 from reversion.admin import VersionAdmin
 
-from auf.django.emploi.models import OffreEmploi, Candidat, CandidatPiece
-from auf.django.references.models import Region, Bureau, Implantation
-from auf.django.export.admin import ExportAdmin
+from project import groups
+from project.permissions import get_user_groupnames
 
-from project.groups import get_employe_from_user as get_emp
 from project.rh import models as rh
-
 from project.recrutement.forms import OffreEmploiForm
-from project.recrutement.groups import \
-        grp_drh, grp_drh2, \
-        grp_directeurs_bureau, \
-        grp_administrateurs, \
-        grp_correspondants_rh, \
-        grp_haute_direction
 from project.recrutement.models import \
         Evaluateur, CandidatEvaluation, \
         ProxyOffreEmploi, ProxyCandidat, MesCandidatEvaluation, \
-        CourrielTemplate
-        
+        CourrielTemplate, OffreEmploiEvaluateur
+
 
 ### CONSTANTES
 IMPLANTATIONS_CENTRALES = [15, 19]
@@ -62,7 +56,7 @@ class OrderedChangeList(admin.views.main.ChangeList):
         return qs
 
 
-class OffreEmploiAdmin(BaseAdmin, VersionAdmin):
+class OffreEmploiAdminMixin(BaseAdmin):
     date_hierarchy = 'date_creation'
     list_display = (
         'nom', 'date_limite', 'region',  'statut', 'est_affiche',
@@ -82,18 +76,18 @@ class OffreEmploiAdmin(BaseAdmin, VersionAdmin):
                 'description',
                 'poste',
                 'region',
+                'lieu_affectation',
                 'bureau',
                 'debut_affectation',
                 'duree_affectation',
                 'renumeration',
-                'lieu_affectation',
             )
         }),
     )
 
     ### Actions à afficher
     def get_actions(self, request):
-        actions = super(OffreEmploiAdmin, self).get_actions(request)
+        actions = super(OffreEmploiAdminMixin, self).get_actions(request)
         del actions['delete_selected']
         return actions
 
@@ -112,58 +106,61 @@ class OffreEmploiAdmin(BaseAdmin, VersionAdmin):
     ### Afficher la liste des candidats pour l'offre d'emploi
     def _candidatsList(self, obj):
         return "<a href='%s?offre_emploi__id__exact=%s'>Voir les candidats \
-            </a>" % (reverse('admin:emploi_candidat_changelist'), obj.id)
+            </a>" % (reverse('admin:recrutement_proxycandidat_changelist'), obj.id)
     _candidatsList.allow_tags = True
     _candidatsList.short_description = "Afficher la liste des candidats"
 
     ### Formulaire
     def get_form(self, request, obj=None, **kwargs):
-        form = super(OffreEmploiAdmin, self).get_form(request, obj, **kwargs)
-        employe = get_emp(request.user)
-        user_groupes = request.user.groups.all()
+        form = super(OffreEmploiAdminMixin, self).get_form(request, obj, **kwargs)
+        employe = groups.get_employe_from_user(request.user)
+        user_groupes = get_user_groupnames(request.user)
 
         # Region
-        if 'region' in form.declared_fields:
+        region_field = None
+        if 'region' in form.declared_fields.keys():
             region_field = form.declared_fields['region']
-        else:
+        if 'region' in form.base_fields.keys():
             region_field = form.base_fields['region']
-
-        if grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_haute_direction in user_groupes:
-            region_field.queryset = Region.objects.all()
-        else:
-            region_field.queryset = Region.objects.\
+        if region_field:
+            if groups.DRH_NIVEAU_1 in user_groupes or \
+               groups.DRH_NIVEAU_2 in user_groupes or \
+               groups.HAUTE_DIRECTION in user_groupes:
+                region_field.queryset = Region.objects.all()
+            else:
+                region_field.queryset = Region.objects.\
                                     filter(id=employe.implantation.region.id)
 
         # Poste
-        if 'poste' in form.declared_fields:
+        poste_field = None
+        if 'poste' in form.declared_fields.keys():
             poste_field = form.declared_fields['poste']
-        else:
+        if 'poste' in form.base_fields.keys():
             poste_field = form.base_fields['poste']
-
-        if grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_haute_direction in user_groupes:
-            poste_field.queryset = rh.Poste.objects.all()
-        else:
-            poste_field.queryset = rh.Poste.objects.\
-                    filter(implantation__region=employe.implantation.region).\
-                    exclude(implantation__in=IMPLANTATIONS_CENTRALES)
+        if poste_field:
+            if groups.DRH_NIVEAU_1 in user_groupes or \
+               groups.DRH_NIVEAU_2 in user_groupes or \
+               groups.HAUTE_DIRECTION in user_groupes:
+                poste_field.queryset = rh.Poste.objects.all()
+            else:
+                poste_field.queryset = rh.Poste.objects.\
+                        filter(implantation__region=employe.implantation.region).\
+                        exclude(implantation__in=IMPLANTATIONS_CENTRALES)
 
         # Bureau
-        if 'bureau' in form.declared_fields:
+        bureau_field = None
+        if 'bureau' in form.declared_fields.keys():
             bureau_field = form.declared_fields['bureau']
-        else:
+        if 'bureau' in form.base_fields.keys():
             bureau_field = form.base_fields['bureau']
-
-        if grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_haute_direction in user_groupes:
-            bureau_field.queryset = Bureau.objects.all()
-        else:
-            bureau_field.queryset = \
-                    Bureau.objects.filter(region=employe.implantation.region)
+        if bureau_field:
+            if groups.DRH_NIVEAU_1 in user_groupes or \
+                groups.DRH_NIVEAU_2 in user_groupes or \
+                groups.HAUTE_DIRECTION in user_groupes:
+                bureau_field.queryset = Bureau.objects.all()
+            else:
+                bureau_field.queryset = \
+                        Bureau.objects.filter(region=employe.implantation.region)
 
         return form
 
@@ -172,16 +169,16 @@ class OffreEmploiAdmin(BaseAdmin, VersionAdmin):
     def queryset(self, request):
         qs = self.model._default_manager.get_query_set() \
                 .select_related('offre_emploi')
-        user_groupes = request.user.groups.all()
-        if grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_haute_direction in user_groupes:
+        user_groupes = get_user_groupnames(request.user)
+        if groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
             return qs
 
-        if grp_directeurs_bureau in user_groupes or \
-            grp_correspondants_rh in user_groupes or \
-            grp_administrateurs in user_groupes:
-            employe = get_emp(request.user)
+        if groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.CORRESPONDANT_RH in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes:
+            employe = groups.get_employe_from_user(request.user)
             return qs.filter(region=employe.implantation.region)
 
         if  Evaluateur.objects.filter(user=request.user).exists():
@@ -198,47 +195,72 @@ class OffreEmploiAdmin(BaseAdmin, VersionAdmin):
 
     ### Permission add, delete, change
     def has_add_permission(self, request):
-        user_groupes = request.user.groups.all()
+        user_groupes = get_user_groupnames(request.user)
         if request.user.is_superuser is True or \
-            grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_directeurs_bureau in user_groupes or \
-            grp_administrateurs in user_groupes or \
-            grp_haute_direction in user_groupes:
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
             return True
         return False
 
     def has_delete_permission(self, request, obj=None):
-        user_groupes = request.user.groups.all()
+        user_groupes = get_user_groupnames(request.user)
         if request.user.is_superuser is True or \
-            grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_directeurs_bureau in user_groupes or \
-            grp_administrateurs in user_groupes or \
-            grp_haute_direction in user_groupes:
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
             return True
+
+        if obj is not None:
+            employe = groups.get_employe_from_user(request.user)
+            if (groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+                groups.ADMINISTRATEURS in user_groupes) and ( 
+                employe.implantation.region == obj.lieu_affectation.region):
+                return True
+
         return False
 
     def has_change_permission(self, request, obj=None):
-        user_groupes = request.user.groups.all()
+        user_groupes = get_user_groupnames(request.user)
         if request.user.is_superuser is True or \
-            grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_directeurs_bureau in user_groupes or \
-            grp_administrateurs in user_groupes or \
-            grp_haute_direction in user_groupes:
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
             return True
+
+        if obj is not None:
+            employe = groups.get_employe_from_user(request.user)
+            if (groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+                groups.ADMINISTRATEURS in user_groupes) and ( 
+                employe.implantation.region == obj.lieu_affectation.region):
+                return True
+        else:
+            if  groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+                    groups.ADMINISTRATEURS in user_groupes:
+                return True
+
+
         return False
 
     def formfield_for_foreignkey(self, db_field, request, **kwargs):
         if db_field.name == 'lieu_affectation':
-            employe = get_emp(request.user)
-            kwargs["queryset"] = Implantation.objects.filter(region=employe.implantation.region)
+            user_groupes = [g.name for g in request.user.groups.all()]
+            if not (request.user.is_superuser is True or \
+                groups.DRH_NIVEAU_1 in user_groupes or \
+                groups.DRH_NIVEAU_2 in user_groupes):
+                employe = groups.get_employe_from_user(request.user)
+                kwargs["queryset"] = Implantation.objects.filter(region=employe.implantation.region)
             return db_field.formfield(**kwargs)
-        return super(OffreEmploiAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
+        return super(OffreEmploiAdminMixin, self).formfield_for_foreignkey(db_field, request, **kwargs)
+
 
+class OffreEmploiAdmin(VersionAdmin, OffreEmploiAdminMixin):
+    pass
 
-class ProxyOffreEmploiAdmin(OffreEmploiAdmin):
+
+class ProxyOffreEmploiAdmin(OffreEmploiAdminMixin):
     list_display = (
         'nom', 'date_limite', 'region', 'statut', 'est_affiche'
     )
@@ -269,11 +291,6 @@ class ProxyOffreEmploiAdmin(OffreEmploiAdmin):
     def response_change(self, request, obj):
         return redirect('admin:recrutement_proxyoffreemploi_changelist')
 
-    ### Formulaire
-    def get_form(self, request, obj=None, **kwargs):
-        form = super(OffreEmploiAdmin, self).get_form(request, obj, **kwargs)
-        return form
-
     ### Permissions add, delete, change
     def has_add_permission(self, request):
         return False
@@ -325,8 +342,8 @@ class CandidatEvaluationInline(admin.TabularInline):
             return self.readonly_fields + ('evaluateur', 'note', 'commentaire')
         return self.readonly_fields
 
-class CandidatAdmin(BaseAdmin, VersionAdmin, ExportAdmin):
-    change_list_template = 'admin/recrutement/candidat/change_list.html'
+
+class CandidatAdminMixin(BaseAdmin, ExportAdmin):
     search_fields = ('nom', 'prenom')
     exclude = ('actif', )
     list_editable = ('statut', )
@@ -388,7 +405,7 @@ class CandidatAdmin(BaseAdmin, VersionAdmin, ExportAdmin):
 
     ### Actions à afficher
     def get_actions(self, request):
-        actions = super(CandidatAdmin, self).get_actions(request)
+        actions = super(CandidatAdminMixin, self).get_actions(request)
         del actions['delete_selected']
         return actions
 
@@ -483,47 +500,55 @@ class CandidatAdmin(BaseAdmin, VersionAdmin, ExportAdmin):
 
     ### Permissions add, delete, change
     def has_add_permission(self, request):
-        user_groupes = request.user.groups.all()
+        user_groupes = get_user_groupnames(request.user)
         if request.user.is_superuser is True or \
-            grp_correspondants_rh in user_groupes or \
-            grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_directeurs_bureau in user_groupes or \
-            grp_administrateurs in user_groupes or \
-            grp_haute_direction in user_groupes:
+            groups.CORRESPONDANT_RH in user_groupes or \
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
             return True
         return False
 
     def has_delete_permission(self, request, obj=None):
-        user_groupes = request.user.groups.all()
+        user_groupes = get_user_groupnames(request.user)
         if request.user.is_superuser is True or \
-            grp_correspondants_rh in user_groupes or \
-            grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_directeurs_bureau in user_groupes or \
-            grp_administrateurs in user_groupes or \
-            grp_haute_direction in user_groupes:
+            groups.CORRESPONDANT_RH in user_groupes or \
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
             return True
         return False
 
     def has_change_permission(self, request, obj=None):
-        user_groupes = request.user.groups.all()
+        user_groupes = get_user_groupnames(request.user)
         if request.user.is_superuser is True or \
-            grp_correspondants_rh in user_groupes or \
-            grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_directeurs_bureau in user_groupes or \
-            grp_administrateurs in user_groupes or \
-            grp_haute_direction in user_groupes:
+            groups.CORRESPONDANT_RH in user_groupes or \
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
             return True
         return False
 
     def formfield_for_foreignkey(self, db_field, request, **kwargs):
         if db_field.name == 'offre_emploi':
-            employe = get_emp(request.user)
-            kwargs["queryset"] = OffreEmploi.objects.filter(region=employe.implantation.region)
+            employe = groups.get_employe_from_user(request.user)
+            user_groupes = [g.name for g in request.user.groups.all()]
+            if request.user.is_superuser is True or \
+                groups.CORRESPONDANT_RH in user_groupes or \
+                groups.DRH_NIVEAU_1 in user_groupes or \
+                groups.DRH_NIVEAU_2 in user_groupes:
+                qs_offres = OffreEmploi.objects.all()
+            else:
+                qs_offres =OffreEmploi.objects.filter(region=employe.implantation.region)
+            kwargs["queryset"] = qs_offres
             return db_field.formfield(**kwargs)
-        return super(CandidatAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
+        return super(CandidatAdminMixin, self).formfield_for_foreignkey(db_field, request, **kwargs)
 
     def get_changelist(self, request, **kwargs):
         return OrderedChangeList
@@ -540,16 +565,16 @@ class CandidatAdmin(BaseAdmin, VersionAdmin, ExportAdmin):
                 .select_related('offre_emploi') \
                 .annotate(moyenne=Avg('evaluations__note'))
 
-        user_groupes = request.user.groups.all()
-        if grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_haute_direction in user_groupes:
+        user_groupes = get_user_groupnames(request.user)
+        if groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
             return qs
 
-        if grp_directeurs_bureau in user_groupes or \
-            grp_correspondants_rh in user_groupes or \
-            grp_administrateurs in user_groupes:
-            employe = get_emp(request.user)
+        if groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.CORRESPONDANT_RH in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes:
+            employe = groups.get_employe_from_user(request.user)
             return qs.filter(offre_emploi__region=employe.implantation.region)
 
         if  Evaluateur.objects.filter(user=request.user).exists():
@@ -560,7 +585,13 @@ class CandidatAdmin(BaseAdmin, VersionAdmin, ExportAdmin):
         return qs.none()
 
 
-class ProxyCandidatAdmin(CandidatAdmin):
+class CandidatAdmin(VersionAdmin, CandidatAdminMixin):
+    change_list_template = 'admin/recrutement/candidat/change_list.html'
+    pass
+
+
+class ProxyCandidatAdmin(CandidatAdminMixin):
+    change_list_template = 'admin/recrutement/candidat/change_list.html'
     list_editable = ()
     readonly_fields = (
         'statut', 'offre_emploi', 'prenom', 'nom', 'genre', 'nationalite',
@@ -602,12 +633,16 @@ class ProxyCandidatAdmin(CandidatAdmin):
 
     def has_change_permission(self, request, obj=None):
         if obj is not None:
-            evaluateur = Evaluateur.objects.get(user=request.user)
-            for e in obj.evaluations.all():
-                if e.evaluateur == evaluateur:
-                    return True
-
-        return not super(ProxyCandidatAdmin, self).has_change_permission(request, obj)
+            return obj in self.queryset(request)
+            #try:
+            #    evaluateur = Evaluateur.objects.get(user=request.user)
+            #    for e in obj.evaluations.all():
+            #        if e.evaluateur == evaluateur:
+            #            return True
+            #    return False
+            #except:
+            #    pass
+        return super(ProxyCandidatAdmin, self).has_change_permission(request, obj)
 
     def get_actions(self, request):
         return None
@@ -645,29 +680,29 @@ class EvaluateurAdmin(BaseAdmin, VersionAdmin):
 
     ### Permissions add, delete, change
     def has_add_permission(self, request):
-        user_groupes = request.user.groups.all()
+        user_groupes = get_user_groupnames(request.user)
         if request.user.is_superuser is True or \
-                grp_drh in user_groupes or \
-                grp_drh2 in user_groupes or \
-                grp_haute_direction in user_groupes:
+                groups.DRH_NIVEAU_1 in user_groupes or \
+                groups.DRH_NIVEAU_2 in user_groupes or \
+                groups.HAUTE_DIRECTION in user_groupes:
             return True
         return False
 
     def has_delete_permission(self, request, obj=None):
-        user_groupes = request.user.groups.all()
+        user_groupes = get_user_groupnames(request.user)
         if request.user.is_superuser is True or \
-                grp_drh in user_groupes or \
-                grp_drh2 in user_groupes or \
-                grp_haute_direction in user_groupes:
+                groups.DRH_NIVEAU_1 in user_groupes or \
+                groups.DRH_NIVEAU_2 in user_groupes or \
+                groups.HAUTE_DIRECTION in user_groupes:
             return True
         return False
 
     def has_change_permission(self, request, obj=None):
-        user_groupes = request.user.groups.all()
+        user_groupes = get_user_groupnames(request.user)
         if request.user.is_superuser is True or \
-                grp_drh in user_groupes or \
-                grp_drh2 in user_groupes or \
-                grp_haute_direction in user_groupes:
+                groups.DRH_NIVEAU_1 in user_groupes or \
+                groups.DRH_NIVEAU_2 in user_groupes or \
+                groups.HAUTE_DIRECTION in user_groupes:
             return True
         return False
 
@@ -768,15 +803,15 @@ class CandidatEvaluationAdmin(BaseAdmin):
         mais interdire l'accès à modifier l'objet si l'évaluateur n'est pas
         le request.user
         """
-        user_groupes = request.user.groups.all()
+        user_groupes = get_user_groupnames(request.user)
 
         if request.user.is_superuser or \
-            grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_correspondants_rh in user_groupes or \
-            grp_directeurs_bureau in user_groupes or \
-            grp_administrateurs in user_groupes or \
-            grp_haute_direction in user_groupes:
+            groups.CORRESPONDANT_RH in user_groupes or \
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
             is_recrutement = True
         else:
             is_recrutement = False
@@ -790,14 +825,15 @@ class CandidatEvaluationAdmin(BaseAdmin):
         """
         qs = self.model._default_manager.get_query_set() \
                 .select_related('offre_emploi')
-        user_groupes = request.user.groups.all()
-
-        if grp_drh in user_groupes or \
-            grp_drh2 in user_groupes or \
-            grp_correspondants_rh in user_groupes or \
-            grp_directeurs_bureau in user_groupes or \
-            grp_administrateurs in user_groupes or \
-            grp_haute_direction in user_groupes:
+        user_groupes = get_user_groupnames(request.user)
+
+        if request.user.is_superuser or \
+            groups.CORRESPONDANT_RH in user_groupes or \
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
             return qs.filter(candidat__statut__in=('REC', 'SEL'))
 
         evaluateur = Evaluateur.objects.get(user=request.user)
@@ -828,13 +864,27 @@ class MesCandidatEvaluationAdmin(CandidatEvaluationAdmin):
 
     def queryset(self, request):
         qs = self.model._default_manager.get_query_set() \
-                .select_related('offre_emploi')
+            .select_related('offre_emploi')
         evaluateur = Evaluateur.objects.get(user=request.user)
-        candidats_evaluations = \
-            CandidatEvaluation.objects.filter(evaluateur=evaluateur,
-                    candidat__statut__in=('REC', ))
-        candidats_evaluations_ids = [ce.id for ce in candidats_evaluations]
-        return qs.filter(id__in=candidats_evaluations_ids)
+
+        # XXX: Pas l'idéal, mais on doit créer les objets CandidatEvaluation
+        # ici pour garder la liste à jour. Idéalement, il vaudrait peut-être
+        # mieux utiliser directement les objets Candidat.
+        for candidat in Candidat.objects .filter(
+            offre_emploi__offreemploievaluateur__evaluateur=evaluateur,
+        ).exclude(evaluations__evaluateur=evaluateur):
+            print candidat, candidat.offre_emploi
+            CandidatEvaluation.objects.get_or_create(
+                candidat=candidat, evaluateur=evaluateur
+            )
+
+        return qs.filter(
+            evaluateur=evaluateur, candidat__statut__in=('NOUV', 'REC')
+        )
+
+
+class OffreEmploiEvaluateurAdmin(BaseAdmin):
+    pass
 
 
 class CourrielTemplateAdmin(BaseAdmin, VersionAdmin):
@@ -852,3 +902,4 @@ admin.site.register(CandidatEvaluation, CandidatEvaluationAdmin)
 admin.site.register(MesCandidatEvaluation, MesCandidatEvaluationAdmin)
 admin.site.register(Evaluateur, EvaluateurAdmin)
 admin.site.register(CourrielTemplate, CourrielTemplateAdmin)
+admin.site.register(OffreEmploiEvaluateur, OffreEmploiEvaluateurAdmin)