From 072d62066d0b39d3f519f84f2038427edb5f5b18 Mon Sep 17 00:00:00 2001
From: gauthierb <gauthierb@d57fa8bc-6af1-4de9-8b7d-78e900e231e7>
Date: Mon, 15 Sep 2014 13:21:03 +0000
Subject: [PATCH] =?UTF-8?q?Agr=C3=A9ment=20:=20utilisation=20du=20module?=
 =?UTF-8?q?=20BjyAuthorize=20dans=20sa=20version=20de=20DEV=20(en=20attend?=
 =?UTF-8?q?ant=20la=20version=20stable=201.4)=20pour=20pouvoir=20sp=C3=A9c?=
 =?UTF-8?q?ifier=20une=20assertion=20dans=20les=20controller=20guards=20et?=
 =?UTF-8?q?=20ainsi=20faire=20d=C3=A9pendre=20les=20autorisations=20du=20t?=
 =?UTF-8?q?ype=20d'agr=C3=A9ment=20courant.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 composer.json                                 |   1 +
 composer.lock                                 | 135 ++++++++-------
 module/Application/config/agrement.config.php |  29 ++--
 .../Controller/AgrementController.php         |   6 +
 .../Rule/Intervenant/AgrementAbstractRule.php | 138 +++++++++++++++
 .../Rule/Intervenant/AgrementFourniRule.php   | 140 +---------------
 .../Intervenant/NecessiteAgrementRule.php     |  56 +------
 .../AgrementNavigationPagesProvider.php       |   5 +
 .../Service/Assertion/AbstractAssertion.php   | 114 +++++++++++++
 .../Service/Assertion/AgrementAssertion.php   | 134 +++++++++++----
 .../Service/Assertion/ContratAssertion.php    |  46 ++---
 .../Service/Assertion/EntityAssertion.php     | 157 ------------------
 12 files changed, 489 insertions(+), 472 deletions(-)
 create mode 100644 module/Application/src/Application/Rule/Intervenant/AgrementAbstractRule.php
 create mode 100644 module/Application/src/Application/Service/Assertion/AbstractAssertion.php
 delete mode 100644 module/Application/src/Application/Service/Assertion/EntityAssertion.php

diff --git a/composer.json b/composer.json
index cb47101d2c..69bd80c5a8 100755
--- a/composer.json
+++ b/composer.json
@@ -12,6 +12,7 @@
         "unicaen/unicaen-auth":                 "dev-trunk",
         "unicaen/unicaen-ldap":                 "dev-trunk",
         "zendframework/zend-code":              ">=2.3",
+        "bjyoungblood/bjy-authorize": "dev-master",
         "zf-commons/zfc-user":                  "0.1.3",
         "mpdf/mpdf":                            "v5.7.2"
     },
diff --git a/composer.lock b/composer.lock
index a4d9f95975..e17ab81e83 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,31 +4,31 @@
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "3a4abe9eb3a2f23392513e99e429a1ef",
+    "hash": "10f0b06bca3c3f367d75ba879406a763",
     "packages": [
         {
             "name": "bjyoungblood/bjy-authorize",
-            "version": "1.4.0",
+            "version": "dev-master",
             "source": {
                 "type": "git",
                 "url": "https://github.com/bjyoungblood/BjyAuthorize.git",
-                "reference": "02723bd19f0bba33649d708022f8d0e0b795f57a"
+                "reference": "ff602bb3df17fac51b57645d8501a00f73d8fd66"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/bjyoungblood/BjyAuthorize/zipball/02723bd19f0bba33649d708022f8d0e0b795f57a",
-                "reference": "02723bd19f0bba33649d708022f8d0e0b795f57a",
+                "url": "https://api.github.com/repos/bjyoungblood/BjyAuthorize/zipball/ff602bb3df17fac51b57645d8501a00f73d8fd66",
+                "reference": "ff602bb3df17fac51b57645d8501a00f73d8fd66",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.3",
-                "zendframework/zend-cache": "~2.1",
-                "zendframework/zend-eventmanager": "~2.1",
-                "zendframework/zend-http": "~2.1",
-                "zendframework/zend-mvc": "~2.1",
-                "zendframework/zend-permissions-acl": "~2.1",
-                "zendframework/zend-servicemanager": "~2.1",
-                "zendframework/zend-view": "~2.1"
+                "zendframework/zend-cache": "~2.2",
+                "zendframework/zend-eventmanager": "~2.2",
+                "zendframework/zend-http": "~2.2",
+                "zendframework/zend-mvc": "~2.2",
+                "zendframework/zend-permissions-acl": "~2.2",
+                "zendframework/zend-servicemanager": "~2.2",
+                "zendframework/zend-view": "~2.2"
             },
             "require-dev": {
                 "doctrine/common": ">=2.3,<2.5-dev",
@@ -36,12 +36,12 @@
                 "satooshi/php-coveralls": "~0.6",
                 "squizlabs/php_codesniffer": "1.4.*",
                 "zendframework/zend-developer-tools": "0.*",
-                "zf-commons/zfc-user": "0.*"
+                "zf-commons/zfc-user": "1.*"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.4-dev"
+                    "dev-master": "1.5-dev"
                 }
             },
             "autoload": {
@@ -74,7 +74,7 @@
                 "zf2",
                 "zfc-user"
             ],
-            "time": "2013-07-05 11:59:46"
+            "time": "2014-09-06 10:15:09"
         },
         {
             "name": "doctrine/annotations",
@@ -706,7 +706,7 @@
                 {
                     "name": "Johannes Schmitt",
                     "email": "schmittjoh@gmail.com",
-                    "homepage": "https://github.com/schmittjoh",
+                    "homepage": "http://jmsyst.com",
                     "role": "Developer of wrapped JMSSerializerBundle"
                 }
             ],
@@ -795,23 +795,36 @@
             "time": "2014-07-11 03:05:53"
         },
         {
-            "name": "intouch/phpcas",
-            "version": "1.3.2",
+            "name": "jasig/phpcas",
+            "version": "1.3.3",
             "source": {
                 "type": "git",
-                "url": "https://github.com/In-Touch/phpCAS.git",
-                "reference": "2d77822871a179292e7c2a97cd45ba6d7bbf2bf7"
+                "url": "https://github.com/Jasig/phpCAS.git",
+                "reference": "b6f5d484735d3b0e80b068a87bd1eabac04b2cbe"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/In-Touch/phpCAS/zipball/2d77822871a179292e7c2a97cd45ba6d7bbf2bf7",
-                "reference": "2d77822871a179292e7c2a97cd45ba6d7bbf2bf7",
+                "url": "https://api.github.com/repos/Jasig/phpCAS/zipball/b6f5d484735d3b0e80b068a87bd1eabac04b2cbe",
+                "reference": "b6f5d484735d3b0e80b068a87bd1eabac04b2cbe",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.2.0"
+                "php": ">=5.0.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~3.7.10"
             },
             "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.3.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "source/"
+                ]
+            },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "Apache-2.0"
@@ -832,7 +845,7 @@
                 "cas",
                 "jasig"
             ],
