From ca325a0aed82c1acbc6a9ad3fbc4bbc1a4cb4440 Mon Sep 17 00:00:00 2001
From: Damien <damien.burel@maarch.org>
Date: Wed, 15 Nov 2017 16:11:24 +0100
Subject: [PATCH] [REFACTORING] Create Ext

---
 core/Controllers/ParametersController.php     |  31 +-
 core/Controllers/ResController.php            | 692 +-----------------
 core/Controllers/ResExtController.php         | 352 ---------
 core/Controllers/StoreController.php          |  72 ++
 core/Models/ChronoModel.php                   | 176 +++++
 ...ParametersModel.php => ParameterModel.php} |   3 +-
 ...bstract.php => ParameterModelAbstract.php} |  58 +-
 core/Models/ResExtModelAbstract.php           |  96 +--
 core/Models/ResModelAbstract.php              | 197 +++--
 core/Models/TextFormatModelAbstract.php       |   2 +-
 .../Controllers/AttachmentsController.php     |   4 +-
 .../Controllers/ReconciliationController.php  |   6 +-
 rest/index.php                                |   4 +-
 13 files changed, 461 insertions(+), 1232 deletions(-)
 delete mode 100755 core/Controllers/ResExtController.php
 create mode 100644 core/Models/ChronoModel.php
 rename core/Models/{ParametersModel.php => ParameterModel.php} (73%)
 mode change 100755 => 100644
 rename core/Models/{ParametersModelAbstract.php => ParameterModelAbstract.php} (60%)
 mode change 100755 => 100644

diff --git a/core/Controllers/ParametersController.php b/core/Controllers/ParametersController.php
index 322567bbb5c..41b92d8e6fe 100755
--- a/core/Controllers/ParametersController.php
+++ b/core/Controllers/ParametersController.php
@@ -11,26 +11,25 @@
 
 namespace Core\Controllers;
 
+use Core\Models\ParameterModel;
 use Psr\Http\Message\RequestInterface;
 use Psr\Http\Message\ResponseInterface;
 use Respect\Validation\Validator;
