merge regio
authorOlivier Larchevêque <olivier.larcheveque@auf.org>
Thu, 27 Sep 2012 18:24:09 +0000 (14:24 -0400)
committerOlivier Larchevêque <olivier.larcheveque@auf.org>
Thu, 27 Sep 2012 18:24:09 +0000 (14:24 -0400)
52 files changed:
buildout.cfg
project/assets/js/dae-poste.js
project/assets/js/tous-aucun.js [new file with mode: 0644]
project/conf.py.edit
project/dae/catalogues.py
project/dae/forms.py
project/dae/migrations/0083_auto__chg_field_poste_salaire_min__chg_field_poste_indemn_max__chg_fie.py [new file with mode: 0644]
project/dae/models.py
project/dae/test/poste.py
project/dae/views.py
project/dashboard.py
project/menu.py
project/recrutement/admin.py
project/recrutement/admin.py_ [new file with mode: 0644]
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/test/candidat.py [new file with mode: 0644]
project/recrutement/test/common.py
project/recrutement/tests.py
project/recrutement/views.py
project/rh/change_list.py
project/rh/historique.py
project/rh/managers.py
project/rh/migrations/0036_auto__chg_field_poste_salaire_min__chg_field_poste_indemn_max__chg_fie.py [new file with mode: 0644]
project/rh/models.py
project/rh/templates/rh/rapports/historique_des_modifications.html
project/rh/test/common.py
project/rh/test/employe.py
project/rh/test/manager.py [new file with mode: 0644]
project/rh/test/rapport.py
project/rh/tests.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 076ff10..03068a0 100644 (file)
@@ -9,18 +9,24 @@ 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/
     http://pypi.auf.org/simple/odsgen/
+
 develop = src/qbe
     src/auf.django.metadata
+
 eggs =
     django
     south
+    raven
     django-admin-tools
     django-ajax-selects
     django-alphafilter
@@ -34,12 +40,15 @@ 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
     auf.django.skin
     auf.django.workflow
+    auf.django.piwik
     auf.recipe.django
     odsgen
     django-picklefield
index ea7b841..56e8574 100644 (file)
@@ -189,7 +189,10 @@ $(document).ready(function() {
     sélectionnée.
     Lorsque l'implantation est changée, on ajuste les valeurs de points en fonction de cette sélection */
     var implantation_id = $("#id_implantation").val();
-    if (implantation_id) {
+    var null_vp_min = $("#valeur_point_min").val() == '';
+    var null_vp_max = $("#valeur_point_max").val() == '';
+
+    if (implantation_id && null_vp_min && null_vp_max) {
         charger_postes(implantation_id);
         charger_valeurs_point(implantation_id);
     }
diff --git a/project/assets/js/tous-aucun.js b/project/assets/js/tous-aucun.js
new file mode 100644 (file)
index 0000000..564e37c
--- /dev/null
@@ -0,0 +1,12 @@
+
+$(document).ready(function() {
+
+        $(".tous-handler").click(function() {
+            $('.check-batch input[type=checkbox]').attr('checked', true);
+            });
+
+        $(".aucun-handler").click(function() {
+            $('.check-batch input[type=checkbox]').attr('checked', false);
+            });
+
+        });
index 0f33865..114cec0 100644 (file)
@@ -15,3 +15,5 @@ EMAIL_FROM = ''
 ROA_API_KEY = ''
 
 AUTH_PASSWORD_REQUIRED = True
+
+PIWIK_TOKEN = ''
index ba2d0e3..9c1dc52 100644 (file)
@@ -122,7 +122,8 @@ class Poste(object):
             })
 
         user_groupes = [g.name for g in request.user.groups.all()]
-        if groups.DRH_NIVEAU_1 in user_groupes:
+        if groups.DRH_NIVEAU_1 in user_groupes or \
+           groups.DRH_NIVEAU_2 in user_groupes:
             q_filtre = q_recherche
         else:
             q_filtre = q_place & q_recherche
index e2007a8..537b94d 100644 (file)
@@ -88,7 +88,8 @@ def _implantation_choices(obj, request):
 
     # TRAITEMENT DRH
     user_groupes = [g.name for g in request.user.groups.all()]
-    if groups.DRH_NIVEAU_1 in user_groupes:
+    if groups.DRH_NIVEAU_1 in user_groupes or \
+       groups.DRH_NIVEAU_2 in user_groupes:
         q = Q()
     return [('', '----------')] + \
             [(i.id, unicode(i), )for i in ref.Implantation.objects.filter(q)]
@@ -109,7 +110,8 @@ def _employe_choices(obj, request):
     )
     # TRAITEMENT DRH
     user_groupes = [g.name for g in request.user.groups.all()]
-    if groups.DRH_NIVEAU_1 in user_groupes:
+    if groups.DRH_NIVEAU_1 in user_groupes or \
+       groups.DRH_NIVEAU_2 in user_groupes:
         q_dae_region_service = Q()
         q_rh_region_service = Q()
 