-            "time": "2013-07-16 01:54:58"
+            "time": "2014-07-24 20:29:29"
         },
         {
             "name": "kriswallsmith/assetic",
@@ -1012,17 +1025,17 @@
         },
         {
             "name": "symfony/console",
-            "version": "v2.5.3",
+            "version": "v2.5.4",
             "target-dir": "Symfony/Component/Console",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/Console.git",
-                "reference": "cd2d1e4bac2206b337326b0140ff475fe9ad5f63"
+                "reference": "748beed2a1e73179c3f5154d33fe6ae100c1aeb1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Console/zipball/cd2d1e4bac2206b337326b0140ff475fe9ad5f63",
-                "reference": "cd2d1e4bac2206b337326b0140ff475fe9ad5f63",
+                "url": "https://api.github.com/repos/symfony/Console/zipball/748beed2a1e73179c3f5154d33fe6ae100c1aeb1",
+                "reference": "748beed2a1e73179c3f5154d33fe6ae100c1aeb1",
                 "shasum": ""
             },
             "require": {
@@ -1063,21 +1076,21 @@
             ],
             "description": "Symfony Console Component",
             "homepage": "http://symfony.com",
-            "time": "2014-08-05 09:00:40"
+            "time": "2014-08-14 16:10:54"
         },
         {
             "name": "symfony/process",
-            "version": "v2.5.3",
+            "version": "v2.5.4",
             "target-dir": "Symfony/Component/Process",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/Process.git",
-                "reference": "e0997d2a9a1a763484b34b989900b61322a9b056"
+                "reference": "136cf0bdaacea81f779583376d47dd8aef4fc6ba"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Process/zipball/e0997d2a9a1a763484b34b989900b61322a9b056",
-                "reference": "e0997d2a9a1a763484b34b989900b61322a9b056",
+                "url": "https://api.github.com/repos/symfony/Process/zipball/136cf0bdaacea81f779583376d47dd8aef4fc6ba",
+                "reference": "136cf0bdaacea81f779583376d47dd8aef4fc6ba",
                 "shasum": ""
             },
             "require": {
@@ -1110,7 +1123,7 @@
             ],
             "description": "Symfony Process Component",
             "homepage": "http://symfony.com",
-            "time": "2014-08-05 09:00:40"
+            "time": "2014-08-31 03:22:04"
         },
         {
             "name": "unicaen/unicaen-app",
@@ -1118,7 +1131,7 @@
             "source": {
                 "type": "svn",
                 "url": "https://svn.unicaen.fr/svn/UnicaenApp",
-                "reference": "/trunk/@509"
+                "reference": "/trunk/@525"
             },
             "require": {
                 "doctrine/doctrine-orm-module": ">=0.7",
@@ -1167,11 +1180,11 @@
             "source": {
                 "type": "svn",
                 "url": "https://svn.unicaen.fr/svn/UnicaenAuth",
-                "reference": "/trunk/@209"
+                "reference": "/trunk/@212"
             },
             "require": {
                 "bjyoungblood/bjy-authorize": ">=1.4",
-                "intouch/phpcas": ">=1.3",
+                "jasig/phpcas": ">=1.3.3",
                 "unicaen/unicaen-app": "dev-trunk",
                 "zf-commons/zfc-user-doctrine-orm": ">=0.1"
             },
@@ -3177,23 +3190,23 @@
     "packages-dev": [
         {
             "name": "phpunit/php-code-coverage",
-            "version": "1.2.17",
+            "version": "1.2.18",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "6ef2bf3a1c47eca07ea95f0d8a902a6340390b34"
+                "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6ef2bf3a1c47eca07ea95f0d8a902a6340390b34",
-                "reference": "6ef2bf3a1c47eca07ea95f0d8a902a6340390b34",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b",
+                "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.3",
                 "phpunit/php-file-iterator": ">=1.3.0@stable",
                 "phpunit/php-text-template": ">=1.2.0@stable",
-                "phpunit/php-token-stream": ">=1.1.3@stable"
+                "phpunit/php-token-stream": ">=1.1.3,<1.3.0"
             },
             "require-dev": {
                 "phpunit/phpunit": "3.7.*@dev"
@@ -3234,7 +3247,7 @@
                 "testing",
                 "xunit"
             ],
-            "time": "2014-03-28 10:53:45"
+            "time": "2014-09-02 10:13:14"
         },
         {
             "name": "phpunit/php-file-iterator",
@@ -3371,44 +3384,45 @@
         },
         {
             "name": "phpunit/php-token-stream",
-            "version": "1.3.0",
+            "version": "1.2.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-token-stream.git",
-                "reference": "f8d5d08c56de5cfd592b3340424a81733259a876"
+                "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/f8d5d08c56de5cfd592b3340424a81733259a876",
-                "reference": "f8d5d08c56de5cfd592b3340424a81733259a876",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32",
+                "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32",
                 "shasum": ""
             },
             "require": {
                 "ext-tokenizer": "*",
                 "php": ">=5.3.3"
             },
-            "require-dev": {
-                "phpunit/phpunit": "~4.2"
-            },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.3-dev"
+                    "dev-master": "1.2-dev"
                 }
             },
             "autoload": {
                 "classmap": [
-                    "src/"
+                    "PHP/"
                 ]
             },
             "notification-url": "https://packagist.org/downloads/",
+            "include-path": [
+                ""
+            ],
             "license": [
                 "BSD-3-Clause"
             ],
             "authors": [
                 {
                     "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
+                    "email": "sb@sebastian-bergmann.de",
+                    "role": "lead"
                 }
             ],
             "description": "Wrapper around PHP's tokenizer extension.",
@@ -3416,7 +3430,7 @@
             "keywords": [
                 "tokenizer"
             ],
-            "time": "2014-08-31 06:12:13"
+            "time": "2014-03-03 05:10:30"
         },
         {
             "name": "phpunit/phpunit",
@@ -3542,17 +3556,17 @@
         },
         {
             "name": "symfony/yaml",
-            "version": "v2.5.3",
+            "version": "v2.5.4",
             "target-dir": "Symfony/Component/Yaml",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/Yaml.git",
-                "reference": "5a75366ae9ca8b4792cd0083e4ca4dff9fe96f1f"
+                "reference": "01a7695bcfb013d0a15c6757e15aae120342986f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Yaml/zipball/5a75366ae9ca8b4792cd0083e4ca4dff9fe96f1f",
-                "reference": "5a75366ae9ca8b4792cd0083e4ca4dff9fe96f1f",
+                "url": "https://api.github.com/repos/symfony/Yaml/zipball/01a7695bcfb013d0a15c6757e15aae120342986f",
+                "reference": "01a7695bcfb013d0a15c6757e15aae120342986f",
                 "shasum": ""
             },
             "require": {
@@ -3585,7 +3599,7 @@
             ],
             "description": "Symfony Yaml Component",
             "homepage": "http://symfony.com",
