From d17bc60e71bc12c3f067a7a0140206a32c36bb71 Mon Sep 17 00:00:00 2001
From: Jean-Philippe Metivier <jean-philippe.metivier@unicaen.fr>
Date: Mon, 4 Jul 2022 11:07:07 +0200
Subject: [PATCH] V0 de unicaenValidation

---
 .gitlab-ci.yml                                |  14 ++
 Module.php                                    |  48 +++++
 composer.json                                 |  21 ++
 config/merged/validation-instance.config.php  | 169 +++++++++++++++++
 config/merged/validation-type.config.php      | 127 +++++++++++++
 config/module.config.php                      |  92 +++++++++
 documentation/001_table.sql                   |  38 ++++
 documentation/101_privilege.sql               |  29 +++
 .../ValidationInstanceController.php          | 123 ++++++++++++
 .../ValidationInstanceControllerFactory.php   |  40 ++++
 .../Controller/ValidationTypeController.php   | 105 ++++++++++
 .../ValidationTypeControllerFactory.php       |  36 ++++
 ...ation.Entity.Db.ValidationInstance.dcm.xml |  29 +++
 ...alidation.Entity.Db.ValidationType.dcm.xml |  13 ++
 .../Entity/Db/ValidationInstance.php          |  66 +++++++
 .../Entity/Db/ValidationType.php              |  73 +++++++
 .../Entity/HasValidationsInterface.php        |  15 ++
 .../Entity/HasValidationsTrait.php            |  67 +++++++
 .../ValidationInstanceForm.php                |  68 +++++++
 .../ValidationInstanceFormAwareTrait.php      |  25 +++
 .../ValidationInstanceFormFactory.php         |  33 ++++
 .../ValidationInstanceHydrator.php            |  37 ++++
 .../ValidationInstanceHydratorFactory.php     |  27 +++
 .../ValidationType/ValidationTypeForm.php     |  98 ++++++++++
 .../ValidationTypeFormAwareTrait.php          |  24 +++
 .../ValidationTypeFormFactory.php             |  31 +++
 .../ValidationType/ValidationTypeHydrator.php |  37 ++++
 .../ValidationTypeHydratorFactory.php         |  18 ++
 .../ValidationinstancePrivileges.php          |  13 ++
 .../Privilege/ValidationtypePrivileges.php    |  12 ++
 .../ValidationInstanceService.php             | 179 ++++++++++++++++++
 .../ValidationInstanceServiceAwareTrait.php   |  24 +++
 .../ValidationInstanceServiceFactory.php      |  33 ++++
 .../ValidationType/ValidationTypeService.php  | 158 ++++++++++++++++
 .../ValidationTypeServiceAwareTrait.php       |  24 +++
 .../ValidationTypeServiceFactory.php          |  33 ++++
 .../Helper/ValidationAfficherViewHelper.php   |  26 +++
 .../View/Helper/ValidationBadgeViewHelper.php |  26 +++
 .../Helper/ValidationValiderViewHelper.php    |  29 +++
 .../ValidationValiderViewHelperFactory.php    |  27 +++
 .../Helper/partial/validation-afficher.phtml  |  22 +++
 .../Helper/partial/validation-badge.phtml     |  30 +++
 .../Helper/partial/validation-valider.phtml   |  39 ++++
 .../default/confirmation.phtml                |  37 ++++
 .../default/default-form.phtml                |  43 +++++
 .../validation-instance/index.phtml           | 121 ++++++++++++
 .../validation-modal.phtml                    |  43 +++++
 .../validation-type/index.phtml               | 113 +++++++++++
 48 files changed, 2535 insertions(+)
 create mode 100644 .gitlab-ci.yml
 create mode 100644 Module.php
 create mode 100755 composer.json
 create mode 100644 config/merged/validation-instance.config.php
 create mode 100644 config/merged/validation-type.config.php
 create mode 100644 config/module.config.php
 create mode 100644 documentation/001_table.sql
 create mode 100644 documentation/101_privilege.sql
 create mode 100644 src/UnicaenValidation/Controller/ValidationInstanceController.php
 create mode 100644 src/UnicaenValidation/Controller/ValidationInstanceControllerFactory.php
 create mode 100644 src/UnicaenValidation/Controller/ValidationTypeController.php
 create mode 100644 src/UnicaenValidation/Controller/ValidationTypeControllerFactory.php
 create mode 100644 src/UnicaenValidation/Entity/Db/Mapping/UnicaenValidation.Entity.Db.ValidationInstance.dcm.xml
 create mode 100644 src/UnicaenValidation/Entity/Db/Mapping/UnicaenValidation.Entity.Db.ValidationType.dcm.xml
 create mode 100644 src/UnicaenValidation/Entity/Db/ValidationInstance.php
 create mode 100644 src/UnicaenValidation/Entity/Db/ValidationType.php
 create mode 100644 src/UnicaenValidation/Entity/HasValidationsInterface.php
 create mode 100644 src/UnicaenValidation/Entity/HasValidationsTrait.php
 create mode 100644 src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceForm.php
 create mode 100644 src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceFormAwareTrait.php
 create mode 100644 src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceFormFactory.php
 create mode 100644 src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceHydrator.php
 create mode 100644 src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceHydratorFactory.php
 create mode 100644 src/UnicaenValidation/Form/ValidationType/ValidationTypeForm.php
 create mode 100644 src/UnicaenValidation/Form/ValidationType/ValidationTypeFormAwareTrait.php
 create mode 100644 src/UnicaenValidation/Form/ValidationType/ValidationTypeFormFactory.php
 create mode 100644 src/UnicaenValidation/Form/ValidationType/ValidationTypeHydrator.php
 create mode 100644 src/UnicaenValidation/Form/ValidationType/ValidationTypeHydratorFactory.php
 create mode 100644 src/UnicaenValidation/Provider/Privilege/ValidationinstancePrivileges.php
 create mode 100644 src/UnicaenValidation/Provider/Privilege/ValidationtypePrivileges.php
 create mode 100644 src/UnicaenValidation/Service/ValidationInstance/ValidationInstanceService.php
 create mode 100644 src/UnicaenValidation/Service/ValidationInstance/ValidationInstanceServiceAwareTrait.php
 create mode 100644 src/UnicaenValidation/Service/ValidationInstance/ValidationInstanceServiceFactory.php
 create mode 100644 src/UnicaenValidation/Service/ValidationType/ValidationTypeService.php
 create mode 100644 src/UnicaenValidation/Service/ValidationType/ValidationTypeServiceAwareTrait.php
 create mode 100644 src/UnicaenValidation/Service/ValidationType/ValidationTypeServiceFactory.php
 create mode 100644 src/UnicaenValidation/View/Helper/ValidationAfficherViewHelper.php
 create mode 100644 src/UnicaenValidation/View/Helper/ValidationBadgeViewHelper.php
 create mode 100644 src/UnicaenValidation/View/Helper/ValidationValiderViewHelper.php
 create mode 100644 src/UnicaenValidation/View/Helper/ValidationValiderViewHelperFactory.php
 create mode 100644 src/UnicaenValidation/View/Helper/partial/validation-afficher.phtml
 create mode 100644 src/UnicaenValidation/View/Helper/partial/validation-badge.phtml
 create mode 100644 src/UnicaenValidation/View/Helper/partial/validation-valider.phtml
 create mode 100644 view/unicaen-validation/default/confirmation.phtml
 create mode 100644 view/unicaen-validation/default/default-form.phtml
 create mode 100644 view/unicaen-validation/validation-instance/index.phtml
 create mode 100644 view/unicaen-validation/validation-instance/validation-modal.phtml
 create mode 100644 view/unicaen-validation/validation-type/index.phtml

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..0e61a8f
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,14 @@
+image: registre.unicaen.fr:5000/unicaen-dev-php7.3-apache
+
+stages:
+- publish
+
+cache:
+  key: ${CI_COMMIT_REF_SLUG}
+  paths:
+  - vendor/
+
+update-satis:
+  stage: publish
+  script:
+    - curl https://gest.unicaen.fr/packagist/update
diff --git a/Module.php b/Module.php
new file mode 100644
index 0000000..c2ced8e
--- /dev/null
+++ b/Module.php
@@ -0,0 +1,48 @@
+<?php
+
+
+namespace UnicaenValidation;
+
+//use UnicaenUtilisateur\Event\UserRoleSelectedEventListener;
+use Laminas\Config\Factory as ConfigFactory;
+use Laminas\Mvc\ModuleRouteListener;
+use Laminas\Mvc\MvcEvent;
+use Laminas\Stdlib\ArrayUtils;
+use Laminas\Stdlib\Glob;
+
+class Module
+{
+    public function onBootstrap(MvcEvent $e)
+    {
+        $e->getApplication()->getServiceManager()->get('translator');
+        $eventManager        = $e->getApplication()->getEventManager();
+        $moduleRouteListener = new ModuleRouteListener();
+        $moduleRouteListener->attach($eventManager);
+
+    }
+
+    public function getConfig()
+    {
+        $configInit = [
+            __DIR__ . '/config/module.config.php'
+        ];
+        $configFiles = ArrayUtils::merge(
+            $configInit,
+            Glob::glob(__DIR__ . '/config/merged/{,*.}{config}.php', Glob::GLOB_BRACE)
+        );
+
+        return ConfigFactory::fromFiles($configFiles);
+    }
+
+
+    public function getAutoloaderConfig()
+    {
+        return array(
+            'Laminas\Loader\StandardAutoloader' => array(
+                'namespaces' => array(
+                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
+                ),
+            ),
+        );
+    }
+}
diff --git a/composer.json b/composer.json
new file mode 100755
index 0000000..da93126
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,21 @@
+{
+    "name": "unicaen/validation",
+    "description": "Module de gestion de validation (type et instance)",
+    "repositories": [
+        {
+            "type": "composer",
+            "url": "https://gest.unicaen.fr/packagist"
+        }
+    ],
+    "require": {
+        "unicaen/app": "^4.0",
+        "unicaen/privilege": "^4.0",
+        "laminas/laminas-dependency-plugin": "^2.1"
+    },
+    "autoload": {
+        "psr-0": [],
+        "classmap": [
+            "./Module.php"
+        ]
+    }
+}
diff --git a/config/merged/validation-instance.config.php b/config/merged/validation-instance.config.php
new file mode 100644
index 0000000..9779853
--- /dev/null
+++ b/config/merged/validation-instance.config.php
@@ -0,0 +1,169 @@
+<?php
+
+namespace UnicaenValidation;
+
+use UnicaenPrivilege\Guard\PrivilegeController;
+use UnicaenValidation\Controller\ValidationInstanceController;
+use UnicaenValidation\Controller\ValidationInstanceControllerFactory;
+use UnicaenValidation\Form\ValidationInstance\ValidationInstanceForm;
+use UnicaenValidation\Form\ValidationInstance\ValidationInstanceFormFactory;
+use UnicaenValidation\Form\ValidationInstance\ValidationInstanceHydrator;
+use UnicaenValidation\Form\ValidationInstance\ValidationInstanceHydratorFactory;
+use UnicaenValidation\Provider\Privilege\ValidationinstancePrivileges;
+use UnicaenValidation\Service\ValidationInstance\ValidationInstanceService;
+use UnicaenValidation\Service\ValidationInstance\ValidationInstanceServiceFactory;
+use UnicaenValidation\View\Helper\ValidationAfficherViewHelper;
+use UnicaenValidation\View\Helper\ValidationBadgeViewHelper;
+use UnicaenValidation\View\Helper\ValidationValiderViewHelperFactory;
+use Laminas\Router\Http\Literal;
+use Laminas\Router\Http\Segment;
+
+return [
+    'bjyauthorize' => [
+        'guards' => [
+            PrivilegeController::class => [
+                [
+                    'controller' => ValidationInstanceController::class,
+                    'action' => [
+                        'index',
+                    ],
+                    'privileges' => [
+                        ValidationinstancePrivileges::VALIDATIONINSTANCE_AFFICHER,
+                    ],
+                ],
+                [
+                    'controller' => ValidationInstanceController::class,
+                    'action' => [
+                        'ajouter',
+                        'modifier',
+                    ],
+                    'privileges' => [
+                        ValidationinstancePrivileges::VALIDATIONINSTANCE_MODIFIER,
+                    ],
+                ],
+                [
+                    'controller' => ValidationInstanceController::class,
+                    'action' => [
+                        'historiser',
+                        'restaurer',
+                    ],
+                    'privileges' => [
+                        ValidationinstancePrivileges::VALIDATIONINSTANCE_HISTORISER,
+                    ],
+                ],
+                [
+                    'controller' => ValidationInstanceController::class,
+                    'action' => [
+                        'detruire',
+                    ],
+                    'privileges' => [
+                        ValidationinstancePrivileges::VALIDATIONINSTANCE_DETRUIRE,
+                    ],
+                ],
+            ],
+        ],
+    ],
+
+    'router'          => [
+        'routes' => [
+            'validation' => [
+                'child_routes' => [
+                    'instance' => [
+                        'type' => Literal::class,
+                        'options' => [
+                            'route'    => '/instance',
+                            'defaults' => [
+                                'controller' => ValidationInstanceController::class,
+                                'action'     => 'index',
+                            ],
+                        ],
+                        'may_terminate' => true,
+                        'child_routes' => [
+                            'ajouter' => [
+                                'type' => Literal::class,
+                                'options' => [
+                                    'route'    => '/ajouter',
+                                    'defaults' => [
+                                        'controller' => ValidationInstanceController::class,
+                                        'action'     => 'ajouter',
+                                    ],
+                                ],
+                            ],
+                            'modifier' => [
+                                'type' => Segment::class,
+                                'options' => [
+                                    'route'    => '/modifier/:validation',
+                                    'defaults' => [
+                                        'controller' => ValidationInstanceController::class,
+                                        'action'     => 'modifier',
+                                    ],
+                                ],
+                            ],
+                            'historiser' => [
+                                'type' => Segment::class,
+                                'options' => [
+                                    'route'    => '/historiser/:validation',
+                                    'defaults' => [
+                                        'controller' => ValidationInstanceController::class,
+                                        'action'     => 'historiser',
+                                    ],
+                                ],
+                            ],
+                            'restaurer' => [
+                                'type' => Segment::class,
+                                'options' => [
+                                    'route'    => '/restaurer/:validation',
+                                    'defaults' => [
+                                        'controller' => ValidationInstanceController::class,
+                                        'action'     => 'restaurer',
+                                    ],
+                                ],
+                            ],
+                            'detruire' => [
+                                'type' => Segment::class,
+                                'options' => [
+                                    'route'    => '/detruire/:validation',
+                                    'defaults' => [
+                                        'controller' => ValidationInstanceController::class,
+                                        'action'     => 'detruire',
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ],
+    ],
+
+    'service_manager' => [
+        'factories' => [
+            ValidationInstanceService::class => ValidationInstanceServiceFactory::class,
+        ],
+    ],
+    'controllers'     => [
+        'factories' => [
+            ValidationInstanceController::class => ValidationInstanceControllerFactory::class,
+        ],
+    ],
+    'form_elements' => [
+        'factories' => [
+            ValidationInstanceForm::class => ValidationInstanceFormFactory::class,
+        ],
+    ],
+    'hydrators' => [
+        'factories' => [
+            ValidationInstanceHydrator::class => ValidationInstanceHydratorFactory::class,
+        ],
+    ],
+    'view_helpers' => [
+        'invokables' => [
+            'validationAfficher'              => ValidationAfficherViewHelper::class,
+            'validationBadge'                 => ValidationBadgeViewHelper::class,
+        ],
+        'factories' => [
+            'validationValider'              => ValidationValiderViewHelperFactory::class,
+        ]
+    ]
+
+];
\ No newline at end of file
diff --git a/config/merged/validation-type.config.php b/config/merged/validation-type.config.php
new file mode 100644
index 0000000..ba76fe8
--- /dev/null
+++ b/config/merged/validation-type.config.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace UnicaenValidation;
+
+use UnicaenPrivilege\Guard\PrivilegeController;
+use UnicaenValidation\Controller\ValidationTypeController;
+use UnicaenValidation\Controller\ValidationTypeControllerFactory;
+use UnicaenValidation\Form\ValidationType\ValidationTypeForm;
+use UnicaenValidation\Form\ValidationType\ValidationTypeFormFactory;
+use UnicaenValidation\Form\ValidationType\ValidationTypeHydrator;
+use UnicaenValidation\Form\ValidationType\ValidationTypeHydratorFactory;
+use UnicaenValidation\Provider\Privilege\ValidationtypePrivileges;
+use UnicaenValidation\Service\ValidationType\ValidationTypeService;
+use UnicaenValidation\Service\ValidationType\ValidationTypeServiceFactory;
+use Laminas\Router\Http\Literal;
+use Laminas\Router\Http\Segment;
+
+return [
+    'bjyauthorize' => [
+        'guards' => [
+            PrivilegeController::class => [
+                [
+                    'controller' => ValidationTypeController::class,
+                    'action' => [
+                        'index',
+                    ],
+                    'privileges' => [
+                        ValidationtypePrivileges::VALIDATIONTYPE_AFFICHER,
+                    ],
+                ],
+                [
+                    'controller' => ValidationTypeController::class,
+                    'action' => [
+                        'ajouter',
+                        'modifier',
+                    ],
+                    'privileges' => [
+                        ValidationtypePrivileges::VALIDATIONTYPE_MODIFIER,
+                    ],
+                ],
+                [
+                    'controller' => ValidationTypeController::class,
+                    'action' => [
+                        'detruire',
+                    ],
+                    'privileges' => [
+                        ValidationtypePrivileges::VALIDATIONTYPE_DETRUIRE,
+                    ],
+                ],
+            ],
+        ],
+    ],
+
+    'router'          => [
+        'routes' => [
+            'validation' => [
+                'child_routes' => [
+                    'type' => [
+                        'type' => Literal::class,
+                        'options' => [
+                            'route'    => '/type',
+                            'defaults' => [
+                                'controller' => ValidationTypeController::class,
+                                'action'     => 'index',
+                            ],
+                        ],
+                        'may_terminate' => true,
+                        'child_routes' => [
+                            'ajouter' => [
+                                'type' => Literal::class,
+                                'options' => [
+                                    'route'    => '/ajouter',
+                                    'defaults' => [
+                                        'controller' => ValidationTypeController::class,
+                                        'action'     => 'ajouter',
+                                    ],
+                                ],
+                            ],
+                            'modifier' => [
+                                'type' => Segment::class,
+                                'options' => [
+                                    'route'    => '/modifier/:type',
+                                    'defaults' => [
+                                        'controller' => ValidationTypeController::class,
+                                        'action'     => 'modifier',
+                                    ],
+                                ],
+                            ],
+                            'detruire' => [
+                                'type' => Segment::class,
+                                'options' => [
+                                    'route'    => '/detruire/:type',
+                                    'defaults' => [
+                                        'controller' => ValidationTypeController::class,
+                                        'action'     => 'detruire',
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ],
+    ],
+
+    'service_manager' => [
+        'factories' => [
+            ValidationTypeService::class => ValidationTypeServiceFactory::class,
+        ],
+    ],
+    'controllers'     => [
+        'factories' => [
+            ValidationTypeController::class => ValidationTypeControllerFactory::class,
+        ],
+    ],
+    'form_elements' => [
+        'factories' => [
+            ValidationTypeForm::class => ValidationTypeFormFactory::class,
+        ],
+    ],
+    'hydrators' => [
+        'factories' => [
+            ValidationTypeHydrator::class => ValidationTypeHydratorFactory::class,
+        ],
+    ]
+
+];
\ No newline at end of file
diff --git a/config/module.config.php b/config/module.config.php
new file mode 100644
index 0000000..07ce8e1
--- /dev/null
+++ b/config/module.config.php
@@ -0,0 +1,92 @@
+<?php
+
+use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
+use Doctrine\ORM\Mapping\Driver\XmlDriver;
+use Laminas\Router\Http\Literal;
+use UnicaenPrivilege\Guard\PrivilegeController;
+use UnicaenValidation\Controller\ValidationInstanceController;
+use UnicaenValidation\Controller\ValidationTypeController;
+
+return [
+    'doctrine' => [
+        'driver' => [
+            'orm_default' => [
+                'class' => MappingDriverChain::class,
+                'drivers' => [
+                    'UnicaenValidation\Entity\Db' => 'orm_default_xml_driver',
+                ],
+            ],
+            'orm_default_xml_driver' => [
+                'class' => XmlDriver::class,
+                'cache' => 'apc',
+                'paths' => [
+                    __DIR__ . '/../src/UnicaenValidation/Entity/Db/Mapping',
+                ],
+            ],
+        ],
+        'cache' => [
+            'apc' => [
+                'namespace' => 'UNICAEN-VALIDATION__' . __NAMESPACE__,
+            ],
+        ],
+    ],
+
+    'router'          => [
+        'routes' => [
+            'validation' => [
+                'type' => Literal::class,
+                'options' => [
+                    'route'    => '/validation',
+                ],
+                'may_terminate' => false,
+            ],
+        ],
+    ],
+
+    'navigation'      => [
+        'default' => [
+            'home' => [
+                'pages' => [
+                    'administration' => [
+                        'pages' => [
+                            'validations' => [
+                                'label'    => 'Validations',
+                                'route'    => 'validation/type',
+                                'resource' => PrivilegeController::getResourceId(ValidationTypeController::class, 'index'),
+                                'order'    => 1111,
+                                'pages' => [
+                                    'instance' => [
+                                        'label'    => 'Instances de validation',
+                                        'route'    => 'validation/instance',
+                                        'resource' => PrivilegeController::getResourceId(ValidationInstanceController::class, 'index'),
+                                        'order'    => 1112,
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ],
+    ],
+
+    'service_manager' => [
+        'invokables' => [
+            ],
+        'factories' => [
+        ],
+    ],
+
+    'view_manager'    => [
+        'template_path_stack' => [
+            __DIR__ . '/../view',
+        ],
+    ],
+
+    'view_helpers'  => [
+        'aliases' => [
+        ],
+        'factories' => [
+        ],
+    ],
+];
diff --git a/documentation/001_table.sql b/documentation/001_table.sql
new file mode 100644
index 0000000..4d266a9
--- /dev/null
+++ b/documentation/001_table.sql
@@ -0,0 +1,38 @@
+create table unicaen_validation_type
+(
+    id        serial
+        constraint unicaen_validation_type_pk
+            primary key,
+    code      varchar(256)         not null,
+    libelle   varchar(1024)        not null,
+    refusable boolean default true not null
+);
+create unique index unicaen_validation_type_id_uindex
+    on unicaen_validation_type (id);
+
+create table unicaen_validation_instance
+(
+    id                    serial
+        constraint unicaen_validation_instance_pk
+            primary key,
+    type_id               integer   not null
+        constraint unicaen_validation_instance_unicaen_validation_type_id_fk
+            references unicaen_validation_type
+                on delete cascade,
+    valeur                text,
+    histo_creation        timestamp not null,
+    histo_createur_id     integer   not null
+        constraint unicaen_validation_instance_createur_fk
+            references unicaen_utilisateur_user,
+    histo_modification    timestamp not null,
+    histo_modificateur_id integer   not null
+        constraint unicaen_validation_instance_modificateur_fk
+            references unicaen_utilisateur_user,
+    histo_destruction     timestamp,
+    histo_destructeur_id  integer
+        constraint unicaen_validation_instance_destructeur_fk
+            references unicaen_utilisateur_user
+);
+create unique index unicaen_validation_instance_id_uindex
+    on unicaen_validation_instance (id);
+
diff --git a/documentation/101_privilege.sql b/documentation/101_privilege.sql
new file mode 100644
index 0000000..dcfb55c
--- /dev/null
+++ b/documentation/101_privilege.sql
@@ -0,0 +1,29 @@
+INSERT INTO unicaen_privilege_categorie (code, libelle, ordre, namespace)
+VALUES ('validation_type', 'Gestion des types de validation', 10000, 'UnicaenValidation\Provider\Privilege');
+
+INSERT INTO unicaen_privilege_privilege(CATEGORIE_ID, CODE, LIBELLE, ORDRE)
+WITH d(code, lib, ordre) AS (
+    SELECT 'validationtype_afficher', 'Affichage des types de validations', 10 UNION
+    SELECT 'validationtype_modifier', 'Modifier un type de validation', 20 UNION
+    SELECT 'validationtype_detruire', 'Détruire un type de validation', 30
+)
+SELECT cp.id, d.code, d.lib, d.ordre
+FROM d
+JOIN unicaen_privilege_categorie cp ON cp.CODE = 'validation_type'
+;
+
+INSERT INTO unicaen_privilege_categorie (code, libelle, ordre, namespace)
+VALUES ('validation_instance', 'Gestion des instances de validation', 10000, 'UnicaenValidation\Provider\Privilege');
+
+INSERT INTO unicaen_privilege_privilege(CATEGORIE_ID, CODE, LIBELLE, ORDRE)
+WITH d(code, lib, ordre) AS (
+    SELECT 'validationinstance_afficher', 'Affichage des instances de validations', 10 UNION
+    SELECT 'validationinstance_modifier', 'Modifier une instance de validation', 30 UNION
+    SELECT 'validationinstance_historiser', 'Historiser/restaurer une instance de validation', 40 UNION
+    SELECT 'validationinstance_detruire', 'Détruire une isntance de validation', 50
+
+)
+SELECT cp.id, d.code, d.lib, d.ordre
+FROM d
+         JOIN unicaen_privilege_categorie cp ON cp.CODE = 'validation_instance'
+;
\ No newline at end of file
diff --git a/src/UnicaenValidation/Controller/ValidationInstanceController.php b/src/UnicaenValidation/Controller/ValidationInstanceController.php
new file mode 100644
index 0000000..f158174
--- /dev/null
+++ b/src/UnicaenValidation/Controller/ValidationInstanceController.php
@@ -0,0 +1,123 @@
+<?php
+
+namespace UnicaenValidation\Controller;
+
+use Laminas\Http\Response;
+use UnicaenValidation\Entity\Db\ValidationInstance;
+use UnicaenValidation\Form\ValidationInstance\ValidationInstanceFormAwareTrait;
+use UnicaenValidation\Service\ValidationInstance\ValidationInstanceServiceAwareTrait;
+use UnicaenValidation\Service\ValidationType\ValidationTypeServiceAwareTrait;
+use Laminas\Http\Request;
+use Laminas\Mvc\Controller\AbstractActionController;
+use Laminas\View\Model\ViewModel;
+
+class ValidationInstanceController extends AbstractActionController {
+    use ValidationInstanceServiceAwareTrait;
+    use ValidationTypeServiceAwareTrait;
+    use ValidationInstanceFormAwareTrait;
+
+    public function indexAction() : ViewModel
+    {
+        $instances = $this->getValidationInstanceService()->getValidationsInstances();
+
+        return new ViewModel([
+            'instances' => $instances,
+        ]);
+    }
+
+    public function ajouterAction() : ViewModel
+    {
+        $instance = new ValidationInstance();
+        $form = $this->getValidationInstancForm();
+        $form->setAttribute('action', $this->url()->fromRoute('validation/instance/ajouter', [], [], true));
+        $form->bind($instance);
+
+        /** @var Request $request */
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            $form->setData($data);
+            if ($form->isValid()) {
+                $this->getValidationInstanceService()->create($instance);
+            }
+        }
+
+        $vm = new ViewModel();
+        $vm->setTemplate('unicaen-validation/default/default-form');
+        $vm->setVariables([
+            'title' => "Ajout d'un type de validation",
+            'form' => $form,
+        ]);
+        return $vm;
+    }
+
+    public function modifierAction() : ViewModel
+    {
+        $instance = $this->getValidationInstanceService()->getRequestedValidationInstance($this);
+        $form = $this->getValidationInstancForm();
+        $form->setAttribute('action', $this->url()->fromRoute('validation/instance/modifier', ['validation' => $instance->getId()], [], true));
+        $form->bind($instance);
+
+        /** @var Request $request */
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            $form->setData($data);
+            if ($form->isValid()) {
+                $this->getValidationInstanceService()->update($instance);
+            }
+        }
+
+        $vm = new ViewModel();
+        $vm->setTemplate('unicaen-validation/default/default-form');
+        $vm->setVariables([
+            'title' => "Modification d'un type de validation",
+            'form' => $form,
+        ]);
+        return $vm;
+    }
+
+    public function historiserAction() : Response
+    {
+        $instance = $this->getValidationInstanceService()->getRequestedValidationInstance($this);
+        $this->getValidationInstanceService()->historise($instance);
+
+        $retour = $this->params()->fromQuery('retour');
+        if ($retour) return $this->redirect()->toUrl($retour);
+        return $this->redirect()->toRoute('validation/instance');
+    }
+
+    public function restaurerAction() : Response
+    {
+        $instance = $this->getValidationInstanceService()->getRequestedValidationInstance($this);
+        $this->getValidationInstanceService()->restore($instance);
+
+        $retour = $this->params()->fromQuery('retour');
+        if ($retour) return $this->redirect()->toUrl($retour);
+        return $this->redirect()->toRoute('validation/instance');
+    }
+
+    public function detruireAction() : ViewModel
+    {
+        $instance = $this->getValidationInstanceService()->getRequestedValidationInstance($this);
+
+        /** @var Request $request */
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            if ($data["reponse"] === "oui") $this->getValidationInstanceService()->delete($instance);
+            exit();
+        }
+
+        $vm = new ViewModel();
+        if ($instance !== null) {
+            $vm->setTemplate('unicaen-validation/default/confirmation');
+            $vm->setVariables([
+                'title' => "Suppression de la validation ",
+                'text' => "La suppression est définitive êtes-vous sûr&middot;e de vouloir continuer ?",
+                'action' => $this->url()->fromRoute('validation/instance/detruire', ["validation" => $instance->getId()], [], true),
+            ]);
+        }
+        return $vm;
+    }
+}
diff --git a/src/UnicaenValidation/Controller/ValidationInstanceControllerFactory.php b/src/UnicaenValidation/Controller/ValidationInstanceControllerFactory.php
new file mode 100644
index 0000000..031bf57
--- /dev/null
+++ b/src/UnicaenValidation/Controller/ValidationInstanceControllerFactory.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace UnicaenValidation\Controller;
+
+use Interop\Container\ContainerInterface;
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\NotFoundExceptionInterface;
+use UnicaenValidation\Form\ValidationInstance\ValidationInstanceForm;
+use UnicaenValidation\Service\ValidationInstance\ValidationInstanceService;
+use UnicaenValidation\Service\ValidationType\ValidationTypeService;
+
+class ValidationInstanceControllerFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return ValidationInstanceController
+     * @throws ContainerExceptionInterface
+     * @throws NotFoundExceptionInterface
+     */
+    public function __invoke(ContainerInterface $container) : ValidationInstanceController
+    {
+        /**
+         * @var ValidationInstanceService $validationInstanceService
+         * @var ValidationTypeService $validationTypeService
+         */
+        $validationInstanceService = $container->get(ValidationInstanceService::class);
+        $validationTypeService = $container->get(ValidationTypeService::class);
+
+        /**
+         * @var ValidationInstanceForm $validationInstanceForm
+         */
+        $validationInstanceForm = $container->get('FormElementManager')->get(ValidationInstanceForm::class);
+
+        $controller = new ValidationInstanceController();
+        $controller->setValidationInstanceService($validationInstanceService);
+        $controller->setValidationInstancForm($validationInstanceForm);
+        $controller->setValidationTypeService($validationTypeService);
+        return $controller;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Controller/ValidationTypeController.php b/src/UnicaenValidation/Controller/ValidationTypeController.php
new file mode 100644
index 0000000..e54c481
--- /dev/null
+++ b/src/UnicaenValidation/Controller/ValidationTypeController.php
@@ -0,0 +1,105 @@
+<?php
+
+namespace UnicaenValidation\Controller;
+
+use UnicaenValidation\Entity\Db\ValidationType;
+use UnicaenValidation\Form\ValidationType\ValidationTypeFormAwareTrait;
+use UnicaenValidation\Service\ValidationType\ValidationTypeServiceAwareTrait;
+use Laminas\Http\Request;
+use Laminas\Mvc\Controller\AbstractActionController;
+use Laminas\View\Model\ViewModel;
+
+class ValidationTypeController extends AbstractActionController
+{
+    use ValidationTypeServiceAwareTrait;
+    use ValidationTypeFormAwareTrait;
+
+    public function indexAction() : ViewModel
+    {
+        $types = $this->getValidationTypeService()->getValidationsTypes();
+
+        return new ViewModel([
+            'types' => $types,
+        ]);
+    }
+
+    public function ajouterAction() : ViewModel
+    {
+        $type = new ValidationType();
+        $form = $this->getValidationTypeForm();
+        $form->setAttribute('action', $this->url()->fromRoute('validation/type/ajouter', [], [], true));
+        $form->bind($type);
+
+        /** @var Request $request */
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            $form->setData($data);
+            if ($form->isValid()) {
+                $this->getValidationTypeService()->create($type);
+            }
+        }
+
+        $vm = new ViewModel();
+        $vm->setTemplate('unicaen-validation/default/default-form');
+        $vm->setVariables([
+            'title' => "Ajout d'un type de validation",
+            'form' => $form,
+        ]);
+        return $vm;
+    }
+
+    public function modifierAction() : ViewModel
+    {
+        $type = $this->getValidationTypeService()->getRequestedValidationType($this);
+        $form = $this->getValidationTypeForm();
+        $form->setAttribute('action', $this->url()->fromRoute('validation/type/modifier', ['type' => $type->getId()], [], true));
+        $form->bind($type);
+        $form->get('old-code')->setValue($type->getCode());
+
+
+        /** @var Request $request */
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            $form->setData($data);
+            $oldcode = $type->getCode();
+            if ($form->isValid()) {
+                $this->getValidationTypeService()->update($type);
+            }
+        }
+
+        $vm = new ViewModel();
+        $vm->setTemplate('unicaen-validation/default/default-form');
+        $vm->setVariables([
+            'title' => "Modification d'un type de validation",
+            'form' => $form,
+        ]);
+        return $vm;
+    }
+
+    public function detruireAction() : ViewModel
+    {
+        $type = $this->getValidationTypeService()->getRequestedValidationType($this);
+
+        /** @var Request $request */
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            if ($data["reponse"] === "oui") $this->getValidationTypeService()->delete($type);
+            exit();
+        }
+
+        $vm = new ViewModel();
+        if ($type !== null) {
+            $vm->setTemplate('unicaen-validation/default/confirmation');
+            $vm->setVariables([
+                'title' => "Suppression du type de validation " . $type->getLibelle(),
+                'text' => "La suppression est définitive êtes-vous sûr&middot;e de vouloir continuer ?",
+                'action' => $this->url()->fromRoute('validation/type/detruire', ["type" => $type->getId()], [], true),
+            ]);
+        }
+        return $vm;
+    }
+
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Controller/ValidationTypeControllerFactory.php b/src/UnicaenValidation/Controller/ValidationTypeControllerFactory.php
new file mode 100644
index 0000000..bfa0592
--- /dev/null
+++ b/src/UnicaenValidation/Controller/ValidationTypeControllerFactory.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace UnicaenValidation\Controller;
+
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\ContainerInterface;
+use Psr\Container\NotFoundExceptionInterface;
+use UnicaenValidation\Form\ValidationType\ValidationTypeForm;
+use UnicaenValidation\Service\ValidationType\ValidationTypeService;
+
+class ValidationTypeControllerFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return ValidationTypeController
+     * @throws ContainerExceptionInterface
+     * @throws NotFoundExceptionInterface
+     */
+    public function __invoke(ContainerInterface $container) : ValidationTypeController
+    {
+        /**
+         * @var ValidationTypeService $validationTypeService
+         */
+        $validationTypeService = $container->get(ValidationTypeService::class);
+
+        /**
+         * @var ValidationTypeForm $validationTypeForm
+         */
+        $validationTypeForm = $container->get('FormElementManager')->get(ValidationTypeForm::class);
+
+        $controller = new ValidationTypeController();
+        $controller->setValidationTypeService($validationTypeService);
+        $controller->setValidationTypeForm($validationTypeForm);
+        return $controller;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Entity/Db/Mapping/UnicaenValidation.Entity.Db.ValidationInstance.dcm.xml b/src/UnicaenValidation/Entity/Db/Mapping/UnicaenValidation.Entity.Db.ValidationInstance.dcm.xml
new file mode 100644
index 0000000..fb2b132
--- /dev/null
+++ b/src/UnicaenValidation/Entity/Db/Mapping/UnicaenValidation.Entity.Db.ValidationInstance.dcm.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
+    <entity name="UnicaenValidation\Entity\Db\ValidationInstance" table="unicaen_validation_instance">
+
+        <id name="id" type="integer" column="id">
+            <generator strategy="IDENTITY"/>
+        </id>
+
+        <many-to-one target-entity="UnicaenValidation\Entity\Db\ValidationType"  field="type">
+            <join-column name="type_id" referenced-column-name="id"/>
+        </many-to-one>
+
+        <field name="valeur"            type="string"                    column="valeur"                 nullable="true"/>
+
+        <field name="histoCreation"     type="datetime"                 column="histo_creation"     nullable="false"/>
+        <field name="histoModification" type="datetime"                 column="histo_modification" nullable="false"/>
+        <field name="histoDestruction"  type="datetime"                 column="histo_destruction"  nullable="true"/>
+        <many-to-one target-entity="UnicaenUtilisateur\Entity\Db\User"  field="histoCreateur">
+            <join-column name="histo_createur_id" referenced-column-name="ID"/>
+        </many-to-one>
+        <many-to-one target-entity="UnicaenUtilisateur\Entity\Db\User"  field="histoModificateur">
+            <join-column name="histo_modificateur_id" referenced-column-name="ID"/>
+        </many-to-one>
+        <many-to-one target-entity="UnicaenUtilisateur\Entity\Db\User"  field="histoDestructeur">
+            <join-column name="histo_destructeur_id" referenced-column-name="ID"/>
+        </many-to-one>
+
+    </entity>
+</doctrine-mapping>
diff --git a/src/UnicaenValidation/Entity/Db/Mapping/UnicaenValidation.Entity.Db.ValidationType.dcm.xml b/src/UnicaenValidation/Entity/Db/Mapping/UnicaenValidation.Entity.Db.ValidationType.dcm.xml
new file mode 100644
index 0000000..d0c6712
--- /dev/null
+++ b/src/UnicaenValidation/Entity/Db/Mapping/UnicaenValidation.Entity.Db.ValidationType.dcm.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
+    <entity name="UnicaenValidation\Entity\Db\ValidationType" table="unicaen_validation_type">
+
+        <id name="id" type="integer" column="id">
+            <generator strategy="IDENTITY"/>
+        </id>
+
+        <field name="code"              type="string" length="256"       column="code"                   nullable="false"/>
+        <field name="libelle"           type="string" length="1024"      column="libelle"                nullable="false"/>
+        <field name="refusable"         type="boolean"                   column="refusable"              nullable="false"/>
+    </entity>
+</doctrine-mapping>
diff --git a/src/UnicaenValidation/Entity/Db/ValidationInstance.php b/src/UnicaenValidation/Entity/Db/ValidationInstance.php
new file mode 100644
index 0000000..e03ea4e
--- /dev/null
+++ b/src/UnicaenValidation/Entity/Db/ValidationInstance.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace UnicaenValidation\Entity\Db;
+
+use UnicaenUtilisateur\Entity\HistoriqueAwareInterface;
+use UnicaenUtilisateur\Entity\HistoriqueAwareTrait;
+
+class ValidationInstance implements HistoriqueAwareInterface {
+    use HistoriqueAwareTrait;
+
+    private int $id;
+    private ?ValidationType $type = null;
+    private ?string $valeur = null;
+
+    /**
+     * @return int
+     */
+    public function getId() : int
+    {
+        return $this->id;
+    }
+
+    /**
+     * @return ValidationType|null
+     */
+    public function getType() : ?ValidationType
+    {
+        return $this->type;
+    }
+
+    /**
+     * @param ValidationType $type
+     * @return ValidationInstance
+     */
+    public function setType(ValidationType $type) : ValidationInstance
+    {
+        $this->type = $type;
+        return $this;
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getValeur() : ?string
+    {
+        return $this->valeur;
+    }
+
+    /**
+     * @param string|null $valeur
+     * @return ValidationInstance
+     */
+    public function setValeur(?string $valeur) : ValidationInstance
+    {
+        $this->valeur = $valeur;
+        return $this;
+    }
+
+    public function generateTooltipText() : string
+    {
+        $text  = "Validation effectuée<br/>";
+        $text .= "par <span class='user'>".$this->histoModificateur->getDisplayName()."</span><br/>";
+        $text .= "le <span class='date'>".$this->getHistoModification()->format('d/m/Y')."</span>";
+        return $text;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Entity/Db/ValidationType.php b/src/UnicaenValidation/Entity/Db/ValidationType.php
new file mode 100644
index 0000000..b4d9379
--- /dev/null
+++ b/src/UnicaenValidation/Entity/Db/ValidationType.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace UnicaenValidation\Entity\Db;
+
+class ValidationType {
+
+    private int $id;
+    private ?string $code = null;
+    private ?string $libelle = null;
+    private ?bool $refusable = null;
+
+    /**
+     * @return int
+     */
+    public function getId() : int
+    {
+        return $this->id;
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getCode() : ?string
+    {
+        return $this->code;
+    }
+
+    /**
+     * @param string $code
+     * @return ValidationType
+     */
+    public function setCode(string $code) : ValidationType
+    {
+        $this->code = $code;
+        return $this;
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getLibelle() : ?string
+    {
+        return $this->libelle;
+    }
+
+    /**
+     * @param string $libelle
+     * @return ValidationType
+     */
+    public function setLibelle(string $libelle) : ValidationType
+    {
+        $this->libelle = $libelle;
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isRefusable() : bool
+    {
+        return $this->refusable??false;
+    }
+
+    /**
+     * @param bool $refusable
+     * @return ValidationType
+     */
+    public function setRefusable(bool $refusable) : ValidationType
+    {
+        $this->refusable = $refusable;
+        return $this;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Entity/HasValidationsInterface.php b/src/UnicaenValidation/Entity/HasValidationsInterface.php
new file mode 100644
index 0000000..59ff8f9
--- /dev/null
+++ b/src/UnicaenValidation/Entity/HasValidationsInterface.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace UnicaenValidation\Entity;
+
+use UnicaenValidation\Entity\Db\ValidationInstance;
+
+interface HasValidationsInterface {
+
+    public function getValidations() : array;
+    public function addValidation(ValidationInstance $validation) : void;
+    public function removeValidation(ValidationInstance $validation) : void;
+    public function getValidationsByTypeCode(string $typeCode) : array ;
+    public function getValidationActiveByTypeCode(string $typeCode) : ?ValidationInstance;
+
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Entity/HasValidationsTrait.php b/src/UnicaenValidation/Entity/HasValidationsTrait.php
new file mode 100644
index 0000000..9c7f681
--- /dev/null
+++ b/src/UnicaenValidation/Entity/HasValidationsTrait.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace UnicaenValidation\Entity;
+
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+use UnicaenValidation\Entity\Db\ValidationInstance;
+
+trait HasValidationsTrait {
+
+    private Collection $validations;
+
+    /**
+     * @return ValidationInstance[]
+     */
+    public function getValidations() : array
+    {
+        return $this->validations->toArray();
+    }
+
+    /**
+     * @param ValidationInstance $validation
+     * @return void
+     */
+    public function addValidation(ValidationInstance $validation) : void
+    {
+        $this->validations->add($validation);
+    }
+
+    /**
+     * @param ValidationInstance $validation
+     * @return void
+     */
+    public function removeValidation(ValidationInstance $validation) : void
+    {
+        $this->validations->removeElement($validation);
+    }
+
+    /**
+     * @param string $typeCode
+     * @return array
+     */
+    public function getValidationsByTypeCode(string $typeCode) : array
+    {
+        $result = [];
+        /** @var ValidationInstance $validation */
+        foreach ($this->validations as $validation) {
+            if ($validation->getType()->getCode() === $typeCode AND $validation->estNonHistorise()) $result[] = $validation;
+        }
+        return $result;
+    }
+    /**
+     * @param string $typeCode
+     * @return ValidationInstance|null
+     */
+    public function getValidationActiveByTypeCode(string $typeCode) : ?ValidationInstance
+    {
+        /** @var ValidationInstance $validation */
+        foreach ($this->validations as $validation) {
+            if ($validation->getType()->getCode() === $typeCode AND $validation->estNonHistorise()) return $validation;
+        }
+        return null;
+    }
+
+
+
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceForm.php b/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceForm.php
new file mode 100644
index 0000000..a1138f4
--- /dev/null
+++ b/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceForm.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace UnicaenValidation\Form\ValidationInstance;
+
+use UnicaenValidation\Service\ValidationType\ValidationTypeServiceAwareTrait;
+use Laminas\Form\Element\Button;
+use Laminas\Form\Element\Select;
+use Laminas\Form\Element\Text;
+use Laminas\Form\Form;
+use Laminas\InputFilter\Factory;
+
+class ValidationInstanceForm extends Form {
+    use ValidationTypeServiceAwareTrait;
+
+    public function init() {
+
+        //type
+        $this->add([
+            'type' => Select::class,
+            'name' => 'type',
+            'options' => [
+                'label' => "Type de validation* :",
+                'empty_option' => "Choisir un type de validation",
+                'value_options' => $this->getValidationTypeService()->getValidationsTypesAsOptions(),
+            ],
+            'attributes' => [
+                'id'                => 'type',
+                'class'             => 'bootstrap-selectpicker show-tick',
+                'data-live-search'  => 'true',
+            ],
+        ]);
+        //valeur
+        $this->add([
+            'name' => 'valeur',
+            'type' => Text::class,
+            'options' => [
+                'label' => 'Refus (laisser vide si acceptation) : ',
+                'label_attributes' => [
+                    'class' => 'control-label',
+                ],
+            ],
+            'attributes' => [
+                'id'                => 'valeur',
+            ]
+        ]);
+        //submit
+        $this->add([
+            'type' => Button::class,
+            'name' => 'creer',
+            'options' => [
+                'label' => '<i class="fas fa-save"></i> Enregistrer' ,
+                'label_options' => [
+                    'disable_html_escape' => true,
+                ],
+            ],
+            'attributes' => [
+                'type' => 'submit',
+                'class' => 'btn btn-primary',
+            ],
+        ]);
+
+        //inputfilter
+        $this->setInputFilter((new Factory())->createInputFilter([
+            'type'               => [ 'required' => true,  ],
+            'valeur'             => [ 'required' => false,  ],
+        ]));
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceFormAwareTrait.php b/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceFormAwareTrait.php
new file mode 100644
index 0000000..e5d81b5
--- /dev/null
+++ b/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceFormAwareTrait.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace UnicaenValidation\Form\ValidationInstance;
+
+trait ValidationInstanceFormAwareTrait {
+
+    private ValidationInstanceForm $validationInstancForm;
+
+    /**
+     * @return ValidationInstanceForm
+     */
+    public function getValidationInstancForm() : ValidationInstanceForm
+    {
+        return $this->validationInstancForm;
+    }
+
+    /**
+     * @param ValidationInstanceForm $validationInstancForm
+     */
+    public function setValidationInstancForm(ValidationInstanceForm $validationInstancForm) : void
+    {
+        $this->validationInstancForm = $validationInstancForm;
+    }
+
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceFormFactory.php b/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceFormFactory.php
new file mode 100644
index 0000000..90025cc
--- /dev/null
+++ b/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceFormFactory.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace UnicaenValidation\Form\ValidationInstance;
+
+use Interop\Container\ContainerInterface;
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\NotFoundExceptionInterface;
+use UnicaenValidation\Service\ValidationType\ValidationTypeService;
+
+class ValidationInstanceFormFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return ValidationInstanceForm
+     * @throws ContainerExceptionInterface
+     * @throws NotFoundExceptionInterface
+     */
+    public function __invoke(ContainerInterface $container) : ValidationInstanceForm
+    {
+        /**
+         * @var ValidationTypeService $validationTypeService
+         */
+        $validationTypeService = $container->get(ValidationTypeService::class);
+
+        /** @var ValidationInstanceHydrator $hydrator */
+        $hydrator = $container->get('HydratorManager')->get(ValidationInstanceHydrator::class);
+
+        $form = new ValidationInstanceForm();
+        $form->setValidationTypeService($validationTypeService);
+        $form->setHydrator($hydrator);
+        return $form;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceHydrator.php b/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceHydrator.php
new file mode 100644
index 0000000..a901991
--- /dev/null
+++ b/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceHydrator.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace UnicaenValidation\Form\ValidationInstance;
+
+use UnicaenValidation\Entity\Db\ValidationInstance;
+use UnicaenValidation\Service\ValidationType\ValidationTypeServiceAwareTrait;
+use Laminas\Hydrator\HydratorInterface;
+
+class ValidationInstanceHydrator implements HydratorInterface {
+    use ValidationTypeServiceAwareTrait;
+
+    /**
+     * @param ValidationInstance $object
+     * @return array
+     */
+    public function extract(object $object) : array
+    {
+        $data = [
+            'type'          => ($object AND $object->getType())?$object->getType()->getId():null,
+            'valeur'        => $object?$object->getValeur():null,
+        ];
+        return $data;
+    }
+
+    /**
+     * @param array $data
+     * @param ValidationInstance $object
+     * @return ValidationInstance
+     */
+    public function hydrate(array $data, object $object)
+    {
+        $type = $this->getValidationTypeService()->getValidationType($data['type']);
+        $object->setType($type);
+        $object->setValeur($data['valeur'] ?? null);
+        return $object;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceHydratorFactory.php b/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceHydratorFactory.php
new file mode 100644
index 0000000..4f3adc2
--- /dev/null
+++ b/src/UnicaenValidation/Form/ValidationInstance/ValidationInstanceHydratorFactory.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace UnicaenValidation\Form\ValidationInstance;
+
+use Interop\Container\ContainerInterface;
+use UnicaenValidation\Service\ValidationType\ValidationTypeService;
+
+class ValidationInstanceHydratorFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return ValidationInstanceHydrator
+     * @throws \Psr\Container\ContainerExceptionInterface
+     * @throws \Psr\Container\NotFoundExceptionInterface
+     */
+    public function __invoke(ContainerInterface $container) : ValidationInstanceHydrator
+    {
+        /**
+         * @var ValidationTypeService $validationTypeService
+         */
+        $validationTypeService = $container->get(ValidationTypeService::class);
+
+        $hydrator = new ValidationInstanceHydrator();
+        $hydrator->setValidationTypeService($validationTypeService);
+        return $hydrator;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Form/ValidationType/ValidationTypeForm.php b/src/UnicaenValidation/Form/ValidationType/ValidationTypeForm.php
new file mode 100644
index 0000000..64c3ea0
--- /dev/null
+++ b/src/UnicaenValidation/Form/ValidationType/ValidationTypeForm.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace UnicaenValidation\Form\ValidationType;
+
+use Laminas\Form\Element\Button;
+use Laminas\Form\Element\Checkbox;
+use Laminas\Form\Element\Hidden;
+use Laminas\Form\Element\Text;
+use Laminas\Form\Form;
+use Laminas\InputFilter\Factory;
+use Laminas\Validator\Callback;
+use UnicaenApp\Service\EntityManagerAwareTrait;
+use UnicaenValidation\Entity\Db\ValidationType;
+
+class ValidationTypeForm extends Form {
+    use EntityManagerAwareTrait;
+
+    public function init()
+    {
+        //code
+        $this->add([
+            'type' => Text::class,
+            'name' => 'code',
+            'options' => [
+                'label' => "Code* :",
+            ],
+            'attributes' => [
+                'id' => 'code',
+            ],
+        ]);
+        $this->add([
+            'name' => 'old-code',
+            'type' => Hidden::class,
+            'attributes' => [
+                'value' => "",
+            ],
+        ]);
+        //libelle
+        $this->add([
+            'type' => Text::class,
+            'name' => 'libelle',
+            'options' => [
+                'label' => "Libelle* :",
+            ],
+            'attributes' => [
+                'id' => 'libelle',
+            ],
+        ]);
+        //refusable
+        $this->add([
+            'type' => Checkbox::class,
+            'name' => 'refusable',
+            'options' => [
+                'label' => "Peut-être refusable",
+            ],
+            'attributes' => [
+                'id' => 'refusable',
+            ],
+        ]);
+        //submit
+        $this->add([
+            'type' => Button::class,
+            'name' => 'creer',
+            'options' => [
+                'label' => '<i class="fas fa-save"></i> Enregistrer',
+                'label_options' => [
+                    'disable_html_escape' => true,
+                ],
+            ],
+            'attributes' => [
+                'type' => 'submit',
+                'class' => 'btn btn-primary',
+            ],
+        ]);
+        //inputfilter
+        $this->setInputFilter((new Factory())->createInputFilter([
+            'code' => [
+                'required' => true,
+                'validators' => [[
+                    'name' => Callback::class,
+                    'options' => [
+                        'messages' => [
+                            Callback::INVALID_VALUE => "Ce code existe déjà",
+                        ],
+                        'callback' => function ($value, $context = []) {
+                            if($value == $context['old-code']) return true;
+                            return ($this->getEntityManager()->getRepository(ValidationType::class)->findOneBy(['code'=>$value],[]) == null);
+                        },
+                        //'break_chain_on_failure' => true,
+                    ],
+                ]],
+            ],
+            'old-code' => ['required' => false, ],
+            'libelle'    => [ 'required' => true, ],
+            'refusable'  => [ 'required' => false, ],
+        ]));
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Form/ValidationType/ValidationTypeFormAwareTrait.php b/src/UnicaenValidation/Form/ValidationType/ValidationTypeFormAwareTrait.php
new file mode 100644
index 0000000..0dc05b5
--- /dev/null
+++ b/src/UnicaenValidation/Form/ValidationType/ValidationTypeFormAwareTrait.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace UnicaenValidation\Form\ValidationType;
+
+trait ValidationTypeFormAwareTrait {
+
+    private ValidationTypeForm $validationTypeForm;
+
+    /**
+     * @return ValidationTypeForm
+     */
+    public function getValidationTypeForm() : ValidationTypeForm
+    {
+        return $this->validationTypeForm;
+    }
+
+    /**
+     * @param ValidationTypeForm $validationTypeForm
+     */
+    public function setValidationTypeForm(ValidationTypeForm $validationTypeForm) : void
+    {
+        $this->validationTypeForm = $validationTypeForm;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Form/ValidationType/ValidationTypeFormFactory.php b/src/UnicaenValidation/Form/ValidationType/ValidationTypeFormFactory.php
new file mode 100644
index 0000000..979679d
--- /dev/null
+++ b/src/UnicaenValidation/Form/ValidationType/ValidationTypeFormFactory.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace UnicaenValidation\Form\ValidationType;
+
+use Doctrine\ORM\EntityManager;
+use Interop\Container\ContainerInterface;
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\NotFoundExceptionInterface;
+
+class ValidationTypeFormFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return ValidationTypeForm
+     * @throws ContainerExceptionInterface
+     * @throws NotFoundExceptionInterface
+     */
+    public function __invoke(ContainerInterface $container) : ValidationTypeForm
+    {
+        /** @var EntityManager $entityManager */
+        $entityManager = $container->get('doctrine.entitymanager.orm_default');
+
+        /** @var ValidationTypeHydrator $hydrator */
+        $hydrator = $container->get('HydratorManager')->get(ValidationTypeHydrator::class);
+
+        $form = new ValidationTypeForm();
+        $form->setEntityManager($entityManager);
+        $form->setHydrator($hydrator);
+        return $form;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Form/ValidationType/ValidationTypeHydrator.php b/src/UnicaenValidation/Form/ValidationType/ValidationTypeHydrator.php
new file mode 100644
index 0000000..b2edaea
--- /dev/null
+++ b/src/UnicaenValidation/Form/ValidationType/ValidationTypeHydrator.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace UnicaenValidation\Form\ValidationType;
+
+use UnicaenValidation\Entity\Db\ValidationType;
+use Laminas\Hydrator\HydratorInterface;
+
+class ValidationTypeHydrator implements HydratorInterface {
+
+    /**
+     * @param ValidationType $object
+     * @return array
+     */
+    public function extract(object $object) : array
+    {
+        $data = [
+            "code" => $object->getCode(),
+            "libelle" => $object->getLibelle(),
+            "refusable" => $object->isRefusable(),
+        ];
+        return $data;
+    }
+
+    /**
+     * @param array $data
+     * @param ValidationType $object
+     * @return ValidationType
+     */
+    public function hydrate(array $data, object $object)
+    {
+        $object->setCode($data['code'] ?? null);
+        $object->setLibelle($data['libelle'] ?? null);
+        $object->setRefusable($data['refusable'] ?? null);
+        return $object;
+    }
+
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Form/ValidationType/ValidationTypeHydratorFactory.php b/src/UnicaenValidation/Form/ValidationType/ValidationTypeHydratorFactory.php
new file mode 100644
index 0000000..f4f151c
--- /dev/null
+++ b/src/UnicaenValidation/Form/ValidationType/ValidationTypeHydratorFactory.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace UnicaenValidation\Form\ValidationType;
+
+use Interop\Container\ContainerInterface;
+
+class ValidationTypeHydratorFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return ValidationTypeHydrator
+     */
+    public function __invoke(ContainerInterface $container) : ValidationTypeHydrator
+    {
+        $hydrator = new ValidationTypeHydrator();
+        return $hydrator;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Provider/Privilege/ValidationinstancePrivileges.php b/src/UnicaenValidation/Provider/Privilege/ValidationinstancePrivileges.php
new file mode 100644
index 0000000..dd1415c
--- /dev/null
+++ b/src/UnicaenValidation/Provider/Privilege/ValidationinstancePrivileges.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace UnicaenValidation\Provider\Privilege;
+
+use UnicaenPrivilege\Provider\Privilege\Privileges;
+
+class ValidationinstancePrivileges extends Privileges
+{
+    const VALIDATIONINSTANCE_AFFICHER = 'validationinstance-validationinstance_afficher';
+    const VALIDATIONINSTANCE_MODIFIER = 'validationinstance-validationinstance_modifier';
+    const VALIDATIONINSTANCE_HISTORISER = 'validationinstance-validationinstance_historiser';
+    const VALIDATIONINSTANCE_DETRUIRE = 'validationinstance-validationinstance_detruire';
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Provider/Privilege/ValidationtypePrivileges.php b/src/UnicaenValidation/Provider/Privilege/ValidationtypePrivileges.php
new file mode 100644
index 0000000..f050ecf
--- /dev/null
+++ b/src/UnicaenValidation/Provider/Privilege/ValidationtypePrivileges.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace UnicaenValidation\Provider\Privilege;
+
+use UnicaenPrivilege\Provider\Privilege\Privileges;
+
+class ValidationtypePrivileges extends Privileges
+{
+    const VALIDATIONTYPE_AFFICHER   = 'validationtype-validationtype_afficher';
+    const VALIDATIONTYPE_MODIFIER   = 'validationtype-validationtype_modifier';
+    const VALIDATIONTYPE_DETRUIRE   = 'validationtype-validationtype_detruire';
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Service/ValidationInstance/ValidationInstanceService.php b/src/UnicaenValidation/Service/ValidationInstance/ValidationInstanceService.php
new file mode 100644
index 0000000..3490147
--- /dev/null
+++ b/src/UnicaenValidation/Service/ValidationInstance/ValidationInstanceService.php
@@ -0,0 +1,179 @@
+<?php
+
+namespace UnicaenValidation\Service\ValidationInstance;
+
+use Doctrine\ORM\NonUniqueResultException;
+use Doctrine\ORM\ORMException;
+use Doctrine\ORM\QueryBuilder;
+use Laminas\Mvc\Controller\AbstractActionController;
+use UnicaenApp\Exception\RuntimeException;
+use UnicaenApp\Service\EntityManagerAwareTrait;
+use UnicaenValidation\Entity\Db\ValidationInstance;
+use UnicaenValidation\Service\ValidationType\ValidationTypeServiceAwareTrait;
+
+class ValidationInstanceService {
+    use EntityManagerAwareTrait;
+    use ValidationTypeServiceAwareTrait;
+
+    /** GESTION DES ENTITES *******************************************************************************************/
+
+    /**
+     * @param ValidationInstance $instance
+     * @return ValidationInstance
+     */
+    public function create(ValidationInstance $instance) : ValidationInstance
+    {
+        try {
+            $this->getEntityManager()->persist($instance);
+            $this->getEntityManager()->flush($instance);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Un problème est survenue lors de l'enregistrement en BD.",0,$e);
+        }
+
+        return $instance;
+    }
+
+    /**
+     * @param ValidationInstance $instance
+     * @return ValidationInstance
+     */
+    public function update(ValidationInstance $instance) : ValidationInstance
+    {
+        try {
+            $this->getEntityManager()->flush($instance);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Un problème est survenue lors de l'enregistrement en BD.",0,$e);
+        }
+
+        return $instance;
+    }
+
+    /**
+     * @param ValidationInstance $instance
+     * @return ValidationInstance
+     */
+    public function historise(ValidationInstance $instance) : ValidationInstance
+    {
+        try {
+            $instance->historiser();
+            $this->getEntityManager()->flush($instance);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Un problème est survenue lors de l'enregistrement en BD.",0,$e);
+        }
+
+        return $instance;
+    }
+
+    /**
+     * @param ValidationInstance $instance
+     * @return ValidationInstance
+     */
+    public function restore(ValidationInstance $instance) : ValidationInstance
+    {
+
+        try {
+            $instance->dehistoriser();
+            $this->getEntityManager()->flush($instance);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Un problème est survenue lors de l'enregistrement en BD.",0,$e);
+        }
+
+        return $instance;
+    }
+
+    /**
+     * @param ValidationInstance $instance
+     * @return ValidationInstance
+     */
+    public function delete(ValidationInstance $instance) : ValidationInstance
+    {
+        try {
+            $this->getEntityManager()->remove($instance);
+            $this->getEntityManager()->flush($instance);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Un problème est survenue lors de l'enregistrement en BD.",0,$e);
+        }
+
+        return $instance;
+    }
+
+    /** REQUETAGE *****************************************************************************************************/
+
+    /**
+     * @return QueryBuilder
+     */
+    public function createQueryBuilder() : QueryBuilder
+    {
+        $qb = $this->getEntityManager()->getRepository(ValidationInstance::class)->createQueryBuilder('vinstance')
+            ->addSelect('createur')->join('vinstance.histoCreateur', 'createur')
+            ->addSelect('modificateur')->join('vinstance.histoModificateur', 'modificateur')
+            ->addSelect('vtype')->join('vinstance.type', 'vtype')
+        ;
+        return $qb;
+    }
+
+    /**
+     * @param string $champ
+     * @param string $ordre
+     * @return ValidationInstance[]
+     */
+    public function getValidationsInstances(string $champ = 'histoModification', string $ordre = 'DESC') : array
+    {
+        $qb = $this->createQueryBuilder()
+            ->orderBy('vinstance.' . $champ, $ordre)
+        ;
+
+        $result = $qb->getQuery()->getResult();
+        return $result;
+    }
+
+    /**
+     * @param int|null $id
+     * @return ValidationInstance|null
+     */
+    public function getValidationInstance(?int $id) : ?ValidationInstance
+    {
+        $qb = $this->createQueryBuilder()
+            ->andWhere('vinstance.id = :id')
+            ->setParameter('id', $id)
+        ;
+
+        try {
+            $result = $qb->getQuery()->getOneOrNullResult();
+        } catch (NonUniqueResultException $e) {
+            throw new RuntimeException("Plusieurs ValidationInstance partagent le même id [".$id."]", 0, true);
+        }
+        return $result;
+    }
+
+    /**
+     * @param AbstractActionController $controller
+     * @param string $param
+     * @return ValidationInstance|null
+     */
+    public function getRequestedValidationInstance(AbstractActionController $controller, string $param = "validation") : ?ValidationInstance
+    {
+        $id = $controller->params()->fromRoute($param);
+        $result = $this->getValidationInstance($id);
+        return $result;
+    }
+
+    /** FACADE ********************************************************************************************************/
+
+    /**
+     * @param string $code
+     * @param string|null $valeur
+     * @return ValidationInstance
+     */
+    public function createWithCode(string $code, ?string $valeur = null) : ValidationInstance
+    {
+        $type = $this->getValidationTypeService()->getValidationTypeByCode($code);
+
+        $instance = new ValidationInstance();
+        $instance->setType($type);
+        $instance->setValeur($valeur);
+        $this->create($instance);
+
+        return $instance;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Service/ValidationInstance/ValidationInstanceServiceAwareTrait.php b/src/UnicaenValidation/Service/ValidationInstance/ValidationInstanceServiceAwareTrait.php
new file mode 100644
index 0000000..93583dc
--- /dev/null
+++ b/src/UnicaenValidation/Service/ValidationInstance/ValidationInstanceServiceAwareTrait.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace UnicaenValidation\Service\ValidationInstance;
+
+trait ValidationInstanceServiceAwareTrait {
+
+    private ValidationInstanceService $validationInstanceService;
+
+    /**
+     * @return ValidationInstanceService
+     */
+    public function getValidationInstanceService() : ValidationInstanceService
+    {
+        return $this->validationInstanceService;
+    }
+
+    /**
+     * @param ValidationInstanceService $validationInstanceService
+     */
+    public function setValidationInstanceService(ValidationInstanceService $validationInstanceService) : void
+    {
+        $this->validationInstanceService = $validationInstanceService;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Service/ValidationInstance/ValidationInstanceServiceFactory.php b/src/UnicaenValidation/Service/ValidationInstance/ValidationInstanceServiceFactory.php
new file mode 100644
index 0000000..5bb4bd9
--- /dev/null
+++ b/src/UnicaenValidation/Service/ValidationInstance/ValidationInstanceServiceFactory.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace UnicaenValidation\Service\ValidationInstance;
+
+use Doctrine\ORM\EntityManager;
+use Interop\Container\ContainerInterface;
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\NotFoundExceptionInterface;
+use UnicaenValidation\Service\ValidationType\ValidationTypeService;
+
+class ValidationInstanceServiceFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return ValidationInstanceService
+     * @throws ContainerExceptionInterface
+     * @throws NotFoundExceptionInterface
+     */
+    public function __invoke(ContainerInterface $container) : ValidationInstanceService
+    {
+        /**
+         * @var EntityManager $entityManager
+         * @var ValidationTypeService $validationTypeService
+         */
+        $entityManager = $container->get('doctrine.entitymanager.orm_default');
+        $validationTypeService = $container->get(ValidationTypeService::class);
+
+        $service = new ValidationInstanceService();
+        $service->setEntityManager($entityManager);
+        $service->setValidationTypeService($validationTypeService);
+        return $service;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Service/ValidationType/ValidationTypeService.php b/src/UnicaenValidation/Service/ValidationType/ValidationTypeService.php
new file mode 100644
index 0000000..ec28ac3
--- /dev/null
+++ b/src/UnicaenValidation/Service/ValidationType/ValidationTypeService.php
@@ -0,0 +1,158 @@
+<?php
+
+namespace UnicaenValidation\Service\ValidationType;
+
+use Doctrine\ORM\NonUniqueResultException;
+use Doctrine\ORM\ORMException;
+use Doctrine\ORM\QueryBuilder;
+use Laminas\Mvc\Controller\AbstractActionController;
+use UnicaenApp\Exception\RuntimeException;
+use UnicaenApp\Service\EntityManagerAwareTrait;
+use UnicaenUtilisateur\Service\User\UserServiceAwareTrait;
+use UnicaenValidation\Entity\Db\ValidationType;
+
+class ValidationTypeService {
+    use EntityManagerAwareTrait;
+    use UserServiceAwareTrait;
+
+    /** GESTION DES ENTITES *******************************************************************************************/
+
+    /**
+     * @param ValidationType $type
+     * @return ValidationType
+     */
+    public function create(ValidationType $type) : ValidationType
+    {
+        try {
+            $this->getEntityManager()->persist($type);
+            $this->getEntityManager()->flush($type);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Un problème est survenue lors de l'enregistrement en BD.",0,$e);
+        }
+
+        return $type;
+    }
+
+    /**
+     * @param ValidationType $type
+     * @return ValidationType
+     */
+    public function update(ValidationType $type) : ValidationType
+    {
+        try {
+            $this->getEntityManager()->flush($type);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Un problème est survenue lors de l'enregistrement en BD.",0,$e);
+        }
+
+        return $type;
+    }
+
+    /**
+     * @param ValidationType $type
+     * @return ValidationType
+     */
+    public function delete(ValidationType $type) : ValidationType
+    {
+        try {
+            $this->getEntityManager()->remove($type);
+            $this->getEntityManager()->flush($type);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Un problème est survenue lors de l'enregistrement en BD.",0,$e);
+        }
+
+        return $type;
+    }
+
+    /** REQUETAGE *****************************************************************************************************/
+
+    /**
+     * @return QueryBuilder
+     */
+    public function createQueryBuilder() : QueryBuilder
+    {
+        $qb = $this->getEntityManager()->getRepository(ValidationType::class)->createQueryBuilder('vtype')
+            ;
+
+        return $qb;
+    }
+
+    /**
+     * @param string $champ
+     * @param string $ordre
+     * @return ValidationType[]
+     */
+    public function getValidationsTypes(string $champ = "libelle", string $ordre = "ASC") : array
+    {
+        $qb = $this->createQueryBuilder()
+            ->orderBy('vtype.' . $champ, $ordre)
+        ;
+
+        $result = $qb->getQuery()->getResult();
+        return $result;
+    }
+
+    /**
+     * @param string $champ
+     * @param string $ordre
+     * @return array
+     */
+    public function getValidationsTypesAsOptions(string $champ = "libelle", string $ordre = "ASC") : array
+    {
+        $result = $this->getValidationsTypes($champ, $ordre);
+        $array = [];
+        foreach ($result as $item) $array[$item->getId()] = $item->getCode();
+        return $array;
+    }
+
+    /**
+     * @param int|null $id
+     * @return ValidationType|null
+     */
+    public function getValidationType(?int $id) : ?ValidationType
+    {
+        $qb = $this->createQueryBuilder()
+            ->andWhere('vtype.id = :id')
+            ->setParameter('id', $id)
+        ;
+
+        try {
+            $result = $qb->getQuery()->getOneOrNullResult();
+        } catch (NonUniqueResultException $e) {
+            throw new RuntimeException("Plusieurs ValidationType partagent le même id [".$id."]", 0, $e);
+        }
+
+        return $result;
+    }
+
+    /**
+     * @param AbstractActionController $controller
+     * @param string $param
+     * @return ValidationType|null
+     */
+    public function getRequestedValidationType(AbstractActionController $controller, string $param='type') : ?ValidationType
+    {
+        $id = $controller->params()->fromRoute($param);
+        $result = $this->getValidationType($id);
+        return $result;
+    }
+
+    /**
+     * @param string $code
+     * @return ValidationType|null
+     */
+    public function getValidationTypeByCode(string $code) : ?ValidationType
+    {
+        $qb = $this->createQueryBuilder()
+            ->andWhere('vtype.code = :code')
+            ->setParameter('code', $code)
+        ;
+
+        try {
+            $result = $qb->getQuery()->getOneOrNullResult();
+        } catch (NonUniqueResultException $e) {
+            throw new RuntimeException("Plusieurs ValidationType partagent le même code [".$code."]", 0, $e);
+        }
+        return $result;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Service/ValidationType/ValidationTypeServiceAwareTrait.php b/src/UnicaenValidation/Service/ValidationType/ValidationTypeServiceAwareTrait.php
new file mode 100644
index 0000000..cb39160
--- /dev/null
+++ b/src/UnicaenValidation/Service/ValidationType/ValidationTypeServiceAwareTrait.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace UnicaenValidation\Service\ValidationType;
+
+trait ValidationTypeServiceAwareTrait {
+
+    private ValidationTypeService $validationTypeService;
+
+    /**
+     * @return ValidationTypeService
+     */
+    public function getValidationTypeService() : ValidationTypeService
+    {
+        return $this->validationTypeService;
+    }
+
+    /**
+     * @param ValidationTypeService $validationTypeService
+     */
+    public function setValidationTypeService(ValidationTypeService $validationTypeService) : void
+    {
+        $this->validationTypeService = $validationTypeService;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/Service/ValidationType/ValidationTypeServiceFactory.php b/src/UnicaenValidation/Service/ValidationType/ValidationTypeServiceFactory.php
new file mode 100644
index 0000000..ec92356
--- /dev/null
+++ b/src/UnicaenValidation/Service/ValidationType/ValidationTypeServiceFactory.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace UnicaenValidation\Service\ValidationType;
+
+use Doctrine\ORM\EntityManager;
+use Interop\Container\ContainerInterface;
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\NotFoundExceptionInterface;
+use UnicaenUtilisateur\Service\User\UserService;
+
+class ValidationTypeServiceFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return ValidationTypeService
+     * @throws ContainerExceptionInterface
+     * @throws NotFoundExceptionInterface
+     */
+    public function __invoke(ContainerInterface $container) : ValidationTypeService
+    {
+        /**
+         * @var EntityManager $entityManager
+         * @var UserService $userService
+         */
+        $entityManager = $container->get('doctrine.entitymanager.orm_default');
+        $userService = $container->get(UserService::class);
+
+        $service = new ValidationTypeService();
+        $service->setEntityManager($entityManager);
+        $service->setUserService($userService);
+        return $service;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/View/Helper/ValidationAfficherViewHelper.php b/src/UnicaenValidation/View/Helper/ValidationAfficherViewHelper.php
new file mode 100644
index 0000000..1c0ab3d
--- /dev/null
+++ b/src/UnicaenValidation/View/Helper/ValidationAfficherViewHelper.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace UnicaenValidation\View\Helper;
+
+use UnicaenValidation\Entity\Db\ValidationInstance;
+use Laminas\View\Helper\AbstractHelper;
+use Laminas\View\Helper\Partial;
+use Laminas\View\Renderer\PhpRenderer;
+use Laminas\View\Resolver\TemplatePathStack;
+
+class ValidationAfficherViewHelper extends AbstractHelper
+{
+    /**
+     * @param ValidationInstance $validation
+     * @param array $options
+     * @return string|Partial
+     */
+    public function __invoke(ValidationInstance $validation, array $options = [])
+    {
+        /** @var PhpRenderer $view */
+        $view = $this->getView();
+        $view->resolver()->attach(new TemplatePathStack(['script_paths' => [__DIR__ . "/partial"]]));
+
+        return $view->partial('validation-afficher', ['instance' => $validation]);
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/View/Helper/ValidationBadgeViewHelper.php b/src/UnicaenValidation/View/Helper/ValidationBadgeViewHelper.php
new file mode 100644
index 0000000..6c56a5c
--- /dev/null
+++ b/src/UnicaenValidation/View/Helper/ValidationBadgeViewHelper.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace UnicaenValidation\View\Helper;
+
+use UnicaenValidation\Entity\Db\ValidationInstance;
+use Laminas\View\Helper\AbstractHelper;
+use Laminas\View\Helper\Partial;
+use Laminas\View\Renderer\PhpRenderer;
+use Laminas\View\Resolver\TemplatePathStack;
+
+class ValidationBadgeViewHelper extends AbstractHelper
+{
+    /**
+     * @param ValidationInstance|null $validation
+     * @param array $options
+     * @return string|Partial
+     */
+    public function __invoke(?ValidationInstance $validation, array $options = [])
+    {
+        /** @var PhpRenderer $view */
+        $view = $this->getView();
+        $view->resolver()->attach(new TemplatePathStack(['script_paths' => [__DIR__ . "/partial"]]));
+
+        return $view->partial('validation-badge', ['validation' => $validation, 'options' => $options]);
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/View/Helper/ValidationValiderViewHelper.php b/src/UnicaenValidation/View/Helper/ValidationValiderViewHelper.php
new file mode 100644
index 0000000..ab90eeb
--- /dev/null
+++ b/src/UnicaenValidation/View/Helper/ValidationValiderViewHelper.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace UnicaenValidation\View\Helper;
+
+use UnicaenValidation\Service\ValidationType\ValidationTypeServiceAwareTrait;
+use Laminas\View\Helper\AbstractHelper;
+use Laminas\View\Helper\Partial;
+use Laminas\View\Renderer\PhpRenderer;
+use Laminas\View\Resolver\TemplatePathStack;
+
+class ValidationValiderViewHelper extends AbstractHelper
+{
+    use ValidationTypeServiceAwareTrait;
+    /**
+     * @param string $validationTypeCode
+     * @param array $options
+     * @return string|Partial
+     */
+    public function __invoke(string $validationTypeCode, array $options = [])
+    {
+        $type = $this->getValidationTypeService()->getValidationTypeByCode($validationTypeCode);
+
+        /** @var PhpRenderer $view */
+        $view = $this->getView();
+        $view->resolver()->attach(new TemplatePathStack(['script_paths' => [__DIR__ . "/partial"]]));
+
+        return $view->partial('validation-valider', ['type' => $type, 'options' => $options]);
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/View/Helper/ValidationValiderViewHelperFactory.php b/src/UnicaenValidation/View/Helper/ValidationValiderViewHelperFactory.php
new file mode 100644
index 0000000..d4765eb
--- /dev/null
+++ b/src/UnicaenValidation/View/Helper/ValidationValiderViewHelperFactory.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace UnicaenValidation\View\Helper;
+
+use Interop\Container\ContainerInterface;
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\NotFoundExceptionInterface;
+use UnicaenValidation\Service\ValidationType\ValidationTypeService;
+
+class ValidationValiderViewHelperFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return ValidationValiderViewHelper
+     * @throws ContainerExceptionInterface
+     * @throws NotFoundExceptionInterface
+     */
+    public function __invoke(ContainerInterface $container) : ValidationValiderViewHelper
+    {
+        /** @var ValidationTypeService $validationTypeService */
+        $validationTypeService = $container->get(ValidationTypeService::class);
+
+        $helper = new ValidationValiderViewHelper();
+        $helper->setValidationTypeService($validationTypeService);
+        return $helper;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenValidation/View/Helper/partial/validation-afficher.phtml b/src/UnicaenValidation/View/Helper/partial/validation-afficher.phtml
new file mode 100644
index 0000000..fc3f456
--- /dev/null
+++ b/src/UnicaenValidation/View/Helper/partial/validation-afficher.phtml
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @var ValidationInstance $instance
+ * @var array $options
+ */
+
+use UnicaenValidation\Entity\Db\ValidationInstance;
+
+$type = $instance->getType();
+
+?>
+
+<div class="validation validation-affichage <?php echo ($instance->getValeur() === null)?"validation-valider":"validation-refuser" ?>">
+        <?php if ($instance->getValeur() !== null) : ?>
+            Refusé
+        <?php else : ?>
+            Validé
+        <?php endif; ?>
+        le  <?php echo $instance->getHistoModification()->format('d/m/Y à H:i:s'); ?>
+        par <?php echo $instance->getHistoModificateur()->getDisplayName(); ?>.
+</div>
diff --git a/src/UnicaenValidation/View/Helper/partial/validation-badge.phtml b/src/UnicaenValidation/View/Helper/partial/validation-badge.phtml
new file mode 100644
index 0000000..cd3a3a5
--- /dev/null
+++ b/src/UnicaenValidation/View/Helper/partial/validation-badge.phtml
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @see \UnicaenValidation\View\Helper\ValidationBadgeViewHelper
+ * @var ValidationInstance $validation
+ * @var array $options
+ */
+
+use UnicaenValidation\Entity\Db\ValidationInstance;
+
+$texte = (isset($options['texte']) AND $options['texte'] === true);
+?>
+
+<?php if ($validation !== null) : ?>
+    <?php if ($validation->getValeur() === null) : ?>
+        <span class="icon ok" style="color: darkgreen;"
+              data-toggle="tooltip" data-html="true"
+              title="Validé le <span class='highlight date'> <?php echo $validation->getHistoCreation()->format('d/m/Y'); ?> </span> par <span class='highlight agent'> <?php echo $validation->getHistoCreateur()->getDisplayName(); ?>">
+            <?php echo ($texte)?"Validée":""; ?>
+        </span>
+    <?php else : ?>
+        <span class="icon ko" style="color: darkred;"
+              data-toggle="tooltip" data-html="true"
+              title="Validé le <span class='highlight date'> <?php echo $validation->getHistoCreation()->format('d/m/Y'); ?> </span> par <span class='highlight agent'> <?php echo $validation->getHistoCreateur()->getDisplayName(); ?>">
+            <?php echo ($texte)?"Refusée":""; ?>
+        </span>
+    <?php endif; ?>
+<?php else : ?>
+    <span style="color:#123456;"><span class="icon aucune"></span> &nbsp;<?php echo ($texte)?"Aucune":""; ?></span>
+<?php endif; ?>
diff --git a/src/UnicaenValidation/View/Helper/partial/validation-valider.phtml b/src/UnicaenValidation/View/Helper/partial/validation-valider.phtml
new file mode 100644
index 0000000..007795f
--- /dev/null
+++ b/src/UnicaenValidation/View/Helper/partial/validation-valider.phtml
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @var \UnicaenValidation\Entity\Db\ValidationType $type
+ * @var array $options
+ */
+
+$displayType    = (isset($options["display-type"]) AND $options["display-type"] === true);
+$retour         = $options["retour"] ?? $this->url(null, [], [], true);
+
+
+?>
+
+<div class="validation validation-validation">
+
+    <?php if($displayType) : ?>
+        <dl class="dl-horizontal">
+            <dt> Validation :</dt>
+            <dd> <?php echo $type->getLibelle(); ?> </dd>
+        </dl>
+    <?php endif; ?>
+
+        <a
+            <?php /** @see \UnicaenValidation\Controller\ValidationInstanceController::validerAction() */ ?>
+            href="<?php echo $this->url('validation/instance/valider', ['type' => $type->getId()], ["query" => ["retour" => $retour]]); ?>"
+            class="btn btn-success action"
+        >
+            <span class="icon ok"></span> Valider
+        </a>
+        <?php if ($type->isRefusable()) : ?>
+            <a
+                <?php /** @see \UnicaenValidation\Controller\ValidationInstanceController::refuserAction() */ ?>
+                href="<?php echo $this->url('validation/instance/refuser', ['type' => $type->getId()], ["query" => ["retour" => $retour]]); ?>"
+                class="btn btn-danger action"
+            >
+                <span class="icon ko"></span> Refuser
+            </a>
+        <?php endif; ?>
+</div>
diff --git a/view/unicaen-validation/default/confirmation.phtml b/view/unicaen-validation/default/confirmation.phtml
new file mode 100644
index 0000000..f2e8bdf
--- /dev/null
+++ b/view/unicaen-validation/default/confirmation.phtml
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @var string $title
+ * @var string $text
+ * @var string $action
+ */
+
+?>
+
+<p class="lead">
+<?php echo $text; ?>
+</p>
+
+<table>
+    <tr><td>
+<form method="post" action="<?php echo $action; ?>">
+    <input type="hidden" name="reponse" value="oui">
+    <input type="submit" name="oui" class="btn btn-success action" value="Oui, je suis sûr&middot;e">
+</form>
+        </td><td>
+<form method="post" action="<?php echo $action; ?>">
+    <input type="hidden" name="reponse" value="non">
+    <input type="submit" id="non" name="non" class="btn btn-danger action"  value="Non, je ne veux pas">
+</form>
+        </td></tr>
+</table>
+
+<script>
+    $(function() {
+        $("input#non").click(function(e){
+            $('div.modal').modal('hide');
+            e.preventDefault(e);
+        });
+    });
+</script>
+
diff --git a/view/unicaen-validation/default/default-form.phtml b/view/unicaen-validation/default/default-form.phtml
new file mode 100644
index 0000000..850f1cd
--- /dev/null
+++ b/view/unicaen-validation/default/default-form.phtml
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @var Form $form
+ */
+
+use Laminas\Form\Form;
+
+?>
+
+<?php echo $this->form($form); ?>
+
+<script>
+    $(document).ready(function() {
+        // tinymce.remove();
+        tinymce.init({
+            selector: '.type2',
+            toolbar: 'newdocument undo redo | bold italic underline | bullist',
+            resize: true,
+            language: 'fr_FR',
+            plugins: 'lists',
+            statusbar: true,
+            browser_spellcheck : true,
+            branding: false,
+            menu: {},
+            body_id: 'description',
+            setup: function (editor) {
+                editor.on("focusout", function () {
+                    console.log(tinymce.get('description').getContent());
+                    $('textarea').val(tinymce.get('description').getContent());
+                });
+            }
+        });
+    });
+
+    $('select').selectpicker();
+</script>
+
+<style>
+    .form-control {
+        height:auto;
+    }
+</style>
\ No newline at end of file
diff --git a/view/unicaen-validation/validation-instance/index.phtml b/view/unicaen-validation/validation-instance/index.phtml
new file mode 100644
index 0000000..4b1c9df
--- /dev/null
+++ b/view/unicaen-validation/validation-instance/index.phtml
@@ -0,0 +1,121 @@
+<?php
+
+/**
+ * @see \UnicaenValidation\Controller\ValidationInstanceController::indexAction()
+ * @var ValidationInstance[] $instances
+ */
+
+use UnicaenValidation\Entity\Db\ValidationInstance;
+use UnicaenValidation\Provider\Privilege\ValidationinstancePrivileges;
+use UnicaenValidation\Provider\Privilege\ValidationtypePrivileges;
+
+$this->headTitle("Index des instances de validation");
+
+$canAfficher = $this->isAllowed(ValidationinstancePrivileges::getResourceId(ValidationinstancePrivileges::VALIDATIONINSTANCE_AFFICHER));
+$canAjouter = $this->isAllowed(ValidationinstancePrivileges::getResourceId(ValidationinstancePrivileges::VALIDATIONINSTANCE_MODIFIER));
+$canModifier = $this->isAllowed(ValidationinstancePrivileges::getResourceId(ValidationinstancePrivileges::VALIDATIONINSTANCE_MODIFIER));
+$canHistoriser = $this->isAllowed(ValidationinstancePrivileges::getResourceId(ValidationinstancePrivileges::VALIDATIONINSTANCE_HISTORISER));
+$canDetruire = $this->isAllowed(ValidationinstancePrivileges::getResourceId(ValidationinstancePrivileges::VALIDATIONINSTANCE_DETRUIRE));
+
+$canAfficherType = $this->isAllowed(ValidationTypePrivileges::getResourceId(ValidationTypePrivileges::VALIDATIONTYPE_AFFICHER));
+
+?>
+
+<div class="row">
+    <div class="col-md-6">
+        <h1 class="page-header">
+            Instances de validation
+        </h1>
+    </div>
+    <div class="pull-right">
+        <?php if ($canAfficherType) : ?>
+            <a href="<?php echo $this->url('validation/type', [], [], true); ?>" class="btn btn-primary action">
+                <span class="icon acceder"></span>
+                Types de validation
+            </a>
+        <?php endif; ?>
+    </div>
+</div>
+
+<span class="todo"> Faire un filtre </span>
+<div class="main">
+
+    <?php if ($canAjouter): ?>
+        <a
+            <?php /** @see \UnicaenValidation\Controller\ValidationInstanceController::ajouterAction() */ ?>
+            href="<?php echo $this->url('validation/instance/ajouter', [], [], true); ?>"
+            class="btn btn-primary action ajax-modal"
+            data-event="modification"
+        >
+            <span class="icon ajouter"> Ajouter une instance</span>
+        </a>
+    <?php endif; ?>
+
+    <table class="table table-condensed">
+        <thead>
+        <tr>
+            <th> Type </th>
+            <th> Refus </th>
+            <th> Date </th>
+            <th> Utilisateur </th>
+            <th> Action </th>
+        </tr>
+        </thead>
+        <tbody>
+        <?php /** @var ValidationInstance $instance */ ?>
+        <?php foreach ($instances as $instance) : ?>
+            <tr>
+                <td> <?php echo $instance->getType()->getCode(); ?> </td>
+                <td> <?php echo $instance->getValeur(); ?> </td>
+                <td> <?php echo $instance->getHistoModification()->format('d/m/Y à H:i:s'); ?> </td>
+                <td> <?php echo $instance->getHistoModificateur()->getDisplayName(); ?> </td>
+                <td>
+                    <?php if ($canModifier): ?>
+                        <a
+                            <?php /** @see \UnicaenValidation\Controller\ValidationInstanceController::modifierAction() */?>
+                            href="<?php echo $this->url('validation/instance/modifier', ['validation' => $instance->getId()], [], true); ?>"
+                            class="ajax-modal" data-event="modification"
+                        >
+                            <span class="icon editer" title="Modifier l'instance de validation"></a>
+                    <?php endif; ?>
+
+                    <?php if ($canHistoriser): ?>
+                        <?php if ($instance->estNonHistorise()) :?>
+                            <a
+                                <?php /** @see \UnicaenValidation\Controller\ValidationInstanceController::modifierAction() */?>
+                                href="<?php echo $this->url('validation/instance/historiser', ['validation' => $instance->getId()], [], true); ?>"
+                            >
+                                <span class="icon historiser" title="Historiser l'instance de validation"></a>
+                        <?php else : ?>
+
+                            <a
+                                <?php /** @see \UnicaenValidation\Controller\ValidationInstanceController::modifierAction() */?>
+                                href="<?php echo $this->url('validation/instance/restaurer', ['validation' => $instance->getId()], [], true); ?>"
+                            >
+                                <span class="icon restaurer" title="Restaurer l'instance de validation"></a>
+                        <?php endif; ?>
+                    <?php endif; ?>
+
+                    <?php if ($canDetruire): ?>
+                        <a
+                            <?php /** @see \UnicaenValidation\Controller\ValidationInstanceController::detruireAction() */?>
+                            href="<?php echo $this->url('validation/instance/detruire', ['validation' => $instance->getId()], [], true); ?>"
+                            class="ajax-modal" data-event="modification"
+                        >
+                            <span class="icon detruire" title="Supprimer définitivement l'instance de validation"></a>
+                    <?php endif; ?>
+                </td>
+            </tr>
+        <?php endforeach; ?>
+        </tbody>
+    </table>
+</div>
+
+<script>
+    $(function() {
+        $("body").on("modification", function (event) {
+            event.div.modal('hide');
+            window.location.reload();
+        });
+    });
+</script>
\ No newline at end of file
diff --git a/view/unicaen-validation/validation-instance/validation-modal.phtml b/view/unicaen-validation/validation-instance/validation-modal.phtml
new file mode 100644
index 0000000..d13b9b2
--- /dev/null
+++ b/view/unicaen-validation/validation-instance/validation-modal.phtml
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @var string $title
+ * @var string $text
+ * @var string $action
+ * @var boolean $refus
+ */
+
+$refusable = ($refus === null OR $refus === true)
+?>
+
+<p class="lead">
+    <?php echo $text; ?>
+</p>
+
+<table>
+    <tr><td>
+            <form method="post" action="<?php echo $action; ?>">
+                <input type="hidden" name="reponse" value="oui">
+                <input type="submit" name="oui" class="btn btn-success action" value="Valider">
+            </form>
+        </td>
+        <?php if ($refusable) : ?>
+            <td>
+                <form method="post" action="<?php echo $action; ?>">
+                    <input type="hidden" name="reponse" value="non">
+                    <input type="submit" name="non" class="btn btn-danger action"  value="Refuser">
+                </form>
+            </td>
+        <?php endif; ?>
+    </tr>
+</table>
+
+<script>
+    $(function() {
+        $("input#non").click(function(e){
+            $('div.modal').modal('hide');
+            e.preventDefault(e);
+        });
+    });
+</script>
+
diff --git a/view/unicaen-validation/validation-type/index.phtml b/view/unicaen-validation/validation-type/index.phtml
new file mode 100644
index 0000000..f5eb631
--- /dev/null
+++ b/view/unicaen-validation/validation-type/index.phtml
@@ -0,0 +1,113 @@
+<?php
+
+/**
+ * @see \UnicaenValidation\Controller\ValidationTypeController::indexAction()
+ * @var ValidationType[] $types;
+ */
+
+use UnicaenValidation\Entity\Db\ValidationType;
+use UnicaenValidation\Provider\Privilege\ValidationinstancePrivileges;
+use UnicaenValidation\Provider\Privilege\ValidationtypePrivileges;
+
+$this->headTitle("Index des types de validation");
+
+$canAfficher = $this->isAllowed(ValidationtypePrivileges::getResourceId(ValidationtypePrivileges::VALIDATIONTYPE_AFFICHER));
+$canAjouter = $this->isAllowed(ValidationtypePrivileges::getResourceId(ValidationtypePrivileges::VALIDATIONTYPE_MODIFIER));
+$canModifier = $this->isAllowed(ValidationtypePrivileges::getResourceId(ValidationtypePrivileges::VALIDATIONTYPE_MODIFIER));
+$canDetruire = $this->isAllowed(ValidationtypePrivileges::getResourceId(ValidationtypePrivileges::VALIDATIONTYPE_DETRUIRE));
+
+$canAfficherInstance = $this->isAllowed(ValidationInstancePrivileges::getResourceId(ValidationInstancePrivileges::VALIDATIONINSTANCE_AFFICHER));
+?>
+
+<div class="row">
+    <div class="col-md-6">
+        <h1 class="page-header">
+            Index des types de validations
+        </h1>
+    </div>
+    <div class="pull-right">
+        <?php if ($canAfficherInstance) : ?>
+            <a href="<?php echo $this->url('validation/instance', [], [], true); ?>" class="btn btn-primary action">
+                <span class="icon acceder"></span>
+                Instances de validation
+            </a>
+        <?php endif; ?>
+    </div>
+</div>
+
+<div class="main">
+
+    <div>
+    <?php if ($canAjouter): ?>
+        <a
+            <?php /** @see \UnicaenValidation\Controller\ValidationTypeController::ajouterAction() */ ?>
+            href="<?php echo $this->url('validation/type/ajouter', [], [], true); ?>"
+            class="btn btn-primary action ajax-modal"
+            data-event="modification"
+        >
+            <span class="icon ajouter"> Ajouter un type</span>
+        </a>
+    <?php endif; ?>
+    </div>
+
+    <div>
+        <?php if (empty($types)) : ?>
+            <em>Aucun type de validation</em>
+    <?php else : ?>
+        <table class="table table-condensed table-hover">
+        <thead>
+            <tr>
+                <th> Code </th>
+                <th> Libelle </th>
+                <th> Est refusable </th>
+                <th> Action </th>
+            </tr>
+        </thead>
+        <tbody>
+            <?php /** @var ValidationType $type */ ?>
+            <?php foreach ($types as $type) : ?>
+                <tr>
+                    <td> <?php echo $type->getCode(); ?> </td>
+                    <td> <?php echo $type->getLibelle(); ?> </td>
+                    <td>
+                        <?php if ($type->isRefusable()) : ?>
+                            <span class="icon ok" style="color:darkgreen;"></span>
+                        <?php else : ?>
+                            <span class="icon ko" style="color:darkred;"></span>
+                        <?php endif; ?>
+                    </td>
+                    <td>
+                        <?php if ($canModifier): ?>
+                            <a
+                                <?php /** @see \UnicaenValidation\Controller\ValidationTypeController::modifierAction() */?>
+                                href="<?php echo $this->url('validation/type/modifier', ['type' => $type->getId()], [], true); ?>"
+                                class="ajax-modal" data-event="modification"
+                            >
+                                <span class="icon editer" title="Modifier le type de validation"></a>
+                        <?php endif; ?>
+
+                        <?php if ($canDetruire): ?>
+                            <a
+                                <?php /** @see \UnicaenValidation\Controller\ValidationTypeController::detruireAction() */?>
+                                href="<?php echo $this->url('validation/type/detruire', ['type' => $type->getId()], [], true); ?>"
+                                class="ajax-modal" data-event="modification"
+                            >
+                                <span class="icon detruire" title="Supprimer définitivement le type de validation"></a>
+                        <?php endif; ?>
+                    </td>
+                </tr>
+            <?php endforeach; ?>
+        </tbody>
+    </table>
+    <?php endif; ?>
+    </div>
+</div>
+
+<script>
+    $(function() {
+        $("body").on("modification", function (event) {
+            event.div.modal('hide');
+            window.location.reload();
+        });
+    });
+</script>
\ No newline at end of file
-- 
GitLab