diff --git a/project/dae/migrations/0083_auto__chg_field_poste_salaire_min__chg_field_poste_indemn_max__chg_fie.py b/project/dae/migrations/0083_auto__chg_field_poste_salaire_min__chg_field_poste_indemn_max__chg_fie.py
new file mode 100644 (file)
index 0000000..010c84f
--- /dev/null
@@ -0,0 +1,534 @@
+# 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):
+        
+        # Changing field 'Poste.salaire_min'
+        db.alter_column('dae_poste', 'salaire_min', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2))
+
+        # Changing field 'Poste.indemn_max'
+        db.alter_column('dae_poste', 'indemn_max', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2))
+
+        # Changing field 'Poste.autre_min'
+        db.alter_column('dae_poste', 'autre_min', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2))
+
+        # Changing field 'Poste.autre_max'
+        db.alter_column('dae_poste', 'autre_max', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2))
+
+        # Changing field 'Poste.indemn_min'
+        db.alter_column('dae_poste', 'indemn_min', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2))
+
+        # Changing field 'Poste.salaire_max'
+        db.alter_column('dae_poste', 'salaire_max', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2))
+    
+    
+    def backwards(self, orm):
+        
+        # Changing field 'Poste.salaire_min'
+        db.alter_column('dae_poste', 'salaire_min', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2, blank=True))
+
+        # Changing field 'Poste.indemn_max'
+        db.alter_column('dae_poste', 'indemn_max', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2, blank=True))
+
+        # Changing field 'Poste.autre_min'
+        db.alter_column('dae_poste', 'autre_min', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2, blank=True))
+
+        # Changing field 'Poste.autre_max'
+        db.alter_column('dae_poste', 'autre_max', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2, blank=True))
+
+        # Changing field 'Poste.indemn_min'
+        db.alter_column('dae_poste', 'indemn_min', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2, blank=True))
+
+        # Changing field 'Poste.salaire_max'
+        db.alter_column('dae_poste', 'salaire_max', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2, blank=True))
+    
+    
+    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'})
+        },
+        'dae.contrat': {
+            'Meta': {'object_name': 'Contrat'},
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dae_contrats'", 'db_column': "'dossier'", 'to': "orm['dae.Dossier']"}),
+            'fichier': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type_contrat': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'type_contrat'", 'to': "orm['rh.TypeContrat']"})
+        },
+        'dae.dossier': {
+            'Meta': {'object_name': 'Dossier'},
+            'classement': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'classement'", 'to': "orm['rh.Classement']"}),
+            'classement_anterieur': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Classement']"}),
+            'classement_titulaire_anterieur': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Classement']"}),
+            'compte_compta': ('django.db.models.fields.CharField', [], {'default': "'aucun'", 'max_length': '10'}),
+            'compte_courriel': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'contrat_date_debut': ('django.db.models.fields.DateField', [], {}),
+            'contrat_date_fin': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'dae_numerisee': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_modification': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'default': '5', 'related_name': "'+'", 'to': "orm['rh.Devise']"}),
+            'devise_anterieur': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Devise']"}),
+            'devise_titulaire_anterieur': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Devise']"}),
+            'dossier_rh': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'dossiers_dae'", 'null': 'True', 'to': "orm['rh.Dossier']"}),
+            'employe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_dossiers'", 'db_column': "'employe'", 'to': "orm['dae.Employe']"}),
+            'employe_anterieur': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Employe']"}),
+            'etat': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '20', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'justif_nouveau_commentaire': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'justif_nouveau_salaire': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'justif_nouveau_statut': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'justif_nouveau_tmp_remplacement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'justif_rempl_commentaire': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'justif_rempl_evaluation': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'justif_rempl_salaire': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'justif_rempl_statut_employe': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'justif_rempl_type_contrat': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'organisme_bstg': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'organisme_bstg'", 'to': "orm['rh.OrganismeBstg']"}),
+            'organisme_bstg_autre': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dae_dossiers'", 'db_column': "'poste'", 'to': "orm['dae.Poste']"}),
+            'regime_travail': ('django.db.models.fields.DecimalField', [], {'default': "'100.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'regime_travail_nb_heure_semaine': ('django.db.models.fields.DecimalField', [], {'default': "'35.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'remplacement': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'remplacement_de': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['dae.Dossier']"}),
+            'salaire': ('django.db.models.fields.DecimalField', [], {'default': 'None', 'null': 'True', 'max_digits': '13', 'decimal_places': '2'}),
+            'salaire_anterieur': ('django.db.models.fields.DecimalField', [], {'default': 'None', 'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'salaire_titulaire_anterieur': ('django.db.models.fields.DecimalField', [], {'default': 'None', 'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'statut': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Statut']"}),
+            'statut_anterieur': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Statut']"}),
+            'statut_residence': ('django.db.models.fields.CharField', [], {'default': "'local'", 'max_length': '10', 'null': 'True'}),
+            'statut_titulaire_anterieur': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Statut']"}),
+            'type_contrat': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['rh.TypeContrat']"}),
+            'type_contrat_anterieur': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.TypeContrat']"})
+        },
+        'dae.dossiercomparaison': {
+            'Meta': {'object_name': 'DossierComparaison'},
+            'classement': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Classement']"}),
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Devise']"}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dae_comparaisons'", 'to': "orm['dae.Dossier']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['references.Implantation']"}),
+            'montant': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'personne': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'poste': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'statut': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Statut']"})
+        },
+        'dae.dossierpiece': {
+            'Meta': {'object_name': 'DossierPiece'},
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dae_dossierpieces'", 'db_column': "'dossier'", 'to': "orm['dae.Dossier']"}),
+            'fichier': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'dae.employe': {
+            'Meta': {'object_name': 'Employe'},
+            'genre': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'id_rh': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Employe']"}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'prenom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'dae.poste': {
+            'Meta': {'object_name': 'Poste'},
+            'appel': ('django.db.models.fields.CharField', [], {'default': "'interne'", 'max_length': '10', 'null': 'True'}),
+            'autre_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'autre_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'charges_patronales_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'charges_patronales_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'classement_max': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'classement_max'", 'to': "orm['rh.Classement']"}),
+            'classement_min': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'classement_min'", 'to': "orm['rh.Classement']"}),
+            'comp_autre_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_autre_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_fonctionpub_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_fonctionpub_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_locale_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_locale_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_ong_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_ong_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_universite_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_universite_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_modification': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
+            'devise_comparaison': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'devise_comparaison'", 'to': "orm['rh.Devise']"}),
+            'devise_max': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'devise_max'", 'to': "orm['rh.Devise']"}),
+            'devise_min': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'devise_min'", 'to': "orm['rh.Devise']"}),
+            'etat': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '20', 'null': 'True', 'blank': 'True'}),
+            'expatrie': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'id_rh': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'postes_dae'", 'null': 'True', 'to': "orm['rh.Poste']"}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'implantation'", 'to': "orm['references.Implantation']"}),
+            'indemn_expat_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'indemn_expat_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '13', 'decimal_places': '2'}),
+            'indemn_fct_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'indemn_fct_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'indemn_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'indemn_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'justification': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'local': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}),
+            'mise_a_disposition': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_feminin': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
+            'regime_travail': ('django.db.models.fields.DecimalField', [], {'default': "'100.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'regime_travail_nb_heure_semaine': ('django.db.models.fields.DecimalField', [], {'default': "'35.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'responsable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'responsable'", 'to': "orm['rh.Poste']"}),
+            'salaire_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'salaire_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'service': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dae_postes'", 'null': 'True', 'db_column': "'service'", 'to': "orm['rh.Service']"}),
+            'type_intervention': ('django.db.models.fields.CharField', [], {'default': "'N'", 'max_length': '1'}),
+            'type_poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'type_poste'", 'to': "orm['rh.TypePoste']"}),
+            'valeur_point_max': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'valeur_point_max'", 'to': "orm['rh.ValeurPoint']"}),
+            'valeur_point_min': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'valeur_point_min'", 'to': "orm['rh.ValeurPoint']"})
+        },
+        'dae.postecomparaison': {
+            'Meta': {'object_name': 'PosteComparaison'},
+            'classement': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Classement']"}),
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Devise']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['references.Implantation']"}),
+            'montant': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dae_comparaisons_internes'", 'to': "orm['dae.Poste']"}),
+            'statut': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Statut']"})
+        },
+        'dae.postefinancement': {
+            'Meta': {'object_name': 'PosteFinancement'},
+            'commentaire': ('django.db.models.fields.TextField', [], {}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dae_financements'", 'db_column': "'poste'", 'to': "orm['dae.Poste']"}),
+            'pourcentage': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '1'})
+        },
+        'dae.postepiece': {
+            'Meta': {'object_name': 'PostePiece'},
+            'fichier': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dae_pieces'", 'db_column': "'poste'", 'to': "orm['dae.Poste']"})
+        },
+        'dae.remuneration': {
+            'Meta': {'object_name': 'Remuneration'},
+            'commentaire': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'devise'", 'to': "orm['rh.Devise']"}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dae_remunerations'", 'db_column': "'dossier'", 'to': "orm['dae.Dossier']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'montant': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'type'", 'to': "orm['rh.TypeRemuneration']"}),
+            'type_revalorisation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'type_revalorisation'", 'to': "orm['rh.TypeRevalorisation']"})
+        },
+        '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'})
+        },
+        'rh.categorieemploi': {
+            'Meta': {'object_name': 'CategorieEmploi'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.classement': {
+            'Meta': {'object_name': 'Classement'},
+            'coefficient': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
+            'commentaire': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'degre': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
+            'echelon': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
+        },
+        'rh.devise': {
+            'Meta': {'object_name': 'Devise'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '10'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.dossier': {
+            'Meta': {'object_name': 'Dossier'},
+            'classement': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'classement'", 'to': "orm['rh.Classement']"}),
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_modification': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
+            'employe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_dossiers'", 'db_column': "'employe'", 'to': "orm['rh.Employe']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'organisme_bstg': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'organisme_bstg'", 'to': "orm['rh.OrganismeBstg']"}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_dossiers'", 'db_column': "'poste'", 'to': "orm['rh.Poste']"}),
+            'principal': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'regime_travail': ('django.db.models.fields.DecimalField', [], {'default': "'100.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'regime_travail_nb_heure_semaine': ('django.db.models.fields.DecimalField', [], {'default': "'35.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'remplacement': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'remplacement_de': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Dossier']"}),
+            'statut': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Statut']"}),
+            'statut_residence': ('django.db.models.fields.CharField', [], {'default': "'local'", 'max_length': '10', 'null': 'True'})
+        },
+        'rh.employe': {
+            'Meta': {'object_name': 'Employe'},
+            'adresse': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'code_postal': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'courriel_perso': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'date_entree': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'date_naissance': ('django.db.models.fields.DateField', [], {'null': 'True', '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': "'employes_nationalite'", 'db_column': "'nationalite'", 'to_field': "'code'", 'to': "orm['references.Pays']", 'blank': 'True', 'null': 'True'}),
+            'nb_postes': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_affichage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'employes'", 'db_column': "'pays'", 'to_field': "'code'", 'to': "orm['references.Pays']", 'blank': 'True', 'null': 'True'}),
+            'prenom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'province': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'situation_famille': ('django.db.models.fields.CharField', [], {'max_length': '1', 'null': 'True', 'blank': 'True'}),
+            'tel_cellulaire': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'tel_domicile': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'ville': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
+        },
+        'rh.familleprofessionnelle': {
+            'Meta': {'object_name': 'FamilleProfessionnelle'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'rh.organismebstg': {
+            'Meta': {'object_name': 'OrganismeBstg'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'organismes_bstg'", 'db_column': "'pays'", 'to_field': "'code'", 'to': "orm['references.Pays']", 'blank': 'True', 'null': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
+        },
+        'rh.poste': {
+            'Meta': {'object_name': 'Poste'},
+            'appel': ('django.db.models.fields.CharField', [], {'default': "'interne'", 'max_length': '10', 'null': 'True'}),
+            'autre_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'autre_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'classement_max': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'classement_max'", 'to': "orm['rh.Classement']"}),
+            'classement_min': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'classement_min'", 'to': "orm['rh.Classement']"}),
+            'comp_autre_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_autre_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_fonctionpub_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_fonctionpub_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_locale_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_locale_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_ong_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_ong_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_universite_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_universite_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_modification': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
+            'devise_comparaison': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'devise_comparaison'", 'to': "orm['rh.Devise']"}),
+            'devise_max': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'devise_max'", 'to': "orm['rh.Devise']"}),
+            'devise_min': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'devise_min'", 'to': "orm['rh.Devise']"}),
+            'expatrie': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'implantation'", 'to': "orm['references.Implantation']"}),
+            'indemn_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'indemn_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'justification': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'local': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}),
+            'mise_a_disposition': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_feminin': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
+            'regime_travail': ('django.db.models.fields.DecimalField', [], {'default': "'100.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'regime_travail_nb_heure_semaine': ('django.db.models.fields.DecimalField', [], {'default': "'35.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'responsable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'responsable'", 'to': "orm['rh.Poste']"}),
+            'salaire_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'salaire_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'service': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_postes'", 'null': 'True', 'db_column': "'service'", 'to': "orm['rh.Service']"}),
+            'type_poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'type_poste'", 'to': "orm['rh.TypePoste']"}),
+            'vacant': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+            'valeur_point_max': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'valeur_point_max'", 'to': "orm['rh.ValeurPoint']"}),
+            'valeur_point_min': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'valeur_point_min'", 'to': "orm['rh.ValeurPoint']"})
+        },
+        'rh.service': {
+            'Meta': {'object_name': 'Service'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.statut': {
+            'Meta': {'object_name': 'Statut'},
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '25'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.typecontrat': {
+            'Meta': {'object_name': 'TypeContrat'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_long': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.typeposte': {
+            'Meta': {'object_name': 'TypePoste'},
+            'categorie_emploi': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'categorie_emploi'", 'to': "orm['rh.CategorieEmploi']"}),
+            'famille_professionnelle': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'types_de_poste'", 'null': 'True', 'to': "orm['rh.FamilleProfessionnelle']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_responsable': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_feminin': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.typeremuneration': {
+            'Meta': {'object_name': 'TypeRemuneration'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nature_remuneration': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'type_paiement': ('django.db.models.fields.CharField', [], {'max_length': '30'})
+        },
+        'rh.typerevalorisation': {
+            'Meta': {'object_name': 'TypeRevalorisation'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.valeurpoint': {
+            'Meta': {'unique_together': "(('implantation', 'annee'),)", 'object_name': 'ValeurPoint'},
+            'annee': ('django.db.models.fields.IntegerField', [], {}),
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'devise'", 'to': "orm['rh.Devise']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_valeur_point'", 'db_column': "'implantation'", 'to': "orm['references.Implantation']"}),
+            'valeur': ('django.db.models.fields.FloatField', [], {'null': 'True'})
+        },
+        'workflow.workflowcommentaire': {
+            'Meta': {'object_name': 'WorkflowCommentaire'},
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'etat_final': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'etat_initial': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+            'texte': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
+        }
+    }
+    
+    complete_apps = ['dae']
index 29a87a1..158af84 100644 (file)
@@ -160,8 +160,9 @@ class Poste(PosteWorkflow, rh.Poste_):
                 poste=poste_rh,
                 nom=piece.nom
             )
-            piece_rh.fichier.save(
-                os.path.basename(piece.fichier.name), piece.fichier
+            if not settings.DEBUG:
+                piece_rh.fichier.save(
+                    os.path.basename(piece.fichier.name), piece.fichier
             )
 
         rh.PosteComparaison.objects.filter(poste=poste_rh).delete()
@@ -656,7 +657,6 @@ class Dossier(DossierWorkflow, rh.Dossier_):
         dossier_rh.regime_travail_nb_heure_semaine = \
                 self.regime_travail_nb_heure_semaine
         dossier_rh.date_debut = self.contrat_date_debut
-        dossier_rh.date_fin = self.contrat_date_fin
         dossier_rh.save()
 
         rh.DossierComparaison.objects.filter(dossier=dossier_rh).delete()
@@ -683,9 +683,10 @@ class Dossier(DossierWorkflow, rh.Dossier_):
             piece_rh = dossier_rh.rh_dossierpieces.create(
                 nom=piece.nom
             )
-            piece_rh.fichier.save(
-                os.path.basename(piece.fichier.name), piece.fichier
-            )
+            if not settings.DEBUG:
+                piece_rh.fichier.save(
+                    os.path.basename(piece.fichier.name), piece.fichier
+                )
 
         if self.dae_numerisee:
             dae_numerisee_rh = dossier_rh.rh_dossierpieces.create(
index 0a38b13..6bf619f 100644 (file)
@@ -6,15 +6,18 @@ from django.contrib.auth.models import User
 from project.dae import models as dae
 from project.dae.test.common import DaeTest
 from project.dae.forms import PosteForm
+from project.dae.workflow import POSTE_ACTION_ENVOYER_ADMINISTRATEUR, \
+    POSTE_ETAT_BROUILLON, \
+    POSTE_ETAT_ADMINISTRATEUR
 
-class PosteAddTest(DaeTest):
+class PosteTest(DaeTest):
     """
     Test l'ajout d'un poste
     """
     url = reverse('admin:rh_poste_add')
 
     def setUp(self):
-        super(PosteAddTest, self).setUp()
+        super(PosteTest, self).setUp()
         key = "rh-%s" % self.poste_cnf_ngaoundere.id
         self.url = reverse('poste', kwargs={'key': key})
         self.post = {
@@ -116,6 +119,30 @@ class PosteAddTest(DaeTest):
         for k, expect_value in self.expect.items():
             self.assertEqual(getattr(poste, k), expect_value)
 
+    def test_validation_poste(self):
+        self._test_drh()
+        self.client.post(self.url, self.post)
+
+        p = dae.Poste.objects.get(nom='nom')
+        self.assertEqual(p.etat, POSTE_ETAT_BROUILLON)
+
+        key = "dae-%s" % p.id
+        url = reverse('poste_consulter', args=(key, ))
+        post = {
+            POSTE_ACTION_ENVOYER_ADMINISTRATEUR:  "Envoyer à l'adminstrateur",
+            'commentaire': 'xxx',
+            }
+        resp = self.client.post(url, post)
+        self.assertEqual(resp.status_code, 302)
+
+        p = dae.Poste.objects.get(nom='nom')
+        self.assertEqual(p.etat, POSTE_ETAT_ADMINISTRATEUR)
+        
+        commentaires = p.commentaires.all()
+        self.assertEqual(len(commentaires), 1)
+        self.assertEqual(commentaires[0].texte, post['commentaire'])
+        self.assertEqual(commentaires[0].etat_initial, POSTE_ETAT_BROUILLON)
+        self.assertEqual(commentaires[0].etat_final, POSTE_ETAT_ADMINISTRATEUR)
 
     def test_anonyme(self):
         """
index 08adf19..94d210f 100644 (file)
@@ -75,6 +75,7 @@ def poste_consulter(request, key):
             request.POST, instance=poste, request=request
         )
         if validationForm.is_valid():
+            validationForm.save()
             messages.add_message(
                 request, messages.SUCCESS, "La validation a été enregistrée."
             )
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 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 8db7f58..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)
@@ -389,7 +399,7 @@ class CandidatAdminMixin(BaseAdmin):
 
     ### Actions à afficher
     def get_actions(self, request):
-        actions = super(CandidatAdmin, self).get_actions(request)
+        actions = super(CandidatAdminMixin, self).get_actions(request)
         del actions['delete_selected']
         return actions
 
@@ -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)
diff --git a/project/recrutement/admin.py_ b/project/recrutement/admin.py_
new file mode 100644 (file)
index 0000000..4bc35f3
--- /dev/null
@@ -0,0 +1,846 @@
+# -*- encoding: utf-8 -*-
+
+import textwrap
+
+from auf.django.emploi.models import OffreEmploi, Candidat, CandidatPiece
+from auf.django.references.models import Region, Bureau
+from django.conf import settings
+from django.contrib import admin
+from django.core.urlresolvers import reverse
+from django.db.models import Avg
+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
+
+### CONSTANTES
+IMPLANTATIONS_CENTRALES = [15, 19]
+
+
+class BaseAdmin(admin.ModelAdmin):
+
+    class Media:
+        css = {'screen': (
+            'css/admin_custom.css',
+            'jquery-autocomplete/jquery.autocomplete.css',
+        )}
+        js = (
+            'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js',
+            'jquery-autocomplete/jquery.autocomplete.min.js',
+        )
+
+
+class OrderedChangeList(admin.views.main.ChangeList):
+    """
+    Surcharge pour appliquer le order_by d'un annotate
+    """
+    def get_query_set(self):
+        qs = super(OrderedChangeList, self).get_query_set()
+        qs = qs.order_by('-moyenne')
+        return qs
+
+
+class OffreEmploiAdminMixin(BaseAdmin):
+    date_hierarchy = 'date_creation'
+    list_display = (
+        'nom', 'date_limite', 'region',  'statut', 'est_affiche',
+        '_candidatsList'
+    )
+    exclude = ('actif', 'poste_nom', 'resume',)
+    list_filter = ('statut',)
+    actions = ['affecter_evaluateurs_offre_emploi', ]
+    form = OffreEmploiForm
+
+    ### Actions à afficher
+    def get_actions(self, request):
+        actions = super(OffreEmploiAdminMixin, self).get_actions(request)
+        del actions['delete_selected']
+        return actions
+
+    ### Affecter un évaluateurs à des offres d'emploi
+    def affecter_evaluateurs_offre_emploi(modeladmin, obj, candidats):
+        selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
+
+        return HttpResponseRedirect(
+            reverse('affecter_evaluateurs_offre_emploi') +
+            "?ids=%s" % (",".join(selected))
+        )
+
+    affecter_evaluateurs_offre_emploi.short_description = \
+            u'Affecter évaluateur(s)'
+
+    ### Afficher la liste des candidats pour l'offre d'emploi
+    def _candidatsList(self, obj):
+        return "<a href='%s?offre_emploi__id__exact=%s'>Voir les candidats \
+            </a>" % (reverse('admin:recrutement_proxycandidat_changelist'), obj.id)
+    _candidatsList.allow_tags = True
+    _candidatsList.short_description = "Afficher la liste des candidats"
+
+    ### Formulaire
+    def get_form(self, request, obj=None, **kwargs):
+        form = super(OffreEmploiAdminMixin, self).get_form(request, obj, **kwargs)
+        employe = groups.get_employe_from_user(request.user)
+        user_groupes = [g.name for g in request.user.groups.all()]
+
+        # Region
+        
+        if 'region' in form.declared_fields:
+            region_field = form.declared_fields['region']
+            read_only = False
+        elif 'region' in form.base_fields:
+            region_field = form.base_fields['region']
+            read_only = False
+        else:
+            read_only = True
+
+        if not read_only:
+            if groups.DRH_NIVEAU_1 in user_groupes or \
+               groups.DRH_NIVEAU_2 in user_groupes or \
+               groups.HAUTE_DIRECTION in user_groupes:
+                region_field.queryset = Region.objects.all()
+            else:
+                region_field.queryset = Region.objects.\
+                                    filter(id=employe.implantation.region.id)
+
+        # Poste
+        if 'poste' in form.declared_fields:
+            poste_field = form.declared_fields['poste']
+            read_only = False
+        elif 'poste' in form.base_fields:
+            poste_field = form.base_fields['poste']
+            read_only = False
+        else:
+            read_only = True
+
+        if not read_only:
+            if groups.DRH_NIVEAU_1 in user_groupes or \
+               groups.DRH_NIVEAU_2 in user_groupes or \
+               groups.HAUTE_DIRECTION in user_groupes:
+                poste_field.queryset = rh.Poste.objects.all()
+            else:
+                poste_field.queryset = rh.Poste.objects.\
+                        filter(implantation__region=employe.implantation.region).\
+                        exclude(implantation__in=IMPLANTATIONS_CENTRALES)
+
+        # Bureau
+        if 'bureau' in form.declared_fields:
+            bureau_field = form.declared_fields['bureau']
+            read_only = False
+        elif 'bureau' in form.base_fields:
+            bureau_field = form.base_fields['bureau']
+            read_only = False
+        else:
+            read_only = True
+        if not read_only:
+            if groups.DRH_NIVEAU_1 in user_groupes or \
+                groups.DRH_NIVEAU_2 in user_groupes or \
+                groups.HAUTE_DIRECTION in user_groupes:
+                bureau_field.queryset = Bureau.objects.all()
+            else:
+                bureau_field.queryset = \
+                        Bureau.objects.filter(region=employe.implantation.region)
+
+        return form
+
+    ### Queryset
+
+    def queryset(self, request):
+        qs = self.model._default_manager.get_query_set() \
+                .select_related('offre_emploi')
+        user_groupes = [g.name for g in request.user.groups.all()]
+        if groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
+            return qs
+
+        if groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.CORRESPONDANT_RH in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes:
+            employe = groups.get_employe_from_user(request.user)
+            return qs.filter(region=employe.implantation.region)
+
+        if  Evaluateur.objects.filter(user=request.user).exists():
+            evaluateur = Evaluateur.objects.get(user=request.user)
+            offre_ids = [
+                e.candidat.offre_emploi_id
+                for e in CandidatEvaluation.objects
+                .select_related('candidat')
+                .filter(evaluateur=evaluateur)
+            ]
+            return qs.filter(id__in=offre_ids)
+
+        return qs.none()
+
+    ### Permission add, delete, change
+    def has_add_permission(self, request):
+        user_groupes = [g.name for g in request.user.groups.all()]
+        if request.user.is_superuser is True or \
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
+            return True
+        return False
+
+    def has_delete_permission(self, request, obj=None):
+        user_groupes = [g.name for g in request.user.groups.all()]
+        if request.user.is_superuser is True or \
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
+            return True
+
+        if obj is not None:
+            employe = groups.get_employe_from_user(request.user)
+            if (groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+                groups.ADMINISTRATEURS in user_groupes) and ( 
+                employe.implantation.region == obj.lieu_affectation.region):
+                return True
+
+        return False
+
+    def has_change_permission(self, request, obj=None):
+        user_groupes = [g.name for g in request.user.groups.all()]
+        if request.user.is_superuser is True or \
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
+            return True
+
+        if obj is not None:
+            employe = groups.get_employe_from_user(request.user)
+            if (groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+                groups.ADMINISTRATEURS in user_groupes) and ( 
+                employe.implantation.region == obj.lieu_affectation.region):
+                return True
+        else:
+            if  groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+                    groups.ADMINISTRATEURS in user_groupes:
+                return True
+
+
+        return False
+
+
+class OffreEmploiAdmin(VersionAdmin, OffreEmploiAdminMixin):
+    pass
+
+
+class ProxyOffreEmploiAdmin(OffreEmploiAdminMixin):
+    list_display = (
+        'nom', 'date_limite', 'region', 'statut', 'est_affiche'
+    )
+    readonly_fields = (
+        'description', 'bureau', 'duree_affectation', 'renumeration',
+        'debut_affectation', 'lieu_affectation', 'nom', 'resume',
+        'date_limite', 'region', 'poste'
+    )
+    fieldsets = (
+        ('Nom', {
+            'fields': ('nom',)
+        }),
+        ('Description générale', {
+            'fields': ('description', 'date_limite',)
+        }),
+        ('Coordonnées', {
+            'fields': ('lieu_affectation', 'bureau', 'region', 'poste',)
+        }),
+        ('Autre', {
+            'fields': (
+                'debut_affectation', 'duree_affectation', 'renumeration',
+            )
+        }),
+    )
+    inlines = []
+
+    ### Lieu de redirection après le change
+    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
+
+    def has_delete_permission(self, request, obj=None):
+        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
+
+
+class CandidatPieceInline(admin.TabularInline):
+    model = CandidatPiece
+    fields = ('candidat', 'nom', 'path',)
+    extra = 1
+    max_num = 3
+
+
+class ReadOnlyCandidatPieceInline(CandidatPieceInline):
+    readonly_fields = ('candidat', 'nom', 'path', )
+    cand_delete = False
+
+
+class CandidatEvaluationInlineFormSet(BaseInlineFormSet):
+    """
+    Empêche la suppression d'une évaluation pour le CandidatEvaluationInline
+    """
+    def __init__(self, *args, **kwargs):
+        super(CandidatEvaluationInlineFormSet, self).__init__(*args, **kwargs)
+        self.can_delete = False
+
+
+class CandidatEvaluationInline(admin.TabularInline):
+    model = CandidatEvaluation
+    fields = ('evaluateur', 'note', 'commentaire')
+    max_num = 0
+    extra = 0
+    formset = CandidatEvaluationInlineFormSet
+
+    ### Fields readonly
+    def get_readonly_fields(self, request, obj=None):
+        """
+        Empêche la modification des évaluations
+        """
+        if obj:
+            return self.readonly_fields + ('evaluateur', 'note', 'commentaire')
+        return self.readonly_fields
+
+
+class CandidatAdminMixin(BaseAdmin):
+    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', )
+
+    fieldsets = (
+        ("Offre d'emploi", {
+            'fields': ('offre_emploi', )
+        }),
+        ('Informations personnelles', {
+            'fields': (
+                'prenom', 'nom', 'genre', 'nationalite',
+                'situation_famille', 'nombre_dependant'
+            )
+        }),
+        ('Coordonnées', {
+            'fields': (
+                'telephone', 'email', 'adresse', 'ville', 'etat_province',
+                'code_postal', 'pays'
+            )
+        }),
+        ('Informations professionnelles', {
+            'fields': (
+                'niveau_diplome', 'employeur_actuel', 'poste_actuel',
+                'domaine_professionnel'
+            )
+        }),
+        ('Traitement', {
+            'fields': ('statut', )
+        }),
+    )
+    inlines = [
+        CandidatPieceInline,
+        CandidatEvaluationInline,
+    ]
+    actions = ['envoyer_courriel_candidats']
+
+    def _candidat(self, obj):
+        txt = u"%s %s (%s)" % (obj.nom.upper(), obj.prenom, obj.genre)
+        txt = textwrap.wrap(txt, 30)
+        return "<br/>".join(txt)
+    _candidat.short_description = "Candidat"
+    _candidat.admin_order_field = "nom"
+    _candidat.allow_tags = True
+
+    def _date_creation(self, obj):
+        return obj.date_creation
+    _date_creation.admin_order_field = "date_creation"
+    _date_creation.short_description = "Date de réception"
+
+    ### Actions à afficher
+    def get_actions(self, request):
+        actions = super(CandidatAdminMixin, self).get_actions(request)
+        del actions['delete_selected']
+        return actions
+
+    ### Envoyer un courriel à des candidats
+    def envoyer_courriel_candidats(modeladmin, obj, candidats):
+        selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
+
+        return HttpResponseRedirect(
+            reverse('selectionner_template') + "?ids=%s" % (",".join(selected))
+        )
+    envoyer_courriel_candidats.short_description = u'Envoyer courriel'
+
+    ### Évaluer un candidat
+    def evaluer_candidat(self, obj):
+        return "<a href='%s?candidat__id__exact=%s'>" \
+                "Évaluer le candidat</a>" % (
+                    reverse('admin:recrutement_candidatevaluation_changelist'),
+                    obj.id
+                )
+    evaluer_candidat.allow_tags = True
+    evaluer_candidat.short_description = 'Évaluation'
+
+    ### Afficher un candidat
+    def afficher_candidat(self, obj):
+        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>" % (
+            reverse('admin:recrutement_proxycandidat_change', args=(obj.id,))
+        )
+        return "%s<ul>%s</ul>" % (html, "\n".join(items))
+    afficher_candidat.allow_tags = True
+    afficher_candidat.short_description = u'Détails du candidat'
+
+    ### Voir l'offre d'emploi
+    def voir_offre_emploi(self, obj):
+        return "<a href='%s'>Voir l'offre d'emploi</a>" % (reverse(
+            'admin:recrutement_proxyoffreemploi_change',
+            args=(obj.offre_emploi.id,)
+        ))
+    voir_offre_emploi.allow_tags = True
+    voir_offre_emploi.short_description = "Afficher l'offre d'emploi"
+
+    ### Calculer la moyenne des notes
+    def calculer_moyenne(self, obj):
+        evaluations = CandidatEvaluation.objects.filter(candidat=obj)
+
+        notes = [evaluation.note for evaluation in evaluations \
+                    if evaluation.note is not None]
+
+        if len(notes) > 0:
+            moyenne_votes = round(float(sum(notes)) / len(notes), 2)
+        else:
+            moyenne_votes = "Non disponible"
+
+        totales = len(evaluations)
+        faites = len(notes)
+
+        if obj.statut == 'REC':
+            if totales == faites:
+                color = "green"
+            elif faites > 0 and float(totales) / float(faites) >= 2:
+                color = "orange"
+            else:
+                color = "red"
+        else:
+            color = "black"
+
+        return """<span style="color: %s;">%s (%s/%s)</span>""" % (
+            color, moyenne_votes, faites, totales
+        )
+    calculer_moyenne.allow_tags = True
+    calculer_moyenne.short_description = "Moyenne"
+    calculer_moyenne.admin_order_field = ""
+
+    ### Permissions add, delete, change
+    def has_add_permission(self, request):
+        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
+        return False
+
+    def has_delete_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
+        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
+        return False
+
+    def get_changelist(self, request, **kwargs):
+        return OrderedChangeList
+
+    def queryset(self, request):
+        """
+        Spécifie un queryset limité, autrement Django exécute un
+        select_related() sans paramètre, ce qui a pour effet de charger tous
+        les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
+        modèles de Region, il existe plusieurs boucles, ce qui conduit à la
+        génération d'une requête infinie.
+        """
+        qs = self.model._default_manager.get_query_set() \
+                .select_related('offre_emploi') \
+                .annotate(moyenne=Avg('evaluations__note'))
+
+        user_groupes = [g.name for g in request.user.groups.all()]
+        if groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
+            return qs
+
+        if groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.CORRESPONDANT_RH in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes:
+            employe = groups.get_employe_from_user(request.user)
+            return qs.filter(offre_emploi__region=employe.implantation.region)
+
+        if  Evaluateur.objects.filter(user=request.user).exists():
+            evaluateur = Evaluateur.objects.get(user=request.user)
+            candidat_ids = [e.candidat.id for e in
+                    CandidatEvaluation.objects.filter(evaluateur=evaluateur)]
+            return qs.filter(id__in=candidat_ids)
+        return qs.none()
+
+
+class CandidatAdmin(VersionAdmin, CandidatAdminMixin):
+    pass
+
+
+class ProxyCandidatAdmin(CandidatAdminMixin):
+    list_editable = ()
+    readonly_fields = (
+        'statut', 'offre_emploi', 'prenom', 'nom', 'genre', 'nationalite',
+        'situation_famille', 'nombre_dependant', 'telephone', 'email',
+        'adresse', 'ville', 'etat_province', 'code_postal', 'pays',
+        'niveau_diplome', 'employeur_actuel', 'poste_actuel',
+        'domaine_professionnel', 'pieces_jointes'
+    )
+    fieldsets = (
+        ("Offre d'emploi", {
+            'fields': ('offre_emploi', )
+        }),
+        ('Informations personnelles', {
+            'fields': (
+                'prenom', 'nom', 'genre', 'nationalite', 'situation_famille',
+                'nombre_dependant'
+            )
+        }),
+        ('Coordonnées', {
+            'fields': (
+                'telephone', 'email', 'adresse', 'ville', 'etat_province',
+                'code_postal', 'pays'
+            )
+        }),
+        ('Informations professionnelles', {
+            'fields': (
+                'niveau_diplome', 'employeur_actuel', 'poste_actuel',
+                'domaine_professionnel'
+            )
+        }),
+    )
+    inlines = (CandidatEvaluationInline, )
+
+    def has_add_permission(self, request):
+        return False
+
+    def has_delete_permission(self, request, obj=None):
+        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
+
+    def get_actions(self, request):
+        return None
+
+
+class CandidatPieceAdmin(admin.ModelAdmin):
+    list_display = ('nom', 'candidat', )
+
+    ### Queryset
+    def queryset(self, request):
+        """
+        Spécifie un queryset limité, autrement Django exécute un
+        select_related() sans paramètre, ce qui a pour effet de charger tous
+        les objets FK, sans limite de profondeur. Dès qu'on arrive, dans les
+        modèles de Region, il existe plusieurs boucles, ce qui conduit à la
+        génération d'une requête infinie.  Affiche la liste de candidats que
+        si le user connecté possède un Evaluateur
+        """
+        qs = self.model._default_manager.get_query_set()
+        return qs.select_related('candidat')
+
+
+class EvaluateurAdmin(BaseAdmin, VersionAdmin):
+    fieldsets = (
+        ("Utilisateur", {
+            'fields': ('user',)
+        }),
+    )
+
+    ### Actions à afficher
+    def get_actions(self, request):
+        actions = super(EvaluateurAdmin, self).get_actions(request)
+        del actions['delete_selected']
+        return actions
+
+    ### Permissions add, delete, change
+    def has_add_permission(self, request):
+        user_groupes = [g.name for g in request.user.groups.all()]
+        if request.user.is_superuser is True or \
+                groups.DRH_NIVEAU_1 in user_groupes or \
+                groups.DRH_NIVEAU_2 in user_groupes or \
+                groups.HAUTE_DIRECTION in user_groupes:
+            return True
+        return False
+
+    def has_delete_permission(self, request, obj=None):
+        user_groupes = [g.name for g in request.user.groups.all()]
+        if request.user.is_superuser is True or \
+                groups.DRH_NIVEAU_1 in user_groupes or \
+                groups.DRH_NIVEAU_2 in user_groupes or \
+                groups.HAUTE_DIRECTION in user_groupes:
+            return True
+        return False
+
+    def has_change_permission(self, request, obj=None):
+        user_groupes = [g.name for g in request.user.groups.all()]
+        if request.user.is_superuser is True or \
+                groups.DRH_NIVEAU_1 in user_groupes or \
+                groups.DRH_NIVEAU_2 in user_groupes or \
+                groups.HAUTE_DIRECTION in user_groupes:
+            return True
+        return False
+
+
+class CandidatEvaluationAdmin(BaseAdmin):
+    search_fields = ('candidat__nom', 'candidat__prenom')
+    list_display = (
+        '_candidat', '_statut', '_offre_emploi', 'evaluateur', '_note',
+        '_commentaire'
+    )
+    readonly_fields = ('candidat', 'evaluateur')
+    list_filter = ('candidat__statut', 'candidat__offre_emploi',)
+    fieldsets = (
+        ('Évaluation du candidat', {
+            'fields': ('candidat', 'evaluateur', 'note', 'commentaire', )
+        }),
+    )
+
+    def get_actions(self, request):
+        # on stocke l'evaluateur connecté (pas forcément la meilleure place...)
+        try:
+            self.evaluateur = Evaluateur.objects.get(user=request.user)
+        except:
+            self.evaluateur = None
+
+        actions = super(CandidatEvaluationAdmin, self).get_actions(request)
+        del actions['delete_selected']
+        return actions
+
+    ### Afficher la note
+    def _note(self, obj):
+        """
+        Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
+        un lien pour Évaluer le candidat.
+        Sinon afficher la note.
+        """
+        page = self.model.__name__.lower()
+        redirect_url = 'admin:recrutement_%s_change' % page
+
+        if obj.note is None:
+            label = "Candidat non évalué"
+        else:
+            label = obj.note
+
+        if self.evaluateur == obj.evaluateur:
+            return "<a href='%s'>%s</a>" % (
+                reverse(redirect_url,  args=(obj.id,)), label
+            )
+        else:
+            return label
+    _note.allow_tags = True
+    _note.short_description = "Note"
+    _note.admin_order_field = 'note'
+
+    def _statut(self, obj):
+        return obj.candidat.get_statut_display()
+    _statut.order_field = 'candidat__statut'
+    _statut.short_description = 'Statut'
+
+    ### Lien en lecture seule vers le candidat
+    def _candidat(self, obj):
+        return "<a href='%s'>%s</a>" \
+            % (reverse('admin:recrutement_proxycandidat_change',
+                        args=(obj.candidat.id,)), obj.candidat)
+    _candidat.allow_tags = True
+    _candidat.short_description = 'Candidat'
+
+    ### Afficher commentaire
+    def _commentaire(self, obj):
+        """
+        Si l'évaluateur n'a pas encore donné de note au candidat, indiquer
+        dans le champ commentaire, Aucun au lieu de (None)
+        Sinon afficher la note.
+        """
+        if obj.commentaire is None:
+            return "Aucun"
+        return obj.commentaire
+    _commentaire.allow_tags = True
+    _commentaire.short_description = "Commentaire"
+
+    ### Afficher offre d'emploi
+    def _offre_emploi(self, obj):
+        return "<a href='%s'>%s</a>" % \
+        (reverse('admin:recrutement_proxyoffreemploi_change',
+            args=(obj.candidat.offre_emploi.id,)), obj.candidat.offre_emploi)
+    _offre_emploi.allow_tags = True
+    _offre_emploi.short_description = "Voir offre d'emploi"
+
+    def has_add_permission(self, request):
+        return False
+
+    def has_delete_permission(self, request, obj=None):
+        return False
+
+    def has_change_permission(self, request, obj=None):
+        """
+        Permettre la visualisation dans la changelist
+        mais interdire l'accès à modifier l'objet si l'évaluateur n'est pas
+        le request.user
+        """
+        user_groupes = [g.name for g in request.user.groups.all()]
+
+        if request.user.is_superuser or \
+            groups.CORRESPONDANT_RH in user_groupes or \
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
+            is_recrutement = True
+        else:
+            is_recrutement = False
+
+        return is_recrutement
+
+    def queryset(self, request):
+        """
+        Afficher uniquement les évaluations de l'évaluateur, sauf si
+        l'utilisateur est dans les groupes suivants.
+        """
+        qs = self.model._default_manager.get_query_set() \
+                .select_related('offre_emploi')
+        user_groupes = request.user.groups.all()
+        user_groupes = [g.name for g in request.user.groups.all()]
+
+        if request.user.is_superuser or \
+            groups.CORRESPONDANT_RH in user_groupes or \
+            groups.DRH_NIVEAU_1 in user_groupes or \
+            groups.DRH_NIVEAU_2 in user_groupes or \
+            groups.DIRECTEUR_DE_BUREAU in user_groupes or \
+            groups.ADMINISTRATEURS in user_groupes or \
+            groups.HAUTE_DIRECTION in user_groupes:
+            return qs
+
+        evaluateur = Evaluateur.objects.get(user=request.user)
+        candidats_evaluations = \
+            CandidatEvaluation.objects.filter(evaluateur=evaluateur,
+                    candidat__statut__in=('REC', ))
+        candidats_evaluations_ids = [ce.id for ce in candidats_evaluations]
+        return qs.filter(id__in=candidats_evaluations_ids)
+
+
+class MesCandidatEvaluationAdmin(CandidatEvaluationAdmin):
+
+    def has_change_permission(self, request, obj=None):
+        try:
+            Evaluateur.objects.get(user=request.user)
+            is_evaluateur = True
+        except:
+            is_evaluateur = False
+
+        if obj is None and is_evaluateur:
+            return True
+
+        try:
+            return request.user == obj.evaluateur.user
+        except:
+            return False
+
+    def queryset(self, request):
+        qs = self.model._default_manager.get_query_set() \
+                .select_related('offre_emploi')
+        evaluateur = Evaluateur.objects.get(user=request.user)
+        candidats_evaluations = \
+            CandidatEvaluation.objects.filter(evaluateur=evaluateur,
+                    candidat__statut__in=('REC', ))
+        candidats_evaluations_ids = [ce.id for ce in candidats_evaluations]
+        return qs.filter(id__in=candidats_evaluations_ids)
+
+
+class CourrielTemplateAdmin(BaseAdmin, VersionAdmin):
+    ### Actions à afficher
+    def get_actions(self, request):
+        actions = super(CourrielTemplateAdmin, self).get_actions(request)
+        del actions['delete_selected']
+        return actions
+
+admin.site.register(OffreEmploi, OffreEmploiAdmin)
+admin.site.register(ProxyOffreEmploi, ProxyOffreEmploiAdmin)
+admin.site.register(Candidat, CandidatAdmin)
+admin.site.register(ProxyCandidat, ProxyCandidatAdmin)
+admin.site.register(CandidatEvaluation, CandidatEvaluationAdmin)
+admin.site.register(MesCandidatEvaluation, MesCandidatEvaluationAdmin)
+admin.site.register(Evaluateur, EvaluateurAdmin)
+admin.site.register(CourrielTemplate, CourrielTemplateAdmin)
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 %}
diff --git a/project/recrutement/test/candidat.py b/project/recrutement/test/candidat.py
new file mode 100644 (file)
index 0000000..4c46036
--- /dev/null
@@ -0,0 +1,343 @@
+
+# -*- coding: utf-8 -*-
+
+from django.core.urlresolvers import reverse
+from project.recrutement.test.common import RecrutementTest
+
+class CandidatAddTest(RecrutementTest):
+    """
+    Test l'ajout d'un candidat
+    """
+    url = reverse('admin:emploi_candidat_add')
+
+    def test_anonyme(self):
+        """
+        Un anonyme ne peut pas ajouter un candidat
+        """
+        self._test_anonyme()
+        self._test_acces_ko(self.url)
+
+    def test_correspondant_rh(self):
+        """
+        Un correspondant RH peut ajouter un candidat
+        """
+        self._test_correspondant_rh()
+        self._test_acces_ok(self.url)
+
+    def test_administrateur_regional(self):
+        """
+        Un administrateur peut ajouter un candidat
+        """
+        self._test_administrateur_regional()
+        self._test_acces_ok(self.url)
+
+    def test_directeur_bureau(self):
+        """
+        Un directeur de bureau peut ajouter un candidat
+        """
+        self._test_directeur_bureau()
+        self._test_acces_ok(self.url)
+
+    def test_drh(self):
+        """
+        Un DRH peut ajouter un candidat
+        """
+        self._test_drh()
+        self._test_acces_ok(self.url)
+
+    def test_drh2(self):
+        """
+        Un DRH (2ieme niveau) peut ajouter un candidat
+        """
+        self._test_drh2()
+        self._test_acces_ok(self.url)
+
+    def _test_grp_accior(self):
+        """
+        Un membre de l'ACCIOR ne peut ajouter un candidat
+        """
+        self._test_grp_accior()
+        self._test_acces_ko(self.url)
+
+    def _test_grp_abf(self):
+        """
+        Un membre de l'ABF ne  peut ajouter un candidat
+        """
+        self._test_grp_abf(self)
+        self._test_acces_ko(self.url)
+
+    def _test_grp_haute_direction(self):
+        """
+        Un membre de la haute direction  peut ajouter un candidat
+        """
+        self._test_grp_haute_direction()
+        self._test_acces_ok(self.url)
+
+    def _test_grp_service_utilisateurs(self):
+        """
+        Un membre du groupe service utilisateur ne  peut ajouter un candidat
+        """
+        self._test_grp_service_utilisateurs()
+        self._test_acces_ko(self.url)
+
+
+class CandidatDeleteTest(RecrutementTest):
+    """
+    Test la suppression d'un candidat
+    """
+
+    def setUp(self):
+        super(CandidatDeleteTest, self).setUp()
+        self.url = reverse('admin:emploi_candidat_delete',
+                args=[self.candidat_cnf_ngaoundere.id])
+
+    def test_anonyme(self):
+        """
+        Un anonyme ne peut pas supprimer un candidat
+        """
+        self._test_anonyme()
+        self._test_acces_ko(self.url)
+
+    def test_correspondant_rh(self):
+        """
+        Un correspondant RH peut supprimer un candidat
+        """
+        self._test_correspondant_rh()
+        self._test_acces_ok(self.url)
+
+    def test_administrateur_regional(self):
+        """
+        Un administrateur peut supprimer un candidat
+        """
+        self._test_administrateur_regional()
+        self._test_acces_ok(self.url)
+        self._test_directeur_bureau(email="2@test.auf")
+        self._test_acces_ko(self.url)
+
+    def test_directeur_bureau(self):
+        """
+        Un directeur de bureau peut supprimer un candidat
+        """
+        self._test_directeur_bureau()
+        self._test_acces_ok(self.url)
+        self._test_directeur_bureau(email="2@test.auf")
+        self._test_acces_ko(self.url)
+
+    def test_drh(self):
+        """
+        Un DRH peut supprimer un candidat
+        """
+        self._test_drh()
+        self._test_acces_ok(self.url)
+
+    def test_drh2(self):
+        """
+        Un DRH (2ieme niveau) peut supprimer un candidat
+        """
+        self._test_drh2()
+        self._test_acces_ok(self.url)
+
+    def _test_grp_accior(self):
+        """
+        Un membre de l'ACCIOR ne peut supprimer un candidat
+        """
+        self._test_grp_accior()
+        self._test_acces_ko(self.url)
+
+    def _test_grp_abf(self):
+        """
+        Un membre de l'ABF ne  peut supprimer un candidat
+        """
+        self._test_grp_abf(self)
+        self._test_acces_ko(self.url)
+
+    def _test_grp_haute_direction(self):
+        """
+        Un membre de la haute direction  peut supprimer un candidat
+        """
+        self._test_grp_haute_direction()
+        self._test_acces_ok(self.url)
+
+    def _test_grp_service_utilisateurs(self):
+        """
+        Un membre du groupe service utilisateur ne  peut supprimer un candidat
+        """
+        self._test_grp_service_utilisateurs()
+        self._test_acces_ko(self.url)
+
+
+class CandidatChangeTest(RecrutementTest):
+    """
+    Test la modification d'un candidat
+    """
+
+    def setUp(self):
+        super(CandidatChangeTest, self).setUp()
+        self.url = reverse('admin:emploi_candidat_change',
+                args=[self.candidat_cnf_ngaoundere.id])
+
+    def test_anonyme(self):
+        """
+        Un anonyme ne peut pas modifier un candidat
+        """
+        self._test_anonyme()
+        self._test_acces_ko(self.url)
+
+    def test_correspondant_rh(self):
+        """
+        Un correspondant RH peut modifier un candidat
+        """
+        self._test_correspondant_rh()
+        self._test_acces_ok(self.url)
+
+    def test_administrateur_regional(self):
+        """
+        Un administrateur peut modifier un candidat
+        """
+        self._test_administrateur_regional()
+        self._test_acces_ok(self.url)
+        self._test_administrateur_regional(email="2@test.auf")
+        self._test_acces_ko(self.url)
+
+    def test_directeur_bureau(self):
+        """
+        Un directeur de bureau peut modifier un candidat
+        """
+        self._test_directeur_bureau()
+        self._test_acces_ok(self.url)
+        self._test_directeur_bureau(email="2@test.auf")
+        self._test_acces_ko(self.url)
+
+    def test_drh(self):
+        """
+        Un DRH peut modifier un candidat
+        """
+        self._test_drh()
+        self._test_acces_ok(self.url)
+
+    def test_drh2(self):
+        """
+        Un DRH (2ieme niveau) peut modifier un candidat
+        """
+        self._test_drh2()
+        self._test_acces_ok(self.url)
+
+    def _test_grp_accior(self):
+        """
+        Un membre de l'ACCIOR ne peut modifier un candidat
+        """
+        self._test_grp_accior()
+        self._test_acces_ko(self.url)
+
+    def _test_grp_abf(self):
+        """
+        Un membre de l'ABF ne  peut modifier un candidat
+        """
+        self._test_grp_abf(self)
+        self._test_acces_ko(self.url)
+
+    def _test_grp_haute_direction(self):
+        """
+        Un membre de la haute direction  peut modifier un candidat
+        """
+        self._test_grp_haute_direction()
+        self._test_acces_ok(self.url)
+
+    def _test_grp_service_utilisateurs(self):
+        """
+        Un membre du groupe service utilisateur ne  peut modifier un candidat
+        """
+        self._test_grp_service_utilisateurs()
+        self._test_acces_ko(self.url)
+
+
+class CandidatChangeListTest(RecrutementTest):
+    """
+    Test l'acces à la liste des candidats
+    """
+
+    def setUp(self):
+        super(CandidatChangeListTest, self).setUp()
+        self.url = reverse('admin:emploi_candidat_changelist')
+
+    def test_anonyme(self):
+        """
+        Un anonyme ne peut pas lister les candidats
+        """
+        self._test_anonyme()
+        self._test_acces_ko(self.url)
+
+    def test_correspondant_rh(self):
+        """
+        Un correspondant RH peut lister les candidats
+        """
+        self._test_correspondant_rh()
+        self._test_acces_ok(self.url)
+
+    def test_administrateur_regional(self):
+        """
+        Un administrateur peut lister les candidats
+        """
+        self._test_administrateur_regional()
+        self._test_acces_ok(self.url)
+        qs = self.client.get(self.url).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+        self._test_administrateur_regional(email="2@test.auf")
+        self._test_acces_ok(self.url)
+        qs = self.client.get(self.url).context['cl'].query_set
+        self.assertEqual(len(qs), 0)
+
+    def test_directeur_bureau(self):
+        """
+        Un directeur de bureau peut lister les candidats
+        """
+        self._test_directeur_bureau()
+        self._test_acces_ok(self.url)
+        qs = self.client.get(self.url).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+        self._test_directeur_bureau(email="2@test.auf")
+        self._test_acces_ok(self.url)
+        qs = self.client.get(self.url).context['cl'].query_set
+        self.assertEqual(len(qs), 0)
+
+    def test_drh(self):
+        """
+        Un DRH peut lister les candidats
+        """
+        self._test_drh()
+        self._test_acces_ok(self.url)
+
+    def test_drh2(self):
+        """
+        Un DRH (2ieme niveau) peut lister les candidats
+        """
+        self._test_drh2()
+        self._test_acces_ok(self.url)
+
+    def _test_grp_accior(self):
+        """
+        Un membre de l'ACCIOR ne peut lister les candidats
+        """
+        self._test_grp_accior()
+        self._test_acces_ko(self.url)
+
+    def _test_grp_abf(self):
+        """
+        Un membre de l'ABF ne  peut lister les candidats
+        """
+        self._test_grp_abf(self)
+        self._test_acces_ko(self.url)
+
+    def _test_grp_haute_direction(self):
+        """
+        Un membre de la haute direction  peut lister les candidats
+        """
+        self._test_grp_haute_direction()
+        self._test_acces_ok(self.url)
+
+    def _test_grp_service_utilisateurs(self):
+        """
+        Un membre du groupe service utilisateur ne  peut lister les candidats
+        """
+        self._test_grp_service_utilisateurs()
+        self._test_acces_ko(self.url)
index 06f8053..c4b3887 100644 (file)
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 
 from auf.django.references import models as ref
-from auf.django.emploi.models import OffreEmploi
+from auf.django.emploi.models import OffreEmploi, Candidat
 from project.rh.test.common import RhTest
 
 class RecrutementTest(RhTest):
@@ -11,6 +11,10 @@ class RecrutementTest(RhTest):
         OFFRE_EMPLOIS
         =============
         self.offre_cnf_ngaoundere
+
+        CANDIDATS
+        =========
+        self.canditat_cnf_ngaoundere
         """
         super(RecrutementTest, self).setUp()
     
@@ -23,3 +27,14 @@ class RecrutementTest(RhTest):
                 )
         self.offre_cnf_ngaoundere.save()
 
+        self.candidat_cnf_ngaoundere = Candidat(
+                prenom="olivier",
+                nom="larchevêque",
+                genre='M',
+                nationalite=ref.Pays.objects.get(code='FR'),
+                pays=ref.Pays.objects.get(code='CA'),
+                offre_emploi=self.offre_cnf_ngaoundere,
+                nombre_dependant=3,
+                )
+        self.candidat_cnf_ngaoundere.save()
+        
index c9bcec4..0877a46 100644 (file)
@@ -1,7 +1,2 @@
 from project.recrutement.test.offre_emploi import *
-#from project.recrutement.test.offre_emploi_visualisation import *
-#from project.recrutement.test.candidat import *
-#from project.recrutement.test.candidat_visualisation import *
-#from project.recrutement.test.candidatevaluation import *
-#from project.recrutement.test.evaluateur import *
-#from project.recrutement.test.modele_courriel import *
+from project.recrutement.test.candidat import *
index d9755cb..02ee759 100644 (file)
@@ -23,7 +23,7 @@ def mediaserve(request, path, document_root=None, show_indexes=False):
     grant_ok = False
     user = request.user
 
-    for grp in user.groups.all():
+    for grp in [g.name for g in user.groups.all()]:
         if grp in recrutement_groupes:
             grant_ok = True
             break
@@ -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 7528287..f3ad620 100644 (file)
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 import time, datetime
 import operator
 
@@ -52,40 +54,35 @@ class RechercheTemporelle(object):
         annees.sort(reverse=True)
         return annees
 
-    def get_q_inconnu(self, prefix):
-        date_debut_nulle = Q(**{"%s%s__isnull" % (prefix, KEY_DATE_DEBUT) : True})
-        date_fin_nulle = Q(**{"%s%s__isnull" % (prefix, KEY_DATE_FIN) : True})
-        return Q(date_debut_nulle & date_fin_nulle)
-
-    def get_q_range(self, prefix, borne_gauche=None, borne_droite=None):
-
-        date_debut_nulle = Q(**{"%s%s__isnull" % (prefix, KEY_DATE_DEBUT) : True})
-        date_fin_nulle = Q(**{"%s%s__isnull" % (prefix, KEY_DATE_FIN) : True})
-        date_debut_superieure_ou_egale_a_borne_gauche = Q(**{"%s%s__gte" % (prefix, KEY_DATE_DEBUT) : borne_gauche})
-        date_debut_strict_superieure_ou_egale_a_borne_gauche = Q(**{"%s%s__gt" % (prefix, KEY_DATE_DEBUT) : borne_gauche})
-        date_debut_inferieure_ou_egale_a_borne_gauche = Q(**{"%s%s__lte" % (prefix, KEY_DATE_DEBUT) : borne_gauche})
-        date_fin_superieure_ou_egale_a_borne_gauche = Q(**{"%s%s__gte" % (prefix, KEY_DATE_FIN) : borne_gauche})
-        date_fin_inferieure_ou_egale_a_borne_droite = Q(**{"%s%s__lte" % (prefix, KEY_DATE_FIN) : borne_droite})
-        date_fin_strict_inferieure_ou_egale_a_borne_droite = Q(**{"%s%s__lt" % (prefix, KEY_DATE_FIN) : borne_droite})
-        date_debut_inferieure_ou_egale_a_borne_droite = Q(**{"%s%s__lte" % (prefix, KEY_DATE_DEBUT) : borne_droite})
-        date_fin_superieure_ou_egale_a_borne_droite = Q(**{"%s%s__gte" % (prefix, KEY_DATE_FIN) : borne_droite})
-
-        if borne_droite is None:
-            q_range = date_debut_strict_superieure_ou_egale_a_borne_gauche
+    def get_q_actifs(self):
+        qs = self.model.objects.get_query_set()
+        q = qs.get_q_actifs()
+        return q
 
-        if borne_gauche is None:
-            q_range = date_fin_strict_inferieure_ou_egale_a_borne_droite
+    def get_q_inactifs(self):
+        qs = self.model.objects.get_query_set()
+        q = qs.get_q_inactifs()
+        return q
 
-        if borne_droite is not None and borne_gauche is not None:
-            q_range = (date_debut_superieure_ou_egale_a_borne_gauche & date_fin_inferieure_ou_egale_a_borne_droite) |  \
-                          ((date_debut_inferieure_ou_egale_a_borne_gauche | date_debut_nulle) & date_fin_superieure_ou_egale_a_borne_gauche & date_fin_inferieure_ou_egale_a_borne_droite) | \
-                          ((date_fin_superieure_ou_egale_a_borne_droite | date_fin_nulle) & date_debut_inferieure_ou_egale_a_borne_droite) | \
-                          (date_debut_inferieure_ou_egale_a_borne_gauche & date_fin_superieure_ou_egale_a_borne_droite)
+    def get_q_futurs(self):
+        qs = self.model.objects.get_query_set()
+        q = qs.get_q_futurs()
+        return q
 
-        if borne_droite is None and borne_gauche is None:
-            q_range = Q()
+    def get_q_inconnus(self):
+        qs = self.model.objects.get_query_set()
+        q = qs.get_q_inconnus()
+        return q
 
-        return q_range
+    def get_q_range(self, prefix, borne_gauche=None, borne_droite=None):
+        # on filtre si on a au moins une borne, car par défaut q_actifs est
+        # un filtre sur actif à l'instant présent
+        if borne_gauche is not None and  borne_droite is not None:
+            qs = self.model.objects.get_query_set()
+            q = qs.get_q_actifs(borne_gauche,  borne_droite)
+            return q
+        else:
+            return Q()
 
     def purge_params(self, lookup_params):
         self.lookup_recherche_temporelle = {}
@@ -103,6 +100,7 @@ class RechercheTemporelle(object):
         prefix = self.get_prefix()
         borne_gauche = None
         borne_droite = None
+        
         for k, v in self.lookup_recherche_temporelle.items():
 
             if k.endswith(KEY_ANNEE):
@@ -120,19 +118,14 @@ class RechercheTemporelle(object):
             if k.endswith(KEY_STATUT):
                 aujourdhui = datetime.date.today()
                 if v == STATUT_ACTIF:
-                    borne_gauche = aujourdhui
-                    borne_droite = aujourdhui
+                    q = q & self.get_q_actifs()
                 elif v == STATUT_INACTIF:
-                    # dans le cas d'une FK, on retire des inactifs ceux qui ont une FK active
-                    if prefix != "":
-                        q_range = self.get_q_range(prefix, aujourdhui, aujourdhui)
-                        id_actifs = [o.id for o in qs.filter(q_range).distinct()]
-                        qs = qs.exclude(id__in=id_actifs)
+                    q = q & self.get_q_inactifs()
                     borne_droite = aujourdhui
                 elif v == STATUT_FUTUR:
-                    borne_gauche = aujourdhui
+                    q = q & self.get_q_futurs()
                 elif v == STATUT_INCONNU:
-                    q = q & self.get_q_inconnu(prefix)
+                    q = q & self.get_q_inconnus()
         q_range = self.get_q_range(prefix, borne_gauche, borne_droite)
         return q & q_range
 
@@ -149,6 +142,7 @@ class ChangeList(DjangoChangeList, RechercheTemporelle):
         use_distinct = True
 
         qs = self.root_query_set
+        
         lookup_params = self.params.copy() # a dictionary of the query string
         for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR, TO_FIELD_VAR):
             if i in lookup_params:
@@ -192,7 +186,7 @@ class ChangeList(DjangoChangeList, RechercheTemporelle):
         
         q_temporel = self.get_q_temporel(qs)
         q = Q(**lookup_params) & q_temporel
-
+        
         # Apply lookup parameters from the query string.
         try:
             qs = qs.filter(q)
index 176d708..141a250 100644 (file)
@@ -64,7 +64,8 @@ def get_active_revisions():
                 filter(version__content_type__app_label="rh").
                 exclude(user__isnull=True).
                 exclude(id__in=ids_revisions_traitees).
-                order_by('-date_created'))
+                order_by('-date_created').
+                distinct('id'))
 
 
 class TodoForm(forms.Form):
index bee3f71..c1a459a 100644 (file)
@@ -70,10 +70,12 @@ class SecurityManager(models.Manager):
 
 
 class ActifsQuerySet(QuerySet):
+    debut_field = 'date_debut'
+    fin_field = 'date_fin'
 
     def _actifs(self, debut_field, fin_field, date_min=None, date_max=None,
-                annee=None):
-        qs = self
+            annee=None):
+        q = Q()
         if annee:
             janvier = date(annee, 1, 1)
             decembre = date(annee, 12, 31)
@@ -82,17 +84,69 @@ class ActifsQuerySet(QuerySet):
         if not date_min and not date_max:
             date_min = date_max = date.today()
         if date_min:
-            qs = qs.filter(
+            q = q & (
                 Q(**{fin_field + '__gte': date_min}) |
                 Q(**{fin_field: None}))
         if date_max:
-            qs = qs.filter(
+            q = q & (
                 Q(**{debut_field + '__lte': date_max}) |
                 Q(**{debut_field: None}))
-        return qs
 
-    def actifs(self, *args, **kwargs):
-        return self._actifs('date_debut', 'date_fin', *args, **kwargs)
+        q_inconnus = self._inconnus(debut_field, fin_field)
+        return q & ~q_inconnus
+
+    def _inconnus(self, debut_field, fin_field):
+        q = Q(**{
+            debut_field + '__isnull': True,
+            fin_field + '__isnull': True,
+            })
+        return q
+
+    def get_q_actifs(self, date_min=None, date_max=None, annee=None):
+        return self._actifs(self.debut_field, self.fin_field,
+                date_min, date_max, annee)
+
+    def actifs(self, date_min=None, date_max=None, annee=None):
+        qs = self
+        q = self.get_q_actifs(date_min, date_max, annee)
+        return qs.filter(q)
+
+    def get_q_inconnus(self, date_min=None, date_max=None, annee=None):
+        return self._inconnus(self.debut_field, self.fin_field)
+
+    def inconnus(self):
+        qs = self
+        q = self.get_q_inconnus()
+        return qs.filter(q)
+
+    def get_q_inactifs(self, date_min=None, date_max=None, annee=None):
+        actifs_ids = [e['id'] for e in self.actifs(date_min, date_max,
+            annee).values('id')]
+        q_non_actifs = ~Q(id__in=actifs_ids)
+        q_inconnus = self.get_q_inconnus()
+        q_futurs = self.get_q_futurs(date_min, date_max, annee)
+        return q_non_actifs & ~q_inconnus & ~q_futurs
+
+    def inactifs(self, date_min=None, date_max=None, annee=None):
+        return self.get_q_inactifs(date_min, date_max, annee)
+
+    def get_q_futurs(self, date_min=None, date_max=None, annee=None):
+        q = Q()
+        if annee:
+            janvier = date(annee, 1, 1)
+            decembre = date(annee, 12, 31)
+            date_min = max(janvier, date_min) if date_min else janvier
+            date_max = min(decembre, date_max) if date_max else decembre
+        if not date_min and not date_max:
+            date_min = date_max = date.today()
+        if date_min:
+            q = q & Q(**{self.debut_field + '__gt': date_min})
+        if date_max:
+            q = q & Q(**{self.debut_field + '__gt': date_max})
+        return q
+
+    def futurs(self, date_min=None, date_max=None, annee=None):
+        return self.get_q_futurs(date_min, date_max, annee)
 
 
 class PosteQuerySet(ActifsQuerySet):
@@ -106,12 +160,11 @@ class PosteManager(SecurityManager):
     def get_query_set(self):
         return PosteQuerySet(self.model).select_related('type_poste')
 
-    def actifs(self, *args, **kwargs):
-        return self.get_query_set().actifs(*args, **kwargs)
-
     def ma_region_ou_service(self, user):
         return super(PosteManager, self).ma_region_ou_service(user)
 
+    def actifs(self, *args, **kwargs):
+        return self.get_query_set().actifs(*args, **kwargs)
 
 class DossierQuerySet(ActifsQuerySet):
     pass
@@ -144,11 +197,10 @@ class DossierManager(SecurityManager):
 class RemunerationQuerySet(ActifsQuerySet):
 
     def actifs(self, *args, **kwargs):
-        return self \
-                ._actifs('date_debut', 'date_fin', *args, **kwargs) \
-                ._actifs(
-                    'dossier__date_debut', 'dossier__date_fin',
-                    *args, **kwargs)
+        remun_q = self._actifs('date_debut', 'date_fin', *args, **kwargs)
+        dossier_q = self._actifs('dossier__date_debut', 'dossier__date_fin',
+                *args, **kwargs)
+        return self.filter(remun_q & dossier_q)
 
 
 class RemunerationManager(models.Manager):
@@ -161,11 +213,8 @@ class RemunerationManager(models.Manager):
 
 
 class EmployeQuerySet(ActifsQuerySet):
-
-    def actifs(self, date_min=None, date_max=None, annee=None):
-        return self \
-                ._actifs('rh_dossiers__date_debut', 'rh_dossiers__date_fin') \
-                .distinct()
+    debut_field = 'rh_dossiers__date_debut'
+    fin_field = 'rh_dossiers__date_fin'
 
 
 class EmployeManager(models.Manager):
@@ -177,6 +226,16 @@ class EmployeManager(models.Manager):
         return self.get_query_set().actifs(*args, **kwargs)
 
 
+class ContratQuerySet(ActifsQuerySet):
+    pass
+
+class ContratManager(models.Manager):
+
+    def get_query_set(self):
+        return ContratQuerySet(self.model)\
+                .select_related('dossier', 'dossier__poste')
+
+
 class PosteComparaisonManager(SecurityManager):
     use_for_related_fields = True
     prefixe_implantation = "implantation__zone_administrative"
diff --git a/project/rh/migrations/0036_auto__chg_field_poste_salaire_min__chg_field_poste_indemn_max__chg_fie.py b/project/rh/migrations/0036_auto__chg_field_poste_salaire_min__chg_field_poste_indemn_max__chg_fie.py
new file mode 100644 (file)
index 0000000..10a99f3
--- /dev/null
@@ -0,0 +1,490 @@
+# 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):
+        
+        # Changing field 'Poste.salaire_min'
+        db.alter_column('rh_poste', 'salaire_min', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2))
+
+        # Changing field 'Poste.indemn_max'
+        db.alter_column('rh_poste', 'indemn_max', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2))
+
+        # Changing field 'Poste.autre_min'
+        db.alter_column('rh_poste', 'autre_min', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2))
+
+        # Changing field 'Poste.autre_max'
+        db.alter_column('rh_poste', 'autre_max', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2))
+
+        # Changing field 'Poste.indemn_min'
+        db.alter_column('rh_poste', 'indemn_min', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2))
+
+        # Changing field 'Poste.salaire_max'
+        db.alter_column('rh_poste', 'salaire_max', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=2))
+    
+    
+    def backwards(self, orm):
+        
+        # Changing field 'Poste.salaire_min'
+        db.alter_column('rh_poste', 'salaire_min', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2, blank=True))
+
+        # Changing field 'Poste.indemn_max'
+        db.alter_column('rh_poste', 'indemn_max', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2, blank=True))
+
+        # Changing field 'Poste.autre_min'
+        db.alter_column('rh_poste', 'autre_min', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2, blank=True))
+
+        # Changing field 'Poste.autre_max'
+        db.alter_column('rh_poste', 'autre_max', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2, blank=True))
+
+        # Changing field 'Poste.indemn_min'
+        db.alter_column('rh_poste', 'indemn_min', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2, blank=True))
+
+        # Changing field 'Poste.salaire_max'
+        db.alter_column('rh_poste', 'salaire_max', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2, blank=True))
+    
+    
+    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'})
+        },
+        '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'})
+        },
+        'reversion.revision': {
+            'Meta': {'object_name': 'Revision'},
+            'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'manager_slug': ('django.db.models.fields.CharField', [], {'default': "'default'", 'max_length': '200', 'db_index': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
+        },
+        'rh.ayantdroit': {
+            'Meta': {'object_name': 'AyantDroit'},
+            'date_naissance': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'employe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ayantdroits'", 'db_column': "'employe'", 'to': "orm['rh.Employe']"}),
+            'genre': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'lien_parente': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+            'nationalite': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ayantdroits_nationalite'", 'db_column': "'nationalite'", 'to_field': "'code'", 'to': "orm['references.Pays']", 'blank': 'True', 'null': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_affichage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'prenom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.ayantdroitcommentaire': {
+            'Meta': {'object_name': 'AyantDroitCommentaire'},
+            'ayant_droit': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'commentaires'", 'db_column': "'ayant_droit'", 'to': "orm['rh.AyantDroit']"}),
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'owner'", 'to': "orm['auth.User']"}),
+            'texte': ('django.db.models.fields.TextField', [], {})
+        },
+        'rh.categorieemploi': {
+            'Meta': {'object_name': 'CategorieEmploi'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.classement': {
+            'Meta': {'object_name': 'Classement'},
+            'coefficient': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
+            'commentaire': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'degre': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
+            'echelon': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
+        },
+        'rh.contrat': {
+            'Meta': {'object_name': 'Contrat'},
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_contrats'", 'db_column': "'dossier'", 'to': "orm['rh.Dossier']"}),
+            'fichier': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'type_contrat': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'type_contrat'", 'to': "orm['rh.TypeContrat']"})
+        },
+        'rh.devise': {
+            'Meta': {'object_name': 'Devise'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '10'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.dossier': {
+            'Meta': {'object_name': 'Dossier'},
+            'classement': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'classement'", 'to': "orm['rh.Classement']"}),
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_modification': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
+            'employe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_dossiers'", 'db_column': "'employe'", 'to': "orm['rh.Employe']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'organisme_bstg': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'organisme_bstg'", 'to': "orm['rh.OrganismeBstg']"}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_dossiers'", 'db_column': "'poste'", 'to': "orm['rh.Poste']"}),
+            'principal': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+            'regime_travail': ('django.db.models.fields.DecimalField', [], {'default': "'100.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'regime_travail_nb_heure_semaine': ('django.db.models.fields.DecimalField', [], {'default': "'35.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'remplacement': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'remplacement_de': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Dossier']"}),
+            'statut': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Statut']"}),
+            'statut_residence': ('django.db.models.fields.CharField', [], {'default': "'local'", 'max_length': '10', 'null': 'True'})
+        },
+        'rh.dossiercommentaire': {
+            'Meta': {'object_name': 'DossierCommentaire'},
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'commentaires'", 'db_column': "'dossier'", 'to': "orm['rh.Dossier']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'owner'", 'to': "orm['auth.User']"}),
+            'texte': ('django.db.models.fields.TextField', [], {})
+        },
+        'rh.dossiercomparaison': {
+            'Meta': {'object_name': 'DossierComparaison'},
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Devise']"}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_comparaisons'", 'to': "orm['rh.Dossier']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['references.Implantation']"}),
+            'montant': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'personne': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'poste': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
+        },
+        'rh.dossierpiece': {
+            'Meta': {'object_name': 'DossierPiece'},
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_dossierpieces'", 'db_column': "'dossier'", 'to': "orm['rh.Dossier']"}),
+            'fichier': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.employe': {
+            'Meta': {'object_name': 'Employe'},
+            'adresse': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'code_postal': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'courriel_perso': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'date_entree': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+            'date_naissance': ('django.db.models.fields.DateField', [], {'null': 'True', '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': "'employes_nationalite'", 'db_column': "'nationalite'", 'to_field': "'code'", 'to': "orm['references.Pays']", 'blank': 'True', 'null': 'True'}),
+            'nb_postes': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_affichage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'employes'", 'db_column': "'pays'", 'to_field': "'code'", 'to': "orm['references.Pays']", 'blank': 'True', 'null': 'True'}),
+            'prenom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'province': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'situation_famille': ('django.db.models.fields.CharField', [], {'max_length': '1', 'null': 'True', 'blank': 'True'}),
+            'tel_cellulaire': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'tel_domicile': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'ville': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
+        },
+        'rh.employecommentaire': {
+            'Meta': {'object_name': 'EmployeCommentaire'},
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'employe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'commentaires'", 'db_column': "'employe'", 'to': "orm['rh.Employe']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'owner'", 'to': "orm['auth.User']"}),
+            'texte': ('django.db.models.fields.TextField', [], {})
+        },
+        'rh.employepiece': {
+            'Meta': {'object_name': 'EmployePiece'},
+            'employe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pieces'", 'db_column': "'employe'", 'to': "orm['rh.Employe']"}),
+            'fichier': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.familleprofessionnelle': {
+            'Meta': {'object_name': 'FamilleProfessionnelle'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'rh.modificationtraite': {
+            'Meta': {'object_name': 'ModificationTraite'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'revision': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reversion.Revision']"})
+        },
+        'rh.organismebstg': {
+            'Meta': {'object_name': 'OrganismeBstg'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'pays': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'organismes_bstg'", 'db_column': "'pays'", 'to_field': "'code'", 'to': "orm['references.Pays']", 'blank': 'True', 'null': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
+        },
+        'rh.poste': {
+            'Meta': {'object_name': 'Poste'},
+            'appel': ('django.db.models.fields.CharField', [], {'default': "'interne'", 'max_length': '10', 'null': 'True'}),
+            'autre_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'autre_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'classement_max': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'classement_max'", 'to': "orm['rh.Classement']"}),
+            'classement_min': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'classement_min'", 'to': "orm['rh.Classement']"}),
+            'comp_autre_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_autre_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_fonctionpub_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_fonctionpub_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_locale_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_locale_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_ong_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_ong_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_universite_max': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'comp_universite_min': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_modification': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
+            'devise_comparaison': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'devise_comparaison'", 'to': "orm['rh.Devise']"}),
+            'devise_max': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'devise_max'", 'to': "orm['rh.Devise']"}),
+            'devise_min': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'devise_min'", 'to': "orm['rh.Devise']"}),
+            'expatrie': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'implantation'", 'to': "orm['references.Implantation']"}),
+            'indemn_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'indemn_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'justification': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'local': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}),
+            'mise_a_disposition': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_feminin': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
+            'regime_travail': ('django.db.models.fields.DecimalField', [], {'default': "'100.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'regime_travail_nb_heure_semaine': ('django.db.models.fields.DecimalField', [], {'default': "'35.00'", 'null': 'True', 'max_digits': '12', 'decimal_places': '2'}),
+            'responsable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'responsable'", 'to': "orm['rh.Poste']"}),
+            'salaire_max': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'salaire_min': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}),
+            'service': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_postes'", 'null': 'True', 'db_column': "'service'", 'to': "orm['rh.Service']"}),
+            'type_poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'db_column': "'type_poste'", 'to': "orm['rh.TypePoste']"}),
+            'vacant': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
+            'valeur_point_max': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'valeur_point_max'", 'to': "orm['rh.ValeurPoint']"}),
+            'valeur_point_min': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'valeur_point_min'", 'to': "orm['rh.ValeurPoint']"})
+        },
+        'rh.postecommentaire': {
+            'Meta': {'object_name': 'PosteCommentaire'},
+            'date_creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'owner'", 'to': "orm['auth.User']"}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'commentaires'", 'db_column': "'poste'", 'to': "orm['rh.Poste']"}),
+            'texte': ('django.db.models.fields.TextField', [], {})
+        },
+        'rh.postecomparaison': {
+            'Meta': {'object_name': 'PosteComparaison'},
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['rh.Devise']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['references.Implantation']"}),
+            'montant': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_comparaisons_internes'", 'to': "orm['rh.Poste']"})
+        },
+        'rh.postefinancement': {
+            'Meta': {'object_name': 'PosteFinancement'},
+            'commentaire': ('django.db.models.fields.TextField', [], {}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_financements'", 'db_column': "'poste'", 'to': "orm['rh.Poste']"}),
+            'pourcentage': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '1'})
+        },
+        'rh.postepiece': {
+            'Meta': {'object_name': 'PostePiece'},
+            'fichier': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'poste': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_pieces'", 'db_column': "'poste'", 'to': "orm['rh.Poste']"})
+        },
+        'rh.remuneration': {
+            'Meta': {'object_name': 'Remuneration'},
+            'commentaire': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'date_debut': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'date_fin': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'devise'", 'to': "orm['rh.Devise']"}),
+            'dossier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_remunerations'", 'db_column': "'dossier'", 'to': "orm['rh.Dossier']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'montant': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
+            'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'type'", 'to': "orm['rh.TypeRemuneration']"}),
+            'type_revalorisation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'type_revalorisation'", 'to': "orm['rh.TypeRevalorisation']"})
+        },
+        'rh.responsableimplantation': {
+            'Meta': {'object_name': 'ResponsableImplantation'},
+            'employe': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'db_column': "'employe'", 'to': "orm['rh.Employe']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'responsable'", 'unique': 'True', 'db_column': "'implantation'", 'to': "orm['references.Implantation']"})
+        },
+        'rh.responsableimplantationproxy': {
+            'Meta': {'managed': 'False', 'object_name': 'ResponsableImplantationProxy', 'db_table': "u'ref_implantation'", '_ormbases': ['references.Implantation']}
+        },
+        'rh.service': {
+            'Meta': {'object_name': 'Service'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.statut': {
+            'Meta': {'object_name': 'Statut'},
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '25'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.tauxchange': {
+            'Meta': {'unique_together': "(('devise', 'annee'),)", 'object_name': 'TauxChange'},
+            'annee': ('django.db.models.fields.IntegerField', [], {}),
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rh.Devise']", 'db_column': "'devise'"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'taux': ('django.db.models.fields.FloatField', [], {})
+        },
+        'rh.typecontrat': {
+            'Meta': {'object_name': 'TypeContrat'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_long': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.typeposte': {
+            'Meta': {'object_name': 'TypePoste'},
+            'categorie_emploi': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'categorie_emploi'", 'to': "orm['rh.CategorieEmploi']"}),
+            'famille_professionnelle': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'types_de_poste'", 'null': 'True', 'to': "orm['rh.FamilleProfessionnelle']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_responsable': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'nom_feminin': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.typeremuneration': {
+            'Meta': {'object_name': 'TypeRemuneration'},
+            'archive': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nature_remuneration': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'type_paiement': ('django.db.models.fields.CharField', [], {'max_length': '30'})
+        },
+        'rh.typerevalorisation': {
+            'Meta': {'object_name': 'TypeRevalorisation'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nom': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+        },
+        'rh.valeurpoint': {
+            'Meta': {'unique_together': "(('implantation', 'annee'),)", 'object_name': 'ValeurPoint'},
+            'annee': ('django.db.models.fields.IntegerField', [], {}),
+            'devise': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'db_column': "'devise'", 'to': "orm['rh.Devise']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'implantation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rh_valeur_point'", 'db_column': "'implantation'", 'to': "orm['references.Implantation']"}),
+            'valeur': ('django.db.models.fields.FloatField', [], {'null': 'True'})
+        }
+    }
+    
+    complete_apps = ['rh']
index ada39b5..944df17 100644 (file)
@@ -20,6 +20,7 @@ from project.rh.managers import PosteManager, DossierManager, EmployeManager, \
         DossierComparaisonManager, \
         PosteComparaisonManager, \
         TypeRemunerationManager, \
+        ContratManager, \
         RemunerationManager
 from project.rh.validators import validate_date_passee
 
@@ -40,6 +41,9 @@ storage_prive = FileSystemStorage(settings.PRIVE_MEDIA_ROOT,
                             base_url=settings.PRIVE_MEDIA_URL)
 
 
+class RemunIntegrityException(Exception):
+    pass
+
 def poste_piece_dispatch(instance, filename):
     path = "%s/poste/%s/%s" % (
         instance._meta.app_label, instance.poste_id, filename
@@ -257,22 +261,22 @@ class Poste_( DateActiviteMixin, models.Model,):
         'Devise', db_column='devise_max', null=True, related_name='+'
     )
     salaire_min = models.DecimalField(
-        max_digits=12, decimal_places=2, null=True, blank=True
+        max_digits=12, decimal_places=2, default=0,
     )
     salaire_max = models.DecimalField(
-        max_digits=12, decimal_places=2, null=True, blank=True
+        max_digits=12, decimal_places=2, default=0,
     )
     indemn_min = models.DecimalField(
-        max_digits=12, decimal_places=2, null=True, blank=True
+        max_digits=12, decimal_places=2, default=0,
     )
     indemn_max = models.DecimalField(
-        max_digits=12, decimal_places=2, null=True, blank=True
+        max_digits=12, decimal_places=2, default=0,
     )
     autre_min = models.DecimalField(
-        max_digits=12, decimal_places=2, null=True, blank=True
+        max_digits=12, decimal_places=2, default=0,
     )
     autre_max = models.DecimalField(
-        max_digits=12, decimal_places=2, null=True, blank=True
+        max_digits=12, decimal_places=2, default=0,
     )
 
     # Comparatifs de rémunération
@@ -1217,13 +1221,6 @@ reversion.register(Remuneration, format='xml')
 
 ### CONTRATS
 
-class ContratManager(models.Manager):
-
-    def get_query_set(self):
-        return super(ContratManager, self).get_query_set() \
-                .select_related('dossier', 'dossier__poste')
-
-
 class Contrat_(models.Model):
     """
     Document juridique qui encadre la relation de travail d'un Employe
index 31fcaaa..823483c 100644 (file)
@@ -6,7 +6,12 @@
   <script type="text/javascript" src="/admin/jsi18n"></script>
   <script type="text/javascript" src="{{ STATIC_URL }}/admin/js/core.js"></script>
   <script type="text/javascript" src="{{ STATIC_URL }}admin/js/admin/RelatedObjectLookups.js"></script>
+  <script type="text/javascript" src="{{ STATIC_URL }}/js/jquery-1.5.1.min.js"></script>
+  <script type="text/javascript" src="{{ STATIC_URL }}/js/tous-aucun.js"></script>
   {{ block.super }}
+  <style>
+      .tous-handler, .aucun-handler {cursor: pointer;}
+  </style>
 {% endblock %}
 
 {% block title %}
 <br />
 
 <form method="post">
-    <table id="result_list" class="results">
+    <table id="result_list" class="results check-batch">
       <thead>
           <tr>
               {% for h in headers %}
                 <th>{{ h }}</th>
               {% endfor %}
+              <th>Traité (<span class="tous-handler">tous</span>/<span
+                      class="aucun-handler">aucun</span>)</th>
           </tr>
       </thead>
       {% for revision in revisions %}
index 5a23741..643229e 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
@@ -260,8 +261,8 @@ class RhTest(TestCase):
             # on le porte dans le référentiel employé
             ref_e = ref.Employe(id=u.id,
                     nom=e.nom, prenom=e.prenom,
-                    implantation=e.poste_principal().implantation,
-                    implantation_physique=e.poste_principal().implantation,
+                    implantation=e.dossier_principal().poste.implantation,
+                    implantation_physique=e.dossier_principal().poste.implantation,
                     service=ref.Service.objects.get(id=1))
             ref_e.save()
 
@@ -284,7 +285,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 42849a9..2ca5076 100644 (file)
@@ -3,6 +3,7 @@
 from django.core.urlresolvers import reverse
 from project.rh.test.common import RhTest
 
+
 class EmployeAddTest(RhTest):
     """
     Test l'ajout d'un employé
@@ -155,7 +156,8 @@ class EmployeDeleteTest(RhTest):
 
     def _test_grp_service_utilisateurs(self):
         """
-        Un membre du groupe service utilisateur  ne peut pas supprimer un employé
+        Un membre du groupe service utilisateur
+        ne peut pas supprimer un employé
         """
         self._test_grp_service_utilisateurs()
         self._test_acces_ko(self.url)
@@ -320,7 +322,8 @@ class EmployeApercuTest(RhTest):
 
     def test_drh2(self):
         """
-        Un DRH (2ieme niveau) peut voir tous les aperçus d'employés avec tous les dossiers
+        Un DRH (2ieme niveau) peut voir tous les aperçus d'employés
+        avec tous les dossiers
         """
         self._test_drh2()
         self._test_acces_ok(self.url)
@@ -346,14 +349,16 @@ class EmployeApercuTest(RhTest):
 
     def _test_grp_haute_direction(self):
         """
-        Un membre de la haute direction ne peut pas voir les aperçus d'employés
+        Un membre de la haute direction ne peut pas voir
+        les aperçus d'employés
         """
         self._test_grp_haute_direction()
         self._test_acces_ko(self.url)
 
     def _test_grp_service_utilisateurs(self):
         """
-        Un membre du groupe service utilisateur ne pas pas voir les aperçus d'employés
+        Un membre du groupe service utilisateur ne pas pas voir
+        les aperçus d'employés
         """
         self._test_grp_service_utilisateurs()
         self._test_acces_ko(self.url)
diff --git a/project/rh/test/manager.py b/project/rh/test/manager.py
new file mode 100644 (file)
index 0000000..e279f13
--- /dev/null
@@ -0,0 +1,543 @@
+# -*- coding: utf-8 -*-
+
+import datetime
+from django.core.urlresolvers import reverse
+from project.rh.test.common import RhTest
+from project.rh.change_list import KEY_STATUT, STATUT_ACTIF, STATUT_INACTIF,\
+    STATUT_FUTUR
+
+
+class PosteVolumetrieTest(RhTest):
+    """
+    Test les notions d'actifs / inactifs
+    """
+
+    today = datetime.date.today()
+    annee_moins_2 = datetime.date(today.year - 2, 1, 1)
+    annee_moins_1 = datetime.date(today.year - 1, 1, 1)
+    annee_plus_2 = datetime.date(today.year + 2, 1, 1)
+    annee_plus_1 = datetime.date(today.year + 1, 1, 1)
+
+    def test_actifs(self):
+        """
+        Test la remontée des postes actifs.
+        """
+        self.poste_cnf_ngaoundere.date_debut = self.annee_moins_1
+        self.poste_cnf_ngaoundere.date_fin = self.annee_plus_1
+        self.poste_cnf_ngaoundere.save()
+
+        self.poste_cnf_bangui.date_debut = self.annee_moins_1
+        self.poste_cnf_bangui.date_fin = self.annee_plus_1
+        self.poste_cnf_bangui.save()
+
+        self.poste_bap_bureau.date_debut = self.annee_moins_1
+        self.poste_bap_bureau.date_fin = None
+        self.poste_bap_bureau.save()
+
+        self.poste_bap_ifi.date_debut = self.annee_moins_1
+        self.poste_bap_ifi.date_fin = None
+        self.poste_bap_ifi.save()
+    
+        self._test_drh()
+        url = reverse('admin:rh_poste_changelist')
+        params = {KEY_STATUT: STATUT_ACTIF}
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 4)
+
+        # puis 1 poste inactif
+        self.poste_bap_ifi.date_debut = self.annee_moins_2
+        self.poste_bap_ifi.date_fin = self.annee_moins_1
+        self.poste_bap_ifi.save()
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 3)
+
+        # puis 1 poste futur
+        self.poste_cnf_bangui.date_debut = self.annee_plus_1
+        self.poste_cnf_bangui.date_fin = None
+        self.poste_cnf_bangui.save()
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 2)
+
+    def test_inactifs(self):
+        """
+        Test la remontée des postes inactifs.
+        """
+        self.poste_cnf_ngaoundere.date_debut = self.annee_moins_2
+        self.poste_cnf_ngaoundere.date_fin = self.annee_moins_1
+        self.poste_cnf_ngaoundere.save()
+
+        self.poste_cnf_bangui.date_debut = self.annee_moins_2
+        self.poste_cnf_bangui.date_fin = self.annee_moins_1
+        self.poste_cnf_bangui.save()
+
+        self.poste_bap_bureau.date_debut = self.annee_moins_2
+        self.poste_bap_bureau.date_fin = self.annee_moins_1
+        self.poste_bap_bureau.save()
+
+        self.poste_bap_ifi.date_debut = self.annee_moins_2
+        self.poste_bap_ifi.date_fin = self.annee_moins_1
+        self.poste_bap_ifi.save()
+    
+        self._test_drh()
+        url = reverse('admin:rh_poste_changelist')
+        params = {KEY_STATUT: STATUT_INACTIF}
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 4)
+
+        # puis 1 actif
+        self.poste_bap_bureau.date_debut = self.annee_moins_2
+        self.poste_bap_bureau.date_fin = self.annee_plus_1
+        self.poste_bap_bureau.save()
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 3)
+
+        # puis 1 futur
+        self.poste_bap_ifi.date_debut = self.annee_plus_1
+        self.poste_bap_ifi.date_fin = self.annee_plus_2
+        self.poste_bap_ifi.save()
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 2)
+
+    def test_futurs(self):
+        """
+        Test la remontée des postes futurs.
+        """
+        self.poste_cnf_ngaoundere.date_debut = self.annee_plus_1
+        self.poste_cnf_ngaoundere.date_fin = self.annee_plus_2
+        self.poste_cnf_ngaoundere.save()
+
+        self.poste_cnf_bangui.date_debut = self.annee_plus_1
+        self.poste_cnf_bangui.date_fin = self.annee_plus_2
+        self.poste_cnf_bangui.save()
+
+        self.poste_bap_bureau.date_debut = self.annee_plus_1
+        self.poste_bap_bureau.date_fin = self.annee_plus_2
+        self.poste_bap_bureau.save()
+
+        self.poste_bap_ifi.date_debut = self.annee_plus_1
+        self.poste_bap_ifi.date_fin = self.annee_plus_2
+        self.poste_bap_ifi.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_poste_changelist')
+        params = {KEY_STATUT: STATUT_FUTUR}
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 4)
+
+        # puis 1 actif
+        self.poste_bap_bureau.date_debut = self.annee_moins_1
+        self.poste_bap_bureau.date_fin = self.annee_plus_2
+        self.poste_bap_bureau.save()
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 3)
+
+        # puis 1 inactif
+        self.poste_bap_ifi.date_debut = self.annee_moins_2
+        self.poste_bap_ifi.date_fin = self.annee_moins_1
+        self.poste_bap_ifi.save()
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 2)
+
+
+class EmployeVolumetrieTest(RhTest):
+    """
+    Test les notions d'actifs / inactifs
+    """
+
+    today = datetime.date.today()
+    annee_moins_2 = datetime.date(today.year - 2, 1, 1)
+    annee_moins_1 = datetime.date(today.year - 1, 1, 1)
+    annee_plus_2 = datetime.date(today.year + 2, 1, 1)
+    annee_plus_1 = datetime.date(today.year + 1, 1, 1)
+
+    def test_actifs(self):
+        """
+        Test la remontée des dossiers actifs pour 4 employés différents
+        avec chacun un dossier.
+        """
+        # 2 dossiers actifs
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_1
+        self.dossier_cnf_ngaoundere.date_fin = self.annee_plus_1
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_1
+        self.dossier_cnf_bangui.date_fin = self.annee_plus_1
+        self.dossier_cnf_bangui.save()
+
+        # 1 dossier inactif
+        self.dossier_bap_bureau.date_debut = self.annee_moins_2
+        self.dossier_bap_bureau.date_fin = self.annee_moins_1
+        self.dossier_bap_bureau.save()
+
+        # 1 dossier futur
+        self.dossier_bap_ifi.date_debut = self.annee_plus_1
+        self.dossier_bap_ifi.date_fin = self.annee_plus_2
+        self.dossier_bap_ifi.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_employe_changelist')
+        params = {KEY_STATUT: STATUT_ACTIF}
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 2)
+
+        # Puis 1 seul dossier actif
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_2
+        self.dossier_cnf_bangui.date_fin = self.annee_moins_1
+        self.dossier_cnf_bangui.save()
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+
+    def test_inactifs(self):
+        """
+        Test la remontée des dossiers inactifs de 4 employés différents
+        avec chacun un dossier
+        """
+        # 2 dossiers actifs
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_1
+        self.dossier_cnf_ngaoundere.date_fin = self.annee_plus_1
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_1
+        self.dossier_cnf_bangui.date_fin = self.annee_plus_1
+        self.dossier_cnf_bangui.save()
+
+        # 1 dossier inactif
+        self.dossier_bap_bureau.date_debut = self.annee_moins_2
+        self.dossier_bap_bureau.date_fin = self.annee_moins_1
+        self.dossier_bap_bureau.save()
+
+        # 1 dossier futur
+        self.dossier_bap_ifi.date_debut = self.annee_plus_1
+        self.dossier_bap_ifi.date_fin = self.annee_plus_2
+        self.dossier_bap_ifi.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_employe_changelist')
+        params = {KEY_STATUT: STATUT_INACTIF}
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+
+        # Puis 1 seul dossier actif
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_2
+        self.dossier_cnf_bangui.date_fin = self.annee_moins_1
+        self.dossier_cnf_bangui.save()
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 2)
+
+    def test_futurs(self):
+        """
+        Test la remontée des dossiers futurs pour 4 employés différents
+        avec chacun un dossier.
+        """
+        # 2 dossiers actifs
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_1
+        self.dossier_cnf_ngaoundere.date_fin = self.annee_plus_1
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_1
+        self.dossier_cnf_bangui.date_fin = self.annee_plus_1
+        self.dossier_cnf_bangui.save()
+
+        # 1 dossier inactif
+        self.dossier_bap_bureau.date_debut = self.annee_moins_2
+        self.dossier_bap_bureau.date_fin = self.annee_moins_1
+        self.dossier_bap_bureau.save()
+
+        # 1 dossier futur
+        self.dossier_bap_ifi.date_debut = self.annee_plus_1
+        self.dossier_bap_ifi.date_fin = self.annee_plus_2
+        self.dossier_bap_ifi.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_employe_changelist')
+        params = {KEY_STATUT: STATUT_FUTUR}
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+
+        # Puis 1 seul dossier actif
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_2
+        self.dossier_cnf_bangui.date_fin = self.annee_moins_1
+        self.dossier_cnf_bangui.save()
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+
+    def test_2_dossiers_actifs(self):
+        """
+        Test employe qui a 2 dossiers actifs.
+        """
+        self.dossier_bap_bureau.delete()
+        self.dossier_bap_ifi.delete()
+
+        # 2 dossiers actifs
+        self.dossier_cnf_ngaoundere = self.employe_cnf_ngaoundere
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_1
+        self.dossier_cnf_ngaoundere.date_fin = self.annee_plus_1
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.employe = self.employe_cnf_ngaoundere
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_1
+        self.dossier_cnf_bangui.date_fin = self.annee_plus_1
+        self.dossier_cnf_bangui.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_employe_changelist')
+        params = {KEY_STATUT: STATUT_ACTIF}
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+
+    def test_1_dossier_actif(self):
+        """
+        Test employe qui a 1 dossier actifs et 1 inactif.
+        """
+        self.dossier_bap_bureau.delete()
+        self.dossier_bap_ifi.delete()
+
+        self.dossier_cnf_ngaoundere = self.employe_cnf_ngaoundere
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_2
+        self.dossier_cnf_ngaoundere.date_fin = None
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.employe = self.employe_cnf_ngaoundere
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_2
+        self.dossier_cnf_bangui.date_fin = self.annee_moins_1
+        self.dossier_cnf_bangui.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_employe_changelist')
+        params = {KEY_STATUT: STATUT_ACTIF}
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+
+    def test_2_dossiers_inactifs(self):
+        """
+        Test employe qui a 2 dossiers inactifs.
+        """
+        self.dossier_bap_bureau.delete()
+        self.dossier_bap_ifi.delete()
+
+        self.dossier_cnf_ngaoundere.employe = self.employe_cnf_ngaoundere
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_2
+        self.dossier_cnf_ngaoundere.date_fin = self.annee_moins_1
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.employe = self.employe_cnf_ngaoundere
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_2
+        self.dossier_cnf_bangui.date_fin = self.annee_moins_1
+        self.dossier_cnf_bangui.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_employe_changelist')
+        params = {KEY_STATUT: STATUT_ACTIF}
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 0)
+
+
+class DossierVolumetrieTest(RhTest):
+    """
+    Test les notions d'actifs / inactifs
+    """
+
+    today = datetime.date.today()
+    annee_moins_2 = datetime.date(today.year - 2, 1, 1)
+    annee_moins_1 = datetime.date(today.year - 1, 1, 1)
+    annee_plus_2 = datetime.date(today.year + 2, 1, 1)
+    annee_plus_1 = datetime.date(today.year + 1, 1, 1)
+
+    def test_actifs(self):
+        """
+        Test la remontée des dossiers actifs pour 4 employés différents
+        avec chacun un dossier.
+        """
+        # 2 dossiers actifs
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_1
+        self.dossier_cnf_ngaoundere.date_fin = self.annee_plus_1
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_1
+        self.dossier_cnf_bangui.date_fin = self.annee_plus_1
+        self.dossier_cnf_bangui.save()
+
+        # 1 dossier inactif
+        self.dossier_bap_bureau.date_debut = self.annee_moins_2
+        self.dossier_bap_bureau.date_fin = self.annee_moins_1
+        self.dossier_bap_bureau.save()
+
+        # 1 dossier futur
+        self.dossier_bap_ifi.date_debut = self.annee_plus_1
+        self.dossier_bap_ifi.date_fin = self.annee_plus_2
+        self.dossier_bap_ifi.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_dossier_changelist')
+        params = {KEY_STATUT: STATUT_ACTIF}
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 2)
+
+        # Puis 1 seul dossier actif
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_2
+        self.dossier_cnf_bangui.date_fin = self.annee_moins_1
+        self.dossier_cnf_bangui.save()
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+
+    def test_inactifs(self):
+        """
+        Test la remontée des dossiers inactifs de 4 employés différents
+        avec chacun un dossier
+        """
+        # 2 dossiers actifs
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_1
+        self.dossier_cnf_ngaoundere.date_fin = self.annee_plus_1
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_1
+        self.dossier_cnf_bangui.date_fin = self.annee_plus_1
+        self.dossier_cnf_bangui.save()
+
+        # 1 dossier inactif
+        self.dossier_bap_bureau.date_debut = self.annee_moins_2
+        self.dossier_bap_bureau.date_fin = self.annee_moins_1
+        self.dossier_bap_bureau.save()
+
+        # 1 dossier futur
+        self.dossier_bap_ifi.date_debut = self.annee_plus_1
+        self.dossier_bap_ifi.date_fin = self.annee_plus_2
+        self.dossier_bap_ifi.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_dossier_changelist')
+        params = {KEY_STATUT: STATUT_INACTIF}
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+
+        # Puis 1 seul dossier actif
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_2
+        self.dossier_cnf_bangui.date_fin = self.annee_moins_1
+        self.dossier_cnf_bangui.save()
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 2)
+
+    def test_futurs(self):
+        """
+        Test la remontée des dossiers futurs pour 4 employés différents
+        avec chacun un dossier.
+        """
+        # 2 dossiers actifs
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_1
+        self.dossier_cnf_ngaoundere.date_fin = self.annee_plus_1
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_1
+        self.dossier_cnf_bangui.date_fin = self.annee_plus_1
+        self.dossier_cnf_bangui.save()
+
+        # 1 dossier inactif
+        self.dossier_bap_bureau.date_debut = self.annee_moins_2
+        self.dossier_bap_bureau.date_fin = self.annee_moins_1
+        self.dossier_bap_bureau.save()
+
+        # 1 dossier futur
+        self.dossier_bap_ifi.date_debut = self.annee_plus_1
+        self.dossier_bap_ifi.date_fin = self.annee_plus_2
+        self.dossier_bap_ifi.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_dossier_changelist')
+        params = {KEY_STATUT: STATUT_FUTUR}
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+
+        # Puis 1 seul dossier actif
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_2
+        self.dossier_cnf_bangui.date_fin = self.annee_moins_1
+        self.dossier_cnf_bangui.save()
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+
+    def test_2_dossiers_actifs(self):
+        """
+        Test employe qui a 2 dossiers actifs.
+        """
+        self.dossier_bap_bureau.delete()
+        self.dossier_bap_ifi.delete()
+
+        # 2 dossiers actifs
+        self.dossier_cnf_ngaoundere = self.employe_cnf_ngaoundere
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_1
+        self.dossier_cnf_ngaoundere.date_fin = self.annee_plus_1
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.employe = self.employe_cnf_ngaoundere
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_1
+        self.dossier_cnf_bangui.date_fin = self.annee_plus_1
+        self.dossier_cnf_bangui.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_dossier_changelist')
+        params = {KEY_STATUT: STATUT_ACTIF}
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 2)
+
+    def test_1_dossier_actif(self):
+        """
+        Test employe qui a 1 dossier actifs et 1 inactif.
+        """
+        self.dossier_bap_bureau.delete()
+        self.dossier_bap_ifi.delete()
+
+        self.dossier_cnf_ngaoundere = self.employe_cnf_ngaoundere
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_2
+        self.dossier_cnf_ngaoundere.date_fin = None
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.employe = self.employe_cnf_ngaoundere
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_2
+        self.dossier_cnf_bangui.date_fin = self.annee_moins_1
+        self.dossier_cnf_bangui.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_dossier_changelist')
+        params = {KEY_STATUT: STATUT_ACTIF}
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 1)
+
+    def test_2_dossiers_inactifs(self):
+        """
+        Test employe qui a 2 dossiers inactifs.
+        """
+        self.dossier_bap_bureau.delete()
+        self.dossier_bap_ifi.delete()
+
+        self.dossier_cnf_ngaoundere.employe = self.employe_cnf_ngaoundere
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_2
+        self.dossier_cnf_ngaoundere.date_fin = self.annee_moins_1
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.employe = self.employe_cnf_ngaoundere
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_2
+        self.dossier_cnf_bangui.date_fin = self.annee_moins_1
+        self.dossier_cnf_bangui.save()
+
+        self._test_drh()
+        url = reverse('admin:rh_dossier_changelist')
+        params = {KEY_STATUT: STATUT_ACTIF}
+
+        qs = self.client.get(url, params).context['cl'].query_set
+        self.assertEqual(len(qs), 0)
index ab14bcb..69e3454 100644 (file)
@@ -1,6 +1,8 @@
 # -*- coding: utf-8 -*-
 