-            "time": "2014-08-05 09:00:40"
+            "time": "2014-08-31 03:22:04"
         },
         {
             "name": "zendframework/zend-dom",
@@ -3692,7 +3706,8 @@
     "stability-flags": {
         "unicaen/unicaen-app": 20,
         "unicaen/unicaen-auth": 20,
-        "unicaen/unicaen-ldap": 20
+        "unicaen/unicaen-ldap": 20,
+        "bjyoungblood/bjy-authorize": 20
     },
     "prefer-stable": false,
     "platform": [
diff --git a/module/Application/config/agrement.config.php b/module/Application/config/agrement.config.php
index fa68490c53..6186cd6a31 100644
--- a/module/Application/config/agrement.config.php
+++ b/module/Application/config/agrement.config.php
@@ -4,6 +4,7 @@ namespace Application;
 
 use Application\Acl\ComposanteRole;
 use Application\Acl\IntervenantRole;
+use Application\Controller\AgrementController;
 
 return array(
     'router' => array(
@@ -44,7 +45,7 @@ return array(
                                         'typeAgrement' => '[0-9]*',
                                     ),
                                     'defaults' => array(
-                                        'action' => 'ajouter',
+                                        'action' => AgrementController::ACTION_AJOUTER,
                                     ),
                                 ),
                             ),
@@ -56,7 +57,7 @@ return array(
                                         'agrement' => '[0-9]*',
                                     ),
                                     'defaults' => array(
-                                        'action' => 'voir',
+                                        'action' => AgrementController::ACTION_VOIR,
                                     ),
                                 ),
                             ),
@@ -69,7 +70,7 @@ return array(
                                         'structure' => '[0-9]*',
                                     ),
                                     'defaults' => array(
-                                        'action' => 'voir-str',
+                                        'action' => AgrementController::ACTION_VOIR_STR,
                                     ),
                                 ),
                             ),
@@ -81,19 +82,7 @@ return array(
                                         'agrement' => '[0-9]*',
                                     ),
                                     'defaults' => array(
-                                        'action' => 'modifier',
-                                    ),
-                                ),
-                            ),
-                            'supprimer' => array(
-                                'type'    => 'Segment',
-                                'options' => array(
-                                    'route' => '/supprimer/:agrement',
-                                    'constraints' => array(
-                                        'agrement' => '[0-9]*',
-                                    ),
-                                    'defaults' => array(
-                                        'action' => 'supprimer',
+                                        'action' => AgrementController::ACTION_MODIFIER,
                                     ),
                                 ),
                             ),
@@ -122,7 +111,7 @@ return array(
                                         'typeAgrement' => '[0-9]*',
                                     ),
                                     'defaults' => array(
-                                        'action' => 'ajouter-lot',
+                                        'action' => AgrementController::ACTION_AJOUTER_LOT,
                                     ),
                                 ),
                             ),
@@ -172,7 +161,9 @@ return array(
                                     'type'  => 'AgrementNavigationPagesProvider',
                                     'route' => 'gestion/agrement/ajouter-lot',
                                     'withtarget' => true,
-                                    'resource'   => 'controller/Application\Controller\Agrement:ajouter-lot',
+                                    'resource'   => 'controller/Application\Controller\Agrement:' . AgrementController::ACTION_AJOUTER_LOT,
+                                    'privilege'  => AgrementController::ACTION_AJOUTER_LOT,
+                                    // NB: le code du type d'agrément sera concaténé au 'privilege' par le AgrementNavigationPagesProvider
                                 ),
                             ),
                         ),
@@ -188,11 +179,13 @@ return array(
                     'controller' => 'Application\Controller\Agrement',
                     'action'     => array('index', 'lister', 'voir'),
                     'roles'      => array(IntervenantRole::ROLE_ID, ComposanteRole::ROLE_ID, 'Administrateur'),
+                    'assertion'  => 'AgrementAssertion',
                 ),
                 array(
                     'controller' => 'Application\Controller\Agrement',
                     'action'     => array('ajouter', 'ajouter-lot', 'modifier', 'supprimer', 'voir-str'),
                     'roles'      => array(ComposanteRole::ROLE_ID, 'Administrateur'),
+                    'assertion'  => 'AgrementAssertion',
                 ),
             ),
         ),
diff --git a/module/Application/src/Application/Controller/AgrementController.php b/module/Application/src/Application/Controller/AgrementController.php
index df94b398c1..3679025a26 100644
--- a/module/Application/src/Application/Controller/AgrementController.php
+++ b/module/Application/src/Application/Controller/AgrementController.php
@@ -46,6 +46,12 @@ implements ContextProviderAwareInterface,
     use IntervenantServiceAwareTrait;
     use ServiceServiceAwareTrait;
     
+    const ACTION_VOIR        = "voir";
+    const ACTION_VOIR_STR    = "voir-str";
+    const ACTION_AJOUTER     = "ajouter";
+    const ACTION_AJOUTER_LOT = "ajouter-lot";
+    const ACTION_MODIFIER    = "modifier";
+
     /**
      * @var RoleInterface
      */
