id.auf + regio + qbe + recrutement
authorOlivier Larchevêque <olivier.larcheveque@auf.org>
Fri, 28 Sep 2012 14:42:54 +0000 (10:42 -0400)
committerOlivier Larchevêque <olivier.larcheveque@auf.org>
Fri, 28 Sep 2012 14:42:54 +0000 (10:42 -0400)
51 files changed:
buildout.cfg
project/dae/catalogues.py
project/dae/forms.py
project/dae/managers.py
project/dae/templates/dae/embauche-row.html
project/dae/templates/dae/embauches_finalisees.html
project/dae/templates/dae/poste-row.html
project/dae/templatetags/dae.py
project/dae/views.py
project/dashboard.py
project/decorators.py
project/menu.py
project/permissions.py
project/recrutement/admin.py
project/recrutement/forms.py
project/recrutement/migrations/0005_auto__add_offreemploievaluateur.py [new file with mode: 0644]
project/recrutement/migrations/0006_convert_candidatevaluation.py [new file with mode: 0644]
project/recrutement/models.py
project/recrutement/templates/admin/recrutement/candidat/change_list.html [new file with mode: 0644]
project/recrutement/templates/recrutement/selectionner_statut.html [new file with mode: 0644]
project/recrutement/views.py
project/rh/admin.py
project/rh/catalogues.py
project/rh/forms.py
project/rh/managers.py
project/rh/models.py
project/rh/ods.py
project/rh/templates/rh/include/dossier.html
project/rh/templates/rh/rapports/contrats.html
project/rh/templates/rh/rapports/employes_sans_contrat.html
project/rh/templates/rh/rapports/masse_salariale.html
project/rh/templatetags/rapports.py
project/rh/test/common.py
project/rh/test/rapport.py
project/rh/views.py
project/settings.py
project/templates/actions.html
project/templates/index.html
project/templates/menu.html
project/urls.py
project/views.py
src/qbe/django_qbe/forms.py
src/qbe/django_qbe/locale/fr/LC_MESSAGES/django.mo [new file with mode: 0644]
src/qbe/django_qbe/locale/fr/fr_CA/LC_MESSAGES/django.mo [new file with mode: 0644]
src/qbe/django_qbe/locale/fr/fr_CA/LC_MESSAGES/django.po [new file with mode: 0644]
src/qbe/django_qbe/locale/fr_CA/LC_MESSAGES/django.mo [deleted file]
src/qbe/django_qbe/locale/fr_CA/LC_MESSAGES/django.po [deleted file]
src/qbe/django_qbe/static/django_qbe/css/qbe.css
src/qbe/django_qbe/static/django_qbe/js/qbe.core.js
src/qbe/django_qbe/templates/qbe.html
versions.cfg

index c9158dc..03068a0 100644 (file)
@@ -9,10 +9,12 @@ parts = django
 find-links = http://pypi.auf.org/simple/auf.recipe.django/
     http://pypi.auf.org/simple/auf.django.skin/
     http://pypi.auf.org/simple/auf.django.auth/
+    http://pypi.auf.org/simple/auf.django.saml/
     http://pypi.auf.org/simple/auf.django.workflow/
     http://pypi.auf.org/simple/auf.django.admingroup/
     http://pypi.auf.org/simple/auf.django.permissions/
     http://pypi.auf.org/simple/auf.django.emploi/
+    http://pypi.auf.org/simple/auf.django.export/
     http://pypi.auf.org/simple/auf.django.references/
     http://pypi.auf.org/simple/auf.django.piwik/
     http://pypi.auf.org/simple/django-alphafilter/
@@ -38,7 +40,9 @@ eggs =
     django-urldecorators
     auf.django.admingroup
     auf.django.auth
+    auf.django.saml
     auf.django.emploi
+    auf.django.export
     auf.django.metadata
     auf.django.permissions
     auf.django.references
index 5451a74..9c1dc52 100644 (file)
@@ -72,12 +72,10 @@ class Dossier(object):
             Q(employe__nom__icontains=q) | \
             Q(employe__prenom__icontains=q)
 
-        if groups.is_user_dans_services_centraux(request.user):
-            q_place = Q(**{prefixe_implantation: employe.implantation})
-        else:
-            q_place = Q(**{
-                prefixe_implantation + '__region': employe.implantation.region
-            })
+        q_place = Q(**{
+            prefixe_implantation + '__zone_administrative':
+            employe.implantation.zone_administrative
+        })
 
         user_groupes = [g.name for g in request.user.groups.all()]
         if groups.DRH_NIVEAU_1 in user_groupes:
@@ -119,7 +117,8 @@ class Poste(object):
             q_place = Q(**{prefixe_implantation: employe.implantation})
         else:
             q_place = Q(**{
-                prefixe_implantation + '__region': employe.implantation.region
+                prefixe_implantation + '__zone_administrative':
+                employe.implantation.zone_administrative
             })
 
         user_groupes = [g.name for g in request.user.groups.all()]
index 2cfa767..537b94d 100644 (file)
@@ -84,12 +84,7 @@ class BaseInlineFormSetWithInitial(BaseInlineFormSet):
 def _implantation_choices(obj, request):
     # TRAITEMENT NORMAL
     employe = groups.get_employe_from_user(request.user)
-    # SERVICE
-    if groups.is_user_dans_services_centraux(request.user):
-        q = Q(**{'id': employe.implantation_id})
-    # REGION
-    else:
-        q = Q(**{'region': employe.implantation.region})
+    q = Q(**{'zone_administrative': employe.implantation.zone_administrative})
 
     # TRAITEMENT DRH
     user_groupes = [g.name for g in request.user.groups.all()]
@@ -103,18 +98,16 @@ def _implantation_choices(obj, request):
 def _employe_choices(obj, request):
     # TRAITEMENT NORMAL
     employe = groups.get_employe_from_user(request.user)
-    # SERVICE
-    if groups.is_user_dans_services_centraux(request.user):
-        q_dae_region_service = Q(poste__implantation=employe.implantation)
-        q_rh_region_service = Q(poste__implantation=employe.implantation)
-    # REGION
-    else:
-        q_dae_region_service = Q(
-            poste__implantation__region=employe.implantation.region
+    q_dae_region_service = Q(
+        poste__implantation__zone_administrative=(
+            employe.implantation.zone_administrative
         )
-        q_rh_region_service = Q(
-            poste__implantation__region=employe.implantation.region
+    )
+    q_rh_region_service = Q(
+        poste__implantation__zone_administrative=(
+            employe.implantation.zone_administrative
         )
+    )
     # TRAITEMENT DRH
     user_groupes = [g.name for g in request.user.groups.all()]
     if groups.DRH_NIVEAU_1 in user_groupes or \
index ca64649..f4bc09e 100644 (file)
@@ -32,7 +32,8 @@ class TodoManagerMixin(object):
                     groups.DRH_NIVEAU_2,
                 ):
                     q2 &= Q(**{
-                        self.prefixe_implantation: employe.implantation.region
+                        self.prefixe_implantation:
+                        employe.implantation.zone_administrative
                     })
                 q |= q2
 
index dc4584b..6027968 100644 (file)
@@ -1,6 +1,6 @@
 {% load dae %}
 <tr>
-    <td>{{ dossier.poste.implantation|region_ou_service }}</td>
+    <td>{{ dossier.poste.implantation.zone_administrative }}</td>
     <td>{{ dossier.poste.implantation }}</td>
     <td><a href="{% url embauche_consulter dossier.id %}">{{ dossier.poste.nom }}</a></td>
     <td>{{ dossier.employe }}</td>
index 90bf4c7..af4ec45 100644 (file)
@@ -31,7 +31,7 @@
     <thead>
       <tr>
         <th></th>
-        {% sort_header "region" "Région" %}
+        {% sort_header "zone_administrative" "Zone administrative" %}
         {% sort_header "implantation" "Implantation" %}
         {% sort_header "poste" "Poste" %}
         {% sort_header "personne" "Personne" %}
@@ -46,7 +46,7 @@
       {% for dossier in embauches.object_list %}
       <tr>
         <td><input type="checkbox" name="ids" value="{{ dossier.id }}"></td>
-        <td>{{ dossier.poste.implantation|region_ou_service }}</td>
+        <td>{{ dossier.poste.implantation.zone_administrative }}</td>
         <td>{{ dossier.poste.implantation }}</td>
         <td><a href="{% url poste_consulter dossier.poste.key %}">{{ dossier.poste.nom }}</a></td>
         <td><a href="{% url embauche_consulter dossier.id %}">{{ dossier.employe }}</a></td>
index 8118def..40a82aa 100644 (file)
@@ -1,6 +1,6 @@
 {% load dae %}
 <tr>
-    <td>{{ poste.implantation|region_ou_service }}</td>
+    <td>{{ poste.implantation.zone_administrative }}</td>
     <td>{{ poste.implantation }}</td>
     <td><a href="{% url poste_consulter poste.key %}">{{ poste.nom }}</a></td>
     <td>{{ poste.date_creation|date:"d-m-Y" }}</td>
index 2b69560..3fbe768 100644 (file)
@@ -46,14 +46,6 @@ def est_editable(obj, user):
         return False
 
 @register.filter
-def region_ou_service(implantation):
-    if implantation.id == 15:
-        return u"Services centraux de Montréal (SCM)"
-    if implantation.id == 19:
-        return u"Services centraux de Paris (SCP)"
-    return implantation.region
-
-@register.filter
 def basename(path):
     return os.path.basename(path)
 
index ff1df56..94d210f 100644 (file)
@@ -539,8 +539,8 @@ def embauches_finalisees(request):
         importees = search_form.cleaned_data.get('importees')
         if q:
             criteria = [
-                Q(poste__implantation__region__nom__icontains=word) |
-                Q(poste__implantation__region__code=word) |
+                Q(poste__implantation__zone_administrative__nom__icontains=word) |
+                Q(poste__implantation__zone_administrative__code=word) |
                 Q(poste__implantation__nom__icontains=word) |
                 Q(poste__nom__icontains=word) |
                 Q(employe__nom__icontains=word) |
@@ -562,7 +562,7 @@ def embauches_finalisees(request):
         dir = ''
     if tri == 'region':
         embauches = embauches.order_by(
-            dir + 'poste__implantation__region__nom'
+            dir + 'poste__implantation__zone_administrative__nom'
         )
     elif tri == 'implantation':
         embauches = embauches.order_by(dir + 'poste__implantation__nom')
index 97a9b70..652853c 100644 (file)
@@ -20,7 +20,7 @@ from project.rh.historique import get_active_revisions
 
 class CustomIndexDashboard(Dashboard):
     """
-    Custom index dashboard for SIGMA.
+    Custom index dashboard for SGRH.
     """
     def init_with_context(self, context):
         request = context['request']
@@ -46,6 +46,7 @@ class CustomIndexDashboard(Dashboard):
                         'project.recrutement.models.CandidatEvaluation',
                         'project.recrutement.models.MesCandidatEvaluation',
                         'project.recrutement.models.Evaluateur',
+                        'project.recrutement.models.OffreEmploiEvaluateur',
                         'project.recrutement.models.CourrielTemplate',
                     )
                 ),
index d9d8ce9..c386666 100644 (file)
@@ -69,7 +69,8 @@ def region_protected(model):
                groups.DIRECTEUR_DE_BUREAU in user_groups:
                 employe = groups.get_employe_from_user(request.user)
                 q = Q(**{
-                    model.prefix_implantation: employe.implantation.region
+                    model.prefix_implantation:
+                    employe.implantation.zone_administrative
                 })
                 qs = model.objects.filter(q)
                 if int(id) in [o.id for o in qs]:
@@ -77,7 +78,8 @@ def region_protected(model):
             return redirect_interdiction(request)
         return wrapped
     return wrapper