+import datetime
 from django.core.urlresolvers import reverse
+from django.contrib.auth.models import User
 from project.rh.test.common import RhTest
 from project.rh import models as rh
 
@@ -28,31 +30,6 @@ class RapportContratTest(RhTest):
                 dossier=self.dossier_bap_ifi)
         contrat.save()
 
-        salaire = rh.TypeRemuneration(nom="salaire",
-                type_paiement="Régulier",
-                nature_remuneration="Indemnité",
-                )
-        salaire.save()
-
-        remun_cnf_ngaoundere = rh.Remuneration(
-                type=salaire,
-                date_debut=self.today,
-                dossier=self.dossier_cnf_ngaoundere,
-                montant="100",
-                devise=self.devise_cad,
-                )
-        remun_cnf_ngaoundere.save()
-
-        remun_bap_ifi = rh.Remuneration(
-                type=salaire,
-                date_debut=self.today,
-                dossier=self.dossier_bap_ifi,
-                montant="200",
-                devise=self.devise_cad,
-                )
-        remun_bap_ifi.save()
-
-
     def test_anonyme(self):
         """
         Un anonyme ne peut pas accéder à ce rapport
@@ -183,7 +160,6 @@ class RapportMasseSalarialeTest(RhTest):
         """
         self._test_drh()
         self._test_acces_ok(self.url)