diff --git a/module/Application/src/Application/Rule/Intervenant/AgrementAbstractRule.php b/module/Application/src/Application/Rule/Intervenant/AgrementAbstractRule.php
new file mode 100644
index 0000000000..67cd63ff5e
--- /dev/null
+++ b/module/Application/src/Application/Rule/Intervenant/AgrementAbstractRule.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace Application\Rule\Intervenant;
+
+use Application\Entity\Db\Agrement;
+use Application\Entity\Db\Dossier;
+use Application\Entity\Db\IntervenantExterieur;
+use Application\Entity\Db\Structure;
+use Application\Rule\AbstractRule;
+use Application\Service\Agrement as AgrementService;
+use Application\Service\ContextProviderAwareInterface;
+use Application\Service\ContextProviderAwareTrait;
+use Application\Service\TypeAgrementStatut;
+use Application\Service\TypeAgrementStatut as TypeAgrementStatutService;
+use Application\Traits\IntervenantAwareTrait;
+use Application\Traits\TypeAgrementAwareTrait;
+use Doctrine\ORM\EntityManager;
+use Zend\ServiceManager\ServiceLocatorAwareInterface;
+use Zend\ServiceManager\ServiceLocatorAwareTrait;
+
+/**
+ * Description of AgrementFourniRule
+ *
+ * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
+ */
+abstract class AgrementAbstractRule extends AbstractRule implements ServiceLocatorAwareInterface, ContextProviderAwareInterface
+{
+    use ServiceLocatorAwareTrait;
+    use ContextProviderAwareTrait;
+    use IntervenantAwareTrait;
+    use TypeAgrementAwareTrait;
+
+    /**
+     * 
+     * @return array id => TypeAgrementStatut
+     */
+    protected function getTypesAgrementStatut()
+    {
+        $qb = $this->getServiceTypeAgrementStatut()->finderByStatutIntervenant($this->getIntervenant()->getStatut());
+        if ($this->getIntervenant() instanceof IntervenantExterieur 
+                && ($dossier = $this->getIntervenant()->getDossier())) { /* @var $dossier Dossier */
+            $this->getServiceTypeAgrementStatut()->finderByPremierRecrutement($dossier->getPremierRecrutement(), $qb);
+        }
+        $typesAgrementStatut = $this->getServiceTypeAgrementStatut()->getList($qb);
+        
+        return $typesAgrementStatut;
+    }
+    
+    /**
+     * 
+     * @return array id => TypeAgrement
+     */
+    public function getTypesAgrementAttendus()
+    {
+        $typesAgrementAttendus = array();
+        foreach ($this->getTypesAgrementStatut() as $tas) { /* @var $tas TypeAgrementStatut */
+            $type = $tas->getType();
+            $typesAgrementAttendus[$type->getId()] = $type;
+        }
+        
+        return $typesAgrementAttendus;
+    }
+    
+    /**
+     * 
+     * @return array id => TypeAgrement
+     */
+    public function getTypesAgrementFournis()
+    {
+        $typesAgrementFournis = array();
+        foreach ($this->getAgrementsFournis() as $a) { /* @var $a Agrement */
+            $type = $a->getType();
+            $typesAgrementFournis[$type->getId()] = $type;
+        }
+        
+        return $typesAgrementFournis;
+    }
+    
+    /**
+     * Recherche les agréments déjà fournis.
+     * 
+     * @param Structure|null $structure Structure concernée éventuelle
+     * @return array id => Agrement
+     */
+    public function getAgrementsFournis(Structure $structure = null)
+    {
+        $qb = $this->getServiceAgrement()->finderByType($this->getTypeAgrement());
+        $qb = $this->getServiceAgrement()->finderByIntervenant($this->getIntervenant(), $qb);
+        $qb = $this->getServiceAgrement()->finderByAnnee($this->getContextProvider()->getGlobalContext()->getAnnee(), $qb);
+        $agrementsFournis = $this->getServiceAgrement()->getList($qb);
+        
+        // filtrage par structure éventuel
+        if ($structure) {
+            $agrements = [];
+            foreach ($agrementsFournis as $agrement) { /* @var $agrement Agrement */
+                if ($structure === $agrement->getStructure()) {
+                    $agrements[$agrement->getId()] = $agrement;
+                }
+            }
+            return $agrements;
+        }
+        
+        return $agrementsFournis;
+    }
+    
+    /**
+     * 
+     * @return array id => Structure
+     */
+    public function getStructuresEnseignement()
+    {
+        // recherche des structures d'enseignements de l'intervenant
+        $em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default'); /* @var $em EntityManager */
+        $qb = $em->getRepository('Application\Entity\Db\Structure')->createQueryBuilder("str")
+                ->join("str.service", "s")
+                ->where("s.intervenant = :intervenant")
+                ->setParameter('intervenant', $this->getIntervenant());
+        $structuresEns = $qb->getQuery()->getResult();
+        
+        return $structuresEns;
+    }
+    
+    /**
+     * @return TypeAgrementStatutService
+     */
+    protected function getServiceTypeAgrementStatut()
+    {
+        return $this->getServiceLocator()->get('applicationTypeAgrementStatut');
+    }
+    
+    /**
+     * @return AgrementService
+     */
+    protected function getServiceAgrement()
+    {
+        return $this->getServiceLocator()->get('applicationAgrement');
+    }
+}
diff --git a/module/Application/src/Application/Rule/Intervenant/AgrementFourniRule.php b/module/Application/src/Application/Rule/Intervenant/AgrementFourniRule.php
index 963d9a28a6..75cb827d15 100644
--- a/module/Application/src/Application/Rule/Intervenant/AgrementFourniRule.php
+++ b/module/Application/src/Application/Rule/Intervenant/AgrementFourniRule.php
@@ -2,38 +2,21 @@
 
 namespace Application\Rule\Intervenant;
 
-use Application\Entity\Db\Agrement;
-use Application\Entity\Db\Structure;
 use Application\Entity\Db\TypeAgrement;
-use Application\Rule\AbstractRule;
-use Application\Service\Agrement as AgrementService;
 use Application\Service\ContextProviderAwareInterface;
-use Application\Service\ContextProviderAwareTrait;
-use Application\Service\Service as ServiceService;
-use Application\Service\Structure as StructureService;
-use Application\Service\TypeAgrementStatut;
-use Application\Service\TypeAgrementStatut as TypeAgrementStatutService;
-use Application\Traits\IntervenantAwareTrait;
-use Application\Traits\StructureAwareTrait;
-use Application\Traits\TypeAgrementAwareTrait;
 use Common\Exception\LogicException;
-use Doctrine\ORM\EntityManager;
 use Zend\ServiceManager\ServiceLocatorAwareInterface;
-use Zend\ServiceManager\ServiceLocatorAwareTrait;
+use Application\Traits\StructureAwareTrait;
 
 /**
  * Description of AgrementFourniRule
  *
  * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
  */