-    
+
+
 def in_one_of_group(groups):
     """
     Test si le user appartient au moins 1 des ces groupes
index 03e4c1a..ff84e67 100644 (file)
@@ -66,11 +66,8 @@ class CustomMenu(Menu):
                         items.MenuItem('Rapport des modifications',
                             reverse('rhr_historique_des_modifications')),
                         )
-            self.children += [
-                items.MenuItem('Rapports',
-                    children=rapports),
 
-                items.MenuItem('Organigrammes',
+            items_organigrammes = items.MenuItem('Organigrammes',
                     children=[
                         items.MenuItem('Organigramme par employé',
                             reverse('admin:rh_employeproxy_changelist')),
@@ -80,13 +77,22 @@ class CustomMenu(Menu):
                             reverse('admin:rh_implantationproxy_changelist')),
                         items.MenuItem('Organigramme par bureau',
                             reverse('admin:rh_regionproxy_changelist')),
-                        ]),
-                items.MenuItem('Requêtes',
+                        ])
+
+            items_rapports = items.MenuItem('Rapports', children=rapports)
+
+            items_requetes = items.MenuItem('Requêtes',
                     children=[
                         items.MenuItem('Requêtes sauvegardées',
                             reverse('admin:django_qbe_savedquery_changelist')),
                         items.MenuItem('Constructeur de requêtes',
                             reverse('qbe_form')),
-                        ]),
-            ]
+                        ])
+
+            children = [items_rapports, items_organigrammes, ]
+            if in_drh_or_admin(request.user):
+                children.append(items_requetes)
+
+            self.children += children
+
         super(CustomMenu, self).init_with_context(context)
index 213b55c..09db52e 100644 (file)
@@ -38,11 +38,11 @@ def obj_in_region_user(user, obj):
     if isinstance(obj, rh.Dossier):
         return True
     if isinstance(obj, rh.Poste):
-        return obj.implantation.region == region_user
+        return obj.implantation.zone_administrative == region_user
     return False
     
 def get_region_user(user):
     # gère actuellement qu'une seule région par user
     employe = get_employe_from_user(user)
-    region_user = employe.implantation.region
+    region_user = employe.implantation.zone_administrative
     return region_user
index 4bc35f3..f06e047 100644 (file)
@@ -3,23 +3,29 @@
 import textwrap
 
 from auf.django.emploi.models import OffreEmploi, Candidat, CandidatPiece
-from auf.django.references.models import Region, Bureau
+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
 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 project import groups
+
 from project.rh import models as rh
 from project.recrutement.forms import OffreEmploiForm
 from project.recrutement.models import \
         Evaluateur, CandidatEvaluation, \
         ProxyOffreEmploi, ProxyCandidat, MesCandidatEvaluation, \
-        CourrielTemplate
+        CourrielTemplate, OffreEmploiEvaluateur
 
 ### CONSTANTES
 IMPLANTATIONS_CENTRALES = [15, 19]
@@ -58,6 +64,24 @@ class OffreEmploiAdminMixin(BaseAdmin):
     list_filter = ('statut',)
     actions = ['affecter_evaluateurs_offre_emploi', ]
     form = OffreEmploiForm
+    fieldsets = (
+        (None, {
+            'fields': (
+                'est_affiche',
+                'statut',
+                'date_limite',
+                'nom',
+                'description',
+                'poste',
+                'region',
+                'lieu_affectation',
+                'bureau',
+                'debut_affectation',
+                'duree_affectation',
+                'renumeration',
+            )
+        }),
+    )
 
     ### Actions à afficher
     def get_actions(self, request):
@@ -91,17 +115,12 @@ class OffreEmploiAdminMixin(BaseAdmin):
         user_groupes = [g.name for g in request.user.groups.all()]
 
         # Region
-        
-        if 'region' in form.declared_fields:
+        region_field = None
+        if 'region' in form.declared_fields.keys():
             region_field = form.declared_fields['region']
-            read_only = False
-        elif 'region' in form.base_fields:
+        if 'region' in form.base_fields.keys():
             region_field = form.base_fields['region']
-            read_only = False
-        else:
-            read_only = True
-
-        if not read_only:
+        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:
@@ -111,16 +130,12 @@ class OffreEmploiAdminMixin(BaseAdmin):
                                     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']
-            read_only = False
-        elif 'poste' in form.base_fields:
+        if 'poste' in form.base_fields.keys():
             poste_field = form.base_fields['poste']
-            read_only = False
-        else:
-            read_only = True
-
-        if not read_only:
+        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:
@@ -131,15 +146,12 @@ class OffreEmploiAdminMixin(BaseAdmin):
                         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']
-            read_only = False
-        elif 'bureau' in form.base_fields:
+        if 'bureau' in form.base_fields.keys():
             bureau_field = form.base_fields['bureau']
-            read_only = False
-        else:
-            read_only = True
-        if not read_only:
+        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:
@@ -230,6 +242,13 @@ class OffreEmploiAdminMixin(BaseAdmin):
 
         return False
 
+    def formfield_for_foreignkey(self, db_field, request, **kwargs):
+        if db_field.name == 'lieu_affectation':
+            employe = groups.get_employe_from_user(request.user)
+            kwargs["queryset"] = Implantation.objects.filter(region=employe.implantation.region)
+            return db_field.formfield(**kwargs)
+        return super(OffreEmploiAdminMixin, self).formfield_for_foreignkey(db_field, request, **kwargs)
+
 
 class OffreEmploiAdmin(VersionAdmin, OffreEmploiAdminMixin):
     pass
@@ -266,11 +285,6 @@ class ProxyOffreEmploiAdmin(OffreEmploiAdminMixin):
     def response_change(self, request, obj):
         return redirect('admin:recrutement_proxyoffreemploi_changelist')
 
-    ### Formulaire
-    def get_form(self, request, obj=None, **kwargs):
-        form = super(ProxyOffreEmploiAdmin, self).get_form(request, obj, **kwargs)
-        return form
-
     ### Permissions add, delete, change
     def has_add_permission(self, request):
         return False
@@ -279,20 +293,10 @@ class ProxyOffreEmploiAdmin(OffreEmploiAdminMixin):
         return False
 
     def has_change_permission(self, request, obj=None):
-        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 or \
-            groups.DIRECTEUR_DE_BUREAU in user_groupes or \
-            groups.ADMINISTRATEURS in user_groupes or \
-            groups.HAUTE_DIRECTION in user_groupes:
-            return True
-
         if obj is not None:
             return True
 
-        return False
+        return not super(ProxyOffreEmploiAdmin, self).has_change_permission(request, obj)
 
 
 class CandidatPieceInline(admin.TabularInline):
@@ -333,14 +337,14 @@ class CandidatEvaluationInline(admin.TabularInline):
         return self.readonly_fields
 
 
-class CandidatAdminMixin(BaseAdmin):
+class CandidatAdminMixin(BaseAdmin, ExportAdmin):
     search_fields = ('nom', 'prenom')
     exclude = ('actif', )
     list_editable = ('statut', )
     list_display = ('_candidat', 'offre_emploi',
                     'voir_offre_emploi', 'calculer_moyenne',
                     'afficher_candidat', '_date_creation', 'statut', )
-    list_filter = ('offre_emploi', 'offre_emploi__region', 'statut', )
+    list_filter = ('offre_emploi__nom', 'offre_emploi__region', 'statut', )
 
     fieldsets = (
         ("Offre d'emploi", {
@@ -348,7 +352,7 @@ class CandidatAdminMixin(BaseAdmin):
         }),
         ('Informations personnelles', {
             'fields': (
-                'prenom', 'nom', 'genre', 'nationalite',
+                'nom', 'prenom', 'genre', 'nationalite',
                 'situation_famille', 'nombre_dependant'
             )
         }),
@@ -372,7 +376,13 @@ class CandidatAdminMixin(BaseAdmin):
         CandidatPieceInline,
         CandidatEvaluationInline,
     ]
-    actions = ['envoyer_courriel_candidats']
+    actions = ['envoyer_courriel_candidats', 'changer_statut']
+
+    export_fields = ['statut', 'offre_emploi', 'prenom', 'nom', 'genre',
+                     'nationalite', 'situation_famille', 'nombre_dependant',
+                     'niveau_diplome', 'employeur_actuel', 'poste_actuel',
+                     'domaine_professionnel', 'telephone', 'email', 'adresse',
+                     'ville', 'etat_province', 'code_postal', 'pays']
 
     def _candidat(self, obj):
         txt = u"%s %s (%s)" % (obj.nom.upper(), obj.prenom, obj.genre)
@@ -402,6 +412,23 @@ class CandidatAdminMixin(BaseAdmin):
         )
     envoyer_courriel_candidats.short_description = u'Envoyer courriel'
 
+    ### Changer le statut à des candidats
+    def changer_statut(modeladmin, request, queryset):
+        if request.POST.get('post'):
+            queryset.update(statut=request.POST.get('statut'))
+            return None
+
+        context = {
+            'action_checkbox_name': admin.helpers.ACTION_CHECKBOX_NAME,
+            'queryset': queryset,
+            'status': STATUT_CHOICES,
+        }
+
+        return render_to_response("recrutement/selectionner_statut.html",
+                context, context_instance = RequestContext(request))
+
+    changer_statut.short_description = u'Changer statut'
+
     ### Évaluer un candidat
     def evaluer_candidat(self, obj):
         return "<a href='%s?candidat__id__exact=%s'>" \
@@ -417,7 +444,7 @@ class CandidatAdminMixin(BaseAdmin):
         items = [u"<li><a href='%s%s'>%s</li>" % \
                 (settings.OE_PRIVE_MEDIA_URL, pj.path, pj.get_nom_display()) \
                 for pj in obj.pieces_jointes()]
-        html = "<a href='%s'>Voir le candidat</a>" % (
+        html = "<a href='%s'>Candidature</a>" % (
             reverse('admin:recrutement_proxycandidat_change', args=(obj.id,))
         )
         return "%s<ul>%s</ul>" % (html, "\n".join(items))
@@ -502,6 +529,13 @@ class CandidatAdminMixin(BaseAdmin):
             return True
         return False
 
+    def formfield_for_foreignkey(self, db_field, request, **kwargs):
+        if db_field.name == 'offre_emploi':
+            employe = groups.get_employe_from_user(request.user)
+            kwargs["queryset"] = OffreEmploi.objects.filter(region=employe.implantation.region)
+            return db_field.formfield(**kwargs)
+        return super(CandidatAdminMixin, self).formfield_for_foreignkey(db_field, request, **kwargs)
+
     def get_changelist(self, request, **kwargs):
         return OrderedChangeList
 
@@ -538,10 +572,12 @@ class CandidatAdminMixin(BaseAdmin):
 
 
 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',
@@ -582,23 +618,17 @@ class ProxyCandidatAdmin(CandidatAdminMixin):
         return False
 
     def has_change_permission(self, request, obj=None):
-        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 or \
-            groups.DIRECTEUR_DE_BUREAU in user_groupes or \
-            groups.ADMINISTRATEURS in user_groupes or \
-            groups.HAUTE_DIRECTION in user_groupes:
-            return True
-
         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 False
+            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
@@ -791,7 +821,7 @@ class CandidatEvaluationAdmin(BaseAdmin):
             groups.DIRECTEUR_DE_BUREAU in user_groupes or \
             groups.ADMINISTRATEURS in user_groupes or \
             groups.HAUTE_DIRECTION in user_groupes:
-            return qs
+            return qs.filter(candidat__statut__in=('REC', 'SEL'))
 
         evaluateur = Evaluateur.objects.get(user=request.user)
         candidats_evaluations = \
@@ -802,6 +832,7 @@ class CandidatEvaluationAdmin(BaseAdmin):
 
 
 class MesCandidatEvaluationAdmin(CandidatEvaluationAdmin):
+    list_filter = []
 
     def has_change_permission(self, request, obj=None):
         try:
@@ -829,6 +860,10 @@ class MesCandidatEvaluationAdmin(CandidatEvaluationAdmin):
         return qs.filter(id__in=candidats_evaluations_ids)
 
 
+class OffreEmploiEvaluateurAdmin(BaseAdmin):
+    pass
+
+
 class CourrielTemplateAdmin(BaseAdmin, VersionAdmin):
     ### Actions à afficher
     def get_actions(self, request):
@@ -844,3 +879,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)
index e3ff7d7..94e0577 100644 (file)
@@ -4,6 +4,7 @@ from django import forms
 from django.forms import ModelForm
 
 from auf.django.emploi import forms as emploi
+from auf.django.emploi import models as emploi_models
 
 from project.recrutement import models as recr
 
@@ -74,6 +75,11 @@ class PostulerOffreEmploiForm(emploi.PostulerOffreEmploiForm):
     pass
 
 class OffreEmploiForm(ModelForm):
+    nom = forms.CharField(label='Intitulé du poste')
+
+    class Meta:
+        model = emploi_models.OffreEmploi
+
     def clean(self):
         cleaned_data = self.cleaned_data
         date_limite = cleaned_data.get("date_limite")
diff --git a/project/recrutement/migrations/0005_auto__add_offreemploievaluateur.py b/project/recrutement/migrations/0005_auto__add_offreemploievaluateur.py
new file mode 100644 (file)
index 0000000..502b960
--- /dev/null
@@ -0,0 +1,241 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+    
+    def forwards(self, orm):
+        
+        # Adding model 'OffreEmploiEvaluateur'
+        db.create_table('recrutement_offreemploievaluateur', (
+            ('offre_emploi', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['emploi.OffreEmploi'], db_column='offre_emploi')),
+            ('evaluateur', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['recrutement.Evaluateur'], db_column='evaluateur')),
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+        ))
+        db.send_create_signal('recrutement', ['OffreEmploiEvaluateur'])
+    
+    
+    def backwards(self, orm):
+        
+        # Deleting model 'OffreEmploiEvaluateur'
+        db.delete_table('recrutement_offreemploievaluateur')
+    
+    
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'emploi.candidat': {
+            'Meta': {'object_name': 'Candidat'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'adresse': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'code_postal': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'date_creation': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'domaine_professionnel': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
+            'employeur_actuel': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'etat_province': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'genre': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nationalite': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'nationalite'", 'to': "orm['references.Pays']"}),
+            'niveau_diplome': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nombre_dependant': ('django.db.models.fields.IntegerField', [], {}),
+            'offre_emploi': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'offre_emploi'", 'to': "orm['emploi.OffreEmploi']"}),
+            'pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'pays'", 'to': "orm['references.Pays']"}),
+            'poste_actuel': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'prenom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'situation_famille': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'statut': ('django.db.models.fields.CharField', [], {'default': "'NOUV'", 'max_length': '4'}),
+            'telephone': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'ville': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'emploi.offreemploi': {
+            'Meta': {'object_name': 'OffreEmploi'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'bureau': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Bureau']", 'db_column': "'bureau'"}),
+            'date_creation': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'date_limite': ('django.db.models.fields.DateField', [], {}),
+            'debut_affectation': ('django.db.models.fields.DateField', [], {}),
+            'description': ('django.db.models.fields.TextField', [], {}),
+            'duree_affectation': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'est_affiche': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'lieu_affectation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Implantation']", 'db_column': "'implantation'"}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'poste': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'poste_nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'region': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Region']", 'db_column': "'region'"}),
+            'renumeration': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'resume': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'statut': ('django.db.models.fields.CharField', [], {'default': "'NOUV'", 'max_length': '4'})
+        },
+        'recrutement.candidat': {
+            'Meta': {'object_name': 'Candidat', 'db_table': "'emploi_candidat'", '_ormbases': ['emploi.Candidat']}
+        },
+        'recrutement.candidatcourriel': {
+            'Meta': {'object_name': 'CandidatCourriel'},
+            'candidats': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['emploi.Candidat']", 'symmetrical': 'False'}),
+            'html': ('tinymce.models.HTMLField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'plain_text': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'sujet': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'template'", 'to': "orm['recrutement.CourrielTemplate']"})
+        },
+        'recrutement.candidatevaluation': {
+            'Meta': {'object_name': 'CandidatEvaluation'},
+            'candidat': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'evaluations'", 'db_column': "'candidat'", 'to': "orm['emploi.Candidat']"}),
+            'commentaire': ('django.db.models.fields.TextField', [], {'default': "'Aucun'", 'null': 'True', 'blank': 'True'}),
+            'date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'evaluateur': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'evaluateur'", 'to': "orm['recrutement.Evaluateur']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'note': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+        },
+        'recrutement.courrieltemplate': {
+            'Meta': {'object_name': 'CourrielTemplate'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom_modele': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'plain_text': ('django.db.models.fields.TextField', [], {}),
+            'sujet': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'recrutement.evaluateur': {
+            'Meta': {'object_name': 'Evaluateur'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
+        },
+        'recrutement.offreemploievaluateur': {
+            'Meta': {'unique_together': "(('offre_emploi', 'evaluateur'),)", 'object_name': 'OffreEmploiEvaluateur'},
+            'evaluateur': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['recrutement.Evaluateur']", 'db_column': "'evaluateur'"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'offre_emploi': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['emploi.OffreEmploi']", 'db_column': "'offre_emploi'"})
+        },
+        'references.bureau': {
+            'Meta': {'object_name': 'Bureau', 'db_table': "u'ref_bureau'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Implantation']", 'db_column': "'implantation'"}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_court': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'nom_long': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'region': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Region']", 'db_column': "'region'"})
+        },
+        'references.implantation': {
+            'Meta': {'object_name': 'Implantation', 'db_table': "u'ref_implantation'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'adresse_physique_bureau': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_code_postal': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'adresse_physique_code_postal_avant_ville': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+            'adresse_physique_no': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'adresse_physique_pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'impl_adresse_physique'", 'to_field': "'code'", 'db_column': "'adresse_physique_pays'", 'to': "orm['references.Pays']"}),
+            'adresse_physique_precision': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_precision_avant': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_region': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_rue': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_ville': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'adresse_postale_boite_postale': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_bureau': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_code_postal': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_code_postal_avant_ville': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+            'adresse_postale_no': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'impl_adresse_postale'", 'to_field': "'code'", 'db_column': "'adresse_postale_pays'", 'to': "orm['references.Pays']"}),
+            'adresse_postale_precision': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_precision_avant': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_region': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_rue': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_ville': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'bureau_rattachement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Implantation']", 'db_column': "'bureau_rattachement'"}),
+            'code_meteo': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'commentaire': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'courriel': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'courriel_interne': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'date_extension': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'date_fermeture': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'date_inauguration': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'date_ouverture': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'fax': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'fax_interne': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'fuseau_horaire': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'hebergement_convention': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+            'hebergement_convention_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'hebergement_etablissement': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modif_date': ('django.db.models.fields.DateField', [], {}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_court': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'nom_long': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'region': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Region']", 'db_column': "'region'"}),
+            'remarque': ('django.db.models.fields.TextField', [], {}),
+            'responsable_implantation': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'statut': ('django.db.models.fields.IntegerField', [], {}),
+            'telephone': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'telephone_interne': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '255', 'blank': 'True'}),
+            'zone_administrative': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.ZoneAdministrative']"})
+        },
+        'references.pays': {
+            'Meta': {'object_name': 'Pays', 'db_table': "u'ref_pays'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2'}),
+            'code_bureau': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Bureau']", 'to_field': "'code'", 'null': 'True', 'db_column': "'code_bureau'", 'blank': 'True'}),
+            'code_iso3': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '3'}),
+            'developpement': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'monnaie': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nord_sud': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'region': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Region']", 'db_column': "'region'"})
+        },
+        'references.region': {
+            'Meta': {'object_name': 'Region', 'db_table': "u'ref_region'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation_bureau': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'gere_region'", 'null': 'True', 'db_column': "'implantation_bureau'", 'to': "orm['references.Implantation']"}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
+        },
+        'references.zoneadministrative': {
+            'Meta': {'object_name': 'ZoneAdministrative', 'db_table': "'ref_zoneadministrative'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'max_length': '4', 'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        }
+    }
+    
+    complete_apps = ['recrutement']
diff --git a/project/recrutement/migrations/0006_convert_candidatevaluation.py b/project/recrutement/migrations/0006_convert_candidatevaluation.py
new file mode 100644 (file)
index 0000000..6d2fbfa
--- /dev/null
@@ -0,0 +1,235 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+
+class Migration(DataMigration):
+
+    def forwards(self, orm):
+        "Write your forwards methods here."
+        for ce in orm.CandidatEvaluation.objects.all():
+            orm.OffreEmploiEvaluateur.objects.get_or_create(
+                offre_emploi=ce.candidat.offre_emploi,
+                evaluateur=ce.evaluateur
+            )
+
+    def backwards(self, orm):
+        "Write your backwards methods here."
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'emploi.candidat': {
+            'Meta': {'object_name': 'Candidat'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'adresse': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'code_postal': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'date_creation': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'domaine_professionnel': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
+            'employeur_actuel': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'etat_province': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'genre': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nationalite': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'nationalite'", 'to': "orm['references.Pays']"}),
+            'niveau_diplome': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nombre_dependant': ('django.db.models.fields.IntegerField', [], {}),
+            'offre_emploi': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'offre_emploi'", 'to': "orm['emploi.OffreEmploi']"}),
+            'pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'pays'", 'to': "orm['references.Pays']"}),
+            'poste_actuel': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'prenom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'situation_famille': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'statut': ('django.db.models.fields.CharField', [], {'default': "'NOUV'", 'max_length': '4'}),
+            'telephone': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'ville': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'emploi.offreemploi': {
+            'Meta': {'object_name': 'OffreEmploi'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'bureau': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Bureau']", 'db_column': "'bureau'"}),
+            'date_creation': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'date_limite': ('django.db.models.fields.DateField', [], {}),
+            'debut_affectation': ('django.db.models.fields.DateField', [], {}),
+            'description': ('django.db.models.fields.TextField', [], {}),
+            'duree_affectation': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'est_affiche': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'lieu_affectation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Implantation']", 'db_column': "'implantation'"}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'poste': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'poste_nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'region': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Region']", 'db_column': "'region'"}),
+            'renumeration': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'resume': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'statut': ('django.db.models.fields.CharField', [], {'default': "'NOUV'", 'max_length': '4'})
+        },
+        'recrutement.candidat': {
+            'Meta': {'object_name': 'Candidat', 'db_table': "'emploi_candidat'", '_ormbases': ['emploi.Candidat']}
+        },
+        'recrutement.candidatcourriel': {
+            'Meta': {'object_name': 'CandidatCourriel'},
+            'candidats': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['emploi.Candidat']", 'symmetrical': 'False'}),
+            'html': ('tinymce.models.HTMLField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'plain_text': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'sujet': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'template'", 'to': "orm['recrutement.CourrielTemplate']"})
+        },
+        'recrutement.candidatevaluation': {
+            'Meta': {'object_name': 'CandidatEvaluation'},
+            'candidat': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'evaluations'", 'db_column': "'candidat'", 'to': "orm['emploi.Candidat']"}),
+            'commentaire': ('django.db.models.fields.TextField', [], {'default': "'Aucun'", 'null': 'True', 'blank': 'True'}),
+            'date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'evaluateur': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'evaluateur'", 'to': "orm['recrutement.Evaluateur']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'note': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+        },
+        'recrutement.courrieltemplate': {
+            'Meta': {'object_name': 'CourrielTemplate'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom_modele': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'plain_text': ('django.db.models.fields.TextField', [], {}),
+            'sujet': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'recrutement.evaluateur': {
+            'Meta': {'object_name': 'Evaluateur'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
+        },
+        'recrutement.offreemploievaluateur': {
+            'Meta': {'unique_together': "(('offre_emploi', 'evaluateur'),)", 'object_name': 'OffreEmploiEvaluateur'},
+            'evaluateur': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['recrutement.Evaluateur']", 'db_column': "'evaluateur'"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'offre_emploi': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['emploi.OffreEmploi']", 'db_column': "'offre_emploi'"})
+        },
+        'references.bureau': {
+            'Meta': {'object_name': 'Bureau', 'db_table': "u'ref_bureau'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Implantation']", 'db_column': "'implantation'"}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_court': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'nom_long': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'region': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Region']", 'db_column': "'region'"})
+        },
+        'references.implantation': {
+            'Meta': {'object_name': 'Implantation', 'db_table': "u'ref_implantation'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'adresse_physique_bureau': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_code_postal': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'adresse_physique_code_postal_avant_ville': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+            'adresse_physique_no': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'adresse_physique_pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'impl_adresse_physique'", 'to_field': "'code'", 'db_column': "'adresse_physique_pays'", 'to': "orm['references.Pays']"}),
+            'adresse_physique_precision': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_precision_avant': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_region': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_rue': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'adresse_physique_ville': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'adresse_postale_boite_postale': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_bureau': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_code_postal': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_code_postal_avant_ville': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+            'adresse_postale_no': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'impl_adresse_postale'", 'to_field': "'code'", 'db_column': "'adresse_postale_pays'", 'to': "orm['references.Pays']"}),
+            'adresse_postale_precision': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_precision_avant': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_region': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_rue': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'adresse_postale_ville': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'bureau_rattachement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Implantation']", 'db_column': "'bureau_rattachement'"}),
+            'code_meteo': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'commentaire': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'courriel': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'courriel_interne': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'date_extension': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'date_fermeture': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'date_inauguration': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'date_ouverture': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'fax': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'fax_interne': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'fuseau_horaire': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'hebergement_convention': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+            'hebergement_convention_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'hebergement_etablissement': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modif_date': ('django.db.models.fields.DateField', [], {}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_court': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'nom_long': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'region': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Region']", 'db_column': "'region'"}),
+            'remarque': ('django.db.models.fields.TextField', [], {}),
+            'responsable_implantation': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'statut': ('django.db.models.fields.IntegerField', [], {}),
+            'telephone': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'telephone_interne': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '255', 'blank': 'True'}),
+            'zone_administrative': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.ZoneAdministrative']"})
+        },
+        'references.pays': {
+            'Meta': {'object_name': 'Pays', 'db_table': "u'ref_pays'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2'}),
+            'code_bureau': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Bureau']", 'to_field': "'code'", 'null': 'True', 'db_column': "'code_bureau'", 'blank': 'True'}),
+            'code_iso3': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '3'}),
+            'developpement': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'monnaie': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nord_sud': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'region': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['references.Region']", 'db_column': "'region'"})
+        },
+        'references.region': {
+            'Meta': {'object_name': 'Region', 'db_table': "u'ref_region'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation_bureau': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'gere_region'", 'null': 'True', 'db_column': "'implantation_bureau'", 'to': "orm['references.Implantation']"}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
+        },
+        'references.zoneadministrative': {
+            'Meta': {'object_name': 'ZoneAdministrative', 'db_table': "'ref_zoneadministrative'", 'managed': 'False'},
+            'actif': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'max_length': '4', 'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        }
+    }
+
+    complete_apps = ['recrutement']
index 06b01e0..10d8175 100644 (file)
@@ -108,6 +108,37 @@ def sync_delete_groupe_evaluateur(sender, **kwargs):
     instance.user.save()
 
 
+class OffreEmploiEvaluateur(models.Model):
+    offre_emploi = models.ForeignKey(emploi.OffreEmploi, db_column='offre_emploi',
+                                     verbose_name=u'offre d\'emploi')
+    evaluateur = models.ForeignKey(Evaluateur, db_column='evaluateur',
+                                   verbose_name=u'évaluateur')
+
+    class Meta:
+        unique_together = ('offre_emploi', 'evaluateur')
+        verbose_name = 'Évaluateur - offre emploi'
+        verbose_name_plural = 'Évaluateurs - offre emploi'
+
+    def __unicode__(self):
+        return u"%s - %s" % (self.offre_emploi, self.evaluateur)
+
+    def save(self):
+
+        if self.pk is None:
+            candidats = Candidat.objects.filter(offre_emploi=self.offre_emploi)
+            for candidat in candidats:
+                candidat_evaluation, created = CandidatEvaluation.objects.get_or_create(candidat=candidat, evaluateur=self.evaluateur)
+
+        super(OffreEmploiEvaluateur, self).save()
+
+    def delete(self):
+        candidats = Candidat.objects.filter(offre_emploi=self.offre_emploi)
+        for candidat in candidats:
+            CandidatEvaluation.objects.filter(candidat=candidat, evaluateur=self.evaluateur).delete()
+
+        super(OffreEmploiEvaluateur, self).delete()
+
+
 class CandidatEvaluation(models.Model):
     candidat = models.ForeignKey(emploi.Candidat, db_column='candidat',
                 related_name='evaluations',)
diff --git a/project/recrutement/templates/admin/recrutement/candidat/change_list.html b/project/recrutement/templates/admin/recrutement/candidat/change_list.html
new file mode 100644 (file)
index 0000000..253a058
--- /dev/null
@@ -0,0 +1,17 @@
+{% extends "admin/change_list.html" %}
+{% load i18n %}
+
+
+{% block object-tools %}
+    <ul class="object-tools">
+        {% if not is_popup %}
+                       <li><a href="{{ export_csv_url }}">{% trans 'Export CSV' %}</a></li>
+                       <li><a href="{{ export_ods_url }}">{% trans 'Export ODS' %}</a></li>
+            <li><a href="{{recoverlist_url}}" class="recoverlink">{% blocktrans with cl.opts.verbose_name_plural|escape as name %}Recover deleted {{name}}{% endblocktrans %}</a></li>
+        {% endif %}
+               {% if has_add_permission %}
+            <li><a href="{{add_url}}{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name|escape as name %}Add {{name}}{% endblocktrans %}</a></li>
+        {% endif %}
+    </ul>
+{% endblock %}
+
diff --git a/project/recrutement/templates/recrutement/selectionner_statut.html b/project/recrutement/templates/recrutement/selectionner_statut.html
new file mode 100644 (file)
index 0000000..b60e3e8
--- /dev/null
@@ -0,0 +1,60 @@
+{% extends 'admin/base_site.html' %}
+{% load i18n adminmedia form_utils_tags %}
+
+{% block title %}RH - Recrutement{% endblock %}
+{% block sous_titre %}Changer statut aux candidats{% endblock %}
+{% block extrahead %}
+{{ form.media }}
+{% endblock %}
+{% block breadcrumbs %}{% if not is_popup %}
+<div class="breadcrumbs">
+     <a href="../../">{% trans "Home" %}</a> &rsaquo;
+     <a href="../">{% trans "Recrutement" %}</a> &rsaquo;
+     {% trans "Changer statut - Sélectionner le statut" %}
+</div>
+{% endif %}{% endblock %}
+
+
+{% block content %}
+<div id="content-main">
+    {% block object-tools %}{% endblock %}
+
+    <div class="module">
+        <h2>Sélectionner le statut</h2>
+
+        <form action="" method="post">{% csrf_token %}
+            <table>
+                <tr>
+                    <td>Changer le statut des candidats suivant:</td>
+                    <td>
+                        <ul>
+                            {{ queryset|unordered_list }}
+                        </ul>
+                    </td>
+                </tr>
+                <tr>
+                    <td>Nouveau statut</td>
+                    <td>
+                        <select name="statut">
+                        {% for statut in status %}
+                        <option value="{{ statut.0 }}">{{ statut.1 }}</option>
+                        {% endfor %}
+                        </select>
+                    </td>
+                </tr>
+            </table>
+            {% for obj in queryset %}
+            <input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk }}" />
+            {% endfor %}
+            <input type="hidden" name="action" value="changer_statut" />
+            <input type="hidden" name="post" value="yes" />
+            <div class="submit-row">
+                <input type="submit" value="Changer">
+            </div>
+        </form>
+    </div>
+
+
+</div>
+
+{% endblock %}
index dd5d037..02ee759 100644 (file)
@@ -83,7 +83,7 @@ def envoyer_courriel_candidats(request):
                 request, messages.SUCCESS,
                 "Le email a été envoyé aux candidats."
             )
-            return redirect("admin:recrutement_candidat_changelist")
+            return redirect("admin:emploi_candidat_changelist")
     else:
         form = forms.CandidatCourrielForm(
             candidats=candidats, template=template,
@@ -108,7 +108,7 @@ def affecter_evaluateurs_offre_emploi(request):
                 request, messages.SUCCESS,
                 "Les évaluateurs ont été affectés aux offres d'emploi."
             )
-            return redirect("admin:recrutement_proxyoffreemploi_changelist")
+            return redirect("admin:emploi_offreemploi_changelist")
     else:
         form = forms.EvaluateurForm(offres_emploi=offres_emploi)
     return render(request, "recrutement/affecter_evaluateurs.html", {
index 6a90877..62df1c9 100644 (file)
@@ -20,12 +20,26 @@ from project.rh import models as rh
 from project.permissions import user_gere_obj_de_sa_region, \
         user_can_add_obj, \
         user_can_change_obj, \
-        user_can_delete_obj
+        user_can_delete_obj, \
+        get_region_user
 
 from project.rh.forms import ContratForm, AyantDroitForm, EmployeAdminForm, \
         AjaxSelect, DossierForm, ResponsableInlineForm
 from project.rh.change_list import ChangeList
 
+def listing_par_defaut(model, request):
+    """
+    Teste si la requete provient de la même page.
+    """
+    if not 'HTTP_REFERER' in request.META.keys():
+        return False
+    referer = request.META['HTTP_REFERER']
+    referer = "/".join(referer.split('/')[3:])
+    referer = "/%s" % referer.split('?')[0]
+    change_list_view = 'admin:%s_%s_changelist' % (
+            model._meta.app_label,
+            model.__name__.lower(),)
+    return referer != reverse(change_list_view)
 
 class BaseAdmin(admin.ModelAdmin):
 
@@ -39,6 +53,7 @@ class BaseAdmin(admin.ModelAdmin):
             'jquery-autocomplete/jquery.autocomplete.min.js',
         )
 
+
 # Admin pour reversion
 
 class ArchivableAdmin(admin.ModelAdmin):
@@ -100,17 +115,14 @@ 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
+        """
+        On filtre par défaut sur les items 'actifs'.
+        Le changelist plug le filtrage temporel.
+        """
+        if listing_par_defaut(self.model, request):
+            params = request.GET.copy()
+            params.update({'statut': 'Actif'})
+            request.GET = params
         return ChangeList
 
 
@@ -127,31 +139,42 @@ class LinkedInline(admin.options.InlineModelAdmin):
 
 class ProtectRegionMixin(object):
 
+    def changelist_view(self, request, extra_context=None):
+        """
+        On filtre par défaut sur la ZA du user connecté
+        """
+        if listing_par_defaut(self.model, request):
+            if user_gere_obj_de_sa_region(request.user):
+                params = request.GET.copy()
+                employe = groups.get_employe_from_user(request.user)
+                za = employe.implantation.zone_administrative.code
+                prefix_za = "%s__code__exact" % self.model.prefix_implantation
+                params.update({prefix_za: za})
+                request.GET = params
+        return super(ProtectRegionMixin, self).changelist_view(request, extra_context)
+
     def queryset(self, request):
         qs = super(ProtectRegionMixin, self).queryset(request)
 
         if in_drh_or_admin(request.user):
             return qs
 
-        #if user_gere_obj_de_sa_region(request.user):
-        #    region_user = get_region_user(request.user)
-        #    q = Q(**{self.model.prefix_implantation: \
-        #            region_user})
-        #    qs = qs.filter(q).distinct()
-        #    return qs
+        if user_gere_obj_de_sa_region(request.user):
+            region_user = get_region_user(request.user)
+            q = Q(**{self.model.prefix_implantation: \
+                    region_user})
+            qs = qs.filter(q).distinct()
+            return qs
         return qs.none()
 
     def has_add_permission(self, request):
-        return in_drh_or_admin(request.user)
-        #return user_can_add_obj(request.user)
+        return user_can_add_obj(request.user)
 
     def has_change_permission(self, request, obj=None):
-        return in_drh_or_admin(request.user)
-        #return user_can_change_obj(request.user, obj) if obj else True
+        return user_can_change_obj(request.user, obj) if obj else True
 
     def has_delete_permission(self, request, obj=None):
-        return in_drh_or_admin(request.user)
-        #return user_can_delete_obj(request.user, obj) if obj else True
+        return user_can_delete_obj(request.user, obj) if obj else True
 
 
 class DerniereModificationAdmin(admin.ModelAdmin):
@@ -367,7 +390,7 @@ class DossierAdmin(DateRangeMixin, ProtectRegionMixin, reversion.VersionAdmin,
         '_nom',
         '_employe',
         '_poste',
-        '_region',
+        '_zone_administrative',
         '_implantation',
         '_date_debut',
         '_date_fin',
@@ -376,7 +399,7 @@ class DossierAdmin(DateRangeMixin, ProtectRegionMixin, reversion.VersionAdmin,
     )
     list_display_links = ('_nom',)
     list_filter = (
-        'poste__implantation__region',
+        'poste__implantation__zone_administrative',
         'poste__implantation',
         'poste__type_poste__categorie_emploi',
         'poste__type_poste',
@@ -417,7 +440,7 @@ class DossierAdmin(DateRangeMixin, ProtectRegionMixin, reversion.VersionAdmin,
     def lookup_allowed(self, key, value):
         if key in (
             'employe__nom__istartswith',
-            'poste__implantation__region__id__exact',
+            'poste__implantation__zone_administrative__code__exact',
             'poste__implantation__id__exact',
             'poste__type_poste__id__exact',
             'poste__type_poste__categorie_emploi__id__exact',
@@ -483,10 +506,10 @@ class DossierAdmin(DateRangeMixin, ProtectRegionMixin, reversion.VersionAdmin,
     _poste.short_description = u'Poste'
     _poste.admin_order_field = 'poste__nom'
 
-    def _region(self, obj):
-        return obj.poste.implantation.region.code
-    _region.short_description = u"Région"
-    _region.admin_order_field = 'poste__implantation__region__code'
+    def _zone_administrative(self, obj):
+        return obj.poste.implantation.zone_administrative.code
+    _zone_administrative.short_description = u"Zone administrative"
+    _zone_administrative.admin_order_field = 'poste__implantation__zone_administrative__code'
 
     def _implantation(self, obj):
         return obj.poste.implantation.nom
@@ -550,14 +573,14 @@ class EmployeAdminBase(DateRangeMixin, ProtectRegionMixin,
     form = EmployeAdminForm
     list_display = (
         '_id', '_apercu', '_nom', '_dossiers_postes',
-        #'_region',
+        #'_zone_administrative',
         #'_implantation',
         'date_entree',
         'derniere_modification'
     )
     list_display_links = ('_nom',)
     list_filter = (
-        'rh_dossiers__poste__implantation__region',
+        'rh_dossiers__poste__implantation__zone_administrative',
         'rh_dossiers__poste__implantation', 'nb_postes'
     )
     inlines = (
@@ -610,14 +633,14 @@ class EmployeAdminBase(DateRangeMixin, ProtectRegionMixin,
     _nom.short_description = u"Employé"
     _nom.admin_order_field = "nom"
 
-    def _region(self, obj):
+    def _zone_administrative(self, obj):
         try:
             d = rh.Dossier.objects.filter(employe=obj.id, principal=True)[0]
-            region = d.poste.implantation.region.code
+            zone = d.poste.implantation.zone_administrative.code
         except:
-            region = None
-        return region
-    _region.short_description = u"Région"
+            zone = None
+        return zone
+    _zone_administrative.short_description = u"Zone administrative"
 
     def _implantation(self, obj):
         try:
@@ -795,8 +818,8 @@ class PosteAdmin(DateRangeMixin, ProtectRegionMixin, reversion.VersionAdmin,
         'id',
         'nom',
         'implantation__nom',
-        'implantation__region__code',
-        'implantation__region__nom',
+        'implantation__zone_administrative__code',
+        'implantation__zone_administrative__nom',
         'rh_dossiers__employe__id',
         'rh_dossiers__employe__nom',
         'rh_dossiers__employe__prenom',
@@ -807,7 +830,7 @@ class PosteAdmin(DateRangeMixin, ProtectRegionMixin, reversion.VersionAdmin,
         '_dae'
     )
     list_filter = (
-        'implantation__region',
+        'implantation__zone_administrative',
         'implantation',
         'service',
         'type_poste',
@@ -873,7 +896,7 @@ class PosteAdmin(DateRangeMixin, ProtectRegionMixin, reversion.VersionAdmin,
     def lookup_allowed(self, key, value):
         return key in (
             'date_debut__gte', 'date_debut__isnull', 'date_fin__lte',
-            'date_fin__isnull', 'implantation__region__id__exact',
+            'date_fin__isnull', 'implantation__zone_administrative__code__exact',
             'implantation__id__exact', 'type_poste__id__exact',
             'type_poste__categorie_emploi__id__exact', 'service__id__exact',
             'service__isnull', 'vacant__exact', 'vacant__isnull',
@@ -929,10 +952,10 @@ class PosteAdmin(DateRangeMixin, ProtectRegionMixin, reversion.VersionAdmin,
     _occupe_par.allow_tags = True
     _occupe_par.short_description = "Occupé par"
 
-    def _region(self, poste):
-        return poste.implantation.region.code
-    _region.short_description = 'Région'
-    _region.admin_order_field = 'implantation__region__code'
+    def _zone_administrative(self, poste):
+        return poste.implantation.zone_administrative.code
+    _zone_administrative.short_description = 'Zone administrative'
+    _zone_administrative.admin_order_field = 'implantation__zone_administrative__code'
 
     def _implantation(self, poste):
         return poste.implantation.nom
@@ -1029,8 +1052,8 @@ class ResponsableImplantationAdmin(BaseAdmin):
     actions = None
     fields = ('nom', )
     inlines = (ResponsableInline, )
-    list_filter = ('region', 'statut', )
-    list_display = ('_region', '_nom', 'statut', '_responsable', )
+    list_filter = ('zone_administrative', 'statut', )
+    list_display = ('_zone_administrative', '_nom', 'statut', '_responsable', )
     list_display_links = ('_nom',)
     list_per_page = 500
     readonly_fields = ('nom', )
@@ -1043,10 +1066,10 @@ class ResponsableImplantationAdmin(BaseAdmin):
     ordering = ('nom',)
     inlines = (ResponsableInline, )
 
-    def _region(self, obj):
-        return obj.region.code
-    _region.short_description = u"Région"
-    _region.admin_order_field = 'region__code'
+    def _zone_administrative(self, obj):
+        return obj.zone_administrative.code
+    _zone_administrative.short_description = u"Zone administrative"
+    _zone_administrative.admin_order_field = 'zone_administrative__code'
 
     def _nom(self, obj):
         return obj.nom
@@ -1209,7 +1232,7 @@ class ValeurPointAdmin(reversion.VersionAdmin, DerniereModificationAdmin,
         '_devise_code', '_devise_nom', 'annee', 'implantation',
         'valeur', 'derniere_modification'
     )
-    list_filter = ('annee', 'devise', 'implantation__region', )
+    list_filter = ('annee', 'devise', 'implantation__zone_administrative', )
     fieldsets = (
         (None, {'fields': ('valeur', 'devise', 'implantation', 'annee')}),
     )
index c039911..96d745e 100644 (file)
@@ -33,12 +33,12 @@ class Implantation(object):
     def get_query(self, q, request):
         implantations = ref.Implantation.objects.filter(
             Q(nom__icontains=q) | Q(nom_court__icontains=q) |
-            Q(nom_long__icontains=q) | Q(region__nom__icontains=q)
+            Q(nom_long__icontains=q) | Q(zone_administrative__nom__icontains=q)
         )
         if user_gere_obj_de_sa_region(request.user):
             employe = get_employe_from_user(request.user)
             implantations = implantations.filter(
-                region=employe.implantation.region
+                zone_administrative=employe.implantation.zone_administrative
             )
         return implantations
 
index 272fecb..6333ffe 100644 (file)
@@ -89,8 +89,9 @@ class ResponsableInlineForm(forms.ModelForm):
 
 
 class MasseSalarialeForm(forms.Form):
-    region = forms.ModelChoiceField(
-        label=u'Région', queryset=ref.Region.objects.all(), required=False
+    zone_administrative = forms.ModelChoiceField(
+        label=u'Région', queryset=ref.ZoneAdministrative.objects.all(),
+        required=False
     )
     implantation = forms.ModelChoiceField(
         label=u'Implantation', queryset=ref.Implantation.objects.all(),
@@ -112,10 +113,13 @@ class MasseSalarialeForm(forms.Form):
         )
         if is_user_dans_region(user):
             employe = get_employe_from_user(user)
-            self.fields['region'].queryset = ref.Region.objects.filter(
-                id=employe.implantation.region.id
-            )
+            self.fields['zone_administrative'].queryset = \
+                    ref.ZoneAdministrative.objects.filter(
+                        code=employe.implantation.zone_administrative.code
+                    )
             self.fields['implantation'].queryset = \
                     ref.Implantation.objects.filter(
-                        region=employe.implantation.region
+                        zone_administrative=(
+                            employe.implantation.zone_administrative
+                        )
                     )
index 6b8da7e..c1a459a 100644 (file)
@@ -27,7 +27,10 @@ class SecurityManager(models.Manager):
         # TRAITEMENT NORMAL
         ############################################
         # REGION
-        q = Q(**{self.prefixe_implantation: employe.implantation.region})
+        q = Q(**{
+            self.prefixe_implantation:
+            employe.implantation.zone_administrative
+        })
 
         # SERVICE
         if self.prefixe_service \
@@ -152,7 +155,7 @@ class PosteQuerySet(ActifsQuerySet):
 
 class PosteManager(SecurityManager):
     prefixe_service = "service"
-    prefixe_implantation = "implantation__region"
+    prefixe_implantation = "implantation__zone_administrative"
 
     def get_query_set(self):
         return PosteQuerySet(self.model).select_related('type_poste')
@@ -169,7 +172,7 @@ class DossierQuerySet(ActifsQuerySet):
 
 class DossierManager(SecurityManager):
     prefixe_service = "poste__service"
-    prefixe_implantation = "poste__implantation__region"
+    prefixe_implantation = "poste__implantation__zone_administrative"
 
     def get_query_set(self):
         return DossierQuerySet(self.model) \
@@ -235,12 +238,12 @@ class ContratManager(models.Manager):
 
 class PosteComparaisonManager(SecurityManager):
     use_for_related_fields = True
-    prefixe_implantation = "implantation__region"
+    prefixe_implantation = "implantation__zone_administrative"
 
 
 class DossierComparaisonManager(SecurityManager):
     use_for_related_fields = True
-    prefixe_implantation = "implantation__region"
+    prefixe_implantation = "implantation__zone_administrative"
 
 
 class DeviseManager(models.Manager):
index 598520f..944df17 100644 (file)
@@ -341,10 +341,10 @@ class Poste_( DateActiviteMixin, models.Model,):
         )
         return representation
 
-    prefix_implantation = "implantation__region"
+    prefix_implantation = "implantation__zone_administrative"
 
-    def get_regions(self):
-        return [self.implantation.region]
+    def get_zones_administratives(self):
+        return [self.implantation.zone_administrative]
 
     def get_devise(self):
         vp = ValeurPoint.objects.filter(
@@ -629,13 +629,14 @@ class Employe(models.Model):
             pass
         return poste
 
-    prefix_implantation = "rh_dossiers__poste__implantation__region"
+    prefix_implantation = \
+            "rh_dossiers__poste__implantation__zone_administrative"
 
-    def get_regions(self):
-        regions = []
-        for d in self.dossiers.all():
-            regions.append(d.poste.implantation.region)
-        return regions
+    def get_zones_administratives(self):
+        return [
+            d.poste.implantation.zone_administrative
+            for d in self.dossiers.all()
+        ]
 
 reversion.register(Employe, format='xml', follow=[
     'pieces', 'commentaires', 'ayantdroits'
@@ -726,13 +727,14 @@ class AyantDroit(models.Model):
     def __unicode__(self):
         return u'%s %s' % (self.nom.upper(), self.prenom, )
 
-    prefix_implantation = "employe__dossiers__poste__implantation__region"
+    prefix_implantation = \
+            "employe__dossiers__poste__implantation__zone_administrative"
 
-    def get_regions(self):
-        regions = []
-        for d in self.employe.dossiers.all():
-            regions.append(d.poste.implantation.region)
-        return regions
+    def get_zones_administratives(self):
+        return [
+            d.poste.implantation.zone_administrative
+            for d in self.employe.dossiers.all()
+        ]
 
 reversion.register(AyantDroit, format='xml', follow=['commentaires'])
 
@@ -844,10 +846,10 @@ class Dossier_(DateActiviteMixin, models.Model, DevisableMixin,):
             poste = self.poste.nom_feminin
         return u'%s - %s' % (self.employe, poste)
 
-    prefix_implantation = "poste__implantation__region"
+    prefix_implantation = "poste__implantation__zone_administrative"
 
-    def get_regions(self):
-        return [self.poste.implantation.region]
+    def get_zones_administratives(self):
+        return [self.poste.implantation.zone_administrative]
 
     def remunerations(self):
         key = "%s_remunerations" % self._meta.app_label
@@ -1428,11 +1430,6 @@ class OrganismeBstg(models.Model):
     def __unicode__(self):
         return u'%s (%s)' % (self.nom, self.get_type_display())
 
-    prefix_implantation = "pays__region"
-
-    def get_regions(self):
-        return [self.pays.region]
-
 reversion.register(OrganismeBstg, format='xml')
 
 
index ca731a9..af83eed 100644 (file)
@@ -90,7 +90,7 @@ def masse_salariale(lignes, annee, titres_traitements, titres_indemnites,
         # GESTION de l'affichage des VACANTS
         if 'dossier' not in ligne.keys():
             row.add_cells([
-                ligne['poste'].implantation.region.code,
+                ligne['poste'].implantation.zone_administrative.code,
                 ligne['poste'].implantation.adresse_physique_pays.nom,
                 ligne['poste'].implantation.nom_court
             ])
@@ -158,7 +158,7 @@ def masse_salariale(lignes, annee, titres_traitements, titres_indemnites,
             continue
 
         row.add_cells([
-            ligne['poste'].implantation.region.code,
+            ligne['poste'].implantation.zone_administrative.code,
             ligne['poste'].implantation.adresse_physique_pays.nom,
             ligne['poste'].implantation.nom_court
         ])
index de978f5..206e1d6 100644 (file)
@@ -1,6 +1,6 @@
 <fieldset class="module aligned">
     <h2>Localisation</h2>
-    {% include "rh/form-row.html" with label="Région" value=dossier.poste.implantation.region %}
+    {% include "rh/form-row.html" with label="Zone administrative" value=dossier.poste.implantation.zone_administrative %}
     {% include "rh/form-row.html" with label="Implantation" value=dossier.poste.implantation %}
 </fieldset>
 
index 27afccf..19d5f5b 100644 (file)
@@ -25,7 +25,7 @@
 <div id="changelist-filter">
   <h2>{% trans 'Filter' %}</h2>
   
-  {% filter_region_contrat %}
+  {% filter_zone_administrative_contrat %}
   {% filter_implantation_contrat %}
   {% filter_type_contrat %}
   {% filter_echeance_contrat %}
@@ -57,7 +57,7 @@
     <td>{{ contrat.date_debut }}</td>
     <td>{{ contrat.date_fin|default:'' }}</td>
     <td>{{ contrat.dossier.get_statut_residence_display }}</td>
-    <td>{{ contrat.dossier.poste.implantation.region.nom }}</td>
+    <td>{{ contrat.dossier.poste.implantation.zone_administrative.nom }}</td>
     <td>{{ contrat.dossier.poste.implantation.nom }}</td>
   </tr>
   {% endfor %}
index 56af714..ae74f3c 100644 (file)
@@ -17,7 +17,7 @@
 {% block contentrapport %}
 <div id="changelist-filter">
   <h2>{% trans 'Filter' %}</h2>
-  {% filter_region_dossier %}
+  {% filter_zone_administrative_dossier %}
   {% filter_implantation_dossier %}
 </div>
 
@@ -40,7 +40,7 @@
       <td>{{ d.dernier_contrat.date_debut|default_if_none:"" }}</td>
       <td>{{ d.dernier_contrat.date_fin|default_if_none:"" }}</td>
       <td>{{ d.get_statut_residence_display }}</td>
-      <td>{{ d.poste.implantation.region.code }}</td>
+      <td>{{ d.poste.implantation.zone_administrative.code }}</td>
       <td>{{ d.poste.implantation.nom }}</td>
     </tr>
     {% endfor %}
index 73c90fa..60a3f33 100644 (file)
@@ -109,7 +109,7 @@ $(document).ready(function() {
   <tbody>
     {% for ligne in lignes %}
     <tr class="{% cycle 'row1' 'row2' %}">
-      <td>{{ ligne.poste.implantation.region.code }}</td>
+      <td>{{ ligne.poste.implantation.zone_administrative.code }}</td>
       <td>{{ ligne.poste.implantation.adresse_physique_pays.nom }}</td>
       <td>{{ ligne.poste.implantation.nom_court }}</td>
       <td class="numeric">
index 7faf777..484326c 100644 (file)
@@ -6,7 +6,8 @@ from django.utils.encoding import smart_unicode
 from django.template import Library
 from django.utils.http import urlencode
 
-from auf.django.references.models import Implantation, Region
+from auf.django.references.models import \
+        Implantation, Region, ZoneAdministrative
 
 from project import groups
 
@@ -39,6 +40,18 @@ def filter_region(context, prefix=None):
 
 
 @register.inclusion_tag('admin/filter.html', takes_context=True)
+def filter_zone_administrative(context, prefix=None):
+    label = "".join([prefix or "", "implantation__zone_administrative"])
+    return {
+        'title': u"zone administrative",
+        'choices': prepare_choices(
+            ZoneAdministrative.objects.values_list('code', 'nom'), label, context,
+            remove=['pays', 'nord_sud']
+        )
+    }
+
+
+@register.inclusion_tag('admin/filter.html', takes_context=True)
 def filter_implantation(context, prefix=None):
     label = "".join([prefix or "", "implantation"])
     return {
@@ -50,27 +63,35 @@ def filter_implantation(context, prefix=None):
 
 
 @register.inclusion_tag('admin/filter.html', takes_context=True)
-def filter_region_contrat(context):
+def filter_zone_administrative_contrat(context):
     request = context['request']
     user_groups = [g.name for g in request.user.groups.all()]
     if groups.CORRESPONDANT_RH in user_groups or\
          groups.ADMINISTRATEURS in user_groups or\
          groups.DIRECTEUR_DE_BUREAU in user_groups:
         employe = groups.get_employe_from_user(request.user)
-        regions = Region.objects.filter(id=employe.implantation.region.id)
+        zones = ZoneAdministrative.objects.filter(
+            code=employe.implantation.zone_administrative.code
+        )
     else:
-       regions = Region.objects.all()
-    return {'title': u"région",
-            'choices': prepare_choices(regions.values_list('id', 'nom'), 'dossier__poste__implantation__region', context, remove=['pays', 'nord_sud'])}
+       zones = ZoneAdministrative.objects.all()
+    return {
+        'title': u"région",
+        'choices': prepare_choices(
+            zones.values_list('code', 'nom'),
+            'dossier__poste__implantation__zone_administrative',
+            context, remove=['pays', 'nord_sud']
+        )
+    }
 
 
 @register.inclusion_tag('admin/filter.html', takes_context=True)
-def filter_region_dossier(context):
+def filter_zone_administrative_dossier(context):
     return {
         'title': u"région",
         'choices': prepare_choices(
-            Region.objects.values_list('id', 'nom'),
-            'poste__implantation__region', context,
+            ZoneAdministrative.objects.values_list('code', 'nom'),
+            'poste__implantation__zone_administrative', context,
             remove=['pays', 'nord_sud']
         )
     }
@@ -95,7 +116,9 @@ def filter_implantation_contrat(context):
          groups.ADMINISTRATEURS in user_groups or\
          groups.DIRECTEUR_DE_BUREAU in user_groups:
         employe = groups.get_employe_from_user(request.user)
-        implantations = Implantation.objects.filter(region=employe.implantation.region)
+        implantations = Implantation.objects.filter(
+            zone_administrative=employe.implantation.zone_administrative
+        )
     else:
        implantations = Implantation.objects.all()
     return {'title': u"implantation",
@@ -193,12 +216,12 @@ def filter_a_venir(context):
 
 
 @register.inclusion_tag('admin/filter_select.html', takes_context=True)
-def filter_region_remun(context):
+def filter_zone_administrative_remun(context):
     return {
         'title': u"région",
         'choices': prepare_choices(
-            Region.objects.values_list('id', 'nom'),
-            'dossiers__poste__implantation__region', context,
+            ZoneAdministrative.objects.values_list('code', 'nom'),
+            'dossiers__poste__implantation__zone_administrative', context,
             remove=['pays', 'nord_sud']
         )
     }
index fb238c3..cadadb6 100644 (file)
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 
 import datetime
+from auf.django.saml.settings import SAML_REDIRECT_FIELD_NAME
 from django.contrib.auth.models import User, Group
 from project import groups
 from auf.django.references import models as ref
@@ -158,10 +159,12 @@ class RhTest(TestCase):
         # Régions / Implantations
         #########################
         self.REGION_ACGL = ref.Region.objects.get(id=1)
+        self.ZA_ACGL = ref.ZoneAdministrative.objects.get(code=u'ACGL')
         self.IMPLANTATION_ACGL_CNF_NGAOUNDERE = ref.Implantation.objects.get(id=90)
         self.IMPLANTATION_ACGL_CNF_BANGUI = ref.Implantation.objects.get(id=85)
 
         self.REGION_BAP = ref.Region.objects.get(id=4)
+        self.ZA_BAP = ref.ZoneAdministrative.objects.get(code=u'AP')
         self.IMPLANTATION_BAP_BUREAU = ref.Implantation.objects.get(id=51)
         self.IMPLANTATION_BAP_IFI = ref.Implantation.objects.get(id=55)
 
@@ -284,7 +287,9 @@ class RhTest(TestCase):
 
     def _test_acces_ko(self, url):
         response = self.client.get(url, follow=True)
-        is_ko = response.status_code in (403, 404) or 'next' in response.context
+        is_ko = response.status_code in (403, 404) or \
+                'next' in response.context or \
+                SAML_REDIRECT_FIELD_NAME in response.context['request'].GET.keys()
         self.assertEqual(is_ko, True)
 
     def _test_anonyme(self):
index 69e3454..e14d503 100644 (file)
@@ -430,7 +430,7 @@ class RapportMasseSalarialeCalculTest(RhTest):
         self.assertEqual(len(resp.context['lignes']), 1)
 
         params = {
-                'region': self.REGION_ACGL.id,
+                'zone_administrative': self.ZA_ACGL.code,
                 'annee': self.today.year,
                 }
         resp = self.client.get(self.url, params)
index ea56d88..0dca607 100644 (file)
@@ -110,7 +110,11 @@ def rapports_contrat(request):
        groups.ADMINISTRATEURS in user_groups or\
        groups.DIRECTEUR_DE_BUREAU in user_groups:
         employe = get_employe_from_user(request.user)
-        q = q & Q(dossier__poste__implantation__region=employe.implantation.region)
+        q = q & Q(
+            dossier__poste__implantation__zone_administrative=(
+                employe.implantation.zone_administrative
+            )
+        )
 
     contrats = contrats.filter(q)
 
@@ -130,7 +134,7 @@ def rapports_contrat(request):
         ("date_debut", u"Début contrat"),
         ("date_fin", u"Fin contrat"),
         ("dossier__statut_residence", u"Statut"),
-        ("dossier__poste__implantation__region", u"Région"),
+        ("dossier__poste__implantation__zone_administrative", u"Zone administrative"),
         ("dossier__poste__implantation", u"Implantation"),
     ]
     h = SortHeaders(
@@ -168,7 +172,8 @@ def rapports_employes_sans_contrat(request):
        groups.ADMINISTRATEURS in user_groups or\
        groups.DIRECTEUR_DE_BUREAU in user_groups:
         employe = get_employe_from_user(request.user)
-        lookup_params['poste__implantation__region'] = employe.implantation.region
+        lookup_params['poste__implantation__zone_administrative'] = \
+                employe.implantation.zone_administrative
 
     
     dossiers = rh.Dossier.objects.sans_contrats_ou_echus(**lookup_params)
@@ -190,7 +195,7 @@ def rapports_employes_sans_contrat(request):
         ("rh_contrats__date_debut", u"Début contrat"),
         ("rh_contrats__date_fin", u"Fin contrat"),
         ("statut_residence", u"Statut"),
-        ("poste__implantation__region__code", u"Région"),
+        ("poste__implantation__zone_administrative__code", u"Zone administrative"),
         ("poste__implantation__nom", u"Implantation"),
     ]
     h = SortHeaders(
@@ -217,7 +222,7 @@ def rapports_employes_sans_contrat(request):
 def rapports_masse_salariale(request):
     form = MasseSalarialeForm(request.user, request.GET)
     if 'annee' in request.GET and form.is_valid():
-        region = form.cleaned_data['region']
+        zone_administrative = form.cleaned_data['zone_administrative']
         implantation = form.cleaned_data['implantation']
         annee = form.cleaned_data['annee']
         debut_annee = date(annee, 1, 1)
@@ -230,7 +235,7 @@ def rapports_masse_salariale(request):
                 .actifs(annee=annee) \
                 .select_related(
                     'poste', 'poste__implantation',
-                    'poste__implantation__region',
+                    'poste__implantation__zone_administrative',
                     'poste__implantation__adresse_physique_pays',
                     'employe', 'poste__type_poste', 'classement',
                     'statut', 'organisme_bstg'
@@ -251,8 +256,8 @@ def rapports_masse_salariale(request):
                         )
                     }
                 )
-        if region:
-            dossiers = dossiers.filter(poste__implantation__region=region)
+        if zone_administrative:
+            dossiers = dossiers.filter(poste__implantation__zone_administrative=zone_administrative)
         if implantation:
             dossiers = dossiers.filter(poste__implantation=implantation)
 
@@ -277,8 +282,8 @@ def rapports_masse_salariale(request):
             raise rh.RemunIntegrityException("Toutes les remunerations ne disposent pas d'un "
                 "taux de change pour l'année %d" % annee)
 
-        if region:
-            remuns = remuns.filter(dossier__poste__implantation__region=region)
+        if zone_administrative:
+            remuns = remuns.filter(dossier__poste__implantation__zone_administrative=zone_administrative)
         if implantation:
             remuns = remuns.filter(dossier__poste__implantation=implantation)
         remuns_par_dossier = defaultdict(list)
@@ -425,8 +430,8 @@ def rapports_masse_salariale(request):
                         'taux_change': 'rh_tauxchange.taux'
                     }
                 )
-        if region:
-            postes = postes.filter(implantation__region=region)
+        if zone_administrative:
+            postes = postes.filter(implantation__zone_administrative=zone_administrative)
         if implantation:
             postes = postes.filter(implantation=implantation)
         postes = list(postes)
@@ -672,8 +677,12 @@ def employe_apercu(request, employe_id):
        groups.ADMINISTRATEURS in user_groups or\
        groups.DIRECTEUR_DE_BUREAU in user_groups:
         employe_connecte = get_employe_from_user(request.user)
-        q = Q(employe=employe) & Q(poste__implantation__region=employe_connecte.implantation.region)
-    
+        q = Q(employe=employe) & Q(
+            poste__implantation__zone_administrative=(
+                employe_connecte.implantation.zone_administrative
+            )
+        )
+
     dossiers = rh.Dossier.objects.filter(q).order_by('-date_debut')
 
     c = {
index fd2c315..4459b14 100644 (file)
@@ -24,15 +24,18 @@ DATE_INPUT_FORMATS = ('%d-%m-%Y', )
 SESSION_SAVE_EVERY_REQUEST = True
 SESSION_EXPIRE_AT_BROWSER_CLOSE = True
 
+PROJECT_ROOT = os.path.dirname(__file__)
+SITE_ROOT = os.path.dirname(PROJECT_ROOT)
+
 # Absolute path to the directory that holds media.
 # Example: "/home/media/media.lawrence.com/"
-MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'media')
-PRIVE_MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'media_prive')
+MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'media')
+PRIVE_MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'media_prive')
 
 STATICFILES_DIRS = (
-    os.path.join(os.path.dirname(__file__), 'assets'),
+    os.path.join(PROJECT_ROOT, 'assets'),
 )
-STATIC_ROOT = os.path.join(os.path.dirname(__file__), 'static')
+STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
 STATIC_URL = '/static/'
 
 # URL that handles the media served from MEDIA_ROOT. Make sure to use a
@@ -55,6 +58,7 @@ MIDDLEWARE_CLASSES = (
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'auf.django.saml.middleware.SPMiddleware',
     'auf.django.piwik.middleware.TrackMiddleware',
     'django.middleware.doc.XViewMiddleware',
     'reversion.middleware.RevisionMiddleware',
@@ -70,6 +74,8 @@ INSTALLED_APPS = (
     'auf.django.workflow',
     'auf.django.permissions',
     'auf.django.emploi',
+    'auf.django.saml',
+    'auf.django.export',
     'admin_tools',
     'admin_tools.theming',
     'admin_tools.menu',
@@ -108,11 +114,9 @@ TEMPLATE_CONTEXT_PROCESSORS = (
 )
 
 AUTHENTICATION_BACKENDS = (
-    'auf.django.auth.backends.CascadeBackend',
+    'auf.django.saml.backends.SPBackend',
     'auf.django.permissions.backends.AuthenticationBackend',
 )
-LOGIN_URL = "/connexion"
-LOGIN_REDIRECT_URL = "/"
 
 TEMPLATE_DIRS = (
     os.path.join(os.path.dirname(__file__), "templates"),
index cdc8f6d..4f6a8c5 100644 (file)
@@ -1,11 +1 @@
-<ul>
-    {% if user.is_authenticated %}
-      <li class="username">{{ user }}</li>
-      {% if perms.recrutement or user_in_dae_groupes or perms.rh %}
-        <li><a href="{% url admin:index %}">Administration</a></li>
-      {% endif %}
-      <li><a href="{% url django.contrib.auth.views.logout %}?next=/">Déconnexion</a></li>
-    {% else %}
-      <li><a href="{% url django.contrib.auth.views.login %}?next={{request.path}}">Connexion</a></li>
-    {% endif %}
-</ul>
+{% include "saml/auth.html" %}
index 856a8b0..519d264 100644 (file)
@@ -6,31 +6,23 @@
 
 {% block main %}
 
-{% if not request.user.is_authenticated %}
-<h1>Connexion</h1>
+{% for k,v in meta.items %}
+<p>{{ k }} : {{ v }}</p>
+{% endfor %}
 
-    <form method="post" action="{% url django.contrib.auth.views.login %}">{% csrf_token %}
-        <table>
-        {{ form.as_table }}
-        </table>
-        <input type="submit" value="Se connecter" />
-        <input type="hidden" name="next" value="{{ next }}" />
-    </form>
+<h1>Vos droits d'accès</h1>
+{% if request.user.groups.all %}
+  <p>Vous faîtes partie des groupes suivants : </p>
+  <ul>
+      {% for g in request.user.groups.all %}
+      <li>{{ g.name }}</li>
+      {% endfor %}
+  </ul>
 {% else %}
-    <h1>Vos droits d'accès</h1>
-    {% if request.user.groups.all %}
-      <p>Vous faîtes partie des groupes suivants : </p>
-      <ul>
-          {% for g in request.user.groups.all %}
-          <li>{{ g.name }}</li>
-          {% endfor %}
-      </ul>
-    {% else %}
-      <p>
-      Vous n'avez actuellement aucun droit dans ce système.<br />
-      Contactez la DRH si vous croyez qu'il s'agit d'une erreur.
-      </p>
-    {% endif %}
+  <p>
+  Vous n'avez actuellement aucun droit dans ce système.<br />
+  Contactez la DRH si vous croyez qu'il s'agit d'une erreur.
+  </p>
 {% endif %}
 
 {% endblock %}
index cfb73df..f3d39c1 100644 (file)
     <a href="{% url admin:app_list app_label="rh" %}">Gestion des personnels</a>
   </li>
   {% endif %}
+
+  {% if user.is_staff %}
+  <li>
+    <a href="{% url admin:index %}">Administration</a>
+  </li>
+  {% endif %}
+
 </ul>
index 5334386..dd06a52 100644 (file)
@@ -4,6 +4,7 @@ from django.contrib import admin
 from urldecorators.defaults import patterns, include, url
 from urldecorators.defaults import handler500  # NOQA
 from auf.django import permissions
+from auf.django.saml import settings as saml_settings
 from project.monkey import patch_ajax_selects
 
 patch_ajax_selects()
@@ -13,28 +14,43 @@ permissions.autodiscover()
 
 urlpatterns = patterns(
     '',
-    url(r'^$', 'project.views.index', name='index'),
-    url(r'^admin_tools/', include('admin_tools.urls')),
+    url(r'^$', 'project.views.index', name='index',
+        decorators=['auf.django.saml.decorators.login_required']),
+
+    url(r'^', include('auf.django.saml.urls')),
+
+    url(r'^admin_tools/', include('admin_tools.urls'),
+        decorators=['auf.django.saml.decorators.login_required']),
     (r'^admin/', include(admin.site.urls)),
+
     url(r'^api/(?P<method>[a-z_-]+)/(?P<offre_id>\d+)/$',
         'project.recrutement.api.api', name='recrutement_api'),
     url(r'^api/(?P<method>[a-z_-]+)/$', 'project.recrutement.api.api',
         name='recrutement_api'),
-    (r'^connexion/$', 'django.contrib.auth.views.login'),
-    (r'^deconnexion/$', 'django.contrib.auth.views.logout'),
-    #url(r'^private_files/', include('private_files.urls')),
-    url(r'^captcha/', include('captcha.urls')),
-    (r'^ajax_select/', include('ajax_select.urls')),
-    (r'^tinymce/', include('tinymce.urls')),
-    url(r'^prive/(?P<filename>.*)$', 'project.views.piece'),
+
+    url(r'^captcha/', include('captcha.urls'),
+        decorators=['auf.django.saml.decorators.login_required']),
+    url(r'^ajax_select/', include('ajax_select.urls'),
+        decorators=['auf.django.saml.decorators.login_required']),
+    url(r'^tinymce/', include('tinymce.urls'),
+        decorators=['auf.django.saml.decorators.login_required']),
+    url(r'^prive/(?P<filename>.*)$', 'project.views.piece',
+        decorators=['auf.django.saml.decorators.login_required']),
 
     # apps
     url(r'^dae/', include('project.dae.urls'),
-        decorators=['django.contrib.auth.decorators.login_required']),
+        decorators=['auf.django.saml.decorators.login_required']),
     url(r'^recrutement/', include('project.recrutement.urls'),
-        decorators=['django.contrib.auth.decorators.login_required']),
+        decorators=['auf.django.saml.decorators.login_required']),
     url(r'^rh/', include('project.rh.urls'),
-        decorators=['django.contrib.auth.decorators.login_required']),
+        decorators=['auf.django.saml.decorators.login_required']),
 
-    url(r'^qbe/', include('django_qbe.urls')),
+    url(r'^qbe/', include('django_qbe.urls'),
+        decorators=['auf.django.saml.decorators.login_required']),
 )
+
+if not saml_settings.SAML_AUTH:
+    urlpatterns += patterns(
+        '',
+        (r'^', include('auf.django.saml.mellon_urls')),
+    )
index 7466549..fd83264 100644 (file)
@@ -4,8 +4,8 @@ import os
 from sendfile import sendfile
 
 from django.conf import settings
+from django.shortcuts import render
 from django.contrib.auth.decorators import login_required
-from django.contrib.auth.views import login
 from django.http import Http404
 
 from project.decorators import redirect_interdiction
@@ -13,8 +13,10 @@ from project.rh import models as rh_models
 from project.dae import models as dae_models
 
 
+@login_required
 def index(request):
-    return login(request, template_name='index.html')
+    c = {}
+    return render(request, 'index.html', c)
 
 
 @login_required
index 620696b..d926cbb 100644 (file)
@@ -29,7 +29,15 @@ except AttributeError:
 SORT_CHOICES = (
     ("", ""),
     ("asc", _("Ascending")),
-    ("des", _("Descending")),
+    ("desc", _("Descending")),
+)
+
+STATUS_CHOICES = (
+    ("", "Tous"),
+    ("inactive", "Inactifs"),
+    ("active", "Actifs"),
+    ("futur", "Futurs"),
+    ("unknown", "Inconnus"),
 )
 
 
@@ -38,6 +46,8 @@ class QueryByExampleForm(forms.Form):
     model = forms.CharField(label=_("Model"))
     field = forms.CharField(label=_("Field"))
     criteria = forms.CharField(label=_("Criteria"), required=False)
+    status = forms.ChoiceField(label=_("Statut"), choices=STATUS_CHOICES,
+                             required=False)
     sort = forms.ChoiceField(label=_("Sort"), choices=SORT_CHOICES,
                              required=False)
 
@@ -59,6 +69,10 @@ class QueryByExampleForm(forms.Form):
             field_attr_class = "qbeFillFields enable:sort,%s" % criteria_names
         else:
             field_attr_class = "qbeFillFields enable:sort,criteria"
+        status_widget = forms.Select(attrs={'disabled': "disabled",
+                                          'class': 'hidden'},
+                                   choices=STATUS_CHOICES)
+        self.fields['status'].widget = status_widget
         field_widget = forms.Select(attrs={'class': field_attr_class})
         self.fields['field'].widget = field_widget
 
@@ -79,6 +93,7 @@ class BaseQueryByExampleFormSet(BaseFormSet):
     _selects = []
     _froms = []
     _wheres = []
+    _statuses = []
     _sorts = []
     _params = []
     _models = {}
@@ -120,7 +135,7 @@ class BaseQueryByExampleFormSet(BaseFormSet):
             # Don't bother validating the formset unless each form is valid on
             # its own
             return
-        selects, froms, wheres, sorts, params = self.get_query_parts()
+        selects, froms, wheres, sorts, params, statuses = self.get_query_parts()
         if not selects:
             validation_message = _(u"At least you must check a row to get.")
             raise forms.ValidationError, validation_message
@@ -129,6 +144,7 @@ class BaseQueryByExampleFormSet(BaseFormSet):
         self._wheres = wheres
         self._sorts = sorts
         self._params = params
+        self._statuses = statuses
 
     def translate_model_to_db_table(self, model_name):
         """