-        # todo TEST rapport
 
     def test_drh2(self):
         """
@@ -330,3 +306,142 @@ class RapportOrganigrammeTest(RhTest):
         self._test_grp_service_utilisateurs()
         for url in self.urls:
             self._test_acces_ko(url)
+
+class RapportMasseSalarialeCalculTest(RhTest):
+    """
+    Test l'accès au rapport de masse salariale
+    """
+    url = reverse('rhr_masse_salariale')
+
+    today = datetime.date.today()
+    annee_moins_2 = datetime.date(today.year - 2, 1, 1)
+    annee_moins_1 = datetime.date(today.year - 1, 1, 1)
+    annee_plus_2 = datetime.date(today.year + 2, 1, 1)
+    annee_plus_1 = datetime.date(today.year + 1, 1, 1)
+
+
+    def setUp(self):
+        super(RapportMasseSalarialeCalculTest, self).setUp()
+
+        self.type_salaire = rh.TypeRemuneration(nom="salaire",
+                type_paiement="Régulier",
+                nature_remuneration="Indemnité",
+                )
+        self.type_salaire.save()
+
+        # 4 dossiers actifs
+        self.dossier_cnf_ngaoundere.date_debut = self.annee_moins_1
+        self.dossier_cnf_ngaoundere.date_fin = self.annee_plus_1
+        self.dossier_cnf_ngaoundere.save()
+
+        self.dossier_cnf_bangui.date_debut = self.annee_moins_1
+        self.dossier_cnf_bangui.date_fin = self.annee_plus_1
+        self.dossier_cnf_bangui.save()
+
+        self.dossier_bap_bureau.date_debut = self.annee_moins_1
+        self.dossier_bap_bureau.date_fin = self.annee_plus_1
+        self.dossier_bap_bureau.save()
+
+        self.dossier_bap_ifi.date_debut = self.annee_moins_1
+        self.dossier_bap_ifi.date_fin = self.annee_plus_1
+        self.dossier_bap_ifi.save()
+
+
+        self.remun_cnf_ngaoundere = rh.Remuneration(
+                type=self.type_salaire,
+                date_debut=self.annee_moins_1,
+                dossier=self.dossier_cnf_ngaoundere,
+                montant="111",
+                devise=self.devise_cad,
+                )
+        self.remun_cnf_ngaoundere.save()
+
+        self.remun_cnf_bangui = rh.Remuneration(
+                type=self.type_salaire,
+                date_debut=self.annee_moins_1,
+                dossier=self.dossier_cnf_bangui,
+                montant="222",
+                devise=self.devise_cad,
+                )
+        self.remun_cnf_bangui.save()
+
+        self.remun_bap_bureau = rh.Remuneration(
+                type=self.type_salaire,
+                date_debut=self.annee_moins_1,
+                dossier=self.dossier_bap_bureau,
+                montant="333",
+                devise=self.devise_cad,
+                )
+        self.remun_bap_bureau.save()
+
+        self.remun_bap_ifi = rh.Remuneration(
+                type=self.type_salaire,
+                date_debut=self.annee_moins_1,
+                dossier=self.dossier_bap_ifi,
+                montant="444",
+                devise=self.devise_cad,
+                )
+        self.remun_bap_ifi.save()
+
+        self.taux_change_cad = \
+            rh.TauxChange(devise=self.devise_cad,
+                taux=0.5,
+                annee=self.today.year)
+        self.taux_change_cad.save()
+
+    def test_taux_change_presence(self):
+        """
+        Intégrité des rémunérations.
+        """
+        from project.rh.views import rapports_masse_salariale
+
+        self._test_drh()
+        user_drh = User.objects.get(email="0@test.auf")
+        params = {'annee': self.today.year,  }
+
+        class Request:
+            GET = params
+            user = user_drh
+            
+            def get_full_path(self):
+                return
+
+        request = Request()
+        
+        self.taux_change_cad.delete()
+
+        self.assertRaises(rh.RemunIntegrityException,
+                rapports_masse_salariale, request)
+
+
+    def test_filtrage(self):
+        """
+        Test la page avec des paramètres de filtrage.
+        """
+        self._test_drh()
+        self._test_acces_ok(self.url)
+
+        params = {'implantation': self.IMPLANTATION_ACGL_CNF_NGAOUNDERE.id,
+                'annee': self.today.year,
+                }
+        resp = self.client.get(self.url, params)
+        self.assertEqual(resp.status_code, 200)
+        self.assertEqual(resp.context['form'].is_valid(), True, resp.context['form'].errors)
+        self.assertEqual(len(resp.context['lignes']), 1)
+
+        params = {
+                'region': self.REGION_ACGL.id,
+                'annee': self.today.year,
+                }
+        resp = self.client.get(self.url, params)
+        self.assertEqual(resp.status_code, 200)
+        self.assertEqual(resp.context['form'].is_valid(), True)
+        self.assertEqual(len(resp.context['lignes']), 2)
+
+        params = {
+                'annee': self.today.year,
+                }
+        resp = self.client.get(self.url, params)
+        self.assertEqual(resp.status_code, 200)
+        self.assertEqual(resp.context['form'].is_valid(), True)
+        self.assertEqual(len(resp.context['lignes']), 4)
index cf55b67..79db73c 100644 (file)
@@ -2,3 +2,4 @@ from project.rh.test.employe import *
 from project.rh.test.dossier import *
 from project.rh.test.poste import *
 from project.rh.test.rapport import *
+from project.rh.test.manager import *
index 5010814..0dca607 100644 (file)
@@ -262,10 +262,11 @@ def rapports_masse_salariale(request):
             dossiers = dossiers.filter(poste__implantation=implantation)
 
         # Récupérer les rémunérations actives
-        remuns = rh.Remuneration.objects \
+        remun_actives = rh.Remuneration.objects \
                 .actifs(annee=annee) \
-                .select_related('devise', 'type') \
-                .extra(
+                .select_related('devise', 'type')
+
+        remuns = remun_actives.extra(
                     tables=['rh_tauxchange'],
                     where=[
                         'rh_tauxchange.annee = %s',
@@ -276,6 +277,11 @@ def rapports_masse_salariale(request):
                         'taux_change': 'rh_tauxchange.taux'
                     }
                 )
+
+        if len(remun_actives) != len(remuns):
+            raise rh.RemunIntegrityException("Toutes les remunerations ne disposent pas d'un "
+                "taux de change pour l'année %d" % annee)
+
         if zone_administrative:
             remuns = remuns.filter(dossier__poste__implantation__zone_administrative=zone_administrative)
         if implantation:
@@ -858,7 +864,7 @@ def historique_des_modifications(request,):
     
     c = {
             'headers': ('Date', 'Auteur', 'Type', 'Objet', 'Historique',
-                'Commentaire',  'Traité'),
+                'Commentaire', ),
             'revisions': results,
             'page': page_revisions,
             'form': form,
index ba8fc23..4459b14 100644 (file)
@@ -9,9 +9,7 @@ PROJET_TITRE = "Ressources humaines"
 # Rapports d'erreurs
 SERVER_EMAIL = 'ne-pas-repondre@auf.org'
 EMAIL_SUBJECT_PREFIX = '[auf_rh_dae - %s] ' % socket.gethostname()
-ADMINS = (
-    ('Équipe ARI-SI', 'developpeurs@ca.auf.org'),
-)
+ADMINS = ()
 
 MANAGERS = ADMINS
 
@@ -21,19 +19,23 @@ FORMAT_MODULE_PATH = 'project.formats'
 USE_L10N = True
 USE_THOUSAND_SEPARATOR = False
 DATE_FORMAT = 'd-m-Y'
+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
@@ -56,6 +58,8 @@ 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',
@@ -84,6 +90,7 @@ INSTALLED_APPS = (
     'django_qbe',
     'ajax_select',
     'south',
+    'raven.contrib.django',
     'reversion',
     'alphafilter',
     'form_utils',
@@ -107,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"),
@@ -193,3 +198,45 @@ QBE_ALLOWED_FIELDS = {'Rh': {
 }}
 
 SOUTH_TESTS_MIGRATE = False
+
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': True,
+    'root': {
+        'level': 'WARNING',
+        'handlers': ['sentry'],
+    },
+    'formatters': {
+        'verbose': {
+            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
+        },
+    },
+    'handlers': {
+        'sentry': {
+            'level': 'WARNING',
+            'class': 'raven.contrib.django.handlers.SentryHandler',
+        },
+        'console': {
+            'level': 'DEBUG',
+            'class': 'logging.StreamHandler',
+            'formatter': 'verbose'
+        }
+    },
+    'loggers': {
+        'django.db.backends': {
+            'level': 'ERROR',
+            'handlers': ['console'],
+            'propagate': False,
+        },
+        'raven': {
+            'level': 'DEBUG',
+            'handlers': ['console'],
+            'propagate': False,
+        },
+        'sentry.errors': {
+            'level': 'DEBUG',
+            'handlers': ['console'],
+            'propagate': False,
+        },
+    },
+}
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 b56d9b8..7fcf178 100644 (file)
@@ -1,10 +1,10 @@
 [versions]
-django = 1.3.1
+django = 1.3.3
 south = 0.7
 django-admin-tools = 0.4.1
 django-ajax-selects = 1.1.4
 django-alphafilter = 0.5.3auf4
-django-reversion = 1.5.2
+django-reversion = 1.5.4
 django-sendfile = 0.2.1
 django-urldecorators = 0.3
 auf.django.auth = 0.5.5dev
@@ -17,7 +17,6 @@ pygraphviz = 1.0
 
 # Added by Buildout Versions at 2012-05-09 13:24:49.321297
 auf.django.admingroup = 0.3dev
-auf.recipe.django = 1.7
 buildout-versions = 1.7
 distribute = 0.6.15
 django-debug-toolbar = 0.9.4
@@ -64,5 +63,20 @@ 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
+
+# Added by Buildout Versions at 2012-08-23 09:19:43.234537
+auf.recipe.django = 2.1
+
+# Added by Buildout Versions at 2012-08-23 09:21:24.235070
+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