From cfbe66f6fafc87e50a816d9e172bc9afe2fd3ea4 Mon Sep 17 00:00:00 2001
From: Jean-Philippe Metivier <jean-philippe.metivier@unicaen.fr>
Date: Thu, 10 Mar 2022 10:02:36 +0100
Subject: [PATCH] =?UTF-8?q?Recup=C3=A9ration=20initiale?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Module.php                                    |  56 ++++++
 composer.json                                 |  22 +++
 config/example.php                            |  36 ++++
 config/merged/categorie.config.php            | 167 ++++++++++++++++++
 config/merged/parametre.config.php            | 127 +++++++++++++
 config/module.config.php                      |  51 ++++++
 doc/database.sql                              |  62 +++++++
 readme.md                                     |  41 +++++
 .../Controller/CategorieController.php        | 103 +++++++++++
 .../Controller/CategorieControllerFactory.php |  32 ++++
 .../Controller/ParametreController.php        | 110 ++++++++++++
 .../Controller/ParametreControllerFactory.php |  36 ++++
 src/UnicaenParametre/Entity/Db/Categorie.php  | 101 +++++++++++
 ...icaenParametre.Entity.Db.Categorie.dcm.xml |  15 ++
 ...icaenParametre.Entity.Db.Parametre.dcm.xml |  21 +++
 src/UnicaenParametre/Entity/Db/Parametre.php  | 164 +++++++++++++++++
 .../Form/Categorie/CategorieForm.php          | 123 +++++++++++++
 .../Categorie/CategorieFormAwareTrait.php     |  27 +++
 .../Form/Categorie/CategorieFormFactory.php   |  28 +++
 .../Form/Categorie/CategorieHydrator.php      |  45 +++++
 .../Categorie/CategorieHydratorFactory.php    |  18 ++
 .../Form/Parametre/ParametreForm.php          | 150 ++++++++++++++++
 .../Parametre/ParametreFormAwareTrait.php     |  27 +++
 .../Form/Parametre/ParametreFormFactory.php   |  24 +++
 .../Form/Parametre/ParametreHydrator.php      |  48 +++++
 .../Parametre/ParametreHydratorFactory.php    |  18 ++
 .../Privilege/ParametrePrivileges.php         |  14 ++
 .../ParametrecategoriePrivileges.php          |  14 ++
 .../Service/Categorie/CategorieService.php    | 148 ++++++++++++++++
 .../Categorie/CategorieServiceAwareTrait.php  |  28 +++
 .../Categorie/CategorieServiceFactory.php     |  26 +++
 .../Service/Parametre/ParametreService.php    | 158 +++++++++++++++++
 .../Parametre/ParametreServiceAwareTrait.php  |  28 +++
 .../Parametre/ParametreServiceFactory.php     |  26 +++
 view/unicaen-parametre/categorie/index.phtml  | 156 ++++++++++++++++
 .../default/confirmation.phtml                |  37 ++++
 .../default/default-form.phtml                |  88 +++++++++
 view/unicaen-parametre/default/probleme.phtml |  15 ++
 view/unicaen-parametre/default/reponse.phtml  |   8 +
 .../parametre/modifier-valeur.phtml           |  50 ++++++
 40 files changed, 2448 insertions(+)
 create mode 100644 Module.php
 create mode 100644 composer.json
 create mode 100644 config/example.php
 create mode 100644 config/merged/categorie.config.php
 create mode 100644 config/merged/parametre.config.php
 create mode 100644 config/module.config.php
 create mode 100644 doc/database.sql
 create mode 100644 readme.md
 create mode 100644 src/UnicaenParametre/Controller/CategorieController.php
 create mode 100644 src/UnicaenParametre/Controller/CategorieControllerFactory.php
 create mode 100644 src/UnicaenParametre/Controller/ParametreController.php
 create mode 100644 src/UnicaenParametre/Controller/ParametreControllerFactory.php
 create mode 100644 src/UnicaenParametre/Entity/Db/Categorie.php
 create mode 100644 src/UnicaenParametre/Entity/Db/Mapping/UnicaenParametre.Entity.Db.Categorie.dcm.xml
 create mode 100644 src/UnicaenParametre/Entity/Db/Mapping/UnicaenParametre.Entity.Db.Parametre.dcm.xml
 create mode 100644 src/UnicaenParametre/Entity/Db/Parametre.php
 create mode 100644 src/UnicaenParametre/Form/Categorie/CategorieForm.php
 create mode 100644 src/UnicaenParametre/Form/Categorie/CategorieFormAwareTrait.php
 create mode 100644 src/UnicaenParametre/Form/Categorie/CategorieFormFactory.php
 create mode 100644 src/UnicaenParametre/Form/Categorie/CategorieHydrator.php
 create mode 100644 src/UnicaenParametre/Form/Categorie/CategorieHydratorFactory.php
 create mode 100644 src/UnicaenParametre/Form/Parametre/ParametreForm.php
 create mode 100644 src/UnicaenParametre/Form/Parametre/ParametreFormAwareTrait.php
 create mode 100644 src/UnicaenParametre/Form/Parametre/ParametreFormFactory.php
 create mode 100644 src/UnicaenParametre/Form/Parametre/ParametreHydrator.php
 create mode 100644 src/UnicaenParametre/Form/Parametre/ParametreHydratorFactory.php
 create mode 100644 src/UnicaenParametre/Provider/Privilege/ParametrePrivileges.php
 create mode 100644 src/UnicaenParametre/Provider/Privilege/ParametrecategoriePrivileges.php
 create mode 100644 src/UnicaenParametre/Service/Categorie/CategorieService.php
 create mode 100644 src/UnicaenParametre/Service/Categorie/CategorieServiceAwareTrait.php
 create mode 100644 src/UnicaenParametre/Service/Categorie/CategorieServiceFactory.php
 create mode 100644 src/UnicaenParametre/Service/Parametre/ParametreService.php
 create mode 100644 src/UnicaenParametre/Service/Parametre/ParametreServiceAwareTrait.php
 create mode 100644 src/UnicaenParametre/Service/Parametre/ParametreServiceFactory.php
 create mode 100644 view/unicaen-parametre/categorie/index.phtml
 create mode 100644 view/unicaen-parametre/default/confirmation.phtml
 create mode 100644 view/unicaen-parametre/default/default-form.phtml
 create mode 100644 view/unicaen-parametre/default/probleme.phtml
 create mode 100644 view/unicaen-parametre/default/reponse.phtml
 create mode 100644 view/unicaen-parametre/parametre/modifier-valeur.phtml