@@ -152,6 +168,7 @@ class BaseQueryByExampleFormSet(BaseFormSet):
         wheres = []
         sorts = []
         params = []
+        statuses = []
         app_model_labels = None
         lookup_cast = self._db_operations.lookup_cast
         qn = self._db_operations.quote_name
@@ -176,13 +193,20 @@ class BaseQueryByExampleFormSet(BaseFormSet):
             show = data["show"]
             criteria = data["criteria"]
             sort = data["sort"]
+            status = data["status"]
             db_field = u"%s.%s" % (qn(model), qn(field))
             operator, over = criteria
-            is_join = operator.lower() == 'join'
+            try:
+                is_join = operator.lower() == 'join'
+            except:
+                is_join = False
             if show and not is_join:
                 selects.append(db_field)
             if sort:
-                sorts.append(db_field)
+                sorts.append((db_field, sort))
+            if status:
+                statuses.append((model, status))
+            
             if all(criteria):
                 if is_join:
                     over_split = over.lower().rsplit(".", 1)
@@ -191,9 +215,14 @@ class BaseQueryByExampleFormSet(BaseFormSet):
                     
                     if model in self._models:
                         _field = self._models[model]._meta.get_field(field)
+                        try:
+                            _db_column = qn(_field.db_column)
+                        except:
+                            _db_column = qn(_field.attname)
+
                         join = u"%s.%s = %s.%s" \
                                % (join_model, join_field, qn(model),
-                                  qn(_field.db_column))
+                                  qn(_db_column))
                     else:
                         join = u"%s.%s = %s" \
                                % (join_model, join_field,
@@ -216,18 +245,40 @@ class BaseQueryByExampleFormSet(BaseFormSet):
                                      db_operator))
             if qn(model) not in froms and model in self._db_table_names:
                 froms.append(qn(model))