-class AgrementFourniRule extends AbstractRule implements ServiceLocatorAwareInterface, ContextProviderAwareInterface
+class AgrementFourniRule extends AgrementAbstractRule implements ServiceLocatorAwareInterface, ContextProviderAwareInterface
 {
-    use ServiceLocatorAwareTrait;
-    use ContextProviderAwareTrait;
-    use IntervenantAwareTrait;
     use StructureAwareTrait;
-    use TypeAgrementAwareTrait;
-
+    
     /**
      * 
      * @return boolean
@@ -134,121 +117,4 @@ class AgrementFourniRule extends AbstractRule implements ServiceLocatorAwareInte
         $this->memePartiellement = $memePartiellement;
         return $this;
     }
-    
-    /**
-     * 
-     * @return array id => TypeAgrementStatut
-     */
-    private function getTypesAgrementStatut()
-    {
-        $qb = $this->getServiceTypeAgrementStatut()->finderByStatutIntervenant($this->getIntervenant()->getStatut());
-        
-        return $this->getServiceTypeAgrementStatut()->getList($qb);
-    }
-    
-    /**
-     * 
-     * @return array id => TypeAgrement
-     */
-    public function getTypesAgrementAttendus()
-    {
-        $typesAgrementAttendus = array();
-        foreach ($this->getTypesAgrementStatut() as $tas) { /* @var $tas TypeAgrementStatut */
-            $type = $tas->getType();
-            $typesAgrementAttendus[$type->getId()] = $type;
-        }
-        
-        return $typesAgrementAttendus;
-    }
-    
-    /**
-     * 
-     * @return array id => TypeAgrement
-     */
-    public function getTypesAgrementFournis()
-    {
-        $typesAgrementFournis = array();
-        foreach ($this->getAgrementsFournis() as $a) { /* @var $a Agrement */
-            $type = $a->getType();
-            $typesAgrementFournis[$type->getId()] = $type;
-        }
-        
-        return $typesAgrementFournis;
-    }
-    
-    /**
-     * Recherche les agréments déjà fournis.
-     * 
-     * @param Structure|null $structure Structure concernée éventuelle
-     * @return array id => Agrement
-     */
-    public function getAgrementsFournis(Structure $structure = null)
-    {
-        $qb = $this->getServiceAgrement()->finderByType($this->getTypeAgrement());
-        $qb = $this->getServiceAgrement()->finderByIntervenant($this->getIntervenant(), $qb);
-        $qb = $this->getServiceAgrement()->finderByAnnee($this->getContextProvider()->getGlobalContext()->getAnnee(), $qb);
-        $agrementsFournis = $this->getServiceAgrement()->getList($qb);
-        
-        // filtrage par structure éventuel
-        if ($structure) {
-            $agrements = [];
-            foreach ($agrementsFournis as $agrement) { /* @var $agrement Agrement */
-                if ($structure === $agrement->getStructure()) {
-                    $agrements[$agrement->getId()] = $agrement;
-                }
-            }
-            return $agrements;
-        }
-        
-        return $agrementsFournis;
-    }
-    
-    /**
-     * 
-     * @return array id => Structure
-     */
-    public function getStructuresEnseignement()
-    {
-        // recherche des structures d'enseignements de l'intervenant
-        $em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default'); /* @var $em EntityManager */
-        $qb = $em->getRepository('Application\Entity\Db\Structure')->createQueryBuilder("str")
-                ->join("str.service", "s")
-                ->where("s.intervenant = :intervenant")
-                ->setParameter('intervenant', $this->getIntervenant());
-        $structuresEns = $qb->getQuery()->getResult();
-        
-        return $structuresEns;
-    }
-    
-    /**
-     * @return TypeAgrementStatutService
-     */
-    private function getServiceTypeAgrementStatut()
-    {
-        return $this->getServiceLocator()->get('applicationTypeAgrementStatut');
-    }
-    
-    /**
-     * @return AgrementService
-     */
-    private function getServiceAgrement()
-    {
-        return $this->getServiceLocator()->get('applicationAgrement');
-    }
-    
-    /**
-     * @return StructureService
-     */
-    private function getServiceStructure()
-    {
-        return $this->getServiceLocator()->get('applicationStructure');
-    }
-    
-    /**
-     * @return ServiceService
-     */
-    private function getServiceService()
-    {
-        return $this->getServiceLocator()->get('applicationService');
-    }
 }
diff --git a/module/Application/src/Application/Rule/Intervenant/NecessiteAgrementRule.php b/module/Application/src/Application/Rule/Intervenant/NecessiteAgrementRule.php
index 1d185740e5..bbcc395848 100644
--- a/module/Application/src/Application/Rule/Intervenant/NecessiteAgrementRule.php
+++ b/module/Application/src/Application/Rule/Intervenant/NecessiteAgrementRule.php
@@ -2,26 +2,19 @@
 
 namespace Application\Rule\Intervenant;
 
-use Application\Entity\Db\Dossier;
-use Application\Entity\Db\TypeAgrementStatut;
-use Application\Rule\AbstractRule;
-use Application\Service\TypeAgrementStatut as TypeAgrementStatutService;
-use Application\Traits\IntervenantAwareTrait;
-use Application\Traits\TypeAgrementAwareTrait;
 use Zend\ServiceManager\ServiceLocatorAwareInterface;
-use Zend\ServiceManager\ServiceLocatorAwareTrait;
 
 /**
  * Description of NecessiteAgrementRule
  *
  * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
  */
-class NecessiteAgrementRule extends AbstractRule implements ServiceLocatorAwareInterface
+class NecessiteAgrementRule extends AgrementAbstractRule implements ServiceLocatorAwareInterface
 {
-    use ServiceLocatorAwareTrait;
-    use IntervenantAwareTrait;
-    use TypeAgrementAwareTrait;
-    
+    /**
+     * 
+     * @return boolean
+     */
     public function execute()
     {
         $statut = $this->getIntervenant()->getStatut();
@@ -63,43 +56,4 @@ class NecessiteAgrementRule extends AbstractRule implements ServiceLocatorAwareI
     {
         return true;
     }
-    
-    /**
-     * 
-     * @return TypeAgrementStatut[] id => TypeAgrementStatut
-     */
-    private function getTypesAgrementStatut()
-    {
-        $qb = $this->getServiceTypeAgrementStatut()->finderByStatutIntervenant($this->getIntervenant()->getStatut());
-        if ($this->getIntervenant() instanceof \Application\Entity\Db\IntervenantExterieur 
-                && ($dossier = $this->getIntervenant()->getDossier())) { /* @var $dossier Dossier */
-            $this->getServiceTypeAgrementStatut()->finderByPremierRecrutement($dossier->getPremierRecrutement(), $qb);
-        }
-        $typesAgrementStatut = $this->getServiceTypeAgrementStatut()->getList($qb);
-        
-        return $typesAgrementStatut;
-    }
-    
-    /**
-     * 
-     * @return array id => TypeAgrement
-     */
-    public function getTypesAgrementAttendus()
-    {
-        $typesAgrementAttendus = array();
-        foreach ($this->getTypesAgrementStatut() as $typeAgrementStatut) { /* @var $typeAgrementStatut TypeAgrementStatut */
-            $type = $typeAgrementStatut->getType();
-            $typesAgrementAttendus[$type->getId()] = $type;
-        }
-        
-        return $typesAgrementAttendus;
-    }
-    
-    /**
-     * @return TypeAgrementStatutService
-     */
-    private function getServiceTypeAgrementStatut()
-    {
-        return $this->getServiceLocator()->get('applicationTypeAgrementStatut');
-    }
 }
diff --git a/module/Application/src/Application/Service/AgrementNavigationPagesProvider.php b/module/Application/src/Application/Service/AgrementNavigationPagesProvider.php
index 444c3589f1..b8432db27c 100644
--- a/module/Application/src/Application/Service/AgrementNavigationPagesProvider.php
+++ b/module/Application/src/Application/Service/AgrementNavigationPagesProvider.php
@@ -30,6 +30,11 @@ class AgrementNavigationPagesProvider extends AbstractService
             ];
             $child = array_merge($child, $params);
             
+            // le code du type d'agrément est concaténé au privilège existant éventuel
+            if (isset($child['privilege'])) {
+                $child['privilege'] .= '/' . $typeAgrement->getCode();
+            }
+            
             $pages[$typeAgrement->getCode()] = $child;
         }
         