-use Core\Models\LangModel;
-use Core\Models\ParametersModel;
 
 class ParametersController
 {
     public function getParametersForAdministration(RequestInterface $request, ResponseInterface $response)
     {
         $obj = [
-                'parametersList'    =>  ParametersModel::getList(),
-                'lang'              =>  ParametersModel::getParametersLang()
+                'parametersList'    =>  ParameterModel::getList(),
+                'lang'              =>  ParameterModel::getParametersLang()
         ];
         return $response->withJson($obj);
     }
 
     public function getParameterForAdministration(RequestInterface $request, ResponseInterface $response, $aArgs)
     {
-        $obj['parameter'] = ParametersModel::getById(['id' => $aArgs['id']]);
+        $obj['parameter'] = ParameterModel::getById(['id' => $aArgs['id']]);
         
         if (empty($obj)) {
             return $response->withStatus(400)->withJson(['errors' => 'User not found']);
@@ -44,20 +43,20 @@ class ParametersController
             $obj['type'] = 'string';
         }
 
-        $obj['lang'] = ParametersModel::getParametersLang();
+        $obj['lang'] = ParameterModel::getParametersLang();
 
         return $response->withJson($obj);
     }
 
     public function getNewParameterForAdministration(RequestInterface $request, ResponseInterface $response)
     {
-        $obj['lang'] = ParametersModel::getParametersLang();
+        $obj['lang'] = ParameterModel::getParametersLang();
         return $response->withJson($obj);
     }
 
     public function getById(RequestInterface $request, ResponseInterface $response, $aArgs)
     {
-        $obj = ParametersModel::getById(['id' => $aArgs['id']]);
+        $obj = ParameterModel::getById(['id' => $aArgs['id']]);
         return $response->withJson($obj);
     }
     public function create(RequestInterface $request, ResponseInterface $response)
@@ -72,10 +71,10 @@ class ParametersController
         
         $datas = $request->getParams();
 
-        $return = ParametersModel::create($datas);
+        $return = ParameterModel::create($datas);
 
         if ($return) {
-            $obj = ParametersModel::getById(['id' => $datas['id']]);
+            $obj = ParameterModel::getById(['id' => $datas['id']]);
         } else {
             return $response
                 ->withStatus(500)
@@ -100,10 +99,10 @@ class ParametersController
         }
 
         $aArgs = $request->getParams();
-        $return = ParametersModel::update($aArgs);
+        $return = ParameterModel::update($aArgs);
 
         if ($return) {
-            $obj = ParametersModel::getById(['id' => $aArgs['id']]);
+            $obj = ParameterModel::getById(['id' => $aArgs['id']]);
         } else {
             return $response
                 ->withStatus(500)
@@ -119,11 +118,11 @@ class ParametersController
 
     public function delete(RequestInterface $request, ResponseInterface $response, $aArgs)
     {
-        $obj = ParametersModel::delete(['id' => $aArgs['id']]);
+        $obj = ParameterModel::delete(['id' => $aArgs['id']]);
         return $response->withJson(
             [
             'success'   =>  _PARAMETER. ' <b>' . $aArgs['id'] .'</b> ' ._DELETED,
-            'parameters'    =>  ParametersModel::getList()
+            'parameters'    =>  ParameterModel::getList()
             ]
         );
     }
@@ -133,7 +132,7 @@ class ParametersController
         $errors = [];
 
         if ($mode == 'update') {
-            $obj = ParametersModel::getById(
+            $obj = ParameterModel::getById(
                 [
                 'id' => $request->getParam('id'),
                 'param_value_int' => $request->getParam('param_value_int')
@@ -158,7 +157,7 @@ class ParametersController
             if (!Validator::regex('/^[0-9]*$/')->validate($request->getParam('param_value_int')) && $request->getParam('param_value_int')!=null) {
                 array_push($errors, _INVALID_INTEGER);
             }
-            $obj = ParametersModel::getById(['id' => $request->getParam('id')]);
+            $obj = ParameterModel::getById(['id' => $request->getParam('id')]);
             if (!empty($obj)) {
                 array_push($errors, _ID . ' ' . $obj[0]['id'] . ' ' . _ALREADY_EXISTS);
             }
diff --git a/core/Controllers/ResController.php b/core/Controllers/ResController.php
index 42352f0406e..c99b243c3da 100755
--- a/core/Controllers/ResController.php
+++ b/core/Controllers/ResController.php
@@ -15,39 +15,33 @@
 
 namespace Core\Controllers;
 
-use Core\Models\CoreConfigModel;
 use Psr\Http\Message\RequestInterface;
 use Psr\Http\Message\ResponseInterface;
 use Respect\Validation\Validator;
-use Core\Models\DocserverModel;
-use Core\Models\DocserverTypeModel;
-use Core\Models\UserModel;
 use Core\Models\ResModel;
 use Notes\Models\NoteModel;
 
-require_once 'core/class/class_db_pdo.php';
-
 class ResController
 {
+    //*****************************************************************************************
+    //LOG ONLY LOG FOR DEBUG
+    // $file = fopen('storeResourceLogs.log', a);
+    // fwrite($file, '[' . date('Y-m-d H:i:s') . '] new request' . PHP_EOL);
+    // foreach ($data as $key => $value) {
+    //     if ($key <> 'encodedFile') {
+    //         fwrite($file, '[' . date('Y-m-d H:i:s') . '] ' . $key . ' : ' . $value . PHP_EOL);
+    //     }
+    // }
+    // fclose($file);
+    // ob_flush();
+    // ob_start();
+    // print_r($data);
+    // file_put_contents("storeResourceLogs.log", ob_get_flush());
+    //END LOG FOR DEBUG ONLY
+    //*****************************************************************************************
     public function create(RequestInterface $request, ResponseInterface $response)
     {
         $data = $request->getParams();
-        //*****************************************************************************************
-        //LOG ONLY LOG FOR DEBUG
-        // $file = fopen('storeResourceLogs.log', a);
-        // fwrite($file, '[' . date('Y-m-d H:i:s') . '] new request' . PHP_EOL);
-        // foreach ($data as $key => $value) {
-        //     if ($key <> 'encodedFile') {
-        //         fwrite($file, '[' . date('Y-m-d H:i:s') . '] ' . $key . ' : ' . $value . PHP_EOL);
-        //     }
-        // }
-        // fclose($file);
-        // ob_flush();
-        // ob_start();
-        // print_r($data);
-        // file_put_contents("storeResourceLogs.log", ob_get_flush());
-        //END LOG FOR DEBUG ONLY
-        //*****************************************************************************************
 
         $check = Validator::notEmpty()->validate($data['encodedFile']);
         $check = $check && Validator::stringType()->notEmpty()->validate($data['fileFormat']);
@@ -68,28 +62,30 @@ class ResController
         return $response->withJson(['resId' => $resId]);
     }
 
-    public function delete(RequestInterface $request, ResponseInterface $response, $aArgs)
+    public function createExt(RequestInterface $request, ResponseInterface $response)
     {
-        if (isset($aArgs['id'])) {
-            $obj = $this->deleteRes([
-                'id' => $aArgs['id']
-            ]);
-            if (!$obj) {
-                return $response
-                    ->withStatus(500)
-                    ->withJson(['errors' => _NOT_DELETE]);
-            }
-        } else {
-            return $response
-                ->withStatus(500)
-                ->withJson(['errors' => _NOT_DELETE]);
+        $data = $request->getParams();
+
+        $check = Validator::intVal()->notEmpty()->validate($data['resId']);
+        $check = $check && Validator::arrayType()->notEmpty()->validate($data['data']);
+        if (!$check) {
+            return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
         }
-        
-        $datas = [
-            $obj,
-        ];
 
-        return $response->withJson($datas);
+        $document = ResModel::getById(['resId' => $data['resId'], 'select' => ['1']]);
+        if (empty($document)) {
+            return $response->withStatus(404)->withJson(['errors' => 'Document does not exist']);
+        }
+        $documentExt = ResModel::getExtById(['resId' => $data['resId'], 'select' => ['1']]);
+        if (!empty($documentExt)) {
+            return $response->withStatus(400)->withJson(['errors' => 'Document already exists in mlb_coll_ext']);
+        }
+
+        $formatedData = StoreController::prepareExtStorage(['resId' => $data['resId'], 'data' => $data['data']]);
+
+        ResModel::createExt($formatedData);
+
+        return $response->withJson(['resId' => $data['resId']]);
     }
 
     public function updateStatus(RequestInterface $request, ResponseInterface $response, $aArgs)
@@ -138,155 +134,6 @@ class ResController
         return $response->withJson(NoteModel::countForCurrentUserByResId(['resId' => $aArgs['resId']]));
     }
 
-    /**
-     * Deletes ext resource on database.
-     * @param  $resId  integer
-     * @param  $table  string
-     * @return res_id
-     */
-    public function deleteRes($aArgs)
-    {
-        if (isset($aArgs['id'])) {
-            $obj = ResModel::delete([
-                'id' => $aArgs['id']
-            ]);
-        } else {
-            return false;
-        }
-        
-        $datas = $obj;
-
-        return $datas;
-    }
-
-    /**
-     * Store resource on database.
-     * @param  $encodedFile  string
-     * @param  $data array
-     * @param  $collId  string
-     * @param  $table  string
-     * @param  $fileFormat  string
-     * @param  $status  string
-     * @return res_id
-     */
-    public function storeResource($aArgs)
-    {
-        if (empty($aArgs['encodedFile'])) {
-            return ['errors' => 'encodedFile ' . _EMPTY];
-        }
-
-        if (empty($aArgs['data'])) {
-            return ['errors' => 'data ' . _EMPTY];
-        }
-
-        if (empty($aArgs['collId'])) {
-            return ['errors' => 'collId ' . _EMPTY];
-        }
-
-        if (empty($aArgs['table'])) {
-            return ['errors' => 'table ' . _EMPTY];
-        }
-
-        if (empty($aArgs['fileFormat'])) {
-            return ['errors' => 'fileFormat ' . _EMPTY];
-        }
-
-        if (empty($aArgs['status'])) {
-            return ['errors' => 'status ' . _EMPTY];
-        }
-        $encodedFile = $aArgs['encodedFile'];
-        $data = $aArgs['data'];
-        $collId = $aArgs['collId'];
-        $table = $aArgs['table'];
-        $fileFormat = $aArgs['fileFormat'];
-        $status = $aArgs['status'];
-
-        try {
-            $count = count($data);
-            for ($i = 0; $i < $count; $i++) {
-                $data[$i]['column'] = strtolower($data[$i]['column']);
-            }
-            
-            $returnCode = 0;
-            //copy sended file on tmp
-            //$fileContent = base64_decode($encodedFile);
-            $fileContent = base64_decode(str_replace(array('-', '_'), array('+', '/'), $encodedFile));
-            $random = rand();
-            $fileName = 'tmp_file_' . $random . '.' . $fileFormat;
-            $Fnm = CoreConfigModel::getTmpPath() . $fileName;
-            $inF = fopen($Fnm, "w");
-            fwrite($inF, $fileContent);
-            fclose($inF);
-
-            //store resource on docserver
-            $ds = new DocserverController();
-            $aArgs = [
-                'collId' => $collId,
-                'fileInfos' =>
-                    [
-                        'tmpDir'        => CoreConfigModel::getTmpPath(),
-                        'size'          => filesize($Fnm),
-                        'format'        => $fileFormat,
-                        'tmpFileName'   => $fileName,
-                    ]
-            ];
-            
-            $storeResult = array();
-            $storeResult = $ds->storeResourceOnDocserver($aArgs);
-            
-            if (!empty($storeResult['errors'])) {
-                return ['errors' => $storeResult['errors']];
-            }
-
-            //store resource metadata in database
-            $aArgs = [
-                'data'        => $data,
-                'docserverId' => $storeResult['docserver_id'],
-                'status'      => $status,
-                'fileFormat'  => $fileFormat,
-            ];
-            
-            $data = $this->prepareStorage($aArgs);
-            
-            unlink($Fnm);
-
-            $aArgs = [
-                'table'         => $table,
-                'path'          => $storeResult['destination_dir'],
-                'filename'      => $storeResult['file_destination_name'],
-                'docserverPath' => $storeResult['path_template'],
-                'docserverId'   => $storeResult['docserver_id'],
-                'docserverPath' => $storeResult['path_template'],
-                'data'          => $data,
-            ];
-
-            $this->loadIntoDb($aArgs);
-
-            $resDetails = ResModel::getByPath([
-                'docserverId' => $storeResult['docserver_id'],
-                'path'        => $storeResult['destination_dir'],
-                'filename'    => $storeResult['file_destination_name'],
-                'table'       => $aArgs['table'],
-                'select'      => ['res_id']
-            ]);
-            
-            $resId = $resDetails[0]['res_id'];
-            
-
-            if (!is_numeric($resId)) {
-                return ['errors' => 'Pb with SQL insertion : ' .$resId];
-            }
-
-            if ($resId == 0) {
-                $resId = '';
-            }
-
-            return [$resId];
-        } catch (Exception $e) {
-            return ['errors' => 'unknown error' . $e->getMessage()];
-        }
-    }
-
     public function update(RequestInterface $request, ResponseInterface $response, $aArgs)
     {
         if(empty($aArgs)){
@@ -352,471 +199,6 @@ class ResController
         return $datas;
     }
 
-    /**
-    * Inserts the Resource Object data into the data base
-    *
-    * @param  $table string Resource table where to insert
-    * @param  $path  string Resource path in the docserver
-    * @param  $filename string Resource file name
-    * @param  $docserverPath  string Docserver path
-    * @param  $docserverId  string Docserver identifier
-    * @param  boolean
-    */
-    public function loadIntoDb($aArgs)
-    {
-        $db = new \Database();
-        if (empty($aArgs['table'])) {
-            return ['errors' => 'table ' . _EMPTY];
-        }
-
-        if (empty($aArgs['path'])) {
-            return ['errors' => 'path ' . _EMPTY];
-        }
-
-        if (empty($aArgs['filename'])) {
-            return ['errors' => 'filename ' . _EMPTY];
-        }
-
-        if (empty($aArgs['docserverPath'])) {
-            return ['errors' => 'docserverPath ' . _EMPTY];
-        }
-
-        if (empty($aArgs['docserverId'])) {
-            return ['errors' => 'docserverId ' . _EMPTY];
-        }
-
-        if (empty($aArgs['data'])) {
-            return ['errors' => 'data ' . _EMPTY];
-        }
-        $table = $aArgs['table'];
-        $path = $aArgs['path'];
-        $filename = $aArgs['filename'];
-        $docserverPath = $aArgs['docserverPath'];
-        $docserverId = $aArgs['docserverId'];
-        $data = $aArgs['data'];
-
-        $filetmp = $docserverPath;
-        $tmp = $path;
-        $tmp = str_replace('#', DIRECTORY_SEPARATOR, $tmp);
-        $filetmp .= $tmp;
-        $filetmp .= $filename;
-        
-        $docserver = DocserverModel::getById([
-            'docserver_id' => $docserverId
-        ]);
-        $docserverType = DocserverTypeModel::getById([
-            'docserver_type_id' => $docserver[0]['docserver_type_id']
-        ]);
-
-        $fingerprint = DocserverToolsController::doFingerprint(
-            [
-                'path'            => $filetmp,
-                'fingerprintMode' => $docserverType[0]['fingerprint_mode'],
-            ]
-        );
-
-        $filesize = filesize($filetmp);
-        array_push(
-            $data,
-            array(
-                'column' => "fingerprint",
-                'value' => $fingerprint['fingerprint'],
-                'type' => "string"
-            )
-        );
-        array_push(
-            $data,
-            array(
-                'column' => "filesize",
-                'value' => $filesize,
-                'type' => "int"
-            )
-        );
-        array_push(
-            $data,
-            array(
-                'column' => "path",
-                'value' => $path,
-                'type' => "string"
-            )
-        );
-        array_push(
-            $data,
-            array(
-                'column' => "filename",
-                'value' => $filename,
-                'type' => "string"
-            )
-        );
-        array_push(
-            $data,
-            array(
-                'column' => 'creation_date',
-                'value' => $db->current_datetime(),
-                'type' => "function"
-            )
-        );
-        $testBasicFields = $this->checkBasicFields($data);
-
-        if (!$testBasicFields['status']) {
-            return ['error' => $testBasicFields['error']];
-        } else {
-            $prepareData = [];
-            $countD = count($data);
-            for ($i = 0; $i < $countD; $i++) {
-                //COLUMN
-                $data[$i]['column'] = strtolower($data[$i]['column']);
-                //VALUE
-                $prepareData[$data[$i]['column']] = $data[$i]['value'];
-            }
-
-            $resInsert = ResModel::create([
-                'table' => $table,
-                'data'  => $prepareData
-            ]);
-
-            return true;
-        }
-    }
-
-    /**
-    * Checks the mininum fields required for an insert into the database
-    *
-    * @param  $data array Array of the fields to insert into the database
-    * @return error $error
-    */
-    private function checkBasicFields($data)
-    {
-        $error = '';
-        $db = new \Database();
-        $find_format = false;
-        $find_typist = false;
-        $find_creation_date = false;
-        $find_docserver_id = false;
-        $find_path = false;
-        $find_filename = false;
-        $find_offset = false;
-        $find_logical_adr = false;
-        $find_fingerprint = false;
-        $find_filesize = false;
-        $find_status = false;
-        for ($i=0; $i < count($data); $i++) {
-            if ($data[$i]['column'] == 'format') {
-                $find_format = true;
-                // must be tested in the file_index.php file (module = indexing_searching)
-            } elseif ($data[$i]['column'] == 'typist') {
-                $find_typist = true;
-            } elseif ($data[$i]['column'] == 'creation_date') {
-                $find_creation_date = true;
-                if ($data[$i]['value'] <> $db->current_datetime()) {
-                    $error .= _CREATION_DATE_ERROR;
-                }
-            } elseif ($data[$i]['column'] == 'docserver_id') {
-                $find_docserver_id =  true;
-            } elseif ($data[$i]['column'] == 'path') {
-                $find_path = true;
-                if (empty($data[$i]['value'])) {
-                    $error .= _PATH_ERROR;
-                }
-            } elseif ($data[$i]['column'] == 'filename') {
-                $find_filename = true;
-                if (!preg_match(
-                    "/^[\w-.]+.([a-zA-Z-0-9][a-zA-Z-0-9][a-zA-Z-0-9][a-zA-Z-0-9]?|maarch)$/",
-                    $data[$i]['value']
-                )
-                ) {
-                    $error .= _FILENAME_ERROR . ' ' . $data[$i]['value'] . '<br/>';
-                }
-            } elseif ($data[$i]['column'] == "offset_doc") {
-                $find_offset = true;
-            } elseif ($data[$i]['column'] == 'logical_adr') {
-                $find_logical_adr = true;
-            } elseif ($data[$i]['column'] == 'fingerprint') {
-                $find_fingerprint  = true;
-                if (!preg_match("/^[0-9A-Fa-f]+$/", $data[$i]['value'])) {
-                    $error .= _FINGERPRINT_ERROR;
-                }
-            } elseif ($data[$i]['column'] == 'filesize') {
-                $find_filesize = true;
-                if ($data[$i]['value'] <= 0) {
-                    $error .= _FILESIZE_ERROR;
-                }
-            } elseif ($data[$i]['column'] == 'status') {
-                $find_status = true;
-            }
-        }
-
-        if ($find_format == false) {
-            $error .= _MISSING_FORMAT;
-        }
-        if ($find_typist == false) {
-            $error .= _MISSING_TYPIST;
-        }
-        if ($find_creation_date == false) {
-            $error .= _MISSING_CREATION_DATE;
-        }
-        if ($find_docserver_id == false) {
-            $error .= _MISSING_DOCSERVER_ID;
-        }
-        if ($find_path == false) {
-            $error .= _MISSING_PATH;
-        }
-        if ($find_filename == false) {
-            $error .= _MISSING_FILENAME;
-        }
-        if ($find_offset == false) {
-            $error .= _MISSING_OFFSET;
-        }
-        if ($find_logical_adr == false) {
-            $error .= _MISSING_LOGICAL_ADR;
-        }
-        if ($find_fingerprint == false) {
-            $error .= _MISSING_FINGERPRINT;
-        }
-        if ($find_filesize == false) {
-            $error .= _MISSING_FILESIZE;
-        }
-        if ($find_status == false) {
-            $error .= _MISSING_STATUS;
-        }
-
-        if (!empty($error)) {
-            $status = false;
-        } else {
-            $status = true;
-        }
-
-        return [
-            'status' => $status,
-            'error'  => $error
-        ];
-    }
-
-    /**
-     * Prepares storage on database.
-     * @param  $data array
-     * @param  $docserverId string
-     * @param  $status string
-     * @param  $fileFormat string
-     * @return array $data
-     */
-    public function prepareStorage($aArgs)
-    {
-        if (empty($aArgs['data'])) {
-            return ['errors' => 'data ' . _EMPTY];
-        }
-
-        if (empty($aArgs['docserverId'])) {
-            return ['errors' => 'docserverId ' . _EMPTY];
-        }
-
-        if (empty($aArgs['status'])) {
-            return ['errors' => 'status ' . _EMPTY];
-        }
-
-        if (empty($aArgs['fileFormat'])) {
-            return ['errors' => 'fileFormat ' . _EMPTY];
-        }
-
-        $statusFound = false;
-        $typistFound = false;
-        $typeIdFound = false;
-        $toAddressFound = false;
-        $userPrimaryEntity = false;
-        $destinationFound = false;
-        $initiatorFound = false;
-        
-        $data = $aArgs['data'];
-        $docserverId = $aArgs['docserverId'];
-        $status = $aArgs['status'];
-        $fileFormat = $aArgs['fileFormat'];
-
-        $userModel = new UserModel();
-        $entityModel = new \Entities\Models\EntityModel();
-
-        $countD = count($data);
-        for ($i = 0; $i < $countD; $i++) {
-            if (strtoupper($data[$i]['type']) == 'INTEGER' ||
-                strtoupper($data[$i]['type']) == 'FLOAT'
-            ) {
-                if ($data[$i]['value'] == '') {
-                    $data[$i]['value'] = '0';
-                }
-            }
-
-            if (strtoupper($data[$i]['type']) == 'STRING') {
-                $data[$i]['value'] = str_replace(";", "", $data[$i]['value']);
-                $data[$i]['value'] = str_replace("--", "", $data[$i]['value']);
-            }
-
-            if (strtoupper($data[$i]['column']) == strtoupper('status')) {
-                $statusFound = true;
-            }
-
-            if (strtoupper($data[$i]['column']) == strtoupper('typist')) {
-                $typistFound = true;
-            }
-
-            if (strtoupper($data[$i]['column']) == strtoupper('type_id')) {
-                $typeIdFound = true;
-            }
-
-            if (strtoupper($data[$i]['column']) == strtoupper('custom_t10')) {
-                $mail = array();
-                $theString = str_replace(">", "", $data[$i]['value']);
-
-                $mail = explode("<", $theString);
-                $user = $userModel->getByEmail(['mail' => $mail[count($mail) -1]]);
-
-                $userIdFound = $user[0]['user_id'];
-                if (!empty($userIdFound)) {
-                    $toAddressFound = true;
-                    $destUser = $userIdFound;
-                    $entity = $entityModel->getByUserId(['userId' => $destUser]);
-                    if (!empty($entity[0]['entity_id'])) {
-                        $userEntity = $entity[0]['entity_id'];
-                        $userPrimaryEntity = true;
-                    }
-                } else {
-                    $entity = $entityModel->getByEmail(['email' => $mail[count($mail) -1]]);
-                    if (!empty($entity[0]['entity_id'])) {
-                        $userPrimaryEntity = true;
-                    }
-                }
-            }
-        }
-
-        if (!$typistFound && !$toAddressFound) {
-            array_push(
-                $data,
-                array(
-                    'column' => 'typist',
-                    'value' => 'auto',
-                    'type' => 'string',
-                )
-            );
-        }
-
-        if (!$typeIdFound) {
-            array_push(
-                $data,
-                array(
-                    'column' => 'type_id',
-                    'value' => '10',
-                    'type' => 'string',
-                )
-            );
-        }
-        
-        if (!$statusFound) {
-            array_push(
-                $data,
-                array(
-                    'column' => 'status',
-                    'value' => $status,
-                    'type' => 'string',
-                )
-            );
-        }
-        
-        if ($toAddressFound) {
-            array_push(
-                $data,
-                array(
-                    'column' => 'dest_user',
-                    'value' => $destUser,
-                    'type' => 'string',
-                )
-            );
-            array_push(
-                $data,
-                array(
-                    'column' => 'typist',
-                    'value' => $destUser,
-                    'type' => 'string',
-                )
-            );
-        }
-        
-        if ($userPrimaryEntity) {
-            for ($i = 0; $i < count($data); $i++) {
-                if (strtoupper($data[$i]['column']) == strtoupper('destination')) {
-                    if ($data[$i]['value'] == "") {
-                        $data[$i]['value'] = $userEntity;
-                    }
-                    $destinationFound = true;
-                    break;
-                }
-            }
-            if (!$destinationFound) {
-                array_push(
-                    $data,
-                    array(
-                        'column' => 'destination',
-                        'value' => $userEntity,
-                        'type' => 'string',
-                    )
-                );
-            }
-        }
-        
-        if ($userPrimaryEntity) {
-            for ($i = 0; $i<count($data); $i++) {
-                if (strtoupper($data[$i]['column']) == strtoupper('initiator')) {
-                    if ($data[$i]['value'] == "") {
-                        $data[$i]['value'] = $userEntity;
-                    }
-                    $initiatorFound = true;
-                    break;
-                }
-            }
-            if (!$initiatorFound) {
-                array_push(
-                    $data,
-                    array(
-                        'column' => 'initiator',
-                        'value' => $userEntity,
-                        'type' => 'string',
-                    )
-                );
-            }
-        }
-        array_push(
-            $data,
-            array(
-                'column' => 'format',
-                'value' => $fileFormat,
-                'type' => 'string',
-            )
-        );
-        array_push(
-            $data,
-            array(
-                'column' => 'offset_doc',
-                'value' => '',
-                'type' => 'string',
-            )
-        );
-        array_push(
-            $data,
-            array(
-                'column' => 'logical_adr',
-                'value' => '',
-                'type' => 'string',
-            )
-        );
-        array_push(
-            $data,
-            array(
-                'column' => 'docserver_id',
-                'value' => $docserverId,
-                'type' => 'string',
-            )
-        );
-
-        return $data;
-    }
-
     /**
     * Convert an object to an array
     * @param  $object object to convert
diff --git a/core/Controllers/ResExtController.php b/core/Controllers/ResExtController.php
deleted file mode 100755
index 9e28cd58a9c..00000000000
--- a/core/Controllers/ResExtController.php
+++ /dev/null
@@ -1,352 +0,0 @@
-<?php
-
-/**
-* Copyright Maarch since 2008 under licence GPLv3.
-* See LICENCE.txt file at the root folder for more details.
-* This file is part of Maarch software.
-*
-*/
-
-/**
-* @brief Resource Controller
-* @author dev@maarch.org
-* @ingroup core
-*/
-
-namespace Core\Controllers;
-
-use Core\Models\ContactModel;
-use Psr\Http\Message\RequestInterface;
-use Psr\Http\Message\ResponseInterface;
-use Respect\Validation\Validator;
-use Core\Models\ResExtModel;
-
-require_once 'core/class/class_db_pdo.php';
-
-class ResExtController
-{
-    public function create(RequestInterface $request, ResponseInterface $response, $aArgs)
-    {
-        if (empty($aArgs)) {
-            $aArgs = $request->getParsedBody();
-        }
-
-        $aArgs['data'] = $this->object2array($aArgs['data']);
-        
-        // if(empty($aArgs)) {
-            
-        //     $aArgs = $request->getQueryParams();
-
-        //     $aArgs['data'] = json_decode($aArgs['data']);
-
-        //     $aArgs['data'] = $this->object2array($aArgs['data']);
-
-        //     //FIX pb if data has parent
-        //     if (isset($aArgs['data']['data'])) {
-        //         $aArgs['data'] = $aArgs['data']['data'];
-        //     }
-        // }
-
-        //*****************************************************************************************
-        //LOG ONLY LOG FOR DEBUG
-        // $file = fopen('storeResourceLogs.log', a);
-        // fwrite($file, '[' . date('Y-m-d H:i:s') . '] new request' . PHP_EOL);
-        // foreach ($aArgs as $key => $value) {
-        //     if ($key <> 'encodedFile') {
-        //         fwrite($file, '[' . date('Y-m-d H:i:s') . '] ' . $key . ' : ' . $value . PHP_EOL);
-        //     }
-        // }
-        // fclose($file);
-        // ob_flush();
-        // ob_start();
-        // print_r($aArgs['data']);
-        // file_put_contents("storeResourceLogs.log", ob_get_flush());
-        //END LOG FOR DEBUG ONLY
-        //*****************************************************************************************
-
-        $return = $this->storeExtResource($aArgs);
-
-        if ($return['errors']) {
-            return $response
-                ->withStatus(500)
-                ->withJson(
-                    ['errors' => _NOT_CREATE . ' ' . $return['errors']]
-                );
-        }
-        
-        //standardize ws response for MaarchCapture
-        $wsReturn['status'] = $return;
-        
-        return $response->withJson($wsReturn);
-    }
-
-    public function delete(RequestInterface $request, ResponseInterface $response, $aArgs)
-    {
-        if (isset($aArgs['id'])) {
-            $obj = $this->deleteExtRes([
-                'id' => $aArgs['id']
-            ]);
-            if (!$obj) {
-                return $response
-                    ->withStatus(500)
-                    ->withJson(['errors' => _NOT_DELETE]);
-            }
-        } else {
-            return $response
-                ->withStatus(500)
-                ->withJson(['errors' => _NOT_DELETE]);
-        }
-        
-        $datas = [
-            $obj,
-        ];
-
-        return $response->withJson($datas);
-    }
-
-    /**
-     * Deletes ext resource on database.
-     * @param  $resId  integer
-     * @param  $table  string
-     * @return res_id
-     */
-    public function deleteExtRes($aArgs)
-    {
-        if (isset($aArgs['id'])) {
-            $obj = ResExtModel::delete([
-                'id' => $aArgs['id']
-            ]);
-        } else {
-            return false;
-        }
-        
-        $datas = $obj;
-
-        return $datas;
-    }
-
-    /**
-     * Store ext resource on database.
-     * @param  $resId  integer
-     * @param  $data array
-     * @param  $table  string
-     * @return res_id
-     */
-    public function storeExtResource($aArgs)
-    {
-        if (empty($aArgs['resId'])) {
-            return ['errors' => 'resId ' . _EMPTY];
-        }
-
-        if (empty($aArgs['data'])) {
-            return ['errors' => 'data ' . _EMPTY];
-        }
-
-        if (empty($aArgs['table'])) {
-            return ['errors' => 'table ' . _EMPTY];
-        }
-
-        if (empty($aArgs['resTable'])) {
-            return ['errors' => 'resTable ' . _EMPTY];
-        }
-
-        $resDetails = ResExtModel::getById([
-            'resId'  => $aArgs['resId'],
-            'table'  => $aArgs['resTable'],
-            'select' => ['res_id']
-        ]);
-        
-        if (empty($resDetails[0]['res_id'])) {
-            return ['errors' => 'res_id ' . _OF . ' ' . $aArgs['resTable'] . ' ' . _NOT_EXISTS];
-        }
-
-        $resDetails = ResExtModel::getById([
-            'resId' => $aArgs['resId'],
-            'table' => $aArgs['table'],
-            'select' => ['res_id']
-        ]);
-        
-        if ($resDetails[0]['res_id'] > 0) {
-            return ['errors' => 'res_id ' . _OF . ' '  . $aArgs['table'] . ' ' . _EXISTS];
-        }
-        
-        $prepareData = $this->prepareStorageExt($aArgs);
-        
-        $resExtInsert = ResExtModel::create([
-            'table' => 'mlb_coll_ext',
-            'data'  => $prepareData
-        ]);
-
-        return true;
-    }
-
-    /**
-    * Convert an object to an array
-    * @param  $object object to convert
-    */
-    private function object2array($object)
-    {
-        $return = null;
-        if (is_array($object)) {
-            foreach ($object as $key => $value) {
-                $return[$key] = $this->object2array($value);
-            }
-        } else {
-            if (is_object($object)) {
-                $var = get_object_vars($object);
-                if ($var) {
-                    foreach ($var as $key => $value) {
-                        $return[$key] = ($key && !$value) ? null : $this->object2array($value);
-                    }
-                } else {
-                    return $object;
-                }
-            } else {
-                return $object;
-            }
-        }
-        return $return;
-    }
-
-    /**
-     * Prepares storage on database for resExt.
-     * @param  $data array
-     * @return array $data
-     */
-    public function prepareStorageExt($aArgs)
-    {
-        if (empty($aArgs['resId'])) {
-            return ['errors' => 'resId ' . _EMPTY];
-        }
-        if (empty($aArgs['data'])) {
-            return ['errors' => 'data ' . _EMPTY];
-        }
-        if (empty($aArgs['table'])) {
-            return ['errors' => 'table ' . _EMPTY];
-        }
-        $queryExtFields = '(';
-        $queryExtValues = '(';
-        $queryExtValuesFinal = '(';
-        $parameters = array();
-        $findProcessLimitDate = false;
-        $findProcessNotes = false;
-        $delayProcessNotes = 0;
-
-        $resId = $aArgs['resId'];
-        $table = $aArgs['table'];
-        $data = $aArgs['data'];
-        $countD = count($data);
-        for ($i = 0; $i < $countD; $i++) {
-            if ($data[$i]['column'] == 'process_limit_date') {
-                $findProcessLimitDate = true;
-            }
-            if ($data[$i]['column'] == 'process_notes') {
-                $findProcessNotes = true;
-                $don = explode(',', $data[$i]['value']);
-                $delayProcessNotes = $don['0'];
-                $calendarType = $don['1'];
-            }
-        }
-        
-        if ($table == 'mlb_coll_ext') {
-            $ResExtModel = new ResExtModel();
-            if ($delayProcessNotes > 0) {
-                $processLimitDate = $ResExtModel->retrieveProcessLimitDate([
-                    'resId' => $resId,
-                    'delayProcessNotes' => $delayProcessNotes,
-                    'calendarType' => $calendarType,
-                ]);
-            } else {
-                $processLimitDate = $ResExtModel->retrieveProcessLimitDate([
-                    'resId' => $resId
-                ]);
-            }
-        }
-
-        if (!$findProcessLimitDate && $processLimitDate <> '') {
-            array_push(
-                $data,
-                array(
-                'column' => 'process_limit_date',
-                'value' => $processLimitDate,
-                'type' => 'date',
-                )
-            );
-        }
-        require_once 'apps/maarch_entreprise/class/class_chrono.php';
-        $chronoX = new \chrono();
-        for ($i=0; $i<count($data); $i++) {
-            if (strtoupper($data[$i]['type']) == 'INTEGER' ||
-                strtoupper($data[$i]['type']) == 'FLOAT'
-            ) {
-                if ($data[$i]['value'] == '') {
-                    $data[$i]['value'] = '0';
-                }
-                $data[$i]['value'] = str_replace(',', '.', $data[$i]['value']);
-            }
-            if (strtoupper($data[$i]['column']) == strtoupper('category_id')) {
-                $categoryId = $data[$i]['value'];
-            }
-            if (strtoupper($data[$i]['column']) == strtoupper('alt_identifier') &&
-                $data[$i]['value'] == ""
-            ) {
-                if ($table == 'mlb_coll_ext') {
-                    $resDetails = ResExtModel::getById([
-                        'resId' => $resId,
-                        'table' => 'res_letterbox',
-                        'select' => ['destination, type_id']
-                    ]);
-                    $myVars = array(
-                        'entity_id' => $resDetails[0]['destination'],
-                        'type_id' => $resDetails[0]['type_id'],
-                        'category_id' => $categoryId,
-                        'folder_id' => "",
-                    );
-                    $myChrono = $chronoX->generate_chrono($categoryId, $myVars, 'false');
-                    $data[$i]['value'] = $myChrono;
-                }
-            }
-            if (strtoupper($data[$i]['column']) == strtoupper('exp_contact_id') &&
-                $data[$i]['value'] <> "" &&
-                !is_numeric($data[$i]['value'])
-            ) {
-                $theString = str_replace(">", "", $data[$i]['value']);
-                $mail = explode("<", $theString);
-                $contactDetails = ContactModel::getByEmail([
-                    'email' => $mail[count($mail) -1],
-                    'select' => ['contact_id']
-                ]);
-                if ($contactDetails[0]['contact_id'] <> "") {
-                    $data[$i]['value'] = $contactDetails[0]['contact_id'];
-                } else {
-                    $data[$i]['value'] = 0;
-                }
-                $data[$i]['type'] = 'integer';
-            }
-            if (strtoupper($data[$i]['column']) == strtoupper('address_id') &&
-                $data[$i]['value'] <> "" &&
-                !is_numeric($data[$i]['value'])
-            ) {
-                $theString = str_replace(">", "", $data[$i]['value']);
-                $mail = explode("<", $theString);
-                $contactDetails = ContactModel::getByEmail([
-                    'email' => $mail[count($mail) -1],
-                    'select' => ['ca_id']
-                ]);
-                if ($contactDetails[0]['ca_id'] <> "") {
-                    $data[$i]['value'] = $contactDetails[0]['ca_id'];
-                } else {
-                    $data[$i]['value'] = 0;
-                }
-                $data[$i]['type'] = 'integer';
-            }
-            //COLUMN
-            $data[$i]['column'] = strtolower($data[$i]['column']);
-            //VALUE
-            $parameters[$data[$i]['column']] = $data[$i]['value'];
-        }
-        $parameters['res_id'] = $resId;
-
-        return $parameters;
-    }
-}
diff --git a/core/Controllers/StoreController.php b/core/Controllers/StoreController.php
index 3a863bd17a7..751feb02f46 100644
--- a/core/Controllers/StoreController.php
+++ b/core/Controllers/StoreController.php
@@ -16,9 +16,12 @@
 namespace Core\Controllers;
 
 use Attachments\Models\AttachmentsModel;
+use Core\Models\ChronoModel;
+use Core\Models\ContactModel;
 use Core\Models\CoreConfigModel;
 use Core\Models\DocserverModel;
 use Core\Models\DocserverTypeModel;
+use Core\Models\ResExtModel;
 use Core\Models\ResModel;
 use Core\Models\UserModel;
 use Core\Models\ValidatorModel;
@@ -578,4 +581,73 @@ class StoreController
 
         return $formatedData;
     }
+
+    public static function prepareExtStorage(array $aArgs)
+    {
+        ValidatorModel::notEmpty($aArgs, ['data', 'resId']);
+        ValidatorModel::arrayType($aArgs, ['data']);
+        ValidatorModel::intVal($aArgs, ['resId']);
+
+        $processLimitDateFound  = false;
+
+        foreach ($aArgs['data'] as $key => $value) {
+            $aArgs['data'][$key]['column'] = strtolower($value['column']);
+        }
+
+        foreach ($aArgs['data'] as $value) {
+            if ($value['column'] == 'process_limit_date') {
+                $processLimitDateFound = true;
+            }
+            if ($value['column'] == 'category_id') {
+                $categoryId = $value['value'];
+            }
+        }
+
+        if (!$processLimitDateFound) {
+            $processLimitDate = ResExtModel::retrieveProcessLimitDate(['resId' => $aArgs['resId']]);
+
+            $aArgs['data'][] = [
+                'column'    => 'process_limit_date',
+                'value'     => $processLimitDate,
+                'type'      => 'date'
+            ];
+        }
+
+        foreach ($aArgs['data'] as $key => $value) {
+            if (strtolower($value['type']) == 'integer' || strtolower($value['type']) == 'float') {
+                if ($value['value'] == '') {
+                    $aArgs['data'][$key]['value'] = '0';
+                }
+                $aArgs['data'][$key]['value'] = str_replace(',', '.', $value['value']);
+            }
+            if ($value['column'] == 'alt_identifier' && empty($value['value']) && !empty($categoryId)) {
+                $document = ResModel::getById(['resId' => $aArgs['resId'], 'select' => ['destination, type_id']]);
+                $aArgs['data'][$key]['value'] = ChronoModel::getChrono(['id' => $categoryId, 'entityId' => $document['destination'], 'typeId' => $document['type_id']]);
+            } elseif ($value['column'] == 'exp_contact_id' && !empty($value['value']) && !is_numeric($value['value'])) {
+                $mail = explode('<', str_replace('>', '', $value['value']));
+                $contact = ContactModel::getByEmail(['email' => $mail[count($mail) - 1], 'select' => ['contact_id']]);
+                if (!empty($contact[0]['contact_id'])) {
+                    $aArgs['data'][$key]['value'] = $contact[0]['contact_id'];
+                } else {
+                    $aArgs['data'][$key]['value'] = 0;
+                }
+            } elseif ($value['column'] == 'address_id' && !empty($value['value']) && !is_numeric($value['value'])) {
+                $mail = explode('<', str_replace('>', '', $value['value']));
+                $contact = ContactModel::getByEmail(['email' => $mail[count($mail) - 1], 'select' => ['ca_id']]);
+                if (!empty($contact[0]['ca_id'])) {
+                    $aArgs['data'][$key]['value'] = $contact[0]['ca_id'];
+                } else {
+                    $aArgs['data'][$key]['value'] = 0;
+                }
+            }
+        }
+
+        $formatedData = [];
+        foreach ($aArgs['data'] as $value) {
+            $formatedData[$value['column']] = $value['value'];
+        }
+        $formatedData['res_id'] = $aArgs['resId'];
+
+        return $formatedData;
+    }
 }
diff --git a/core/Models/ChronoModel.php b/core/Models/ChronoModel.php
new file mode 100644
index 00000000000..6889e8996de
--- /dev/null
+++ b/core/Models/ChronoModel.php
@@ -0,0 +1,176 @@
+<?php
+
+/**
+ * Copyright Maarch since 2008 under licence GPLv3.
+ * See LICENCE.txt file at the root folder for more details.
+ * This file is part of Maarch software.
+ *
+ */
+
+/**
+ * @brief Chrono Model
+ * @author dev@maarch.org
+ * @ingroup core
+ */
+
+namespace Core\Models;
+
+class ChronoModel
+{
+    public static function getChrono(array $aArgs)
+    {
+        ValidatorModel::notEmpty($aArgs, ['id']);
+        ValidatorModel::stringType($aArgs, ['id', 'entityId']);
+        ValidatorModel::intVal($aArgs, ['typeId', 'resId']);
+
+        $customId = CoreConfigModel::getCustomId();
+        if (file_exists("custom/{$customId}/apps/maarch_entreprise/xml/chrono.xml")) {
+            $path = "custom/{$customId}/apps/maarch_entreprise/xml/chrono.xml";
+        } else {
+            $path = 'apps/maarch_entreprise/xml/chrono.xml';
+        }
+
+        $elements = [];
+        if (file_exists($path)) {
+            $loadedXml = simplexml_load_file($path);
+
+            foreach ($loadedXml->CHRONO as $chrono) {
+                if ($chrono->id == $aArgs['id']) {
+                    $separator = (string)$chrono->separator;
+                    foreach ($chrono->ELEMENT as $chronoElement) {
+                        $elements[] = [
+                            'type'  => (string)$chronoElement->type,
+                            'value' => (string)$chronoElement->value
+                        ];
+                    }
+                }
+            }
+        }
+
+        foreach ($elements as $key => $value) {
+            if (!empty($value['type'])) {
+                if ($value['type'] == 'date') {
+                    if ($value['value'] == 'year') {
+                        $elements[$key]['value'] = date('Y');
+                    } else if ($value['value'] == 'month') {
+                        $elements[$key]['value'] = date('m');
+                    } else if ($value['value'] == 'day') {
+                        $elements[$key]['value'] = date('d');
+                    } else if ($value['value'] == 'full_date') {
+                        $elements[$key]['value'] = date('dmY');
+                    }
+                } elseif ($value['type'] == 'maarch_var') {
+                    if ($value['value'] == "entity_id") {
+                        $elements[$key]['value'] = $aArgs['entityId'];
+                    } else if ($value['value'] == 'type_id') {
+                        $elements[$key]['value'] = $aArgs['typeId'];
+                    }
+                } elseif ($value['TYPE'] == 'maarch_functions') {
+                    if ($value['value'] == 'chr_global') {
+                        $elements[$key]['value'] = ChronoModel::getChronoGlobal();
+                    } else if ($value['value'] == 'chr_by_entity') {
+                        $elements[$key]['value'] = ChronoModel::getChronoEntity($aArgs['entityId']);
+                    } else if ($value['value'] == 'chr_by_category') {
+                        $elements[$key]['value'] = ChronoModel::getChronoCategory($aArgs['id']);
+                    } else if ($value['value'] == 'category_char') {
+                        $elements[$key]['value'] = ChronoModel::getChronoCategoryChar($aArgs['id']);
+                    } else if ($value['value'] == 'chr_by_folder') {
+                        $elements[$key]['value'] = ChronoModel::getChronoFolder($aArgs['folderId']);
+                    } else if ($value['value'] == 'chr_by_res_id') {
+                        $elements[$key]['value'] = $aArgs['resId'];
+                    }
+                }
+            }
+        }
+
+        if (empty($separator)) {
+            $separator = '/';
+        }
+        $chrono = $separator . implode($separator, $elements);
+
+        return $chrono;
+    }
+
+    public static function getChronoGlobal()
+    {
+        $chronoId = 'chrono_global_' . date('Y');
+
+        $parameter = ParameterModel::getById(['id' => $chronoId, 'select' => ['param_value_int']]);
+
+        if (empty($parameter)) {
+            ParameterModel::create(['id' => $chronoId, 'param_value_int' => 1]);
+            $chrono = 1;
+        } else {
+            $chrono = $parameter['param_value_int'];
+        }
+
+        ParameterModel::update(['id' => $chronoId, 'param_value_int' => $chrono + 1]);
+
+        return $chrono;
+    }
+
+    public static function getChronoEntity($entityId)
+    {
+        $chronoId = "chrono_{$entityId}_" . date('Y');
+
+        $parameter = ParameterModel::getById(['id' => $chronoId, 'select' => ['param_value_int']]);
+
+        if (empty($parameter)) {
+            ParameterModel::create(['id' => $chronoId, 'param_value_int' => 1]);
+            $chrono = 1;
+        } else {
+            $chrono = $parameter['param_value_int'];
+        }
+
+        ParameterModel::update(['id' => $chronoId, 'param_value_int' => $chrono + 1]);
+
+        return $entityId . "/" . $chrono;
+    }
+
+    public static function getChronoFolder($folderId)
+    {
+        $chronoId = "chrono_folder_{$folderId}";
+
+        $parameter = ParameterModel::getById(['id' => $chronoId, 'select' => ['param_value_int']]);
+
+        if (empty($parameter)) {
+            ParameterModel::create(['id' => $chronoId, 'param_value_int' => 1]);
+            $chrono = 1;
+        } else {
+            $chrono = $parameter['param_value_int'];
+        }
+
+        ParameterModel::update(['id' => $chronoId, 'param_value_int' => $chrono + 1]);
+
+        return $chrono;
+    }
+
+    public static function getChronoCategory($categoryId)
+    {
+        $chronoId = "chrono_{$categoryId}_" . date('Y');
+
+        $parameter = ParameterModel::getById(['id' => $chronoId, 'select' => ['param_value_int']]);
+
+        if (empty($parameter)) {
+            ParameterModel::create(['id' => $chronoId, 'param_value_int' => 1]);
+            $chrono = 1;
+        } else {
+            $chrono = $parameter['param_value_int'];
+        }
+
+        ParameterModel::update(['id' => $chronoId, 'param_value_int' => $chrono + 1]);
+
+        return "/" . $chrono;
+    }
+
+    public static function getChronoCategoryChar($categoryId)
+    {
+        if ($categoryId == 'incoming') {
+            return 'A';
+        } else if ($categoryId == 'outgoing') {
+            return 'D';
+        } else {
+            return '';
+        }
+    }
+}
diff --git a/core/Models/ParametersModel.php b/core/Models/ParameterModel.php
old mode 100755
new mode 100644
similarity index 73%
rename from core/Models/ParametersModel.php
rename to core/Models/ParameterModel.php
index 119c4f0e3e3..bbc9f6f62f8
--- a/core/Models/ParametersModel.php
+++ b/core/Models/ParameterModel.php
@@ -11,9 +11,8 @@
 
 namespace Core\Models;
 
-use Core\Models\ParametersModelAbstract;
 
-class ParametersModel extends ParametersModelAbstract
+class ParameterModel extends ParameterModelAbstract
 {
 
 }
\ No newline at end of file
diff --git a/core/Models/ParametersModelAbstract.php b/core/Models/ParameterModelAbstract.php
old mode 100755
new mode 100644
similarity index 60%
rename from core/Models/ParametersModelAbstract.php
rename to core/Models/ParameterModelAbstract.php
index a7d7d3af068..43a9a197457
--- a/core/Models/ParametersModelAbstract.php
+++ b/core/Models/ParameterModelAbstract.php
@@ -11,12 +11,10 @@
 
 namespace Core\Models;
 
-class ParametersModelAbstract
+class ParameterModelAbstract
 {
     public static function getList()
     {
-        $func = new \functions();
-
         $aReturn = DatabaseModel::select(
             ['select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
             'table'     => ['parameters']]
@@ -25,8 +23,8 @@ class ParametersModelAbstract
         foreach ($aReturn as $key => $parameter) {
 
             if ($parameter['param_value_date'] != null) {
-                $aReturn[$key]['param_value_date'] = $func->format_date($aReturn[$key]['param_value_date']);
-            }                
+                $aReturn[$key]['param_value_date'] =  TextFormatModel::formatDate($aReturn[$key]['param_value_date']);
+            }
         }
 
         return $aReturn;
@@ -38,39 +36,47 @@ class ParametersModelAbstract
         return $aLang;
     }
 
-    public static function getById(array $aArgs = [])
+    public static function getById(array $aArgs)
     {
         ValidatorModel::notEmpty($aArgs, ['id']);
         ValidatorModel::stringType($aArgs, ['id']);
 
-        $aReturn = DatabaseModel::select(
-            [
+        $parameter = DatabaseModel::select([
             'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
-            'table'     =>['parameters'],
+            'table'     => ['parameters'],
             'where'     => ['id = ?'],
             'data'      => [$aArgs['id']]
-            ]
-        );
-        if ($aReturn[0]['param_value_date'] != null) {
-            $aReturn[0]['param_value_date'] = TextFormatModel::format_date($aReturn[0]['param_value_date']);
+        ]);
+
+        if (empty($parameter[0])) {
+            return [];
+        }
+        if (!empty($parameter[0]['param_value_date'])) {
+            $parameter[0]['param_value_date'] = TextFormatModel::formatDate($parameter[0]['param_value_date']);
         }
-        
-        return $aReturn[0];
+
+        return $parameter[0];
     }
 
-    public static function create(array $aArgs = [])
+
+    public static function create(array $aArgs)
     {
         ValidatorModel::notEmpty($aArgs, ['id']);
-        ValidatorModel::stringType($aArgs, ['id']);
+        ValidatorModel::stringType($aArgs, ['id', 'description', 'param_value_string']);
+        ValidatorModel::intVal($aArgs, ['param_value_int']);
 
-        $aReturn = DatabaseModel::insert(
-            [
+        DatabaseModel::insert([
             'table'         => 'parameters',
-            'columnsValues' => $aArgs
+            'columnsValues' => [
+                'id'                    => $aArgs['id'],
+                'description'           => $aArgs['description'],
+                'param_value_string'    => $aArgs['param_value_string'],
+                'param_value_int'       => $aArgs['param_value_int'],
+                'param_value_date'      => $aArgs['param_value_date'],
             ]
-        );
+        ]);
 
-        return $aReturn;
+        return true;
     }
 
     public static function update(array $aArgs = [])
@@ -95,16 +101,12 @@ class ParametersModelAbstract
         ValidatorModel::notEmpty($aArgs, ['id']);
         ValidatorModel::stringType($aArgs, ['id']);
 
-        $aReturn = DatabaseModel::delete(
-            [
+        $aReturn = DatabaseModel::delete([
             'table' => 'parameters',
             'where' => ['id = ?'],
             'data'  => [$aArgs['id']]
-            ]
-        );
+        ]);
 
         return $aReturn;
     }
-
 }
-?>
\ No newline at end of file
diff --git a/core/Models/ResExtModelAbstract.php b/core/Models/ResExtModelAbstract.php
index adad157864a..f8a93784f0a 100755
--- a/core/Models/ResExtModelAbstract.php
+++ b/core/Models/ResExtModelAbstract.php
@@ -17,56 +17,8 @@ namespace Core\Models;
 
 class ResExtModelAbstract
 {
-    /**
-     * Retrieve info of resId
-     * @param  $aArgs array
-     *
-     * @return array
-     */
-    public static function getById(array $aArgs)
-    {
-        ValidatorModel::notEmpty($aArgs, ['resId']);
-        ValidatorModel::intVal($aArgs, ['resId']);
-
-        if (!empty($aArgs['table'])) {
-            $table = $aArgs['table'];
-        } else {
-            $table = 'mlb_coll_ext';
-        }
-
-        $aReturn = DatabaseModel::select([
-            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
-            'table'     => [$table],
-            'where'     => ['res_id = ?'],
-            'data'      => [$aArgs['resId']]
-        ]);
-
-        return $aReturn;
-    }
-
-    /**
-     * Retrieve info of last resId
-     * @param  $aArgs array
-     *
-     * @return array
-     */
-    public static function getLastId(array $aArgs = [])
-    {
-        if (!empty($aArgs['table'])) {
-            $table = $aArgs['table'];
-        } else {
-            $table = 'mlb_coll_ext';
-        }
-
-        $aReturn = DatabaseModel::select([
-            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
-            'table'     => [$table],
-            'order_by'  => ['res_id desc'],
-            'limit'     => 1,
-        ]);
 
-        return $aReturn;
-    }
+    //TODO Remove model after refactoring retrieveProcessLimitDate in ResModel
 
     /**
      * Retrieve process_limit_date for resource in extension table if mlb
@@ -74,7 +26,7 @@ class ResExtModelAbstract
      *
      * @return integer $processLimitDate
      */
-    public function retrieveProcessLimitDate(array $aArgs)
+    public static function retrieveProcessLimitDate(array $aArgs)
     {
         ValidatorModel::notEmpty($aArgs, ['resId']);
         ValidatorModel::intVal($aArgs, ['resId']);
@@ -148,48 +100,4 @@ class ResExtModelAbstract
 
         return $processLimitDate;
     }
-
-    /**
-     * insert into a resTable
-     * @param  $aArgs array
-     *
-     * @return boolean
-     */
-    public static function create(array $aArgs = [])
-    {
-        if (empty($aArgs['table'])) {
-            $aArgs['table'] = 'mlb_coll_ext';
-        }
-
-        DatabaseModel::insert([
-            'table'         => $aArgs['table'],
-            'columnsValues' => $aArgs['data']
-        ]);
-
-        return true;
-    }
-
-    /**
-     * deletes into a resTable
-     * @param  $aArgs array
-     *
-     * @return boolean
-     */
-    public static function delete(array $aArgs)
-    {
-        ValidatorModel::notEmpty($aArgs, ['id']);
-        ValidatorModel::intVal($aArgs, ['id']);
-
-        if (empty($aArgs['table'])) {
-            $aArgs['table'] = 'mlb_coll_ext';
-        }
-
-        DatabaseModel::delete([
-                'table' => $aArgs['table'],
-                'where' => ['res_id = ?'],
-                'data'  => [$aArgs['id']]
-        ]);
-
-        return true;
-    }
 }
diff --git a/core/Models/ResModelAbstract.php b/core/Models/ResModelAbstract.php
index ac7beac1462..1739348cf2a 100755
--- a/core/Models/ResModelAbstract.php
+++ b/core/Models/ResModelAbstract.php
@@ -36,6 +36,25 @@ class ResModelAbstract
         return $aReturn[0];
     }
 
+    public static function getExtById(array $aArgs)
+    {
+        ValidatorModel::notEmpty($aArgs, ['resId']);
+        ValidatorModel::intVal($aArgs, ['resId']);
+
+        $aReturn = DatabaseModel::select([
+            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
+            'table'     => ['mlb_coll_ext'],
+            'where'     => ['res_id = ?'],
+            'data'      => [$aArgs['resId']]
+        ]);
+
+        if (empty($aReturn[0])) {
+            return [];
+        }
+
+        return $aReturn[0];
+    }
+
     public static function updateStatus(array $aArgs = [])
     {
         ValidatorModel::notEmpty($aArgs, ['resId', 'status']);
@@ -53,62 +72,8 @@ class ResModelAbstract
 
         return true;
     }
-
-
-    /**
-     * Retrieve info of last resId
-     * @param  $aArgs array
-
-     * @return array $res
-     */
-    public static function getLastId(array $aArgs = [])
-    {
-        if (!empty($aArgs['table'])) {
-            $table = $aArgs['table'];
-        } else {
-            $table = 'res_letterbox';
-        }
-
-        $aReturn = DatabaseModel::select([
-            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
-            'table'     => [$table],
-            'order_by'  => ['res_id desc'],
-            'limit'     => 1,
-        ]);
-
-        return $aReturn;
-    }
-
-    /**
-     * Retrieve info of resId by path
-     * @param  $aArgs array
-     *
-     * @return array $res
-     */
-    public static function getByPath(array $aArgs = [])
-    {
-        ValidatorModel::notEmpty($aArgs, ['docserverId', 'path', 'filename']);
-        ValidatorModel::stringType($aArgs, ['docserverId', 'path', 'filename', 'table']);
-
-
-        if (!empty($aArgs['table'])) {
-            $table = $aArgs['table'];
-        } else {
-            $table = 'res_letterbox';
-        }
-
-        $aReturn = DatabaseModel::select([
-            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
-            'table'     => [$table],
-            'where'     => ['docserver_id = ? and path = ? and filename = ?'],
-            'data'      => [$aArgs['docserverId'], $aArgs['path'], $aArgs['filename']],
-            'order_by'  => ['res_id desc'],
-        ]);
-
-        return $aReturn;
-    }
-
-    public static function create(array $aArgs = [])
+    
+    public static function create(array $aArgs)
     {
         ValidatorModel::notEmpty($aArgs, ['format', 'typist', 'creation_date', 'docserver_id', 'path', 'filename', 'fingerprint', 'filesize', 'status']);
         ValidatorModel::stringType($aArgs, ['format', 'typist', 'creation_date', 'docserver_id', 'path', 'filename', 'fingerprint', 'status']);
@@ -125,26 +90,15 @@ class ResModelAbstract
         return $nextSequenceId;
     }
 
-    /**
-     * deletes into a resTable
-     * @param  $aArgs array
-     *
-     * @return boolean
-     */
-    public static function delete(array $aArgs = [])
+    public static function createExt(array $aArgs)
     {
-        ValidatorModel::notEmpty($aArgs, ['id']);
-        ValidatorModel::intVal($aArgs, ['id']);
-        ValidatorModel::stringType($aArgs, ['table']);
-
-        if (empty($aArgs['table'])) {
-            $aArgs['table'] = 'res_letterbox';
-        }
+        ValidatorModel::notEmpty($aArgs, ['res_id', 'category_id']);
+        ValidatorModel::stringType($aArgs, ['category_id']);
+        ValidatorModel::intVal($aArgs, ['res_id']);
 
-        DatabaseModel::delete([
-            'table' => $aArgs['table'],
-            'where' => ['res_id = ?'],
-            'data'  => [$aArgs['id']]
+        DatabaseModel::insert([
+            'table'         => 'mlb_coll_ext',
+            'columnsValues' => $aArgs
         ]);
 
         return true;
@@ -202,4 +156,99 @@ class ResModelAbstract
 
         return ['lock' => $lock, 'lockBy' => $lockBy];
     }
+
+    // In Progress
+//    public static function getProcessLimitDate(array $aArgs)
+//    {
+//        ValidatorModel::notEmpty($aArgs, ['resId']);
+//        ValidatorModel::intVal($aArgs, ['resId']);
+//
+//
+//
+//
+//        if (!empty($aArgs['table'])) {
+//            $table = $aArgs['table'];
+//        } else {
+//            $table = 'res_view_letterbox';
+//        }
+//        $aArgs['select'] = ['creation_date, admission_date, type_id'];
+//        $aReturn = static::select([
+//            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
+//            'table'     => [$table],
+//            'where'     => ['res_id = ?'],
+//            'data'      => [$aArgs['resId']]
+//        ]);
+//        require_once('core/class/class_functions.php');
+//        $func = new \functions();
+//        if ($aReturn[0]['type_id'] <> '') {
+//            $typeId = $aReturn[0]['type_id'];
+//            $admissionDate = $aReturn[0]['admission_date'];
+//            $creationDate = $aReturn[0]['creation_date'];
+//            $aArgs['select'] = ['process_delay'];
+//            $aReturnT = static::select([
+//                'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
+//                'table'     => ['mlb_doctype_ext'],
+//                'where'     => ['type_id = ?'],
+//                'data'      => [$aReturn[0]['type_id']]
+//            ]);
+//            $delay = $aReturnT[0]['process_delay'];
+//        }
+//        if ($admissionDate == '') {
+//            $dateToCompute = $creationDate;
+//        } else {
+//            $dateToCompute = $admissionDate;
+//        }
+//
+//
+//
+//
+//
+//        $document = ResModel::getById(['resId' => $aArgs['resId'], 'select' => ['creation_date', 'type_id']]);
+//
+//        if (!empty($document['type_id'])) {
+//            $doctypeExt = DatabaseModel::select([
+//                'select'    => ['process_delay'],
+//                'table'     => ['mlb_doctype_ext'],
+//                'where'     => ['type_id = ?'],
+//                'data'      => [$document['type_id']]
+//            ]);
+//            $processDelay = $doctypeExt[0]['process_delay'];
+//        }
+//
+//
+//
+//
+//        require_once('core/class/class_alert_engine.php');
+//        $alert_engine = new \alert_engine();
+//        if (isset($dateToCompute) && !empty($dateToCompute)) {
+//            $convertedDate = $alert_engine->dateFR2Time(
+//                str_replace(
+//                    "-",
+//                    "/",
+//                    $func->format_date_db(
+//                        $dateToCompute,
+//                        'true',
+//                        '',
+//                        'true'
+//                    )
+//                ),
+//                true
+//            );
+//
+//
+//            $date = $alert_engine->WhenOpenDay(
+//                $convertedDate,
+//                $delay,
+//                false,
+//                $aArgs['calendarType']
+//            );
+//        } else {
+//            $date = $alert_engine->date_max_treatment($delay, false);
+//        }
+//
+//        $processLimitDate = $func->dateformat($date, '-');
+//
+//        return $processLimitDate;
+//    }
+
 }
diff --git a/core/Models/TextFormatModelAbstract.php b/core/Models/TextFormatModelAbstract.php
index 9c71761cf81..b9d5f4fd2ae 100755
--- a/core/Models/TextFormatModelAbstract.php
+++ b/core/Models/TextFormatModelAbstract.php
@@ -32,7 +32,7 @@ class TextFormatModelAbstract
         return utf8_encode($string);
     }
 
-    public function format_date($date)
+    public static function formatDate($date)
     {
         $last_date = '';
 
diff --git a/modules/attachments/Controllers/AttachmentsController.php b/modules/attachments/Controllers/AttachmentsController.php
index 5c89a15c207..64e0e5c5509 100755
--- a/modules/attachments/Controllers/AttachmentsController.php
+++ b/modules/attachments/Controllers/AttachmentsController.php
@@ -15,6 +15,7 @@
 
 namespace Attachments\Controllers;
 
+use Core\Controllers\StoreController;
 use Psr\Http\Message\RequestInterface;
 use Psr\Http\Message\ResponseInterface;
 use Respect\Validation\Validator;
@@ -85,8 +86,7 @@ class AttachmentsController
             'status'        => $returnPrepare['status'],
         ];
 
-        $res = new \Core\Controllers\ResController();
-        $response = $res->storeResource($aArgs);
+        $response = StoreController::storeResource($aArgs);
 
         //return $response;
         if (!is_numeric($response[0])) {
diff --git a/modules/attachments/Controllers/ReconciliationController.php b/modules/attachments/Controllers/ReconciliationController.php
index 2b2b8f4ff81..42e0259eb46 100755
--- a/modules/attachments/Controllers/ReconciliationController.php
+++ b/modules/attachments/Controllers/ReconciliationController.php
@@ -351,11 +351,7 @@ class ReconciliationController{
             }
 
             unset($prepareData['res_id']); // NCH01
-            //var_dump($prepareData);
-            $resInsert = ResModel::create([
-                'table' => 'res_attachments',
-                'data'  => $prepareData
-            ]);
+            AttachmentsModel::create($prepareData);
 
             return true;
         }
diff --git a/rest/index.php b/rest/index.php
index f941d3b4108..e4c61c308fd 100755
--- a/rest/index.php
+++ b/rest/index.php
@@ -155,14 +155,12 @@ $app->put('/attachments/{id}/inSignatureBook', \Attachments\Controllers\Attachme
 
 //Res
 $app->post('/res', \Core\Controllers\ResController::class . ':create');
+$app->post('/resExt', \Core\Controllers\ResController::class . ':createExt');
 $app->put('/res', \Core\Controllers\ResController::class . ':update');
 $app->put('/res/{resId}/status', \Core\Controllers\ResController::class . ':updateStatus');
 $app->get('/res/{resId}/lock', \Core\Controllers\ResController::class . ':isLock');
 $app->get('/res/{resId}/notes/count', \Core\Controllers\ResController::class . ':getNotesCountForCurrentUserById');
 
-//extresource
-$app->post('/resExt', \Core\Controllers\ResExtController::class . ':create');
-
 //Users
 $app->get('/users/autocompleter', \Core\Controllers\UserController::class . ':getUsersForAutocompletion');
 $app->get('/users/profile', \Core\Controllers\UserController::class . ':getCurrentUserInfos');
-- 
GitLab