-        return selects, froms, wheres, sorts, params
+        return selects, froms, wheres, sorts, params, statuses
 
     def get_raw_query(self, limit=None, offset=None, count=False,
                       add_extra_ids=False, add_params=False):
+        qn = self._db_operations.quote_name
         if self._raw_query:
             return self._raw_query
         if self._sorts:
-            order_by = u"ORDER BY %s" % (", ".join(self._sorts))
+            order_by = u"ORDER BY %s" % (", ".join([" ".join(x) for x in self._sorts]))
         else:
             order_by = u""
-        if self._wheres:
-            wheres = u"WHERE %s" % (" AND ".join(self._wheres))
+        _my_wheres = self._wheres
+        if self._statuses:
+            for m, s in self._statuses:
+                # Test cas spécial: Pour état employé, vérifier via les dossiers.
+                if m == 'rh_employe':
+                    m = qn('rh_dossier')
+                    if m not in self._froms:
+                        self._froms.append(m)
+                        _my_wheres.append("`rh_employe`.`id` = `rh_dossier`.`employe`")
+                if s == "inactive":
+                    _my_wheres.append("%s.date_fin < DATE(NOW())" % m)
+                if s == "active":
+                    _my_wheres.append(
+                        "(((%s.`date_debut` <= DATE(NOW()) OR %s.`date_debut` IS NULL) AND %s.`date_fin` >= DATE(NOW())) OR "
+                        "((%s.`date_fin` >= DATE(NOW()) OR %s.`date_fin` IS NULL) AND %s.`date_debut` <= DATE(NOW())) OR "
+                        "(%s.`date_debut` <= DATE(NOW()) AND %s.`date_fin` >= DATE(NOW())))"
+                        % (m, m, m, m, m, m, m, m))
+                if s == "futur":
+                    _my_wheres.append("%s.date_debut > DATE(NOW())" % m)
+                if s == "unknown":
+                    _my_wheres.append("(%s.date_debut IS NULL AND %s.date_fin IS NULL)" % (m, m))
+        if _my_wheres:
+            wheres = u"WHERE %s" % (" AND ".join(_my_wheres))
         else:
             wheres = u""
         if count:
diff --git a/src/qbe/django_qbe/locale/fr/LC_MESSAGES/django.mo b/src/qbe/django_qbe/locale/fr/LC_MESSAGES/django.mo
new file mode 100644 (file)
index 0000000..991632a
Binary files /dev/null and b/src/qbe/django_qbe/locale/fr/LC_MESSAGES/django.mo differ
diff --git a/src/qbe/django_qbe/locale/fr/fr_CA/LC_MESSAGES/django.mo b/src/qbe/django_qbe/locale/fr/fr_CA/LC_MESSAGES/django.mo
new file mode 100644 (file)
index 0000000..991632a
Binary files /dev/null and b/src/qbe/django_qbe/locale/fr/fr_CA/LC_MESSAGES/django.mo differ
diff --git a/src/qbe/django_qbe/locale/fr/fr_CA/LC_MESSAGES/django.po b/src/qbe/django_qbe/locale/fr/fr_CA/LC_MESSAGES/django.po
new file mode 100644 (file)
index 0000000..f5e03eb
--- /dev/null
@@ -0,0 +1,219 @@
+# django-qbe FR translations
+# Copyright (C) 2011
+# This file is distributed under the same license as the django-qbe package.
+# Olivier Larchevêque <olivier.larcheveque@auf.org>, 2011
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-08-02 13:25+0000\n"
+"PO-Revision-Date: 2011-08-02 13:25+0000\n"
+"Last-Translator: Olivier Larchevêque <olivier.larcheveque@auf.org>\n"
+"Language-Team: Olivier Larchevêque <olivier.larcheveque@auf.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: forms.py:29
+msgid "Ascending"
+msgstr "Croissant"
+
+#: forms.py:30
+msgid "Descending"
+msgstr "Décroissant"
+
+#: forms.py:35 templates/qbe.html:48 templates/qbe.html.py:72
+msgid "Show"
+msgstr "Voir"
+
+#: forms.py:36 templates/qbe.html:49
+msgid "Model"
+msgstr "Modèle"
+
+#: forms.py:37 templates/qbe.html:50
+msgid "Field"
+msgstr "Champs"
+
+#: forms.py:38 templates/qbe.html:52
+msgid "Criteria"
+msgstr "Critère"
+
+#: forms.py:39 templates/qbe.html:51
+msgid "Sort"
+msgstr "Trier"
+
+#: forms.py:123
+msgid "At least you must check a row to get."
+msgstr "Sélectionner au moins une ligne à afficher."
+
+#: forms.py:320
+msgid "#"
+msgstr ""
+
+#: views.py:57 views.py:118 views.py:170
+msgid "Query by Example"
+msgstr "Constructeur de requêtes (QBE)"
+
+#: views.py:169
+msgid "Reports"
+msgstr "Rapports"
+
+#: widgets.py:10
+msgid "is equal to"
+msgstr "égal à"
+
+#: widgets.py:11
+msgid "contains"
+msgstr "contient"
+
+#: widgets.py:12
+msgid "matchs regex"
+msgstr "expression régulière"
+
+#: widgets.py:13
+msgid "starts with"
+msgstr "commence par"
+
+#: widgets.py:14
+msgid "ends with"
+msgstr "fini par"
+
+#: widgets.py:15
+msgid "is greater than"
+msgstr "est supérieur à"
+
+#: widgets.py:16
+msgid "is greater than or equal to"
+msgstr "est supérieur ou égal à"
+
+#: widgets.py:17
+msgid "is less than"
+msgstr "est inférieur à"
+
+#: widgets.py:18
+msgid "is less than or equal to"
+msgstr "est inférieur ou égal à"
+
+#: widgets.py:19
+msgid "(i) is equal to"
+msgstr "(i) est égal à"
+
+#: widgets.py:20
+msgid "(i) contains"
+msgstr "(i) contient"
+
+#: widgets.py:21
+msgid "(i) matchs regex"
+msgstr "(i) expression régulière"
+
+#: widgets.py:22
+msgid "(i) starts with"
+msgstr "(i) commence par"
+
+#: widgets.py:23
+msgid "(i) ends with"
+msgstr "(i) fini par"
+
+#: widgets.py:24
+msgid "joins to"
+msgstr "jointure sur"
+
+#: widgets.py:33
+msgid "Check this"
+msgstr ""
+
+#: templates/qbe.html:18 templates/qbe_results.html:9
+msgid "Home"
+msgstr "Accueil"
+
+#: templates/qbe.html:27
+msgid "Diagram"
+msgstr "Diagramme"
+
+#: templates/qbe.html:30
+msgid "Tabular"
+msgstr "Tables"
+
+#: templates/qbe.html:33 templates/qbe.html.py:96
+msgid "Models"
+msgstr "Modèles"
+
+#: templates/qbe.html:53
+msgid "Delete"
+msgstr "Supprimer"
+
+#: templates/qbe.html:72
+msgid "rows"
+msgstr "lignes"
+
+#: templates/qbe.html:74
+msgid "Auto complete"
+msgstr "Auto-complétion"
+
+#: templates/qbe.html:76
+msgid "Run"
+msgstr "Exécuter"
+
+#: templates/qbe.html:80
+msgid "Database"
+msgstr "Base de données"
+
+#: templates/qbe_results.html:9
+msgid "Results"
+msgstr "Résultats"
+
+#: templates/qbe_results.html:21
+#, fuzzy
+msgid "Showing all"
+msgstr "Tout afficher"
+
+#: templates/qbe_results.html:21 templates/qbe_results.html.py:23
+#: templates/qbe_results.html:82
+msgid "result"
+msgstr "résultat"
+
+#: templates/qbe_results.html:23
+msgid "Showing from"
+msgstr "Afficher de"
+
+#: templates/qbe_results.html:23
+msgid "to"
+msgstr "à"
+
+#: templates/qbe_results.html:23
+msgid "of"
+msgstr "de"
+
+#: templates/qbe_results.html:27
+msgid "show first ones"
+msgstr "Montrer les premiers résultats"
+
+#: templates/qbe_results.html:29
+msgid "show all"
+msgstr "Tout afficher"
+
+#: templates/qbe_results.html:31
+msgid "edit query"
+msgstr "Modifier la requête"
+
+#: templates/qbe_results.html:32
+msgid "view query"
+msgstr "Voir la requête"
+
+#: templates/qbe_results.html:36
+msgid "Save query as"
+msgstr "Sauvegarder la requête comme"
+
+#: templates/qbe_results.html:39
+msgid "Drag this yo your bookmarks bar to save this query"
+msgstr "Glisser le lien sur vos favoris pour sauvegarder la requête"
+
+#: templates/qbe_results.html:39
+msgid "bookmark"
+msgstr "favori"
+
+#: templates/qbe_results.html:43
+msgid "Export to"
+msgstr "Exporter en"
diff --git a/src/qbe/django_qbe/locale/fr_CA/LC_MESSAGES/django.mo b/src/qbe/django_qbe/locale/fr_CA/LC_MESSAGES/django.mo
deleted file mode 100644 (file)
index 991632a..0000000
Binary files a/src/qbe/django_qbe/locale/fr_CA/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/src/qbe/django_qbe/locale/fr_CA/LC_MESSAGES/django.po b/src/qbe/django_qbe/locale/fr_CA/LC_MESSAGES/django.po
deleted file mode 100644 (file)
index f5e03eb..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-# django-qbe FR translations
-# Copyright (C) 2011
-# This file is distributed under the same license as the django-qbe package.
-# Olivier Larchevêque <olivier.larcheveque@auf.org>, 2011
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-08-02 13:25+0000\n"
-"PO-Revision-Date: 2011-08-02 13:25+0000\n"
-"Last-Translator: Olivier Larchevêque <olivier.larcheveque@auf.org>\n"
-"Language-Team: Olivier Larchevêque <olivier.larcheveque@auf.org>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: forms.py:29
-msgid "Ascending"
-msgstr "Croissant"
-
-#: forms.py:30
-msgid "Descending"
-msgstr "Décroissant"
-
-#: forms.py:35 templates/qbe.html:48 templates/qbe.html.py:72
-msgid "Show"
-msgstr "Voir"
-
-#: forms.py:36 templates/qbe.html:49
-msgid "Model"
-msgstr "Modèle"
-
-#: forms.py:37 templates/qbe.html:50
-msgid "Field"
-msgstr "Champs"
-
-#: forms.py:38 templates/qbe.html:52
-msgid "Criteria"
-msgstr "Critère"
-
-#: forms.py:39 templates/qbe.html:51
-msgid "Sort"
-msgstr "Trier"
-
-#: forms.py:123
-msgid "At least you must check a row to get."
-msgstr "Sélectionner au moins une ligne à afficher."
-
-#: forms.py:320
-msgid "#"
-msgstr ""
-
-#: views.py:57 views.py:118 views.py:170
-msgid "Query by Example"
-msgstr "Constructeur de requêtes (QBE)"
-
-#: views.py:169
-msgid "Reports"
-msgstr "Rapports"
-
-#: widgets.py:10
-msgid "is equal to"
-msgstr "égal à"
-
-#: widgets.py:11
-msgid "contains"
-msgstr "contient"
-
-#: widgets.py:12
-msgid "matchs regex"
-msgstr "expression régulière"
-
-#: widgets.py:13
-msgid "starts with"
-msgstr "commence par"
-
-#: widgets.py:14
-msgid "ends with"
-msgstr "fini par"
-
-#: widgets.py:15
-msgid "is greater than"
-msgstr "est supérieur à"
-
-#: widgets.py:16
-msgid "is greater than or equal to"
-msgstr "est supérieur ou égal à"
-
-#: widgets.py:17
-msgid "is less than"
-msgstr "est inférieur à"
-
-#: widgets.py:18
-msgid "is less than or equal to"
-msgstr "est inférieur ou égal à"
-
-#: widgets.py:19
-msgid "(i) is equal to"
-msgstr "(i) est égal à"
-
-#: widgets.py:20
-msgid "(i) contains"
-msgstr "(i) contient"
-
-#: widgets.py:21
-msgid "(i) matchs regex"
-msgstr "(i) expression régulière"
-
-#: widgets.py:22
-msgid "(i) starts with"
-msgstr "(i) commence par"
-
-#: widgets.py:23
-msgid "(i) ends with"
-msgstr "(i) fini par"
-
-#: widgets.py:24
-msgid "joins to"
-msgstr "jointure sur"
-
-#: widgets.py:33
-msgid "Check this"
-msgstr ""
-
-#: templates/qbe.html:18 templates/qbe_results.html:9
-msgid "Home"
-msgstr "Accueil"
-
-#: templates/qbe.html:27
-msgid "Diagram"
-msgstr "Diagramme"
-
-#: templates/qbe.html:30
-msgid "Tabular"
-msgstr "Tables"
-
-#: templates/qbe.html:33 templates/qbe.html.py:96
-msgid "Models"
-msgstr "Modèles"
-
-#: templates/qbe.html:53
-msgid "Delete"
-msgstr "Supprimer"
-
-#: templates/qbe.html:72
-msgid "rows"
-msgstr "lignes"
-
-#: templates/qbe.html:74
-msgid "Auto complete"
-msgstr "Auto-complétion"
-
-#: templates/qbe.html:76
-msgid "Run"
-msgstr "Exécuter"
-
-#: templates/qbe.html:80
-msgid "Database"
-msgstr "Base de données"
-
-#: templates/qbe_results.html:9
-msgid "Results"
-msgstr "Résultats"
-
-#: templates/qbe_results.html:21
-#, fuzzy
-msgid "Showing all"
-msgstr "Tout afficher"
-
-#: templates/qbe_results.html:21 templates/qbe_results.html.py:23
-#: templates/qbe_results.html:82
-msgid "result"
-msgstr "résultat"
-
-#: templates/qbe_results.html:23
-msgid "Showing from"
-msgstr "Afficher de"
-
-#: templates/qbe_results.html:23
-msgid "to"
-msgstr "à"
-
-#: templates/qbe_results.html:23
-msgid "of"
-msgstr "de"
-
-#: templates/qbe_results.html:27
-msgid "show first ones"
-msgstr "Montrer les premiers résultats"
-
-#: templates/qbe_results.html:29
-msgid "show all"
-msgstr "Tout afficher"
-
-#: templates/qbe_results.html:31
-msgid "edit query"
-msgstr "Modifier la requête"
-
-#: templates/qbe_results.html:32
-msgid "view query"
-msgstr "Voir la requête"
-
-#: templates/qbe_results.html:36
-msgid "Save query as"
-msgstr "Sauvegarder la requête comme"
-
-#: templates/qbe_results.html:39
-msgid "Drag this yo your bookmarks bar to save this query"
-msgstr "Glisser le lien sur vos favoris pour sauvegarder la requête"
-
-#: templates/qbe_results.html:39
-msgid "bookmark"
-msgstr "favori"
-
-#: templates/qbe_results.html:43
-msgid "Export to"
-msgstr "Exporter en"
index 7564825..ad8fb80 100644 (file)
@@ -166,3 +166,7 @@ input.qbeCheckModels {
     overflow: auto;
     margin-top: 10px;
 }