diff --git a/module/Application/src/Application/Service/Assertion/AbstractAssertion.php b/module/Application/src/Application/Service/Assertion/AbstractAssertion.php
new file mode 100644
index 0000000000..2dfd1cc3c0
--- /dev/null
+++ b/module/Application/src/Application/Service/Assertion/AbstractAssertion.php
@@ -0,0 +1,114 @@
+<?php
+
+namespace Application\Service\Assertion;
+
+use Application\Service\ContextProviderAwareInterface;
+use Application\Service\ContextProviderAwareTrait;
+use Common\Exception\LogicException;
+use Zend\Mvc\MvcEvent;
+use Zend\Permissions\Acl\Acl;
+use Zend\Permissions\Acl\Assertion\AssertionInterface;
+use Zend\Permissions\Acl\Resource\ResourceInterface;
+use Zend\Permissions\Acl\Role\RoleInterface;
+use Zend\ServiceManager\ServiceLocatorAwareInterface;
+use Zend\ServiceManager\ServiceLocatorAwareTrait;
+
+/**
+ * Description of AbstractAssertion
+ *
+ * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
+ */
+abstract class AbstractAssertion implements AssertionInterface, ServiceLocatorAwareInterface, ContextProviderAwareInterface
+{
+    use ServiceLocatorAwareTrait;
+    use ContextProviderAwareTrait;
+ 
+    const PRIVILEGE_CREATE = 'create';
+    const PRIVILEGE_READ   = 'read';
+    const PRIVILEGE_UPDATE = 'update';
+    const PRIVILEGE_DELETE = 'delete';
+    
+    /**
+     * !!!! Pour éviter l'erreur "Serialization of 'Closure' is not allowed"... !!!!
+     * 
+     * @return array
+     */
+    public function __sleep()
+    {
+        return [];
+    }
+    
+    /**
+     * 
+     * @return MvcEvent
+     */
+    protected function getMvcEvent()
+    {
+        return $this->getServiceLocator()->get('Application')->getMvcEvent();
+    }
+
+
+    /**
+     * @return boolean
+     */
+    protected function assertCRUD(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null)
+    {
+        if (!$privilege) {
+            return true;
+        }
+        
+        switch ($privilege) {
+            case self::PRIVILEGE_CREATE:
+                return $this->_assertCreate($resource);
+            case self::PRIVILEGE_READ:
+                return $this->_assertRead($resource);
+            case self::PRIVILEGE_UPDATE:
+                return $this->_assertUpdate($resource);
+            case self::PRIVILEGE_DELETE:
+                return $this->_assertDelete($resource);
+            default:
+                throw new LogicException("Privilège spécifié inconnu: $privilege.");
+        }
+    }
+    
+    private function _assertCreate($resource)
+    {
+        if (is_object($resource) && $resource->getId()) {
+            return false;
+        }
+        
+        return true;
+    }
+    
+    private function _assertRead($resource)
+    {
+        if (is_object($resource) && !$resource->getId()) {
+            return false;
+        }
+        
+        return true;
+    }
+    
+    private function _assertUpdate($resource)
+    {
+        if (is_object($resource) && !$resource->getId()) {
+            return false;
+        }
+        
+        return true;
+    }
+    
+    private function _assertDelete($resource)
+    {
+        if (is_object($resource) && !$resource->getId()) {
+            return false;
+        }
+        
+        return true;
+    }
+    
+    protected function getSelectedIdentityRole()
+    {
+        return $this->getContextProvider()->getSelectedIdentityRole();
+    }
+}
\ No newline at end of file
diff --git a/module/Application/src/Application/Service/Assertion/AgrementAssertion.php b/module/Application/src/Application/Service/Assertion/AgrementAssertion.php
index 5a6175b5f6..15e69e8d6e 100644
--- a/module/Application/src/Application/Service/Assertion/AgrementAssertion.php
+++ b/module/Application/src/Application/Service/Assertion/AgrementAssertion.php
@@ -3,23 +3,27 @@
 namespace Application\Service\Assertion;
 
 use Application\Acl\ComposanteDbRole;
+use Application\Controller\AgrementController;
 use Application\Entity\Db\Agrement;
+use Application\Entity\Db\TypeAgrement;
+use Application\Provider\Role\RoleProvider;
 use Application\Rule\Intervenant\AgrementFourniRule;
 use Application\Rule\Intervenant\NecessiteAgrementRule;
 use Application\Service\Initializer\AgrementServiceAwareInterface;
 use Application\Service\Initializer\AgrementServiceAwareTrait;
+use Application\Service\Workflow\WorkflowIntervenant;
+use Application\Service\Workflow\WorkflowIntervenantAwareInterface;
+use Application\Service\Workflow\WorkflowIntervenantAwareTrait;
 use Zend\Permissions\Acl\Acl;
 use Zend\Permissions\Acl\Resource\ResourceInterface;
 use Zend\Permissions\Acl\Role\RoleInterface;
-use Application\Service\Workflow\WorkflowIntervenantAwareInterface;
-use Application\Service\Workflow\WorkflowIntervenantAwareTrait;
 
 /**
  * Description of Agrement
  *
  * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
  */