diff --git a/Module.php b/Module.php
new file mode 100644
index 000000000..528e34f56
--- /dev/null
+++ b/Module.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace UnicaenParametre;
+
+use Zend\Mvc\ModuleRouteListener;
+use Zend\Mvc\MvcEvent;
+use Zend\Stdlib\ArrayUtils;
+use Zend\Stdlib\Glob;
+use Zend\Config\Factory as ConfigFactory;
+
+class Module
+{
+    public function onBootstrap(MvcEvent $e)
+    {
+        $e->getApplication()->getServiceManager()->get('translator');
+        $eventManager = $e->getApplication()->getEventManager();
+        $moduleRouteListener = new ModuleRouteListener();
+        $moduleRouteListener->attach($eventManager);
+
+        /* Active un layout spécial si la requête est de type AJAX. Valable pour TOUS les modules de l'application. */
+        $eventManager->getSharedManager()->attach('Zend\Mvc\Controller\AbstractActionController', 'dispatch',
+            function (MvcEvent $e) {
+                $request = $e->getRequest();
+                if ($request instanceof HttpRequest && $request->isXmlHttpRequest()) {
+                    $e->getTarget()->layout('layout/ajax.phtml');
+                }
+            }
+        );
+
+    }
+
+    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(
+            'Zend\Loader\StandardAutoloader' => array(
+                'namespaces' => array(
+                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
+                ),
+            ),
+        );
+    }
+}
diff --git a/composer.json b/composer.json
new file mode 100644
index 000000000..18675e2d2
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,22 @@
+{
+  "name": "unicaen/parametre",
+  "description": "Module de gestion des paramètres",
+  "repositories": [
+    {
+      "type": "composer",
+      "url": "https://gest.unicaen.fr/packagist"
+    }
+  ],
+  "require": {
+    "unicaen/app":                                  "^3.x",
+    "unicaen/utilisateur":                          "dev-zf-3.x",
+    "unicaen/privilege":                            "dev-zf-3.x"
+  },
+  "autoload": {
+    "psr-0": {
+    },
+    "classmap": [
+      "./Module.php"
+    ]
+  }
+}
diff --git a/config/example.php b/config/example.php
new file mode 100644
index 000000000..e950d6c7b
--- /dev/null
+++ b/config/example.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace UnicaenParametre;
+
+use UnicaenPrivilege\Guard\PrivilegeController;
+use Zend\Router\Http\Literal;
+use Zend\Router\Http\Segment;
+
+return [
+    'bjyauthorize' => [
+        'guards' => [
+            PrivilegeController::class => [
+
+            ],
+        ],
+    ],
+
+    'router'          => [
+        'routes' => [
+        ],
+    ],
+
+    'service_manager' => [
+        'factories' => [],
+    ],
+    'controllers'     => [
+        'factories' => [],
+    ],
+    'form_elements' => [
+        'factories' => [],
+    ],
+    'hydrators' => [
+        'factories' => [],
+    ]
+
+];
\ No newline at end of file
diff --git a/config/merged/categorie.config.php b/config/merged/categorie.config.php
new file mode 100644
index 000000000..b4aacbcd9
--- /dev/null
+++ b/config/merged/categorie.config.php
@@ -0,0 +1,167 @@
+<?php
+
+namespace UnicaenParametre;
+
+use UnicaenParametre\Controller\CategorieController;
+use UnicaenParametre\Controller\CategorieControllerFactory;
+use UnicaenParametre\Form\Categorie\CategorieForm;
+use UnicaenParametre\Form\Categorie\CategorieFormFactory;
+use UnicaenParametre\Form\Categorie\CategorieHydrator;
+use UnicaenParametre\Form\Categorie\CategorieHydratorFactory;
+use UnicaenParametre\Provider\Privilege\ParametrecategoriePrivileges;
+use UnicaenParametre\Service\Categorie\CategorieService;
+use UnicaenParametre\Service\Categorie\CategorieServiceFactory;
+use UnicaenPrivilege\Guard\PrivilegeController;
+use Zend\Router\Http\Literal;
+use Zend\Router\Http\Segment;
+
+return [
+    'bjyauthorize' => [
+        'guards' => [
+            PrivilegeController::class => [
+                [
+                    'controller' => CategorieController::class,
+                    'action' => [
+                        'index',
+                    ],
+                    'pivileges' => ParametrecategoriePrivileges::PARAMETRECATEGORIE_INDEX,
+                ],
+                [
+                    'controller' => CategorieController::class,
+                    'action' => [
+                        'ajouter',
+                    ],
+                    'pivileges' => ParametrecategoriePrivileges::PARAMETRECATEGORIE_AJOUTER,
+                ],
+                [
+                    'controller' => CategorieController::class,
+                    'action' => [
+                        'modifier',
+                    ],
+                    'pivileges' => ParametrecategoriePrivileges::PARAMETRECATEGORIE_MODIFIER,
+                ],
+                [
+                    'controller' => CategorieController::class,
+                    'action' => [
+                        'supprimer',
+                    ],
+                    'pivileges' => ParametrecategoriePrivileges::PARAMETRECATEGORIE_SUPPRIMER,
+                ],
+            ],
+        ],
+    ],
+
+    'navigation'      => [
+        'default' => [
+            'home' => [
+                'pages' => [
+                    'administration' => [
+                        'pages' => [
+                            'parametre' => [
+                                'label'    => 'Paramètres',
+                                'route'    => 'parametre/index',
+        //                            'resource' => PrivilegeController::getResourceId(CategorieController::class, 'index'),
+                                'resource' => ParametrecategoriePrivileges::getResourceId(ParametrecategoriePrivileges::PARAMETRECATEGORIE_INDEX),
+                                'order'    => 7020,
+                                'pages' => [],
+                                'icon' => 'fas fa-angle-right',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ],
+    ],
+
+    'router'          => [
+        'routes' => [
+            'parametre' => [
+                'type'  => Literal::class,
+                'options' => [
+                    'route'    => '/parametre',
+                    'defaults' => [
+                        'controller' => CategorieController::class,
+                    ],
+                ],
+                'may_terminate' => false,
+                'child_routes' => [
+                    'index' => [
+                        'type'  => Segment::class,
+                        'options' => [
+                            'route'    => '/index[/:categorie]',
+                            'defaults' => [
+                                'controller' => CategorieController::class,
+                                'action' => 'index'
+                            ],
+                        ],
+                        'may_terminate' => true,
+                    ],
+                    'categorie' => [
+                        'type'  => Segment::class,
+                        'options' => [
+                            'route'    => '/categorie',
+                            'defaults' => [
+                                'controller' => CategorieController::class,
+                            ],
+                        ],
+                        'may_terminate' => false,
+                        'child_routes' => [
+                            'ajouter' => [
+                                'type'  => Literal::class,
+                                'options' => [
+                                    'route'    => '/ajouter',
+                                    'defaults' => [
+                                        'controller' => CategorieController::class,
+                                        'action' => 'ajouter'
+                                    ],
+                                ],
+                            ],
+                            'modifier' => [
+                                'type'  => Segment::class,
+                                'options' => [
+                                    'route'    => '/modifier/:categorie',
+                                    'defaults' => [
+                                        'controller' => CategorieController::class,
+                                        'action' => 'modifier'
+                                    ],
+                                ],
+                            ],
+                            'supprimer' => [
+                                'type'  => Segment::class,
+                                'options' => [
+                                    'route'    => '/supprimer/:categorie',
+                                    'defaults' => [
+                                        'controller' => CategorieController::class,
+                                        'action' => 'supprimer'
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ],
+    ],
+
+    'service_manager' => [
+        'factories' => [
+            CategorieService::class => CategorieServiceFactory::class,
+        ],
+    ],
+    'controllers'     => [
+        'factories' => [
+            CategorieController::class => CategorieControllerFactory::class,
+        ],
+    ],
+    'form_elements' => [
+        'factories' => [
+            CategorieForm::class => CategorieFormFactory::class,
+        ],
+    ],
+    'hydrators' => [
+        'factories' => [
+            CategorieHydrator::class => CategorieHydratorFactory::class,
+        ],
+    ]
+
+];
\ No newline at end of file
diff --git a/config/merged/parametre.config.php b/config/merged/parametre.config.php
new file mode 100644
index 000000000..53c9ce959
--- /dev/null
+++ b/config/merged/parametre.config.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace UnicaenParametre;
+
+use UnicaenParametre\Controller\ParametreController;
+use UnicaenParametre\Controller\ParametreControllerFactory;
+use UnicaenParametre\Form\Parametre\ParametreForm;
+use UnicaenParametre\Form\Parametre\ParametreFormFactory;
+use UnicaenParametre\Provider\Privilege\ParametrePrivileges;
+use UnicaenParametre\Service\Parametre\ParametreService;
+use UnicaenParametre\Service\Parametre\ParametreServiceFactory;
+use UnicaenPrivilege\Guard\PrivilegeController;
+use Zend\Router\Http\Literal;
+use Zend\Router\Http\Segment;
+
+return [
+    'bjyauthorize' => [
+        'guards' => [
+            PrivilegeController::class => [
+                [
+                    'controller' => ParametreController::class,
+                    'action' => [
+                        'ajouter',
+                    ],
+                    'pivileges' => ParametrePrivileges::PARAMETRE_AJOUTER,
+                ],
+                [
+                    'controller' => ParametreController::class,
+                    'action' => [
+                        'modifier',
+                    ],
+                    'pivileges' => ParametrePrivileges::PARAMETRE_MODIFIER,
+                ],
+                [
+                    'controller' => ParametreController::class,
+                    'action' => [
+                        'modifier-valeur',
+                    ],
+                    'pivileges' => ParametrePrivileges::PARAMETRE_VALEUR,
+                ],
+                [
+                    'controller' => ParametreController::class,
+                    'action' => [
+                        'supprimer',
+                    ],
+                    'pivileges' => ParametrePrivileges::PARAMETRE_SUPPRIMER,
+                ],
+            ],
+        ],
+    ],
+
+    'router'          => [
+        'routes' => [
+            'parametre' => [
+                'type'  => Literal::class,
+                'options' => [
+                    'route'    => '/parametre',
+                ],
+                'may_terminate' => false,
+                'child_routes' => [
+                    'ajouter' => [
+                        'type'  => Segment::class,
+                        'options' => [
+                            'route'    => '/ajouter/:categorie',
+                            'defaults' => [
+                                'controller' => ParametreController::class,
+                                'action' => 'ajouter'
+                            ],
+                        ],
+                    ],
+                    'modifier' => [
+                        'type'  => Segment::class,
+                        'options' => [
+                            'route'    => '/modifier/:parametre',
+                            'defaults' => [
+                                'controller' => ParametreController::class,
+                                'action' => 'modifier'
+                            ],
+                        ],
+                    ],
+                    'supprimer' => [
+                        'type'  => Segment::class,
+                        'options' => [
+                            'route'    => '/supprimer/:parametre',
+                            'defaults' => [
+                                'controller' => ParametreController::class,
+                                'action' => 'supprimer'
+                            ],
+                        ],
+                    ],
+                    'modifier-valeur' => [
+                        'type'  => Segment::class,
+                        'options' => [
+                            'route'    => '/modifier-valeur/:parametre',
+                            'defaults' => [
+                                'controller' => ParametreController::class,
+                                'action' => 'modifier-valeur'
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ],
+    ],
+
+    'service_manager' => [
+        'factories' => [
+            ParametreService::class => ParametreServiceFactory::class,
+        ],
+    ],
+    'controllers'     => [
+        'factories' => [
+            ParametreController::class => ParametreControllerFactory::class,
+        ],
+    ],
+    'form_elements' => [
+        'factories' => [
+            ParametreForm::class => ParametreFormFactory::class,
+        ],
+    ],
+    'hydrators' => [
+        'factories' => [
+            ParametreService::class => ParametreServiceFactory::class,
+        ],
+    ]
+
+];
\ No newline at end of file
diff --git a/config/module.config.php b/config/module.config.php
new file mode 100644
index 000000000..a20097879
--- /dev/null
+++ b/config/module.config.php
@@ -0,0 +1,51 @@
+<?php
+
+use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
+use Doctrine\ORM\Mapping\Driver\XmlDriver;
+
+return [
+    'doctrine' => [
+        'driver' => [
+            'orm_default' => [
+                'class' => MappingDriverChain::class,
+                'drivers' => [
+                    'UnicaenParametre\Entity\Db' => 'orm_default_xml_driver',
+                ],
+            ],
+            'orm_default_xml_driver' => [
+                'class' => XmlDriver::class,
+                'cache' => 'apc',
+                'paths' => [
+                    __DIR__ . '/../src/UnicaenParametre/Entity/Db/Mapping',
+                ],
+            ],
+        ],
+        'cache' => [
+            'apc' => [
+                'namespace' => 'UNICAEN-PARAMETRE__' . __NAMESPACE__,
+            ],
+        ],
+    ],
+
+    'view_manager'    => [
+        'template_path_stack' => [
+            __DIR__ . '/../view',
+        ],
+    ],
+
+    'view_helpers'  => [
+        'aliases' => [
+        ],
+        'factories' => [
+        ],
+    ],
+
+    'public_files' => [
+        'inline_scripts' => [
+//            '202_' => 'vendor/chart-2.9.3/Chart.bundle.min.js',
+        ],
+        'stylesheets' => [
+            '10001_' => 'css/unicaen-parametre.css',
+        ],
+    ],
+];
\ No newline at end of file
diff --git a/doc/database.sql b/doc/database.sql
new file mode 100644
index 000000000..dc66b339e
--- /dev/null
+++ b/doc/database.sql
@@ -0,0 +1,62 @@
+-- CREATION DES TABLES --------------------------------------------------------------------------
+
+-- table catégorie
+create table unicaen_parametre_categorie
+(
+    id serial not null,
+    code varchar(1024) not null,
+    libelle varchar(1024) not null,
+    description text,
+    ordre integer default 9999
+);
+
+create unique index unicaen_parametre_categorie_code_uindex
+    on unicaen_parametre_categorie (code);
+
+create unique index unicaen_parametre_categorie_id_uindex
+    on unicaen_parametre_categorie (id);
+
+alter table unicaen_parametre_categorie
+    add constraint unicaen_parametre_categorie_pk
+        primary key (id);
+
+-- table parametre
+create table unicaen_parametre_parametre
+(
+    id serial not null
+        constraint unicaen_parametre_parametre_pk
+            primary key,
+    categorie_id integer not null
+        constraint unicaen_parametre_parametre_unicaen_parametre_categorie_id_fk
+            references unicaen_parametre_categorie,
+    code varchar(1024) not null,
+    libelle varchar(1024) not null,
+    description text,
+    valeurs_possibles text,
+    valeur text,
+    ordre integer default 9999
+);
+
+create unique index unicaen_parametre_parametre_id_uindex
+    on unicaen_parametre_parametre (id);
+
+create unique index unicaen_parametre_parametre_code_categorie_id_uindex
+    on unicaen_parametre_parametre (code, categorie_id);
+
+-- PRIVILEGES ----------------------------------------------------------------------------------------------------------
+
+INSERT INTO unicaen_privilege_categorie (id, code, libelle, ordre, namespace) VALUES (nextval(unicaen_privilege_categorie_id_seq), 'parametrecategorie', 'UnicaenParametre - Gestion des catégories de paramètres', 70000, 'UnicaenParametre\Provider\Privilege');
+INSERT INTO unicaen_privilege_privilege (categorie_id, code, libelle, ordre) VALUES (lastval(unicaen_privilege_categorie_id_seq), 'parametrecategorie_index', 'Affichage de l''index des paramètres', 10);
+INSERT INTO unicaen_privilege_privilege (categorie_id, code, libelle, ordre) VALUES (lastval(unicaen_privilege_categorie_id_seq), 'parametrecategorie_modifier', 'Modifier une catégorie de paramètre', 40);
+INSERT INTO unicaen_privilege_privilege (categorie_id, code, libelle, ordre) VALUES (lastval(unicaen_privilege_categorie_id_seq), 'parametrecategorie_ajouter', 'Ajouter une catégorie de paramètre', 30);
+INSERT INTO unicaen_privilege_privilege (categorie_id, code, libelle, ordre) VALUES (lastval(unicaen_privilege_categorie_id_seq), 'parametrecategorie_supprimer', 'Supprimer une catégorie de paramètre', 60);
+INSERT INTO unicaen_privilege_privilege (categorie_id, code, libelle, ordre) VALUES (lastval(unicaen_privilege_categorie_id_seq), 'parametrecategorie_afficher', 'Affichage des détails d''une catégorie', 20);
+
+INSERT INTO unicaen_privilege_categorie (id, code, libelle, ordre, namespace) VALUES (nextval(unicaen_privilege_categorie_id_seq), 'parametre', 'UnicaenParametre - Gestion des paramètres', 70001, 'UnicaenParametre\Provider\Privilege');
+INSERT INTO unicaen_privilege_privilege (categorie_id, code, libelle, ordre) VALUES (lastval(unicaen_privilege_categorie_id_seq), 'parametre_afficher', 'Afficher un paramètre', 10);
+INSERT INTO unicaen_privilege_privilege (categorie_id, code, libelle, ordre) VALUES (lastval(unicaen_privilege_categorie_id_seq), 'parametre_ajouter', 'Ajouter un paramètre', 20);
+INSERT INTO unicaen_privilege_privilege (categorie_id, code, libelle, ordre) VALUES (lastval(unicaen_privilege_categorie_id_seq), 'parametre_modifier', 'Modifier un paramètre', 30);
+INSERT INTO unicaen_privilege_privilege (categorie_id, code, libelle, ordre) VALUES (lastval(unicaen_privilege_categorie_id_seq), 'parametre_supprimer', 'Supprimer un paramètre', 50);
+INSERT INTO unicaen_privilege_privilege (categorie_id, code, libelle, ordre) VALUES (lastval(unicaen_privilege_categorie_id_seq), 'parametre_valeur', 'Modifier la valeur d''un parametre', 100);
+
+--TODO penser à accorder les privilèges selon le besoin
\ No newline at end of file
diff --git a/readme.md b/readme.md
new file mode 100644
index 000000000..4dc1dee2f
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,41 @@
+UnicaenParametre
+============
+
+UnicaenParametre est une biltiothèque de gestion de catégories de paramètre et de paramètres.
+
+Route d'accès
+-------------
+- */parametre/index* donne accès aux paramètres de toutes les catégories
+- */parametre/index/categorieId* donne accès aux paramètres de la catégorie *categorieId*
+
+Récupération de la valeur d'un paramètre
+----------------------------------------
+```php
+$this->getParametreService()->getParametreByCode('ma_categorie','mon_parametre')->getValeur();
+```
+
+**N.B.:** Il n'y a pas d'historisation des paramètres ou de leur catégorie. Est-ce bien nécessaire ?
+
+- - - - - - - - - - - - - 
+
+Installation
+============
+
+Dans le répertoire **doc** du module, on retrouve le fichier *database.sql* qui permet de construire la table associée au
+ module et d'ajouter les privilèges associés.
+ 
+Le module s'attend à avoir un menu **Administration** pour mettre un menu secondaire **Paramètres**. 
+Pensez à l'ajouter s'il n'existe pas ou à modifier la naviguation dans *categorie.config.php*.
+
+- - - - - - - - - - - - - 
+
+Historique
+==========
+
+version 0.1.0 25/02/2021
+------------------------
+Version initiale du module.
+
+Améliorations possibles
+-----------------------
+- Ajouter des "shorthands" vers l'accés aux valeurs des paramètres.
\ No newline at end of file
diff --git a/src/UnicaenParametre/Controller/CategorieController.php b/src/UnicaenParametre/Controller/CategorieController.php
new file mode 100644
index 000000000..ccfd1e304
--- /dev/null
+++ b/src/UnicaenParametre/Controller/CategorieController.php
@@ -0,0 +1,103 @@
+<?php
+
+namespace UnicaenParametre\Controller;
+
+use UnicaenParametre\Entity\Db\Categorie;
+use UnicaenParametre\Form\Categorie\CategorieFormAwareTrait;
+use UnicaenParametre\Service\Categorie\CategorieServiceAwareTrait;
+use UnicaenParametre\Service\Parametre\ParametreServiceAwareTrait;
+use Zend\Mvc\Controller\AbstractActionController;
+use Zend\View\Model\ViewModel;
+
+class CategorieController extends AbstractActionController {
+    use CategorieServiceAwareTrait;
+    use ParametreServiceAwareTrait;
+    use CategorieFormAwareTrait;
+
+    public function indexAction()
+    {
+        $categories = $this->getCategorieService()->getCategories();
+        $parametres = $this->getParametreService()->getParametres();
+        $selection = $this->getCategorieService()->getRequestedCategorie($this);
+
+        return new ViewModel([
+            'categories' => $categories,
+            'parametres' => $parametres,
+            'selection' => $selection,
+        ]);
+    }
+
+    public function ajouterAction() {
+
+        $categorie = new Categorie();
+        $form = $this->getCategorieForm();
+        $form->setAttribute('action', $this->url()->fromRoute('parametre/categorie/ajouter', [], [], true));
+        $form->bind($categorie);
+
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            $form->setData($data);
+            if ($form->isValid()) {
+                $this->getCategorieService()->create($categorie);
+            }
+        }
+
+        $vm = new ViewModel([
+            'title' => "Ajout d'une catégorie de paramètre",
+            'form' => $form,
+        ]);
+        $vm->setTemplate('unicaen-parametre/default/default-form');
+        return $vm;
+    }
+
+    public function modifierAction()
+    {
+        $categorie = $this->getCategorieService()->getRequestedCategorie($this);
+        $form = $this->getCategorieForm();
+        $form->setOldCode($categorie->getCode());
+        $form->setAttribute('action', $this->url()->fromRoute('parametre/categorie/modifier', ['categorie' => $categorie->getId()], [], true));
+        $form->bind($categorie);
+
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            $form->setData($data);
+            if ($form->isValid()) {
+                $this->getCategorieService()->update($categorie);
+            }
+        }
+
+        $vm = new ViewModel([
+            'title' => "Modification de la catégorie [".$categorie->getCode()."] ",
+            'form' => $form,
+        ]);
+        $vm->setTemplate('unicaen-parametre/default/default-form');
+        return $vm;
+    }
+
+    public function supprimerAction()
+    {
+        $categorie = $this->getCategorieService()->getRequestedCategorie($this);
+
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            if ($data["reponse"] === "oui") $this->getCategorieService()->delete($categorie);
+            exit();
+        }
+
+        $vm = new ViewModel();
+        if ($categorie !== null) {
+            $vm->setTemplate('unicaen-parametre/default/confirmation');
+            $vm->setVariables([
+                'title' => "Suppression de la catégorie de  paramètre [" . $categorie->getCode() . "]",
+                'text' => "La suppression est définitive êtes-vous sûr&middot;e de vouloir continuer ?",
+                'action' => $this->url()->fromRoute('parametre/categorie/supprimer', ["categorie" => $categorie->getId()], [], true),
+            ]);
+        }
+        return $vm;
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Controller/CategorieControllerFactory.php b/src/UnicaenParametre/Controller/CategorieControllerFactory.php
new file mode 100644
index 000000000..9c68897f9
--- /dev/null
+++ b/src/UnicaenParametre/Controller/CategorieControllerFactory.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace UnicaenParametre\Controller;
+
+use Interop\Container\ContainerInterface;
+use UnicaenParametre\Form\Categorie\CategorieForm;
+use UnicaenParametre\Service\Categorie\CategorieService;
+use UnicaenParametre\Service\Parametre\ParametreService;
+
+class CategorieControllerFactory {
+
+    public function __invoke(ContainerInterface $container)
+    {
+        /**
+         * @var CategorieService $categorieService
+         * @var ParametreService $parametreService
+         */
+        $categorieService = $container->get(CategorieService::class);
+        $parametreService = $container->get(ParametreService::class);
+
+        /**
+         * @var CategorieForm $categorieForm
+         */
+        $categorieForm = $container->get('FormElementManager')->get(CategorieForm::class);
+
+        $controller = new CategorieController();
+        $controller->setCategorieService($categorieService);
+        $controller->setParametreService($parametreService);
+        $controller->setCategorieForm($categorieForm);
+        return $controller;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Controller/ParametreController.php b/src/UnicaenParametre/Controller/ParametreController.php
new file mode 100644
index 000000000..c812a31c3
--- /dev/null
+++ b/src/UnicaenParametre/Controller/ParametreController.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace UnicaenParametre\Controller;
+
+use UnicaenParametre\Entity\Db\Parametre;
+use UnicaenParametre\Form\Parametre\ParametreFormAwareTrait;
+use UnicaenParametre\Service\Categorie\CategorieServiceAwareTrait;
+use UnicaenParametre\Service\Parametre\ParametreServiceAwareTrait;
+use Zend\Mvc\Controller\AbstractActionController;
+use Zend\View\Model\ViewModel;
+
+class ParametreController extends AbstractActionController {
+    use CategorieServiceAwareTrait;
+    use ParametreServiceAwareTrait;
+    use ParametreFormAwareTrait;
+
+    public function ajouterAction()
+    {
+        $categorie = $this->getCategorieService()->getRequestedCategorie($this);
+        $parametre = new Parametre();
+        $parametre->setCategorie($categorie);
+        $form = $this->getParametreForm();
+        $form->setCategorie($categorie);
+        $form->setAttribute('action', $this->url()->fromRoute('parametre/ajouter', ['categorie' => $categorie->getId()], [], true));
+        $form->bind($parametre);
+
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            $form->setData($data);
+            if ($form->isValid()) {
+                $this->getParametreService()->create($parametre);
+            }
+        }
+
+        $vm = new ViewModel([
+            'title' => "Ajout d'un paramètre pour la catégorie [".$categorie->getCode()."]",
+            'form' => $form,
+        ]);
+        $vm->setTemplate('unicaen-parametre/default/default-form');
+        return $vm;
+    }
+
+    public function modifierAction()
+    {
+        $parametre = $this->getParametreService()->getRequestedParametre($this);
+        $form = $this->getParametreForm();
+        $form->setOldCode($parametre->getCategorie()->getCode(). "-" . $parametre->getCode());
+        $form->setCategorie($parametre->getCategorie());
+        $form->setAttribute('action', $this->url()->fromRoute('parametre/modifier', ['parametre' => $parametre->getId()], [], true));
+        $form->bind($parametre);
+
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            $form->setData($data);
+            if ($form->isValid()) {
+                $this->getParametreService()->update($parametre);
+            }
+        }
+
+        $vm = new ViewModel([
+            'title' => "Modification du paramètre [".$parametre->getCode()."]",
+            'form' => $form,
+        ]);
+        $vm->setTemplate('unicaen-parametre/default/default-form');
+        return $vm;
+    }
+
+    public function supprimerAction()
+    {
+        $parametre = $this->getParametreService()->getRequestedParametre($this);
+
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            if ($data["reponse"] === "oui") $this->getParametreService()->delete($parametre);
+            exit();
+        }
+
+        $vm = new ViewModel();
+        if ($parametre !== null) {
+            $vm->setTemplate('unicaen-parametre/default/confirmation');
+            $vm->setVariables([
+                'title' => "Suppression du paramètre [" . $parametre->getCode() . "]",
+                'text' => "La suppression est définitive êtes-vous sûr&middot;e de vouloir continuer ?",
+                'action' => $this->url()->fromRoute('parametre/supprimer', ["parametre" => $parametre->getId()], [], true),
+            ]);
+        }
+        return $vm;
+    }
+
+    public function modifierValeurAction()
+    {
+        $parametre = $this->getParametreService()->getRequestedParametre($this);
+
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            $valeur = $data['valeur'];
+            $parametre->setValeur($valeur);
+            $this->getParametreService()->update($parametre);
+        }
+
+        return new ViewModel([
+            'title' => "Modification de la valeur du paramètre <strong>". $parametre->getCode() ."</strong>",
+            'parametre' => $parametre,
+        ]);
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Controller/ParametreControllerFactory.php b/src/UnicaenParametre/Controller/ParametreControllerFactory.php
new file mode 100644
index 000000000..8bbc5e00c
--- /dev/null
+++ b/src/UnicaenParametre/Controller/ParametreControllerFactory.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace UnicaenParametre\Controller;
+
+use Interop\Container\ContainerInterface;
+use UnicaenParametre\Form\Parametre\ParametreForm;
+use UnicaenParametre\Service\Categorie\CategorieService;
+use UnicaenParametre\Service\Parametre\ParametreService;
+
+class ParametreControllerFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return ParametreController
+     */
+    public function __invoke(ContainerInterface $container)
+    {
+        /**
+         * @var CategorieService $categorieService
+         * @var ParametreService $parametreService
+         */
+        $categorieService = $container->get(CategorieService::class);
+        $parametreService = $container->get(ParametreService::class);
+
+        /**
+         * @var ParametreForm $parametreForm
+         */
+        $parametreForm = $container->get('FormElementManager')->get(ParametreForm::class);
+
+        $controller = new ParametreController();
+        $controller->setCategorieService($categorieService);
+        $controller->setParametreService($parametreService);
+        $controller->setParametreForm($parametreForm);
+        return $controller;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Entity/Db/Categorie.php b/src/UnicaenParametre/Entity/Db/Categorie.php
new file mode 100644
index 000000000..49cc9fb74
--- /dev/null
+++ b/src/UnicaenParametre/Entity/Db/Categorie.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace UnicaenParametre\Entity\Db;
+
+class Categorie
+{
+    const DEFAULT_ORDER = 9999;
+
+    /** @var integer */
+    private $id;
+    /** @var string */
+    private $code;
+    /** @var string */
+    private $libelle;
+    /** @var string */
+    private $description;
+    /** @var integer */
+    private $ordre;
+
+    /**
+     * @return int
+     */
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getCode(): ?string
+    {
+        return $this->code;
+    }
+
+    /**
+     * @param string|null $code
+     * @return Categorie
+     */
+    public function setCode(?string $code): Categorie
+    {
+        $this->code = $code;
+        return $this;
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getLibelle(): ?string
+    {
+        return $this->libelle;
+    }
+
+    /**
+     * @param string|null $libelle
+     * @return Categorie
+     */
+    public function setLibelle(?string $libelle): Categorie
+    {
+        $this->libelle = $libelle;
+        return $this;
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getDescription(): ?string
+    {
+        return $this->description;
+    }
+
+    /**
+     * @param string|null $description
+     * @return Categorie
+     */
+    public function setDescription(?string $description): Categorie
+    {
+        $this->description = $description;
+        return $this;
+    }
+
+    /**
+     * @return int|null
+     */
+    public function getOrdre(): ?int
+    {
+        return $this->ordre;
+    }
+
+    /**
+     * @param int $ordre
+     * @return Categorie
+     */
+    public function setOrdre(int $ordre = Categorie::DEFAULT_ORDER): Categorie
+    {
+        $this->ordre = $ordre;
+        return $this;
+    }
+
+}
+
diff --git a/src/UnicaenParametre/Entity/Db/Mapping/UnicaenParametre.Entity.Db.Categorie.dcm.xml b/src/UnicaenParametre/Entity/Db/Mapping/UnicaenParametre.Entity.Db.Categorie.dcm.xml
new file mode 100644
index 000000000..ba3719f02
--- /dev/null
+++ b/src/UnicaenParametre/Entity/Db/Mapping/UnicaenParametre.Entity.Db.Categorie.dcm.xml
@@ -0,0 +1,15 @@
+<?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="UnicaenParametre\Entity\Db\Categorie" table="unicaen_parametre_categorie">
+
+        <id name="id"                   column="id"                 type="integer">
+            <generator strategy="IDENTITY"/>
+        </id>
+
+        <field name="code"              column="code"                   type="string"    length="1024"    nullable="false" />
+        <field name="libelle"           column="libelle"                type="string"    length="1024"    nullable="false" />
+        <field name="description"       column="description"            type="string"    length="4096"    nullable="true" />
+        <field name="ordre"             column="ordre"                  type="integer"                    nullable="true" />
+
+    </entity>
+</doctrine-mapping>
\ No newline at end of file
diff --git a/src/UnicaenParametre/Entity/Db/Mapping/UnicaenParametre.Entity.Db.Parametre.dcm.xml b/src/UnicaenParametre/Entity/Db/Mapping/UnicaenParametre.Entity.Db.Parametre.dcm.xml
new file mode 100644
index 000000000..b3237a027
--- /dev/null
+++ b/src/UnicaenParametre/Entity/Db/Mapping/UnicaenParametre.Entity.Db.Parametre.dcm.xml
@@ -0,0 +1,21 @@
+<?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="UnicaenParametre\Entity\Db\Parametre" table="unicaen_parametre_parametre">
+
+        <id name="id"                   column="id"                 type="integer">
+            <generator strategy="IDENTITY"/>
+        </id>
+
+        <many-to-one target-entity="UnicaenParametre\Entity\Db\Categorie"  field="categorie">
+            <join-column name="categorie_id" referenced-column-name="id"/>
+        </many-to-one>
+
+        <field name="code"              column="code"                   type="string"    length="1024"    nullable="false" />
+        <field name="libelle"           column="libelle"                type="string"    length="1024"    nullable="false" />
+        <field name="description"       column="description"            type="string"    length="4096"    nullable="true" />
+        <field name="valeurs_possibles" column="valeurs_possibles"      type="string"    length="4096"    nullable="true" />
+        <field name="valeur"            column="valeur"                 type="string"    length="4096"    nullable="true" />
+        <field name="ordre"             column="ordre"                  type="integer"                    nullable="true" />
+
+    </entity>
+</doctrine-mapping>
\ No newline at end of file
diff --git a/src/UnicaenParametre/Entity/Db/Parametre.php b/src/UnicaenParametre/Entity/Db/Parametre.php
new file mode 100644
index 000000000..85b31397e
--- /dev/null
+++ b/src/UnicaenParametre/Entity/Db/Parametre.php
@@ -0,0 +1,164 @@
+<?php
+
+namespace UnicaenParametre\Entity\Db;
+
+class Parametre
+{
+    const DEFAULT_ORDER = 9999;
+
+    /** @var integer */
+    private $id;
+    /** @var Categorie */
+    private $categorie;
+    /** @var string */
+    private $code;
+    /** @var string */
+    private $libelle;
+    /** @var string */
+    private $description;
+    /** @var string */
+    private $valeur;
+    /** @var string */
+    private $valeurs_possibles;
+    /** @var integer */
+    private $ordre;
+
+    /**
+     * @return int
+     */
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    /**
+     * @return Categorie|null
+     */
+    public function getCategorie(): ?Categorie
+    {
+        return $this->categorie;
+    }
+
+    /**
+     * @param Categorie|null $categorie
+     * @return Parametre
+     */
+    public function setCategorie(?Categorie $categorie): Parametre
+    {
+        $this->categorie = $categorie;
+        return $this;
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getCode(): ?string
+    {
+        return $this->code;
+    }
+
+    /**
+     * @param string|null $code
+     * @return Parametre
+     */
+    public function setCode(?string $code): Parametre
+    {
+        $this->code = $code;
+        return $this;
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getLibelle(): ?string
+    {
+        return $this->libelle;
+    }
+
+    /**
+     * @param string|null $libelle
+     * @return Parametre
+     */
+    public function setLibelle(?string $libelle): Parametre
+    {
+        $this->libelle = $libelle;
+        return $this;
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getDescription(): ?string
+    {
+        return $this->description;
+    }
+
+    /**
+     * @param string|null $description
+     * @return Parametre
+     */
+    public function setDescription(?string $description): Parametre
+    {
+        $this->description = $description;
+        return $this;
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getValeur(): ?string
+    {
+        return $this->valeur;
+    }
+
+    /**
+     * @param string|null $valeur
+     * @return Parametre
+     */
+    public function setValeur(?string $valeur): Parametre
+    {
+        $this->valeur = $valeur;
+        return $this;
+    }
+
+    /**
+     * @return string|null
+     */
+    public function getValeursPossibles(): ?string
+    {
+        return $this->valeurs_possibles;
+    }
+
+    /**
+     * @param string|null $valeurs_possibles
+     * @return Parametre
+     */
+    public function setValeursPossibles(?string $valeurs_possibles): Parametre
+    {
+        $this->valeurs_possibles = $valeurs_possibles;
+        return $this;
+    }
+
+    /**
+     * @return int|null
+     */
+    public function getOrdre(): ?int
+    {
+        return $this->ordre;
+    }
+
+    /**
+     * @param int $ordre
+     * @return Parametre
+     */
+    public function setOrdre(int $ordre = Parametre::DEFAULT_ORDER): Parametre
+    {
+        $this->ordre = $ordre;
+        return $this;
+    }
+
+
+
+
+}
+
diff --git a/src/UnicaenParametre/Form/Categorie/CategorieForm.php b/src/UnicaenParametre/Form/Categorie/CategorieForm.php
new file mode 100644
index 000000000..4dddae66f
--- /dev/null
+++ b/src/UnicaenParametre/Form/Categorie/CategorieForm.php
@@ -0,0 +1,123 @@
+<?php
+
+namespace UnicaenParametre\Form\Categorie;
+
+use UnicaenParametre\Service\Categorie\CategorieServiceAwareTrait;
+use Zend\Form\Element\Button;
+use Zend\Form\Element\Hidden;
+use Zend\Form\Element\Number;
+use Zend\Form\Element\Text;
+use Zend\Form\Element\Textarea;
+use Zend\Form\Form;
+use Zend\InputFilter\Factory;
+use Zend\Validator\Callback;
+
+class CategorieForm extends Form {
+    use CategorieServiceAwareTrait;
+
+    public function init()
+    {
+        //code
+        $this->add([
+            'type' => Text::class,
+            'name' => 'code',
+            'options' => [
+                'label' => "Code de la catégorie : ",
+                'label_attributes' => [
+                    'class' => 'required',
+                ],
+            ],
+            'attributes' => [
+                'id' => 'code',
+            ],
+        ]);
+        //old-code
+        $this->add([
+            'name' => 'old-code',
+            'type' => Hidden::class,
+            'attributes' => [
+                'value' => "",
+            ],
+        ]);
+        //libelle
+        $this->add([
+            'type' => Text::class,
+            'name' => 'libelle',
+            'options' => [
+                'label' => "Libellé de la catégorie : ",
+                'label_attributes' => [
+                    'class' => 'required',
+                ],
+            ],
+            'attributes' => [
+                'id' => 'libelle',
+            ],
+        ]);
+        //description
+        $this->add([
+            'type' => Textarea::class,
+            'name' => 'description',
+            'options' => [
+                'label' => "Description de la catégorie : ",
+            ],
+            'attributes' => [
+                'id' => 'description',
+                'class' => 'type2',
+            ],
+        ]);
+        //ordre
+        $this->add([
+            'type' => Number::class,
+            'name' => 'ordre',
+            'options' => [
+                'label' => "Ordre de la catégorie : ",
+                'label_attributes' => [
+                    'class' => 'required',
+                ],
+            ],
+            'attributes' => [
+                'id' => 'ordre',
+            ],
+        ]);
+        //button
+        $this->add([
+            'type' => Button::class,
+            'name' => 'next',
+            'options' => [
+                'label' => '<i class="fas fa-save"></i> Enregistrer',
+                'label_options' => [
+                    'disable_html_escape' => true,
+                ],
+            ],
+            'attributes' => [
+                'type' => 'submit',
+                'class' => 'btn btn-default',
+            ],
+        ]);
+        //input filter
+        $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->getCategorieService()->getCategoriebyCode($value) == null);
+                        },
+                    ],
+                ]],
+            ],
+            'libelle'     => [     'required' => true, ],
+            'description' => [     'required' => false, ],
+            'ordre'       => [     'required' => false, ],
+        ]));
+    }
+
+    public function setOldCode($value){
+        $this->get('old-code')->setValue($value);
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Form/Categorie/CategorieFormAwareTrait.php b/src/UnicaenParametre/Form/Categorie/CategorieFormAwareTrait.php
new file mode 100644
index 000000000..4d4ee6b05
--- /dev/null
+++ b/src/UnicaenParametre/Form/Categorie/CategorieFormAwareTrait.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace UnicaenParametre\Form\Categorie;
+
+trait CategorieFormAwareTrait {
+
+    /** @var CategorieForm */
+    private $categorieForm;
+
+    /**
+     * @return CategorieForm
+     */
+    public function getCategorieForm(): CategorieForm
+    {
+        return $this->categorieForm;
+    }
+
+    /**
+     * @param CategorieForm $categorieForm
+     * @return CategorieForm
+     */
+    public function setCategorieForm(CategorieForm $categorieForm): CategorieForm
+    {
+        $this->categorieForm = $categorieForm;
+        return $this->categorieForm;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Form/Categorie/CategorieFormFactory.php b/src/UnicaenParametre/Form/Categorie/CategorieFormFactory.php
new file mode 100644
index 000000000..8233d980c
--- /dev/null
+++ b/src/UnicaenParametre/Form/Categorie/CategorieFormFactory.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace UnicaenParametre\Form\Categorie;
+
+use Interop\Container\ContainerInterface;
+use UnicaenParametre\Service\Categorie\CategorieService;
+
+class CategorieFormFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return CategorieForm
+     */
+    public function __invoke(ContainerInterface $container)
+    {
+        /**
+         * @var CategorieService $categorieService
+         * @var CategorieHydrator $hydrator
+         */
+        $categorieService = $container->get(CategorieService::class);
+        $hydrator = $container->get('HydratorManager')->get(CategorieHydrator::class);
+
+        $form = new CategorieForm();
+        $form->setCategorieService($categorieService);
+        $form->setHydrator($hydrator);
+        return $form;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Form/Categorie/CategorieHydrator.php b/src/UnicaenParametre/Form/Categorie/CategorieHydrator.php
new file mode 100644
index 000000000..f48b211a4
--- /dev/null
+++ b/src/UnicaenParametre/Form/Categorie/CategorieHydrator.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace UnicaenParametre\Form\Categorie;
+
+use UnicaenParametre\Entity\Db\Categorie;
+use Zend\Hydrator\HydratorInterface;
+
+class CategorieHydrator implements HydratorInterface {
+
+    /**
+     * @param Categorie $object
+     * @return array|void
+     */
+    public function extract($object)
+    {
+        $data = [
+            'code' => $object->getCode(),
+            'libelle' => $object->getLibelle(),
+            'description' => $object->getDescription(),
+            'ordre' => $object->getOrdre(),
+        ];
+        return $data;
+    }
+
+    /**
+     * @param array $data
+     * @param Categorie $object
+     * @return Categorie
+     */
+    public function hydrate(array $data, $object)
+    {
+        $code = (isset($data['code']) and trim($data['code']) !== '')?trim($data['code']):null;
+        $libelle = (isset($data['libelle']) and trim($data['libelle']) !== '')?trim($data['libelle']):null;
+        $description = (isset($data['description']) and trim($data['description']) !== '')?trim($data['description']):null;
+        $ordre = (isset($data['ordre']) and trim($data['ordre']) !== '')?trim($data['ordre']):null;
+
+        $object->setCode($code);
+        $object->setLibelle($libelle);
+        $object->setDescription($description);
+        $object->setOrdre($ordre);
+
+        return $object;
+    }
+
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Form/Categorie/CategorieHydratorFactory.php b/src/UnicaenParametre/Form/Categorie/CategorieHydratorFactory.php
new file mode 100644
index 000000000..917af1722
--- /dev/null
+++ b/src/UnicaenParametre/Form/Categorie/CategorieHydratorFactory.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace UnicaenParametre\Form\Categorie;
+
+use Interop\Container\ContainerInterface;
+
+class CategorieHydratorFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return CategorieHydrator
+     */
+    public function __invoke(ContainerInterface $container)
+    {
+        $hydrator = new CategorieHydrator();
+        return $hydrator;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Form/Parametre/ParametreForm.php b/src/UnicaenParametre/Form/Parametre/ParametreForm.php
new file mode 100644
index 000000000..7e3cadee5
--- /dev/null
+++ b/src/UnicaenParametre/Form/Parametre/ParametreForm.php
@@ -0,0 +1,150 @@
+<?php
+
+namespace UnicaenParametre\Form\Parametre;
+
+use UnicaenParametre\Entity\Db\Categorie;
+use UnicaenParametre\Service\Parametre\ParametreServiceAwareTrait;
+use Zend\Form\Element\Button;
+use Zend\Form\Element\Hidden;
+use Zend\Form\Element\Number;
+use Zend\Form\Element\Text;
+use Zend\Form\Element\Textarea;
+use Zend\Form\Form;
+use Zend\InputFilter\Factory;
+use Zend\Validator\Callback;
+
+class ParametreForm extends Form {
+    use ParametreServiceAwareTrait;
+
+    public function init() {
+        //code
+        $this->add([
+            'type' => Text::class,
+            'name' => 'code',
+            'options' => [
+                'label' => "Code du paramètre : ",
+                'label_attributes' => [
+                    'class' => 'required',
+                ],
+            ],
+            'attributes' => [
+                'id' => 'code',
+            ],
+        ]);
+        //old-code
+        $this->add([
+            'name' => 'old-code',
+            'type' => Hidden::class,
+            'attributes' => [
+                'value' => "",
+            ],
+        ]);
+        $this->add([
+            'name' => 'categorie-code',
+            'type' => Hidden::class,
+            'attributes' => [
+                'value' => "",
+            ],
+        ]);
+        //libelle
+        $this->add([
+            'type' => Text::class,
+            'name' => 'libelle',
+            'options' => [
+                'label' => "Libellé du paramètre : ",
+                'label_attributes' => [
+                    'class' => 'required',
+                ],
+            ],
+            'attributes' => [
+                'id' => 'libelle',
+            ],
+        ]);
+        //description
+        $this->add([
+            'type' => Textarea::class,
+            'name' => 'description',
+            'options' => [
+                'label' => "Description de la catégorie : ",
+            ],
+            'attributes' => [
+                'id' => 'description',
+                'class' => 'type2',
+            ],
+        ]);
+        //ordre
+        $this->add([
+            'type' => Number::class,
+            'name' => 'ordre',
+            'options' => [
+                'label' => "Ordre de la catégorie : ",
+                'label_attributes' => [
+                    'class' => 'required',
+                ],
+            ],
+            'attributes' => [
+                'id' => 'ordre',
+            ],
+        ]);
+        //possibles
+        $this->add([
+            'type' => Text::class,
+            'name' => 'possibles',
+            'options' => [
+                'label' => "Valeurs possibles (String, Boolean, Number, énumération avec '|' comme séparateur) : ",
+            ],
+            'attributes' => [
+                'id' => 'possibles',
+            ],
+        ]);
+        //button
+        $this->add([
+            'type' => Button::class,
+            'name' => 'next',
+            'options' => [
+                'label' => '<i class="fas fa-save"></i> Enregistrer',
+                'label_options' => [
+                    'disable_html_escape' => true,
+                ],
+            ],
+            'attributes' => [
+                'type' => 'submit',
+                'class' => 'btn btn-default',
+            ],
+        ]);
+        //input filter
+        $this->setInputFilter((new Factory())->createInputFilter([
+            'code'       => [
+                'required' => true,
+                'validators' => [[
+                    'name' => Callback::class,
+                    'options' => [
+                        'messages' => [
+                            Callback::INVALID_VALUE => "Ce code existe déjà pour ce paramètre/catégorie",
+                        ],
+                        'callback' => function ($value, $context = []) {
+                            if($context['categorie-code'] . "-" . $value ==  $context['old-code']) return true;
+                            return ($this->getParametreService()->getParametreByCode($context['categorie-code'], $value) == null);
+                        },
+                    ],
+                ]],
+            ],
+            'libelle'    => [     'required' => true, ],
+            'possibles'  => [     'required' => false, ],
+            'ordre'      => [     'required' => true, ],
+        ]));
+    }
+
+    public function setOldCode($value){
+        $this->get('old-code')->setValue($value);
+    }
+
+    /**
+     * @param Categorie|null $categorie
+     */
+    public function setCategorie(?Categorie $categorie){
+        if ($categorie !== null) {
+            $this->get('categorie-code')->setValue($categorie->getCode());
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Form/Parametre/ParametreFormAwareTrait.php b/src/UnicaenParametre/Form/Parametre/ParametreFormAwareTrait.php
new file mode 100644
index 000000000..fa9fb56fd
--- /dev/null
+++ b/src/UnicaenParametre/Form/Parametre/ParametreFormAwareTrait.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace UnicaenParametre\Form\Parametre;
+
+trait ParametreFormAwareTrait {
+
+    /** @var ParametreForm */
+    private $parametreForm;
+
+    /**
+     * @return ParametreForm
+     */
+    public function getParametreForm(): ParametreForm
+    {
+        return $this->parametreForm;
+    }
+
+    /**
+     * @param ParametreForm $parametreForm
+     * @return ParametreForm
+     */
+    public function setParametreForm(ParametreForm $parametreForm): ParametreForm
+    {
+        $this->parametreForm = $parametreForm;
+        return $this->parametreForm;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Form/Parametre/ParametreFormFactory.php b/src/UnicaenParametre/Form/Parametre/ParametreFormFactory.php
new file mode 100644
index 000000000..1a425c7cd
--- /dev/null
+++ b/src/UnicaenParametre/Form/Parametre/ParametreFormFactory.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace UnicaenParametre\Form\Parametre;
+
+use Interop\Container\ContainerInterface;
+use UnicaenParametre\Service\Parametre\ParametreService;
+
+class ParametreFormFactory {
+
+    public function __invoke(ContainerInterface $container)
+    {
+        /**
+         * @var ParametreService $parametreService
+         * @var ParametreHydrator $hydrator
+         */
+        $parametreService = $container->get(ParametreService::class);
+        $hydrator = $container->get('HydratorManager')->get(ParametreHydrator::class);
+
+        $form = new ParametreForm();
+        $form->setParametreService($parametreService);
+        $form->setHydrator($hydrator);
+        return $form;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Form/Parametre/ParametreHydrator.php b/src/UnicaenParametre/Form/Parametre/ParametreHydrator.php
new file mode 100644
index 000000000..694b36779
--- /dev/null
+++ b/src/UnicaenParametre/Form/Parametre/ParametreHydrator.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace UnicaenParametre\Form\Parametre;
+
+use UnicaenParametre\Entity\Db\Parametre;
+use Zend\Hydrator\HydratorInterface;
+
+class ParametreHydrator implements HydratorInterface {
+
+    /**
+     * @param Parametre $object
+     * @return array
+     */
+    public function extract($object)
+    {
+        $data = [
+            'code' => $object->getCode(),
+            'libelle' => $object->getLibelle(),
+            'description' => $object->getDescription(),
+            'possibles' => $object->getValeursPossibles(),
+            'ordre' => $object->getOrdre(),
+        ];
+        return $data;
+    }
+
+    /**
+     * @param array $data
+     * @param Parametre $object
+     * @return Parametre
+     */
+    public function hydrate(array $data, $object)
+    {
+        $code = (isset($data['code']) and trim($data['code']) !== '')?trim($data['code']):null;
+        $libelle = (isset($data['libelle']) and trim($data['libelle']) !== '')?trim($data['libelle']):null;
+        $description = (isset($data['description']) and trim($data['description']) !== '')?trim($data['description']):null;
+        $valeurs = (isset($data['possibles']) and trim($data['possibles']) !== '')?trim($data['possibles']):null;
+        $ordre = (isset($data['ordre']) and trim($data['ordre']) !== '')?trim($data['ordre']):null;
+
+        $object->setCode($code);
+        $object->setLibelle($libelle);
+        $object->setDescription($description);
+        $object->setValeursPossibles($valeurs);
+        $object->setOrdre($ordre);
+        return $object;
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Form/Parametre/ParametreHydratorFactory.php b/src/UnicaenParametre/Form/Parametre/ParametreHydratorFactory.php
new file mode 100644
index 000000000..d47450e42
--- /dev/null
+++ b/src/UnicaenParametre/Form/Parametre/ParametreHydratorFactory.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace UnicaenParametre\Form\Parametre;
+
+use Interop\Container\ContainerInterface;
+
+class ParametreHydratorFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return ParametreHydrator
+     */
+    public function __invoke(ContainerInterface $container)
+    {
+        $hydrator = new ParametreHydrator();
+        return $hydrator;
+    }
+} 
\ No newline at end of file
diff --git a/src/UnicaenParametre/Provider/Privilege/ParametrePrivileges.php b/src/UnicaenParametre/Provider/Privilege/ParametrePrivileges.php
new file mode 100644
index 000000000..605d98c6f
--- /dev/null
+++ b/src/UnicaenParametre/Provider/Privilege/ParametrePrivileges.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace UnicaenParametre\Provider\Privilege;
+
+use UnicaenPrivilege\Provider\Privilege\Privileges;
+
+class ParametrePrivileges extends Privileges
+{
+    const PARAMETRE_AFFICHER = 'parametre-parametre_afficher';
+    const PARAMETRE_AJOUTER = 'parametre-parametre_ajouter';
+    const PARAMETRE_MODIFIER = 'parametre-parametre_modifier';
+    const PARAMETRE_SUPPRIMER = 'parametre-parametre_supprimer';
+    const PARAMETRE_VALEUR = 'parametre-parametre_valeur';
+}
diff --git a/src/UnicaenParametre/Provider/Privilege/ParametrecategoriePrivileges.php b/src/UnicaenParametre/Provider/Privilege/ParametrecategoriePrivileges.php
new file mode 100644
index 000000000..862e227fd
--- /dev/null
+++ b/src/UnicaenParametre/Provider/Privilege/ParametrecategoriePrivileges.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace UnicaenParametre\Provider\Privilege;
+
+use UnicaenPrivilege\Provider\Privilege\Privileges;
+
+class ParametrecategoriePrivileges extends Privileges
+{
+    const PARAMETRECATEGORIE_INDEX = 'parametrecategorie-parametrecategorie_index';
+    const PARAMETRECATEGORIE_AFFICHER = 'parametrecategorie-parametrecategorie_afficher';
+    const PARAMETRECATEGORIE_AJOUTER = 'parametrecategorie-parametrecategorie_ajouter';
+    const PARAMETRECATEGORIE_MODIFIER = 'parametrecategorie-parametrecategorie_modifier';
+    const PARAMETRECATEGORIE_SUPPRIMER = 'parametrecategorie-parametrecategorie_supprimer';
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Service/Categorie/CategorieService.php b/src/UnicaenParametre/Service/Categorie/CategorieService.php
new file mode 100644
index 000000000..2c0a4ece1
--- /dev/null
+++ b/src/UnicaenParametre/Service/Categorie/CategorieService.php
@@ -0,0 +1,148 @@
+<?php
+
+namespace UnicaenParametre\Service\Categorie;
+
+use Doctrine\ORM\NonUniqueResultException;
+use Doctrine\ORM\ORMException;
+use Doctrine\ORM\QueryBuilder;
+use UnicaenApp\Exception\RuntimeException;
+use UnicaenApp\Service\EntityManagerAwareTrait;
+use UnicaenParametre\Entity\Db\Categorie;
+use Zend\Mvc\Controller\AbstractActionController;
+
+class CategorieService {
+    use EntityManagerAwareTrait;
+
+    /** GESTION ENTITY ************************************************************************************************/
+
+    /**
+     * @param Categorie $categorie
+     * @return Categorie
+     */
+    public function create(Categorie $categorie) : Categorie
+    {
+        try {
+            $this->getEntityManager()->persist($categorie);
+            $this->getEntityManager()->flush($categorie);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Une erreur s'est produite lors de l'enregistrement en base.",0,$e);
+        }
+        return $categorie;
+    }
+
+    /**
+     * @param Categorie $categorie
+     * @return Categorie
+     */
+    public function update(Categorie $categorie) : Categorie
+    {
+        try {
+            $this->getEntityManager()->flush($categorie);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Une erreur s'est produite lors de la mise à jour en base.",0,$e);
+        }
+        return $categorie;
+    }
+
+    /**
+     * @param Categorie $categorie
+     * @return Categorie
+     */
+    public function delete(Categorie $categorie) : Categorie
+    {
+        try {
+            $this->getEntityManager()->remove($categorie);
+            $this->getEntityManager()->flush($categorie);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Une erreur s'est produite lors de la suppression en base.",0,$e);
+        }
+        return $categorie;
+    }
+
+    /** REQUETAGE *****************************************************************************************************/
+
+    /**
+     * @return QueryBuilder
+     */
+    public function createQueryBuilder() : QueryBuilder
+    {
+        $qb = $this->getEntityManager()->getRepository(Categorie::class)->createQueryBuilder('categorie');
+        return $qb;
+    }
+    /**
+     * @param string $champ
+     * @param string $ordre
+     * @return Categorie[]
+     */
+    public function getCategories(string $champ="ordre", string $ordre="ASC") : array
+    {
+        $qb = $this->createQueryBuilder()
+            ->orderBy('categorie.' . $champ, $ordre);
+
+        $result = $qb->getQuery()->getResult();
+        return $result;
+    }
+
+    /**
+     * @param string $champ
+     * @param string $ordre
+     * @return array
+     */
+    public function getCategoriesAsOptions(string $champ="ordre", string $ordre="ASC") : array
+    {
+        $categories = $this->getCategories($champ,$ordre);
+        $array = [];
+        foreach ($categories as $categorie) {
+            $array[$categorie->getId()] = $categorie->getLibelle();
+        }
+        return $array;
+    }
+
+    /**
+     * @param int|null $id
+     * @return Categorie|null
+     */
+    public function getCategorie(?int $id) : ?Categorie
+    {
+        $qb = $this->createQueryBuilder()
+            ->andWhere('categorie.id = :id')
+            ->setParameter('id', $id)
+        ;
+        try {
+            $result = $qb->getQuery()->getOneOrNullResult();
+        } catch (NonUniqueResultException $e) {
+            throw new RuntimeException("Plusieurs ParamatreCategorie partagent le même id [".$id."]",0,$e);
+        }
+        return $result;
+    }
+
+    /**
+     * @param string $code
+     * @return Categorie|null
+     */
+    public function getCategoriebyCode(string $code) : ?Categorie
+    {
+        $qb = $this->createQueryBuilder()
+            ->andWhere('categorie.code = :code')
+            ->setParameter('code', $code)
+        ;
+        try {
+            $result = $qb->getQuery()->getOneOrNullResult();
+        } catch (NonUniqueResultException $e) {
+            throw new RuntimeException("Plusieurs ParamatreCategorie partagent le même code [".$code."]",0,$e);
+        }
+        return $result;
+    }
+
+    /**
+     * @param AbstractActionController $controller
+     * @param string $param
+     * @return Categorie|null
+     */
+    public function getRequestedCategorie(AbstractActionController $controller, string $param='categorie') : ?Categorie
+    {
+        $id = $controller->params()->fromRoute($param);
+        $result = $this->getCategorie($id);
+        return $result;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Service/Categorie/CategorieServiceAwareTrait.php b/src/UnicaenParametre/Service/Categorie/CategorieServiceAwareTrait.php
new file mode 100644
index 000000000..93ecb4d47
--- /dev/null
+++ b/src/UnicaenParametre/Service/Categorie/CategorieServiceAwareTrait.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace UnicaenParametre\Service\Categorie;
+
+trait CategorieServiceAwareTrait {
+
+    /** @var CategorieService */
+    private $parametreCategorieService;
+
+    /**
+     * @return CategorieService
+     */
+    public function getCategorieService(): CategorieService
+    {
+        return $this->parametreCategorieService;
+    }
+
+    /**
+     * @param CategorieService $parametreCategorieService
+     * @return CategorieService
+     */
+    public function setCategorieService(CategorieService $parametreCategorieService): CategorieService
+    {
+        $this->parametreCategorieService = $parametreCategorieService;
+        return $this->parametreCategorieService;
+    }
+
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Service/Categorie/CategorieServiceFactory.php b/src/UnicaenParametre/Service/Categorie/CategorieServiceFactory.php
new file mode 100644
index 000000000..f8b96d4a7
--- /dev/null
+++ b/src/UnicaenParametre/Service/Categorie/CategorieServiceFactory.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace UnicaenParametre\Service\Categorie;
+
+use Doctrine\ORM\EntityManager;
+use Interop\Container\ContainerInterface;
+
+class CategorieServiceFactory {
+
+    /**
+     * @param ContainerInterface $container
+     * @return CategorieService
+     */
+    public function __invoke(ContainerInterface $container)
+    {
+        /**
+         * @var EntityManager $entityManager
+         */
+        $entityManager = $container->get('doctrine.entitymanager.orm_default');
+
+        $service = new CategorieService();
+        $service->setEntityManager($entityManager);
+        return $service;
+    }
+
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Service/Parametre/ParametreService.php b/src/UnicaenParametre/Service/Parametre/ParametreService.php
new file mode 100644
index 000000000..5e8bc5ba8
--- /dev/null
+++ b/src/UnicaenParametre/Service/Parametre/ParametreService.php
@@ -0,0 +1,158 @@
+<?php
+
+namespace UnicaenParametre\Service\Parametre;
+
+use Doctrine\ORM\NonUniqueResultException;
+use Doctrine\ORM\ORMException;
+use Doctrine\ORM\QueryBuilder;
+use UnicaenApp\Exception\RuntimeException;
+use UnicaenApp\Service\EntityManagerAwareTrait;
+use UnicaenParametre\Entity\Db\Categorie;
+use UnicaenParametre\Entity\Db\Parametre;
+use Zend\Mvc\Controller\AbstractActionController;
+
+class ParametreService
+{
+    use EntityManagerAwareTrait;
+
+    /** GESTION ENTITY ************************************************************************************************/
+
+    /**
+     * @param Parametre $parametre
+     * @return Parametre
+     */
+    public function create(Parametre $parametre) : Parametre
+    {
+        try {
+            $this->getEntityManager()->persist($parametre);
+            $this->getEntityManager()->flush($parametre);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Une erreur s'est produite lors de l'enregistrement en base.",0,$e);
+        }
+        return $parametre;
+    }
+
+    /**
+     * @param Parametre $parametre
+     * @return Parametre
+     */
+    public function update(Parametre $parametre) : Parametre
+    {
+        try {
+            $this->getEntityManager()->flush($parametre);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Une erreur s'est produite lors de la mise à jour en base.",0,$e);
+        }
+        return $parametre;
+    }
+
+    /**
+     * @param Parametre $parametre
+     * @return Parametre
+     */
+    public function delete(Parametre $parametre) : Parametre
+    {
+        try {
+            $this->getEntityManager()->remove($parametre);
+            $this->getEntityManager()->flush($parametre);
+        } catch (ORMException $e) {
+            throw new RuntimeException("Une erreur s'est produite lors de la suppression en base.",0,$e);
+        }
+        return $parametre;
+    }
+
+    /** REQUETAGE *****************************************************************************************************/
+
+    /**
+     * @return QueryBuilder
+     */
+    public function createQueryBuilder() : QueryBuilder
+    {
+        $qb = $this->getEntityManager()->getRepository(Parametre::class)->createQueryBuilder('parametre')
+            ->addSelect('categorie')->join('parametre.categorie', 'categorie');
+        return $qb;
+    }
+
+    /**
+     * @param string $champ
+     * @param string $ordre
+     * @return Parametre[]
+     */
+    public function getParametres(string $champ = 'ordre', string $ordre = 'ASC') : array
+    {
+        $qb = $this->createQueryBuilder()
+            ->orderBy('parametre.' . $champ, $ordre);
+        $result = $qb->getQuery()->getResult();
+        return $result;
+    }
+
+    /**
+     * @param Categorie $categorie
+     * @param string $champ
+     * @param string $ordre
+     * @return Parametre[]
+     */
+    public function getParametresByCategorie(Categorie $categorie, string $champ = 'ordre', string $ordre = 'ASC') : array
+    {
+        $qb = $this->createQueryBuilder()
+            ->andWhere('parametre.categorie = :categorie')
+            ->setParameter('categorie', $categorie)
+            ->orderBy('parametre.' . $champ, $ordre);
+        $result = $qb->getQuery()->getResult();
+        return $result;
+    }
+
+    /**
+     * @param int $id
+     * @return Parametre|null
+     */
+    public function getParametre(int $id) : ?Parametre
+    {
+        $qb = $this->createQueryBuilder()
+            ->andWhere('parametre.id = :id')
+            ->setParameter('id', $id)
+        ;
+        try {
+            $result = $qb->getQuery()->getOneOrNullResult();
+        } catch (NonUniqueResultException $e) {
+            throw new RuntimeException("Plusieurs Parametre partagent le même id [".$id."]",0,$e);
+        }
+        return $result;
+    }
+
+    /**
+     * @param string $categorieCode
+     * @param string $parametreCode
+     * @return Parametre|null
+     */
+    public function getParametreByCode(string $categorieCode, string $parametreCode ) : ?Parametre
+    {
+        $qb = $this->createQueryBuilder()
+            ->andWhere('categorie.code = :categorieCode')
+            ->andWhere('parametre.code = :parametreCode')
+            ->setParameter('categorieCode', $categorieCode)
+            ->setParameter('parametreCode', $parametreCode)
+        ;
+
+        try {
+            $result = $qb->getQuery()->getOneOrNullResult();
+        } catch (NonUniqueResultException $e) {
+            throw new RuntimeException("Plusieurs Parametre partagent le même code [".$categorieCode ." - ".$parametreCode."]",0,$e);
+        }
+        return $result;
+    }
+
+    /**
+     * @param AbstractActionController $controller
+     * @param string $param
+     * @return Parametre
+     */
+    public function getRequestedParametre(AbstractActionController $controller, string $param = 'parametre')
+    {
+        $id = $controller->params()->fromRoute($param);
+        /** @var Parametre $parametre */
+        $parametre =  $this->getParametre($id);
+        return $parametre;
+    }
+
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Service/Parametre/ParametreServiceAwareTrait.php b/src/UnicaenParametre/Service/Parametre/ParametreServiceAwareTrait.php
new file mode 100644
index 000000000..327e4c7e2
--- /dev/null
+++ b/src/UnicaenParametre/Service/Parametre/ParametreServiceAwareTrait.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace UnicaenParametre\Service\Parametre;
+
+
+trait ParametreServiceAwareTrait
+{
+    /** @var ParametreService */
+    protected $parametreService;
+
+    /**
+     * @param ParametreService $parametreService
+     * @return ParametreService
+     */
+    public function setParametreService(ParametreService $parametreService) : ParametreService
+    {
+        $this->parametreService = $parametreService;
+        return $this->parametreService;
+    }
+
+    /**
+     * @return ParametreService
+     */
+    public function getParametreService() : ParametreService
+    {
+        return $this->parametreService;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenParametre/Service/Parametre/ParametreServiceFactory.php b/src/UnicaenParametre/Service/Parametre/ParametreServiceFactory.php
new file mode 100644
index 000000000..1bee2aa06
--- /dev/null
+++ b/src/UnicaenParametre/Service/Parametre/ParametreServiceFactory.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace UnicaenParametre\Service\Parametre;
+
+use Doctrine\ORM\EntityManager;
+use Interop\Container\ContainerInterface;
+
+class ParametreServiceFactory
+{
+
+    /**
+     * @param ContainerInterface $container
+     * @return ParametreService
+     */
+    public function __invoke(ContainerInterface $container)
+    {
+        /**
+         * @var EntityManager $entityManager
+         */
+        $entityManager = $container->get('doctrine.entitymanager.orm_default');
+
+        $service = new ParametreService();
+        $service->setEntityManager($entityManager);
+        return $service;
+    }
+}
\ No newline at end of file
diff --git a/view/unicaen-parametre/categorie/index.phtml b/view/unicaen-parametre/categorie/index.phtml
new file mode 100644
index 000000000..62cc9a518
--- /dev/null
+++ b/view/unicaen-parametre/categorie/index.phtml
@@ -0,0 +1,156 @@
+<?php
+
+/**
+ * @see \UnicaenParametre\Controller\CategorieController::indexAction()
+ * @var Parametre[] $parametres
+ * @var Categorie[] $categories
+ * @var Categorie $selection
+ */
+
+use UnicaenParametre\Entity\Db\Categorie;
+use UnicaenParametre\Entity\Db\Parametre;
+use UnicaenParametre\Provider\Privilege\ParametrecategoriePrivileges;
+
+$canAjouterCategorie = $this->isAllowed(ParametrecategoriePrivileges::getResourceId(ParametrecategoriePrivileges::PARAMETRECATEGORIE_AJOUTER));
+
+$array_categorie = [];
+$array_parametre = [];
+foreach ($parametres as $parametre) {
+    $array_categorie[$parametre->getCategorie()->getId()] = $parametre->getCategorie();
+    $array_parametre[$parametre->getCategorie()->getId()][] = $parametre;
+}
+
+$this->headTitle("Affichage des paramètres");
+
+if ($selection !== null) $categories = [ $selection ];
+?>
+
+<h1 class="page-header">
+    Affichage des paramètres
+</h1>
+
+<?php if ($selection === null AND $canAjouterCategorie) : ?>
+    <a
+        <?php /** @see \Application\Controller\ParametreCategorieController::ajouterAction() */ ?>
+        href="<?php echo $this->url('parametre/categorie/ajouter', ['categorie' => -1], [], true); ?>"
+        class="btn btn-primary action ajax-modal" data-event="modification">
+        <i class="fas fa-plus"></i> Ajouter une catégorie
+    </a>
+<?php endif; ?>
+
+<?php foreach ($categories as $categorie) : ?>
+    <?php $id = $categorie->getId(); ?>
+
+    <div class="row">
+        <div class="col-md-12">
+            <h2 title="<?php echo $categorie->getDescription(); ?>" data-toggle="tooltip" data-html="true" style="cursor: help;"> Catégorie : <?php echo $categorie->getLibelle(); ?> </h2>
+        </div>
+        <div class="pull-right">
+            <br/>
+            <a  <?php /** @see \Application\Controller\ParametreController::ajouterAction() */?>
+                href="<?php echo $this->url('parametre/ajouter', ['categorie' => $categorie->getId()], [], true); ?>"
+                class="btn btn-primary action ajax-modal" data-event="modification">
+                <i class="fas fa-plus"></i> Ajouter un paramètre
+            </a>
+            <?php if ($selection === null) : ?>
+                <a  <?php /** @see \Application\Controller\ParametreCategorieController::modifierAction() */?>
+                    href="<?php echo $this->url('parametre/categorie/modifier', ['categorie' => $categorie->getId()], [], true); ?>"
+                    class="btn btn-primary action ajax-modal" data-event="modification">
+                    <i class="fas fa-pencil-alt"></i> Modifier la catégorie
+                </a>
+                <?php if (!isset($array_parametre[$id]) OR empty ($array_parametre[$id])) : ?>
+                    <a  <?php /** @see \Application\Controller\ParametreCategorieController::supprimerAction() */?>
+                        href="<?php echo $this->url('parametre/categorie/supprimer', ['categorie' => $categorie->getId()], [], true); ?>"
+                        class="btn btn-danger action ajax-modal" data-event="modification">
+                        <i class="fas fa-times"></i> Supprimer la catégorie
+                    </a>
+                <?php else : ?>
+                    <span class="btn btn-danger action disabled" data-toggle="tooltip" data-html="true"
+                          title="La catégorie est non vide et ne peut être supprimée"
+                    >
+                    <i class="fas fa-times"></i> Supprimer la catégorie
+                </span>
+                <?php endif; ?>
+            <?php endif; ?>
+        </div>
+    </div>
+
+    <?php if (!isset($array_parametre[$id])) : ?>
+        Aucun paramètre pour cette catégorie
+    <?php else : ?>
+        <table class="table table-condensed">
+            <thead>
+            <tr>
+                <th style="width:60%; min-width:20rem;">
+                    Paramètre
+                </th>
+                <th style="width:30%; min-width:10rem;">
+                    Valeur
+                </th>
+                <th>
+                    Action
+                </th>
+            </tr>
+            </thead>
+            <tbody>
+            <?php foreach ($array_parametre[$id] as $parametre) : ?>
+                <tr>
+                    <td>
+                        <span title="<?php echo $parametre->getDescription(); ?>" data-toggle="tooltip" data-html="true" style="cursor: help;">
+                            <?php echo $parametre->getLibelle(); ?>
+                        </span>
+                    </td>
+                    <td>
+                        <?php $valeur = $parametre->getValeur(); ?>
+                        <?php switch ($valeur) {
+                            case 'true' :
+                                echo '<i class="fas fa-check" style="color:darkgreen;"></i>';
+                                break;
+                            case 'false' :
+                                echo '<i class="fas fa-times" style="color:darkred;"></i>';
+                                break;
+                            case null :
+                                echo '<em style="color: lightcoral">Aucune valeur</em>';
+                                break;
+                            default :
+                                echo $valeur;
+                                break;
+                        }
+                        ?>
+                    </td>
+                    <td>
+                        <a  <?php /** @see \Application\Controller\ParametreController::modifierValeurAction() */?>
+                            href="<?php echo $this->url('parametre/modifier-valeur', ['parametre' => $parametre->getId()], [], true); ?>" title="Modifier la valeur du paramètre <strong><?php echo $parametre->getCode(); ?></strong"
+                            class="ajax-modal" data-event="modification" data-toggle="tooltip" data-html="true">
+                            <i class="fas fa-pencil-alt"></i></a>
+                        <a  <?php /** @see \Application\Controller\ParametreController::modifierAction() */?>
+                            href="<?php echo $this->url('parametre/modifier', ['parametre' => $parametre->getId()], [], true); ?>" title="Modifier le paramètre <strong><?php echo $parametre->getCode(); ?></strong"
+                            class="ajax-modal" data-event="modification" data-toggle="tooltip" data-html="true">
+                            <i class="fas fa-cog"></i></a>
+                        <a  <?php /** @see \Application\Controller\ParametreController::supprimerAction() */?>
+                            href="<?php echo $this->url('parametre/supprimer', ['parametre' => $parametre->getId()], [], true); ?>" title="Supprimer le paramètre <strong><?php echo $parametre->getCode(); ?></strong"
+                            class="ajax-modal disabled" data-event="modification" data-toggle="tooltip" data-html="true" disabled>
+                            <i class="fas fa-times disabled"></i></a>
+                    </td>
+                </tr>
+            <?php endforeach; ?>
+            </tbody>
+        </table>
+    <?php endif;?>
+<?php endforeach; ?>
+
+<script>
+    $(function () {
+        $('body')
+            .on("modification", function (event) {
+                event.div.modal('hide');
+                window.location.reload();
+            })
+            .tooltip({
+                selector: '[data-toggle="tooltip"]',
+                placement: "bottom",
+                html: true
+            });
+    });
+</script>
+
diff --git a/view/unicaen-parametre/default/confirmation.phtml b/view/unicaen-parametre/default/confirmation.phtml
new file mode 100644
index 000000000..f2e8bdf81
--- /dev/null
+++ b/view/unicaen-parametre/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-parametre/default/default-form.phtml b/view/unicaen-parametre/default/default-form.phtml
new file mode 100644
index 000000000..cc6b6761c
--- /dev/null
+++ b/view/unicaen-parametre/default/default-form.phtml
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @var Form $form
+ */
+
+use Zend\Form\Form;
+
+?>
+
+<?php echo $this->form($form); ?>
+
+<script>
+    $(document).ready(function() {
+        tinymce.remove();
+        tinymce.init({
+            selector: '.type2',
+            toolbar: 'newdocument undo redo | bold italic underline removeformat | 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());
+                });
+            }
+        });
+    });
+    tinymce.init({
+        selector: '.type1',
+        toolbar: 'newdocument undo redo | bold italic | bullist | bullist | highlight',
+        language: 'fr_FR',
+        resize: true,
+        statusbar: true,
+        browser_spellcheck : true,
+        branding: false,
+        menu: {},
+        setup: function (editor) {
+            editor.on("focusout", function () {
+                console.log(tinymce.get('description').getContent());
+                $('textarea').val(tinymce.get('description').getContent());
+            });
+            editor.addButton('highlight', {
+                text: '',
+                icon: 'codesample',
+                title: 'Définition',
+                onclick: function () {
+                    let content =  editor.selection.getContent();
+                    if (content !== '') {
+                        let new_content = "";
+                        let regex = /<abbr title="">.*<\/abbr>/g;
+                        let found = content.match(regex);
+                        if (found) {
+                            new_content = content.replace('</abbr>', '');
+                            new_content = new_content.replace('<abbr title="">', '');
+                        } else {
+                            new_content = '<abbr title="">' + content + '</abbr>';
+                        }
+                        editor.insertContent(new_content);
+                    }
+                }
+            });
+        }
+    });
+
+    $('select').selectpicker();
+</script>
+
+<style>
+    .ui-datepicker{
+        position: absolute;
+        z-index:1050 !important;
+    }
+   /*div.ui-datepicker {*/
+   /*    position: absolute;*/
+   /*     z-index:1050;*/
+   /* }*/
+   /* select.ui-datepicker-year option{*/
+   /* position: absolute;*/
+   /*     z-index:3151 !important;*/
+   /* }*/
+</style>
\ No newline at end of file
diff --git a/view/unicaen-parametre/default/probleme.phtml b/view/unicaen-parametre/default/probleme.phtml
new file mode 100644
index 000000000..55666398d
--- /dev/null
+++ b/view/unicaen-parametre/default/probleme.phtml
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @var string $title
+ * @var string $text
+ */
+
+?>
+
+<div class="alert alert-danger">
+    <p class="lead">
+        <?php echo $text; ?>
+    </p>
+</div>
+
diff --git a/view/unicaen-parametre/default/reponse.phtml b/view/unicaen-parametre/default/reponse.phtml
new file mode 100644
index 000000000..9026c479f
--- /dev/null
+++ b/view/unicaen-parametre/default/reponse.phtml
@@ -0,0 +1,8 @@
+<?php
+
+/**
+ * @var string $reponse
+ */
+
+?>
+<?php echo $reponse; ?>
diff --git a/view/unicaen-parametre/parametre/modifier-valeur.phtml b/view/unicaen-parametre/parametre/modifier-valeur.phtml
new file mode 100644
index 000000000..0d6d28cdc
--- /dev/null
+++ b/view/unicaen-parametre/parametre/modifier-valeur.phtml
@@ -0,0 +1,50 @@
+<?php
+
+
+/**
+ * @see \UnicaenParametre\Controller\ParametreController::modifierValeurAction()
+ * @var Parametre $parametre
+ */
+
+use UnicaenParametre\Entity\Db\Parametre;
+
+$possibles = ($parametre->getValeursPossibles())?explode('|',$parametre->getValeursPossibles()):null;
+$nbElement = ($possibles AND is_array($possibles))?count($possibles):(($possibles)?1:0);
+?>
+
+<form action="<?php echo $this->url('parametre/modifier-valeur', ['categorie' => $parametre->getCategorie()->getId(), 'parametre' => $parametre->getId()], [], true); ?>" method="post">
+
+    <label for="valeur">Ancienne valeur du paramètre :</label>
+    <input type="text" name="valeur" id="valeur" class="form-control" value="<?php echo $parametre->getValeur(); ?>" readonly>
+
+    <label for="valeur">Nouvelle valeur du paramètre : </label>
+    <?php if (empty($possibles)) : ?>
+        <input type="text" name="valeur" id="valeur" class="form-control"/>
+    <?php endif; ?>
+    <?php if ($nbElement > 1) : ?>
+        <select name="valeur" id="valeur" class="form-control">
+            <?php foreach ($possibles as $possible) : ?>
+            <option value="<?php echo $possible; ?>"> <?php echo $possible; ?></option>
+            <?php endforeach; ?>
+        </select>
+    <?php endif; ?>
+    <?php if ($nbElement === 1) : ?>
+        <?php if ($possibles[0] === 'String') : ?>
+            <input type="text" name="valeur" id="valeur" class="form-control" value="" placeholder="Renseignez la nouvelle valeur">
+        <?php endif; ?>
+        <?php if ($possibles[0] === 'Number') : ?>
+            <input type="number" name="valeur" id="valeur" class="form-control" value="" placeholder="Renseignez la nouvelle valeur">
+        <?php endif; ?>
+        <?php if ($possibles[0] === 'Boolean') : ?>
+        <div>
+            <input type="radio" id="true" name="valeur" value="true">
+            <label for="true"><i class="fas fa-check" style="color:darkgreen;"></i> true</label><br>
+            <input type="radio" id="false" name="valeur" value="false">
+            <label for="false"><i class="fas fa-times" style="color:darkred;"></i> false</label><br>
+        </div>
+        <?php endif; ?>
+    <?php endif; ?>
+    <br/>
+    <input type="submit" value="Enregistrer" class="btn btn-primary"/>
+</form>
+
-- 
GitLab