+
+.qbeTabular .hidden {
+       display: none;
+}
index 5f230bb..7ef17f5 100644 (file)
@@ -199,7 +199,8 @@ qbe.Core = function() {};
                         optFields.push(option);
                     }
                 }
-                $("#"+ domTo).html('<option value="">*</option>' + optPrimaries.join("") + optForeigns.join("") + optManies.join("") + optFields.join(""));
+                optEtat = '<option value="status">État</option>'
+                $("#"+ domTo).html('<option value="">*</option>' + optPrimaries.join("") + optForeigns.join("") + optManies.join("") + optFields.join("") + optEtat);
                 // We need to raise change event
                 $("#"+ domTo).change();
             }
@@ -216,11 +217,32 @@ qbe.Core = function() {};
             css = $(this).attr("class");
             cssSplit = css.split("enable:")
             inputs = cssSplit[cssSplit.length-1].split(",");
+            if (field == 'status') {
+                $("#"+ prefix + "-sort").attr("disabled", "disabled");
+                $("#"+ prefix + "-sort").val("");
+                $("#"+ prefix + "-criteria").attr("disabled", "disabled");
+                $("#"+ prefix + "-criteria").val("");
+                $("#"+ prefix + "-criteria").addClass("hidden");
+                $("#"+ prefix + "-criteria_0").attr("disabled", "disabled");
+                $("#"+ prefix + "-criteria_0").val("");
+                $("#"+ prefix + "-criteria_0").addClass("hidden");
+                $("#"+ prefix + "-criteria_1").attr("disabled", "disabled");
+                $("#"+ prefix + "-criteria_1").val("");
+                $("#"+ prefix + "-criteria_1").addClass("hidden");
+                $("#"+ prefix + "-status").removeClass("hidden");
+                $("#"+ prefix + "-status").removeAttr("disabled");
+
+            }
+            else {
+                $("#"+ prefix + "-status").val("");
+                $("#"+ prefix + "-status").addClass("hidden");
+
             for(var i=0; i<inputs.length; i++) {
                 input = inputs[i];
                 domTo = prefix +"-"+ input;
                 if (field) {
                     $("#"+ domTo).removeAttr("disabled");
+                    $("#"+ domTo).removeClass("hidden");
                 } else {
                     $("#"+ domTo).attr("disabled", "disabled");
                     $("#"+ domTo).val("");
@@ -262,6 +284,7 @@ qbe.Core = function() {};
                     }
                 }
             }