-class AgrementAssertion extends EntityAssertion implements AgrementServiceAwareInterface, WorkflowIntervenantAwareInterface
+class AgrementAssertion extends AbstractAssertion implements AgrementServiceAwareInterface, WorkflowIntervenantAwareInterface
 {
     use AgrementServiceAwareTrait;
     use WorkflowIntervenantAwareTrait;
@@ -27,7 +31,7 @@ class AgrementAssertion extends EntityAssertion implements AgrementServiceAwareI
     /**
      * @var Agrement
      */
-    protected $resource;
+    protected $agrement;
     
     /**
      * Returns true if and only if the assertion conditions are met
@@ -44,26 +48,98 @@ class AgrementAssertion extends EntityAssertion implements AgrementServiceAwareI
      */
     public function assert(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null)
     {
-        if (!$resource instanceof Agrement) {
-            return false;
+        /**
+         * Cas N°1 : la ressource spécifiée est une entité ; un privilège est spécifié.
+         */
+        if ($resource instanceof Agrement) {
+            return $this->assertEntity($acl, $role, $resource, $privilege);
+        }
+        
+        /**
+         * Cas N°2 : la ressource spécifiée est une chaîne de caractères du type 'controller/Application\Controller\Agrement:action' ;
+         * un privilège est spécifié (config des pages de navigation) ou pas (config des controller guards BjyAuthorize).
+         */
+        
+        $privilege = $this->normalizedPrivilege($privilege, $resource);
+        
+//        var_dump(__CLASS__ . ' >>> ' . $resource . ' : ' . $privilege);
+        
+        $privilegeAjouterLotConseilRestreint  = sprintf("%s/%s", AgrementController::ACTION_AJOUTER_LOT, TypeAgrement::CODE_CONSEIL_RESTREINT);
+        $privilegeAjouterLotConseilAcademique = sprintf("%s/%s", AgrementController::ACTION_AJOUTER_LOT, TypeAgrement::CODE_CONSEIL_ACADEMIQUE);
+
+        // l'ajout par lot d'agréments de type "Conseil Académique" n'est autorisé qu'aux admin
+        if ($privilege === $privilegeAjouterLotConseilAcademique) {
+            if ($this->getSelectedIdentityRole()->getRoleId() !== RoleProvider::ROLE_ID_ADMIN) {
+                return false;
+            }
+        }
+        // l'ajout par lot d'agréments de type "Conseil Restreint" n'est pas autorisé aux admin pour
+        // l'instant car cela nécessiterait la sélection de la composante concernée
+        elseif ($privilege === $privilegeAjouterLotConseilRestreint) {
+            if ($this->getSelectedIdentityRole()->getRoleId() === RoleProvider::ROLE_ID_ADMIN) {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+    
+    /**
+     * 
+     * @param string $privilege
+     * @param string $resource
+     * @return string
+     */
+    protected function normalizedPrivilege($privilege, $resource)
+    {
+        if (is_object($privilege)) {
+            return $privilege;
+        }
+        if (!$privilege) {
+            $privilege = ($tmp = strrchr($resource, $c = ':')) ? ltrim($tmp, $c) : null;
         }
-        if (!parent::assert($acl, $role, $resource, $privilege)) {
+        if ($privilege && false === strpos($privilege, '/') && $this->getTypeAgrement()) {
+            $privilege .= '/' . $this->getTypeAgrement()->getCode();
+        }
+        
+        return $privilege;
+    }
+    
+    /**
+     * 
+     * @param Acl $acl
+     * @param RoleInterface $role
+     * @param ResourceInterface $resource
+     * @param string $privilege
+     * @return boolean
+     */
+    protected function assertEntity(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null)
+    {
+        if (!parent::assertCRUD($acl, $role, $resource, $privilege)) {
             return false;
         }
         
+        $this->agrement = $resource;
+        
         /*********************************************************
          *                      Rôle Composante
          *********************************************************/
-        if ($this->identityRole instanceof ComposanteDbRole) {
+        if ($this->getSelectedIdentityRole() instanceof ComposanteDbRole) {
+            
+            // saisie de l'agrément Conseil Academique interdit aux gestionnaires de composante
+            if ($this->agrement->getType()->isConseilAcademique()) {
+                return false;
+            }
+            
             // structure de responsabilité de l'utilisateur et structure de l'agrément doivent correspondre
-            if ($this->identityRole->getStructure() !== $this->resource->getStructure()) {
-//            if ($this->resource->getStructure() && $this->identityRole->getStructure()->getId() !== $this->resource->getStructure()->getId()) {
+            if ($this->getSelectedIdentityRole()->getStructure() !== $this->agrement->getStructure()) {
+//            if ($this->agrement->getStructure() && $this->getSelectedIdentityRole()->getStructure()->getId() !== $this->agrement->getStructure()->getId()) {
                 return false;
             }
         }
         
-        $agrementStepKey = 'KEY_' . $this->resource->getType()->getCode();
-
+        $agrementStepKey = 'KEY_' . $this->agrement->getType()->getCode();
+        
         // l'étape Agrement du workflow doit être atteignable
         if (!$this->getWorkflow()->isStepReachable($agrementStepKey)) {
             return false;
@@ -72,7 +148,7 @@ class AgrementAssertion extends EntityAssertion implements AgrementServiceAwareI
         /**
          * Modification, suppression
          */
-        if (in_array($this->privilege, ['update', 'delete'])) {
+        if (in_array($privilege, ['update', 'delete'])) {
             // l'étape suivante du workflow ne doit pas avoir été franchie
             $nextStep = $this->getWorkflow()->getNextStep($agrementStepKey);
             if ($nextStep && $this->getWorkflow()->isStepCrossable($nextStep)) {
@@ -81,25 +157,25 @@ class AgrementAssertion extends EntityAssertion implements AgrementServiceAwareI
         }
 
         return true;
-
-        /*********************************************************
-         *                      Rôle X
-         *********************************************************/
-//        if ($this->identityRole->getRoleId() === \Application\Provider\Role\RoleProvider::ROLE_ID_ADMIN) {
-//            
-//        }
-        
-        return false;
     }
     
     /**
-     * @return \Application\Service\Workflow\WorkflowIntervenant
+     * 
+     * @return TypeAgrement
+     */
+    protected function getTypeAgrement()
+    {
+        return $this->getMvcEvent()->getParam('typeAgrement');
+    }
+    
+    /**
+     * @return WorkflowIntervenant
      */
     private function getWorkflow()
     {
         $wf = $this->getWorkflowIntervenant()
-                ->setIntervenant($this->resource->getIntervenant())
-                ->setRole($this->identityRole);
+                ->setIntervenant($this->agrement->getIntervenant())
+                ->setRole($this->getSelectedIdentityRole());
         
         return $wf;
     }
@@ -111,8 +187,8 @@ class AgrementAssertion extends EntityAssertion implements AgrementServiceAwareI
     {
         $rule = $this->getAgrementService()->getRuleNecessiteAgrement();
         $rule
-                ->setIntervenant($this->resource->getIntervenant())
-                ->setTypeAgrement($this->resource->getType());
+                ->setIntervenant($this->agrement->getIntervenant())
+                ->setTypeAgrement($this->agrement->getType());
         
         return $rule;
     }
@@ -124,8 +200,8 @@ class AgrementAssertion extends EntityAssertion implements AgrementServiceAwareI
     {
         $rule = $this->getAgrementService()->getRuleAgrementFourni();
         $rule
-                ->setIntervenant($this->resource->getIntervenant())
-                ->setTypeAgrement($this->resource->getType());
+                ->setIntervenant($this->agrement->getIntervenant())
+                ->setTypeAgrement($this->agrement->getType());
         
         return $rule;
     }
diff --git a/module/Application/src/Application/Service/Assertion/ContratAssertion.php b/module/Application/src/Application/Service/Assertion/ContratAssertion.php
index 54d4ad1845..f61eac8c8f 100644
--- a/module/Application/src/Application/Service/Assertion/ContratAssertion.php
+++ b/module/Application/src/Application/Service/Assertion/ContratAssertion.php
@@ -2,8 +2,6 @@
 
 namespace Application\Service\Assertion;
 
-use Zend\ServiceManager\ServiceLocatorAwareInterface;
-use Zend\ServiceManager\ServiceLocatorAwareTrait;
 use Application\Acl\ComposanteDbRole;
 use Application\Entity\Db\Contrat;
 use Application\Service\Workflow\WorkflowIntervenant;
@@ -18,15 +16,14 @@ use Zend\Permissions\Acl\Role\RoleInterface;
  *
  * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
  */
-class ContratAssertion extends EntityAssertion implements ServiceLocatorAwareInterface, WorkflowIntervenantAwareInterface
+class ContratAssertion extends AbstractAssertion implements WorkflowIntervenantAwareInterface
 {
-    use ServiceLocatorAwareTrait;
     use WorkflowIntervenantAwareTrait;
     
     /**
      * @var Contrat
      */
-    protected $resource;
+    protected $contrat;
     
     /**
      * Returns true if and only if the assertion conditions are met
@@ -43,20 +40,36 @@ class ContratAssertion extends EntityAssertion implements ServiceLocatorAwareInt
      */
     public function assert(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null)
     {
-        if (!$resource instanceof Contrat) {
-            return false;
+        if ($resource instanceof Contrat) {
+            return $this->assertEntity($acl, $role, $resource, $privilege);
         }
-        if (!parent::assert($acl, $role, $resource, $privilege)) {
+        
+        return false;
+    }
+    
+    /**
+     * 
+     * @param Acl $acl
+     * @param RoleInterface $role
+     * @param ResourceInterface $resource
+     * @param string $privilege
+     * @return boolean
+     */
+    protected function assertEntity(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null)
+    {
+        if (!parent::assertCRUD($acl, $role, $resource, $privilege)) {
             return false;
         }
         
+        $this->contrat = $resource;
+        
         /*********************************************************
          *                      Rôle Composante
          *********************************************************/
-        if ($this->identityRole instanceof ComposanteDbRole) 
+        if ($this->getSelectedIdentityRole() instanceof ComposanteDbRole) 
         {
             // structure de responsabilité de l'utilisateur et structure du contrat doivent correspondre
-            if ($this->identityRole->getStructure() !== $this->resource->getStructure()) {
+            if ($this->getSelectedIdentityRole()->getStructure() !== $this->contrat->getStructure()) {
                 return false;
             }
             
@@ -75,15 +88,8 @@ class ContratAssertion extends EntityAssertion implements ServiceLocatorAwareInt
             
             return true;
         }
-
-//        /*********************************************************
-//         *                      Rôle X
-//         *********************************************************/
-//        if ($this->identityRole instanceof XRole) {
-//            
-//        }
         
-        return false;
+        return true;
     }
     
     /**
@@ -92,8 +98,8 @@ class ContratAssertion extends EntityAssertion implements ServiceLocatorAwareInt
     private function getWorkflow()
     {
         $wf = $this->getWorkflowIntervenant()
-                ->setIntervenant($this->resource->getIntervenant())
-                ->setRole($this->identityRole);
+                ->setIntervenant($this->contrat->getIntervenant())
+                ->setRole($this->getSelectedIdentityRole());
         
         return $wf;
     }
diff --git a/module/Application/src/Application/Service/Assertion/EntityAssertion.php b/module/Application/src/Application/Service/Assertion/EntityAssertion.php
deleted file mode 100644
index 76dae9d74c..0000000000
--- a/module/Application/src/Application/Service/Assertion/EntityAssertion.php
+++ /dev/null
@@ -1,157 +0,0 @@
-<?php
-
-namespace Application\Service\Assertion;
-
-use Application\Service\ContextProviderAwareInterface;
-use Application\Service\ContextProviderAwareTrait;
-use Zend\Permissions\Acl\Acl;
-use Zend\Permissions\Acl\Assertion\AssertionInterface;
-use Zend\Permissions\Acl\Resource\ResourceInterface;
-use Zend\Permissions\Acl\Role\RoleInterface;
-
-/**
- * Description of EntityAssertion
- *
- * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
- */
-abstract class EntityAssertion implements AssertionInterface, ContextProviderAwareInterface
-{
-    use ContextProviderAwareTrait;
- 
-    const PRIVILEGE_CREATE = 'create';
-    const PRIVILEGE_READ   = 'read';
-    const PRIVILEGE_UPDATE = 'update';
-    const PRIVILEGE_DELETE = 'delete';
-    
-    protected $acl;
-    protected $role;
-    protected $resource;
-    protected $privilege;
-    protected $identityRole;
-    
-    /**
-     * !!!! Pour éviter l'erreur "Serialization of 'Closure' is not allowed"... !!!!
-     * 
-     * @return array
-     */
-    public function __sleep()
-    {
-        return [];
-    }
-    
-    /**
-     * Returns true if and only if the assertion conditions are met
-     *
-     * This method is passed the ACL, Role, Resource, and privilege to which the authorization query applies. If the
-     * $role, $resource, or $privilege parameters are null, it means that the query applies to all Roles, Resources, or
-     * privileges, respectively.
-     *
-     * @param  Acl                        $acl
-     * @param  RoleInterface         $role
-     * @param  ResourceInterface $resource
-     * @param  string                         $privilege
-     * @return bool
-     */
-    public function assert(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null)
-    {
-        $this->acl       = $acl;
-        $this->role      = $role;
-        $this->resource  = $resource;
-        $this->privilege = $privilege;
-        
-        $this->identityRole = $this->getContextProvider()->getSelectedIdentityRole();
-
-        if (!$this->_assertCRUD()) {
-            return false;
-        }
-        
-        return true;
-    }
-    
-    /**
-     * @return boolean
-     */
-    private function _assertCRUD()
-    {
-        switch ($this->privilege) {
-            case self::PRIVILEGE_CREATE:
-                return $this->_assertCreate();
-            case self::PRIVILEGE_READ:
-                return $this->_assertRead();
-            case self::PRIVILEGE_UPDATE:
-                return $this->_assertUpdate();
-            case self::PRIVILEGE_DELETE:
-                return $this->_assertDelete();
-            default:
-                throw new \Common\Exception\LogicException("Privilège spécifié inconnu: $this->privilege.");
-        }
-    }
-    
-    private function _assertCreate()
-    {
-        if (is_object($this->resource) && $this->resource->getId()) {
-            return false;
-        }
-        
-        return true;
-    }
-    
-    private function _assertRead()
-    {
-        if (is_object($this->resource) && !$this->resource->getId()) {
-            return false;
-        }
-        
-        return true;
-    }
-    
-    private function _assertUpdate()
-    {
-        if (is_object($this->resource) && !$this->resource->getId()) {
-            return false;
-        }
-        
-        return true;
-    }
-    
-    private function _assertDelete()
-    {
-        if (is_object($this->resource) && !$this->resource->getId()) {
-            return false;
-        }
-        
-        return true;
-    }
-    
-    /**
-     * @return boolean
-     */
-    protected function isCreate()
-    {
-        return self::PRIVILEGE_CREATE === $this->privilege;
-    }
-    
-    /**
-     * @return boolean
-     */
-    protected function isRead()
-    {
-        return self::PRIVILEGE_READ === $this->privilege;
-    }
-    
-    /**
-     * @return boolean
-     */
-    protected function isUpdate()
-    {
-        return self::PRIVILEGE_UPDATE === $this->privilege;
-    }
-    
-    /**
-     * @return boolean
-     */
-    protected function isDelete()
-    {
-        return self::PRIVILEGE_DELETE === $this->privilege;
-    }
-}
\ No newline at end of file
-- 
GitLab