+            }
         };
 
         /**
index 99a54be..bb4763c 100644 (file)
@@ -60,7 +60,7 @@
                 <td>{{ form.model.errors }}{{ form.model }}</td>
                 <td>{{ form.field.errors }}{{ form.field }}</td>
                 <td>{{ form.sort.errors }}{{ form.sort }}</td>
-                <td>{{ form.criteria.errors }}{{ form.criteria }}</td>
+                <td>{{ form.criteria.errors }}{{ form.criteria }}{{ form.status }}</td>
                 <td class="delete"></td>
             </tr>
         {% endfor %}
index cc9a84a..7fcf178 100644 (file)
@@ -63,6 +63,9 @@ auf.django.emploi = 1.2dev
 # Added by Buildout Versions at 2012-06-15 14:24:42.911205
 odsgen = 0.1
 
+# Added by Buildout Versions at 2012-07-10 15:40:30.011741
+auf.django.export = 0.4
+
 # Added by Buildout Versions at 2012-07-11 15:30:58.885863
 auf.django.references = 0.21
 
@@ -74,3 +77,6 @@ raven = 2.0.4
 
 # Added by Buildout Versions at 2012-09-18 10:17:13.131666
 auf.django.piwik = 1.7
+
+# Added by Buildout Versions at 2012-09-19 14:46:17.866203
+auf.django.saml = 1.11