From c21b46b03f57d82f50ce766e36208084d933b797 Mon Sep 17 00:00:00 2001
From: Damien <damien.burel@maarch.org>
Date: Mon, 21 Oct 2019 15:12:46 +0200
Subject: [PATCH] FIX #12070 TIME 4:00 Controls and prepare storage

---
 .../documents_list_mlb_search_adv.php         |   2 +-
 migration/19.12/1912-postScript.sql           |   2 +
 modules/sendmail/mail_form.php                |   2 +-
 modules/sendmail/mail_form_to_contact.php     |   4 +-
 src/app/entity/models/EntityModelAbstract.php |   2 +-
 .../folder/controllers/FolderController.php   |   4 +-
 .../controllers/IndexingController.php        |  24 +--
 .../resource/controllers/ResController.php    | 154 +++++++++++++++---
 .../controllers/ResourceListController.php    |   2 +-
 .../resource/controllers/StoreController.php  | 125 +++++++-------
 src/app/resource/models/ResModelAbstract.php  |  47 +-----
 src/app/user/controllers/UserController.php   |  12 +-
 src/app/user/models/UserModelAbstract.php     |  10 +-
 src/core/controllers/CoreController.php       |   2 +-
 14 files changed, 230 insertions(+), 162 deletions(-)

diff --git a/apps/maarch_entreprise/indexing_searching/documents_list_mlb_search_adv.php b/apps/maarch_entreprise/indexing_searching/documents_list_mlb_search_adv.php
index 5c5466e229d..8a8a527839c 100755
--- a/apps/maarch_entreprise/indexing_searching/documents_list_mlb_search_adv.php
+++ b/apps/maarch_entreprise/indexing_searching/documents_list_mlb_search_adv.php
@@ -310,7 +310,7 @@ if ($mode == 'normal') {
         $whereFolders = 'res_id in (select res_id from resources_folders, folders, entities_folders ';
         $whereFolders .= 'where folders.id = entities_folders.folder_id AND folders.id = resources_folders.folder_id AND (user_id = :userSerialId OR entity_id in (:userEntitiesId)))';
         $user = \User\models\UserModel::getByLogin(['login' => $_SESSION['user']['UserId'], 'select' => ['id']]);
-        $entities = \User\models\UserModel::getEntitiesById(['userId' => $_SESSION['user']['UserId']]);
+        $entities = \User\models\UserModel::getEntitiesByLogin(['login' => $_SESSION['user']['UserId']]);
         $entities = array_column($entities, 'id');
 
         $arrayPDO[':userSerialId'] = $user['id'];
diff --git a/migration/19.12/1912-postScript.sql b/migration/19.12/1912-postScript.sql
index 060e3a10658..71d804175fb 100644
--- a/migration/19.12/1912-postScript.sql
+++ b/migration/19.12/1912-postScript.sql
@@ -6,6 +6,8 @@
 --                                                                          --
 -- *************************************************************************--
 
+DROP VIEW IF EXISTS res_view_letterbox;
+
 DROP TABLE IF EXISTS cases;
 DROP TABLE IF EXISTS cases_res;
 
diff --git a/modules/sendmail/mail_form.php b/modules/sendmail/mail_form.php
index 3492cfe5804..858fd52a089 100755
--- a/modules/sendmail/mail_form.php
+++ b/modules/sendmail/mail_form.php
@@ -109,7 +109,7 @@ $core_tools->load_header('', true, false);
 <body><?php
 $core_tools->load_js();
 
-$aUserEntities = \User\models\UserModel::getEntitiesById(['userId' => $_SESSION['user']['UserId']]);
+$aUserEntities = \User\models\UserModel::getEntitiesByLogin(['login' => $_SESSION['user']['UserId']]);
 $userEntities = [];
 foreach ($aUserEntities as $value) {
     $userEntities[] = $value['entity_id'];
diff --git a/modules/sendmail/mail_form_to_contact.php b/modules/sendmail/mail_form_to_contact.php
index 9428e54b303..6126b9204a5 100755
--- a/modules/sendmail/mail_form_to_contact.php
+++ b/modules/sendmail/mail_form_to_contact.php
@@ -117,7 +117,7 @@ $core_tools->load_header('', true, false);
 <body><?php
 $core_tools->load_js();
 
-$aUserEntities = \User\models\UserModel::getEntitiesById(['userId' => $_SESSION['user']['UserId']]);
+$aUserEntities = \User\models\UserModel::getEntitiesByLogin(['login' => $_SESSION['user']['UserId']]);
 $userEntities = [];
 foreach ($aUserEntities as $value) {
     $userEntities[] = $value['entity_id'];
@@ -518,4 +518,4 @@ echo $content;
 ?>
 </body>
 
-</html>
\ No newline at end of file
+</html>
diff --git a/src/app/entity/models/EntityModelAbstract.php b/src/app/entity/models/EntityModelAbstract.php
index 2361ac8baa1..512e5418660 100755
--- a/src/app/entity/models/EntityModelAbstract.php
+++ b/src/app/entity/models/EntityModelAbstract.php
@@ -277,7 +277,7 @@ abstract class EntityModelAbstract
             return $entities;
         }
 
-        $aReturn = UserModel::getEntitiesById(['userId' => $aArgs['userId']]);
+        $aReturn = UserModel::getEntitiesByLogin(['login' => $aArgs['userId']]);
         foreach ($aReturn as $value) {
             $entities = array_merge($entities, EntityModel::getEntityChildren(['entityId' => $value['entity_id']]));
         }
diff --git a/src/app/folder/controllers/FolderController.php b/src/app/folder/controllers/FolderController.php
index 2f6a845fe8b..38691ec14c8 100755
--- a/src/app/folder/controllers/FolderController.php
+++ b/src/app/folder/controllers/FolderController.php
@@ -790,7 +790,7 @@ class FolderController
         return $response->withStatus(204);
     }
 
-    private static function hasFolders(array $args)
+    public static function hasFolders(array $args)
     {
         ValidatorModel::notEmpty($args, ['folders', 'userId']);
         ValidatorModel::arrayType($args, ['folders']);
@@ -798,7 +798,7 @@ class FolderController
 
         $user = UserModel::getById(['id' => $args['userId'], 'select' => ['user_id']]);
 
-        $entities = UserModel::getEntitiesById(['userId' => $user['user_id']]);
+        $entities = UserModel::getEntitiesByLogin(['login' => $user['user_id']]);
         $entities = array_column($entities, 'id');
 
         if (empty($entities)) {
diff --git a/src/app/resource/controllers/IndexingController.php b/src/app/resource/controllers/IndexingController.php
index 99ecfa884de..04d9ca98a06 100755
--- a/src/app/resource/controllers/IndexingController.php
+++ b/src/app/resource/controllers/IndexingController.php
@@ -28,6 +28,17 @@ use SrcCore\models\ValidatorModel;
 
 class IndexingController
 {
+    const KEYWORDS = [
+        'ALL_ENTITIES'          => '@all_entities',
+        'ENTITIES_JUST_BELOW'   => '@immediate_children[@my_primary_entity]',
+        'ENTITIES_BELOW'        => '@subentities[@my_entities]',
+        'ALL_ENTITIES_BELOW'    => '@subentities[@my_primary_entity]',
+        'ENTITIES_JUST_UP'      => '@parent_entity[@my_primary_entity]',
+        'MY_ENTITIES'           => '@my_entities',
+        'MY_PRIMARY_ENTITY'     => '@my_primary_entity',
+        'SAME_LEVEL_ENTITIES'   => '@sisters_entities[@my_primary_entity]'
+    ];
+
     public function getIndexingActions(Request $request, Response $response, array $aArgs)
     {
         if (!Validator::intVal()->notEmpty()->validate($aArgs['groupId'])) {
@@ -58,17 +69,6 @@ class IndexingController
             return $response->withStatus(403)->withJson($indexingParameters);
         }
 
-        $keywords = [
-            'ALL_ENTITIES'          => '@all_entities',
-            'ENTITIES_JUST_BELOW'   => '@immediate_children[@my_primary_entity]',
-            'ENTITIES_BELOW'        => '@subentities[@my_entities]',
-            'ALL_ENTITIES_BELOW'    => '@subentities[@my_primary_entity]',
-            'ENTITIES_JUST_UP'      => '@parent_entity[@my_primary_entity]',
-            'MY_ENTITIES'           => '@my_entities',
-            'MY_PRIMARY_ENTITY'     => '@my_primary_entity',
-            'SAME_LEVEL_ENTITIES'   => '@sisters_entities[@my_primary_entity]'
-        ];
-
         $allowedEntities = [];
         $clauseToProcess = '';
 
@@ -76,7 +76,7 @@ class IndexingController
             if (!empty($clauseToProcess)) {
                 $clauseToProcess .= ', ';
             }
-            $clauseToProcess .= $keywords[$keywordValue];
+            $clauseToProcess .= IndexingController::KEYWORDS[$keywordValue];
         }
 
         if (!empty($clauseToProcess)) {
diff --git a/src/app/resource/controllers/ResController.php b/src/app/resource/controllers/ResController.php
index 55db53134db..bbc577d7463 100755
--- a/src/app/resource/controllers/ResController.php
+++ b/src/app/resource/controllers/ResController.php
@@ -24,6 +24,8 @@ use Convert\models\AdrModel;
 use CustomField\models\CustomFieldModel;
 use Docserver\models\DocserverModel;
 use Docserver\models\DocserverTypeModel;
+use Doctype\models\DoctypeModel;
+use Entity\models\EntityModel;
 use Entity\models\ListInstanceModel;
 use Folder\controllers\FolderController;
 use Folder\models\FolderModel;
@@ -34,6 +36,7 @@ use History\controllers\HistoryController;
 use IndexingModel\models\IndexingModelFieldModel;
 use IndexingModel\models\IndexingModelModel;
 use Note\models\NoteModel;
+use Priority\models\PriorityModel;
 use Resource\models\ResModel;
 use Respect\Validation\Validator;
 use setasign\Fpdi\Tcpdf\Fpdi;
@@ -71,22 +74,19 @@ class ResController
             return $response->withStatus(400)->withJson(['errors' => $control['errors']]);
         }
 
-        $folders = $body['folders'] ?? [];
-        $tags = $body['tags'] ?? [];
-        unset($body['folders'], $body['tags']);
-
         $resId = StoreController::storeResource($body);
         if (empty($resId) || !empty($resId['errors'])) {
             return $response->withStatus(500)->withJson(['errors' => '[ResController create] ' . $resId['errors']]);
         }
 
-        if (!empty($folders)) {
-            foreach ($folders as $folder) {
+        //TODO découper
+        if (!empty($body['folders'])) {
+            foreach ($body['folders'] as $folder) {
                 ResourceFolderModel::create(['res_id' => $resId, 'folder_id' => $folder]);
             }
         }
-        if (!empty($tags)) {
-            foreach ($tags as $tag) {
+        if (!empty($body['tags'])) {
+            foreach ($body['tags'] as $tag) {
                 TagResModel::create(['res_id' => $resId, 'tag_id' => $tag]);
             }
         }
@@ -99,15 +99,14 @@ class ResController
 
         $customId = CoreConfigModel::getCustomId();
         $customId = empty($customId) ? 'null' : $customId;
-        $user = UserModel::getByLogin(['select' => ['id'], 'login' => $GLOBALS['userId']]);
-        exec("php src/app/convert/scripts/FullTextScript.php --customId {$customId} --resId {$resId} --collId 'letterbox_coll' --userId {$user['id']} > /dev/null &");
+        exec("php src/app/convert/scripts/FullTextScript.php --customId {$customId} --resId {$resId} --collId 'letterbox_coll' --userId {$GLOBALS['id']} > /dev/null &");
 
         HistoryController::add([
             'tableName' => 'res_letterbox',
             'recordId'  => $resId,
             'eventType' => 'ADD',
             'info'      => _DOC_ADDED,
-            'moduleId'  => 'res',
+            'moduleId'  => 'resource',
             'eventId'   => 'resadd',
         ]);
 
@@ -656,7 +655,7 @@ class ResController
             }
         }
 
-        $entities = UserModel::getEntitiesById(['userId' => $user['user_id']]);
+        $entities = UserModel::getEntitiesByLogin(['login' => $user['user_id']]);
         $entities = array_column($entities, 'id');
 
         $foldersWithResources = FolderModel::getWithEntitiesAndResources([
@@ -810,6 +809,11 @@ class ResController
             return ['errors' => "Format with this mimeType is not allowed : {$body['format']} {$mimeType}"];
         }
 
+        $doctype = DoctypeModel::getById(['id' => $body['doctype'], 'select' => [1]]);
+        if (empty($doctype)) {
+            return ['errors' => 'Body doctype does not exist'];
+        }
+
         if (!empty($body['customFields'])) {
             if (!Validator::arrayType()->notEmpty()->validate($body['customFields'])) {
                 return ['errors' => 'Body customFields is not an array'];
@@ -857,26 +861,129 @@ class ResController
                     if ($indexingModelField['mandatory'] && empty($body['customFields'][$customFieldId])) {
                         return ['errors' => "Body customFields[{$customFieldId}] is empty"];
                     }
-                    $customField = CustomFieldModel::getById(['id' => $customFieldId, 'select' => ['type', 'values']]);
-                    $possibleValues = empty($customField['values']) ? [] : json_decode($customField['values']);
-                    if (($customField['type'] == 'select' || $customField['type'] == 'checkbox') && !in_array($body['customFields'][$customFieldId], $possibleValues)) {
-                        return ['errors' => "Body customFields[{$customFieldId}] has wrong value"];
-                    } elseif ($customField['type'] == 'checkbox') {
-                        if (!is_array($body['customFields'][$customFieldId])) {
-                            return ['errors' => "Body customFields[{$customFieldId}] is not an array"];
-                        }
-                        foreach ($body['customFields'][$customFieldId] as $value) {
-                            if (!in_array($value, $possibleValues)) {
-                                return ['errors' => "Body customFields[{$customFieldId}] has wrong value"];
+                    if (!empty($body['customFields'][$customFieldId])) {
+                        $customField = CustomFieldModel::getById(['id' => $customFieldId, 'select' => ['type', 'values']]);
+                        $possibleValues = empty($customField['values']) ? [] : json_decode($customField['values']);
+                        if (($customField['type'] == 'select' || $customField['type'] == 'checkbox') && !in_array($body['customFields'][$customFieldId], $possibleValues)) {
+                            return ['errors' => "Body customFields[{$customFieldId}] has wrong value"];
+                        } elseif ($customField['type'] == 'checkbox') {
+                            if (!is_array($body['customFields'][$customFieldId])) {
+                                return ['errors' => "Body customFields[{$customFieldId}] is not an array"];
+                            }
+                            foreach ($body['customFields'][$customFieldId] as $value) {
+                                if (!in_array($value, $possibleValues)) {
+                                    return ['errors' => "Body customFields[{$customFieldId}] has wrong value"];
+                                }
                             }
+                        } elseif ($customField['type'] == 'string' && !Validator::stringType()->notEmpty()->validate($body['customFields'][$customFieldId])) {
+                            return ['errors' => "Body customFields[{$customFieldId}] is not a string"];
+                        } elseif ($customField['type'] == 'integer' && !Validator::intVal()->notEmpty()->validate($body['customFields'][$customFieldId])) {
+                            return ['errors' => "Body customFields[{$customFieldId}] is not an integer"];
+                        } elseif ($customField['type'] == 'date' && !Validator::date()->notEmpty()->validate($body['customFields'][$customFieldId])) {
+                            return ['errors' => "Body customFields[{$customFieldId}] is not a date"];
                         }
                     }
                 } elseif ($indexingModelField['mandatory'] && empty($body[$indexingModelField['identifier']])) {
                     return ['errors' => "Body {$indexingModelField['identifier']} is empty"];
                 }
             }
+
+            if (!empty($body['initiator'])) {
+                $userEntities = UserModel::getEntitiesByLogin(['login' => $GLOBALS['userId']]);
+                $userEntities = array_column($userEntities, 'entity_id');
+                if (!in_array($body['initiator'], $userEntities)) {
+                    return ['errors' => "Body initiator does not belong to your entities"];
+                }
+            }
+
         }
 
+        if (!empty($body['destination'])) {
+            $groups = UserModel::getGroupsByLogin(['login' => $GLOBALS['userId']]);
+
+            $clauseToProcess = '';
+            $allowedEntities = [];
+            foreach ($groups as $group) {
+                if (!$group['can_index']) {
+                    continue;
+                }
+                $group['indexation_parameters'] = json_decode($group['indexation_parameters'], true);
+                foreach ($group['indexation_parameters']['keywords'] as $keywordValue) {
+                    if (strpos($clauseToProcess, IndexingController::KEYWORDS[$keywordValue]) === false) {
+                        if (!empty($clauseToProcess)) {
+                            $clauseToProcess .= ', ';
+                        }
+                        $clauseToProcess .= IndexingController::KEYWORDS[$keywordValue];
+                    }
+                }
+                $allowedEntities = array_merge($allowedEntities, $group['indexation_parameters']['entities']);
+                $allowedEntities = array_unique($allowedEntities);
+            }
+
+            $preparedClause = '';
+            if (!empty($clauseToProcess)) {
+                $preparedClause = PreparedClauseController::getPreparedClause(['clause' => $clauseToProcess, 'login' => $GLOBALS['userId']]);
+            }
+            if (!empty($allowedEntities)) {
+                $preparedEntities = EntityModel::get(['select' => ['entity_id'], 'where' => ['enabled = ?', 'id in (?)'], 'data' => ['Y', $allowedEntities]]);
+                $allowedEntities = array_column($preparedEntities, 'entity_id');
+            }
+
+            if (!in_array($body['destination'], $allowedEntities) && strpos($preparedClause, $body['destination']) === false) {
+                return ['errors' => "Body destination is out of your indexing parameters"];
+            }
+
+        }
+
+        if (!empty($body['documentDate'])) {
+            if (!Validator::date()->notEmpty()->validate($body['documentDate'])) {
+                return ['errors' => "Body documentDate is not a date"];
+            }
+
+            $documentDate = new \DateTime($body['documentDate']);
+            $tmr = new \DateTime('tomorrow');
+
+            if ($documentDate > $tmr) {
+                return ['errors' => "Body documentDate is not a valid date"];
+            }
+        }
+        if (!empty($body['arrivalDate'])) {
+            if (!Validator::date()->notEmpty()->validate($body['arrivalDate'])) {
+                return ['errors' => "Body arrivalDate is not a date"];
+            }
+
+            $documentDate = new \DateTime($body['arrivalDate']);
+            $tmr = new \DateTime('tomorrow');
+
+            if ($documentDate > $tmr) {
+                return ['errors' => "Body arrivalDate is not a valid date"];
+            }
+        }
+        if (!empty($body['departureDate'])) {
+            if (!Validator::date()->notEmpty()->validate($body['departureDate'])) {
+                return ['errors' => "Body departureDate is not a date"];
+            }
+        }
+        if (!empty($body['processLimitDate'])) {
+            if (!Validator::date()->notEmpty()->validate($body['processLimitDate'])) {
+                return ['errors' => "Body processLimitDate is not a date"];
+            }
+
+            $processLimitDate = new \DateTime($body['processLimitDate']);
+            $today = new \DateTime();
+            $today->setTime(00, 00, 00);
+
+            if ($processLimitDate < $today) {
+                return ['errors' => "Body processLimitDate is not a valid date"];
+            }
+        } elseif (!empty($body['priority'])) {
+            $priority = PriorityModel::getById(['id' => $body['priority'], 'select' => [1]]);
+            if (empty($priority)) {
+                return ['errors' => "Body priority does not exist"];
+            }
+        }
+
+
         $tableMatch = [
             'subject'           => 'subject',
             'doctype'           => 'type_id',
@@ -895,6 +1002,7 @@ class ResController
             'origin'            => 'origin'
         ];
 
+        //TODO check attributaire
         if (!empty($body['diffusion'])) {
             if (!Validator::arrayType()->notEmpty()->validate($body['diffusion'])) {
                 return ['errors' => 'Body diffusion is not an array'];
diff --git a/src/app/resource/controllers/ResourceListController.php b/src/app/resource/controllers/ResourceListController.php
index 3d7f69ba0d9..8dd8748f97c 100644
--- a/src/app/resource/controllers/ResourceListController.php
+++ b/src/app/resource/controllers/ResourceListController.php
@@ -793,7 +793,7 @@ class ResourceListController
 
         $user = UserModel::getById(['id' => $args['userId'], 'select' => ['user_id']]);
 
-        $entities = UserModel::getEntitiesById(['userId' => $user['user_id']]);
+        $entities = UserModel::getEntitiesByLogin(['login' => $user['user_id']]);
         $entities = array_column($entities, 'id');
 
         if (empty($entities)) {
diff --git a/src/app/resource/controllers/StoreController.php b/src/app/resource/controllers/StoreController.php
index 808b05c4a96..119854be5d3 100755
--- a/src/app/resource/controllers/StoreController.php
+++ b/src/app/resource/controllers/StoreController.php
@@ -17,6 +17,7 @@ namespace Resource\controllers;
 
 use Attachment\models\AttachmentModel;
 use Docserver\controllers\DocserverController;
+use IndexingModel\models\IndexingModelModel;
 use Resource\models\ChronoModel;
 use SrcCore\models\DatabaseModel;
 use SrcCore\models\ValidatorModel;
@@ -25,30 +26,24 @@ use SrcCore\models\CoreConfigModel;
 
 class StoreController
 {
-    public static function storeResource(array $aArgs)
+    public static function storeResource(array $args)
     {
-        ValidatorModel::notEmpty($aArgs, ['encodedFile', 'format', 'status', 'type_id', 'category_id']);
-        ValidatorModel::stringType($aArgs, ['format', 'status', 'category_id']);
-        ValidatorModel::intVal($aArgs, ['type_id']);
+        ValidatorModel::notEmpty($args, ['encodedFile', 'format', 'status', 'doctype', 'modelId']);
+        ValidatorModel::stringType($args, ['format', 'status']);
+        ValidatorModel::intVal($args, ['doctype', 'modelId']);
 
         try {
-            foreach ($aArgs as $column => $value) {
-                if (empty($value)) {
-                    unset($aArgs[$column]);
-                }
-            }
-            $fileContent = base64_decode(str_replace(['-', '_'], ['+', '/'], $aArgs['encodedFile']));
+            $fileContent = base64_decode(str_replace(['-', '_'], ['+', '/'], $args['encodedFile']));
 
             $storeResult = DocserverController::storeResourceOnDocServer([
                 'collId'            => 'letterbox_coll',
                 'docserverTypeId'   => 'DOC',
                 'encodedResource'   => base64_encode($fileContent),
-                'format'            => $aArgs['format']
+                'format'            => $args['format']
             ]);
             if (!empty($storeResult['errors'])) {
                 return ['errors' => '[storeResource] ' . $storeResult['errors']];
             }
-            unset($aArgs['encodedFile']);
 
             $resId = DatabaseModel::getNextSequenceValue(['sequenceId' => 'res_id_mlb_seq']);
 
@@ -58,9 +53,9 @@ class StoreController
                 'filesize'      => $storeResult['fileSize'],
                 'path'          => $storeResult['destination_dir'],
                 'fingerprint'   => $storeResult['fingerPrint'],
-                'res_id'        => $resId
+                'resId'         => $resId
             ];
-            $data = array_merge($aArgs, $data);
+            $data = array_merge($args, $data);
             $data = StoreController::prepareStorage($data);
 
             ResModel::create($data);
@@ -112,72 +107,58 @@ class StoreController
         }
     }
 
-    public static function controlFingerPrint(array $aArgs)
-    {
-        ValidatorModel::notEmpty($aArgs, ['pathInit', 'pathTarget']);
-        ValidatorModel::stringType($aArgs, ['pathInit', 'pathTarget', 'fingerprintMode']);
-
-        if (!file_exists($aArgs['pathInit'])) {
-            return ['errors' => '[controlFingerprint] PathInit does not exist'];
-        }
-        if (!file_exists($aArgs['pathTarget'])) {
-            return ['errors' => '[controlFingerprint] PathTarget does not exist'];
-        }
-
-        $fingerprint1 = StoreController::getFingerPrint(['filePath' => $aArgs['pathInit'], 'mode' => $aArgs['fingerprintMode']]);
-        $fingerprint2 = StoreController::getFingerPrint(['filePath' => $aArgs['pathTarget'], 'mode' => $aArgs['fingerprintMode']]);
-
-        if ($fingerprint1 != $fingerprint2) {
-            return ['errors' => '[controlFingerprint] Fingerprints do not match: ' . $aArgs['pathInit'] . ' and ' . $aArgs['pathTarget']];
-        }
-
-        return true;
-    }
-
-    public static function getFingerPrint(array $aArgs)
-    {
-        ValidatorModel::notEmpty($aArgs, ['filePath']);
-        ValidatorModel::stringType($aArgs, ['filePath', 'mode']);
-
-        if (empty($aArgs['mode']) || $aArgs['mode'] == 'NONE') {
-            $aArgs['mode'] = 'sha512';
-        }
-
-        return hash_file(strtolower($aArgs['mode']), $aArgs['filePath']);
-    }
-
     public static function prepareStorage(array $args)
     {
-        ValidatorModel::notEmpty($args, ['docserver_id', 'filename', 'format', 'filesize', 'path', 'fingerprint', 'status', 'res_id']);
+        ValidatorModel::notEmpty($args, ['docserver_id', 'filename', 'format', 'filesize', 'path', 'fingerprint', 'status', 'resId', 'modelId']);
         ValidatorModel::stringType($args, ['docserver_id', 'filename', 'format', 'path', 'fingerprint', 'status']);
-        ValidatorModel::intVal($args, ['filesize', 'res_id']);
+        ValidatorModel::intVal($args, ['filesize', 'resId', 'modelId']);
+
+        $indexingModel = IndexingModelModel::getById(['id' => $args['modelId'], 'select' => ['category']]);
 
         if (empty($args['typist'])) {
             $args['typist'] = $GLOBALS['id'];
         }
 
-        unset($args['alt_identifier']);
+        $chrono = null;
         if (!empty($args['chrono'])) {
-            $args['alt_identifier'] = ChronoModel::getChrono(['id' => $args['category_id'], 'entityId' => $args['destination'], 'typeId' => $args['type_id'], 'resId' => $args['res_id']]);
-        }
-        unset($args['chrono']);
-
-        if (empty($args['process_limit_date'])) {
-            $processLimitDate = ResModel::getStoredProcessLimitDate(['typeId' => $args['type_id'], 'admissionDate' => $args['admission_date']]);
-            $args['process_limit_date'] = $processLimitDate;
+            $chrono = ChronoModel::getChrono(['id' => $args['category_id'], 'entityId' => $args['destination'], 'typeId' => $args['doctype'], 'resId' => $args['resId']]);
         }
 
-        unset($args['external_id']);
-        if (!empty($args['externalId'])) {
-            if (is_array($args['externalId'])) {
-                $args['external_id'] = json_encode($args['externalId']);
-            }
-            unset($args['externalId']);
+        $externalId = '{}';
+        if (!empty($args['externalId']) && is_array($args['externalId'])) {
+            $externalId = json_encode($args['externalId']);
         }
 
-        $args['creation_date'] = 'CURRENT_TIMESTAMP';
+        $preparedData = [
+            'res_id'                => $args['resId'],
+            'model_id'              => $args['modelId'],
+            'category_id'           => $indexingModel['category'],
+            'type_id'               => $args['doctype'],
+            'subject'               => $args['subject'] ?? null,
+            'alt_identifier'        => $chrono,
+            'format'                => $args['format'],
+            'typist'                => $args['typist'],
+            'status'                => $args['status'],
+            'destination'           => $args['destination'] ?? null,
+            'initiator'             => $args['initiator'] ?? null,
+            'confidentiality'       => empty('confidentiality') ? 'N' : 'Y',
+            'doc_date'              => $args['documentDate'] ?? null,
+            'admission_date'        => $args['arrivalDate'] ?? null,
+            'departure_date'        => $args['departureDate'] ?? null,
+            'process_limit_date'    => $args['processLimitDate'] ?? null,
+            'priority'              => $args['priority'] ?? null,
+            'barcode'               => $args['barcode'] ?? null,
+            'origin'                => $args['origin'] ?? null,
+            'external_id'           => $externalId,
+            'docserver_id'          => $args['docserver_id'],
+            'filename'              => $args['filename'],
+            'filesize'              => $args['fileSize'],
+            'path'                  => $args['path'],
+            'fingerprint'           => $args['fingerPrint'],
+            'creation_date'         => 'CURRENT_TIMESTAMP'
+        ];
 
-        return $args;
+        return $preparedData;
     }
 
     public static function prepareAttachmentStorage(array $aArgs)
@@ -235,6 +216,18 @@ class StoreController
         return $formatedData;
     }
 
+    public static function getFingerPrint(array $aArgs)
+    {
+        ValidatorModel::notEmpty($aArgs, ['filePath']);
+        ValidatorModel::stringType($aArgs, ['filePath', 'mode']);
+
+        if (empty($aArgs['mode']) || $aArgs['mode'] == 'NONE') {
+            $aArgs['mode'] = 'sha512';
+        }
+
+        return hash_file(strtolower($aArgs['mode']), $aArgs['filePath']);
+    }
+
     public static function isFileAllowed(array $args)
     {
         ValidatorModel::notEmpty($args, ['extension', 'type']);
diff --git a/src/app/resource/models/ResModelAbstract.php b/src/app/resource/models/ResModelAbstract.php
index b3f2e694180..be39a7cce83 100755
--- a/src/app/resource/models/ResModelAbstract.php
+++ b/src/app/resource/models/ResModelAbstract.php
@@ -80,22 +80,18 @@ abstract class ResModelAbstract
         return $aResources[0];
     }
 
-    public static function create(array $aArgs)
+    public static function create(array $args)
     {
-        ValidatorModel::notEmpty($aArgs, ['format', 'typist', 'creation_date', 'docserver_id', 'path', 'filename', 'fingerprint', 'filesize', 'status', 'category_id']);
-        ValidatorModel::stringType($aArgs, ['format', 'creation_date', 'docserver_id', 'path', 'filename', 'fingerprint', 'status', 'category_id']);
-        ValidatorModel::intVal($aArgs, ['filesize', 'res_id', 'typist']);
-
-        if (empty($aArgs['res_id'])) {
-            $aArgs['res_id'] = DatabaseModel::getNextSequenceValue(['sequenceId' => 'res_id_mlb_seq']);
-        }
+        ValidatorModel::notEmpty($args, ['res_id', 'format', 'typist', 'creation_date', 'docserver_id', 'path', 'filename', 'fingerprint', 'filesize', 'status', 'category_id']);
+        ValidatorModel::stringType($args, ['format', 'creation_date', 'docserver_id', 'path', 'filename', 'fingerprint', 'status', 'category_id']);
+        ValidatorModel::intVal($args, ['filesize', 'res_id', 'typist']);
 
         DatabaseModel::insert([
             'table'         => 'res_letterbox',
-            'columnsValues' => $aArgs
+            'columnsValues' => $args
         ]);
 
-        return $aArgs['res_id'];
+        return true;
     }
 
     public static function update(array $aArgs)
@@ -197,37 +193,6 @@ abstract class ResModelAbstract
         return $resource[0];
     }
 
-    public static function getStoredProcessLimitDate(array $aArgs)
-    {
-        ValidatorModel::intVal($aArgs, ['resId', 'typeId']);
-        ValidatorModel::stringType($aArgs, ['admissionDate']);
-
-        if (!empty($aArgs['typeId'])) {
-            $typeId = $aArgs['type_id'];
-        } else {
-            $document = ResModel::getById(['resId' => $aArgs['resId'], 'select' => ['type_id']]);
-            $typeId = $document['type_id'];
-        }
-
-        $processDelay = 30;
-        if (!empty($typeId)) {
-            $doctype = DoctypeModel::getById(['select' => ['process_delay'], 'id' => $typeId]);
-            $processDelay = $doctype['process_delay'];
-        }
-
-        if (!empty($aArgs['admissionDate'])) {
-            if (strtotime($aArgs['admissionDate']) === false) {
-                $defaultDate = date('c');
-            } else {
-                $defaultDate = $aArgs['admissionDate'];
-            }
-        } else {
-            $defaultDate = date('c');
-        }
-
-        return IndexingController::calculateProcessDate(['date' => $defaultDate, 'delay' => $processDelay]);
-    }
-
     public static function getCategories()
     {
         $categories = [
diff --git a/src/app/user/controllers/UserController.php b/src/app/user/controllers/UserController.php
index 7d1fa9aa13f..1e83bfea170 100755
--- a/src/app/user/controllers/UserController.php
+++ b/src/app/user/controllers/UserController.php
@@ -103,7 +103,7 @@ class UserController
         $user['emailSignatures']    = UserModel::getEmailSignaturesById(['userId' => $user['user_id']]);
         $user['groups']             = UserModel::getGroupsByLogin(['login' => $user['user_id']]);
         $user['allGroups']          = GroupModel::getAvailableGroupsByUserId(['userId' => $user['user_id']]);
-        $user['entities']           = UserModel::getEntitiesById(['userId' => $user['user_id']]);
+        $user['entities']           = UserModel::getEntitiesByLogin(['login' => $user['user_id']]);
         $user['allEntities']        = EntityModel::getAvailableEntitiesForAdministratorByUserId(['userId' => $user['user_id'], 'administratorUserId' => $GLOBALS['userId']]);
         $user['baskets']            = BasketModel::getBasketsByLogin(['login' => $user['user_id']]);
         $user['assignedBaskets']    = RedirectBasketModel::getAssignedBasketsByUserId(['userId' => $user['id']]);
@@ -445,7 +445,7 @@ class UserController
         $user['signatures']         = UserSignatureModel::getByUserSerialId(['userSerialid' => $user['id']]);
         $user['emailSignatures']    = UserModel::getEmailSignaturesById(['userId' => $user['user_id']]);
         $user['groups']             = UserModel::getGroupsByLogin(['login' => $user['user_id']]);
-        $user['entities']           = UserModel::getEntitiesById(['userId' => $user['user_id']]);
+        $user['entities']           = UserModel::getEntitiesByLogin(['login' => $user['user_id']]);
         $user['baskets']            = BasketModel::getBasketsByLogin(['login' => $user['user_id']]);
         $user['assignedBaskets']    = RedirectBasketModel::getAssignedBasketsByUserId(['userId' => $user['id']]);
         $user['redirectedBaskets']  = RedirectBasketModel::getRedirectedBasketsByUserId(['userId' => $user['id']]);
@@ -1022,7 +1022,7 @@ class UserController
             return $response->withStatus(400)->withJson(['errors' => 'User does not exist']);
         }
 
-        $entities = UserModel::getEntitiesById(['userId' => $user['user_id']]);
+        $entities = UserModel::getEntitiesByLogin(['login' => $user['user_id']]);
 
         return $response->withJson(['entities' => $entities]);
     }
@@ -1064,7 +1064,7 @@ class UserController
         ]);
 
         return $response->withJson([
-            'entities'      => UserModel::getEntitiesById(['userId' => $user['user_id']]),
+            'entities'      => UserModel::getEntitiesByLogin(['login' => $user['user_id']]),
             'allEntities'   => EntityModel::getAvailableEntitiesForAdministratorByUserId(['userId' => $user['user_id'], 'administratorUserId' => $GLOBALS['userId']])
         ]);
     }
@@ -1110,7 +1110,7 @@ class UserController
         $user = UserModel::getById(['id' => $aArgs['id'], 'select' => ['user_id']]);
         UserEntityModel::updateUserPrimaryEntity(['id' => $aArgs['id'], 'entityId' => $aArgs['entityId']]);
 
-        return $response->withJson(['entities' => UserModel::getEntitiesById(['userId' => $user['user_id']])]);
+        return $response->withJson(['entities' => UserModel::getEntitiesByLogin(['login' => $user['user_id']])]);
     }
 
     public function deleteEntity(Request $request, Response $response, array $aArgs)
@@ -1214,7 +1214,7 @@ class UserController
         ]);
 
         return $response->withJson([
-            'entities'      => UserModel::getEntitiesById(['userId' => $user['user_id']]),
+            'entities'      => UserModel::getEntitiesByLogin(['login' => $user['user_id']]),
             'allEntities'   => EntityModel::getAvailableEntitiesForAdministratorByUserId(['userId' => $user['user_id'], 'administratorUserId' => $GLOBALS['userId']])
         ]);
     }
diff --git a/src/app/user/models/UserModelAbstract.php b/src/app/user/models/UserModelAbstract.php
index c538706c2fe..9883d2ed2ad 100755
--- a/src/app/user/models/UserModelAbstract.php
+++ b/src/app/user/models/UserModelAbstract.php
@@ -431,16 +431,16 @@ abstract class UserModelAbstract
         return $aGroups;
     }
 
-    public static function getEntitiesById(array $aArgs)
+    public static function getEntitiesByLogin(array $aArgs)
     {
-        ValidatorModel::notEmpty($aArgs, ['userId']);
-        ValidatorModel::stringType($aArgs, ['userId']);
+        ValidatorModel::notEmpty($aArgs, ['login']);
+        ValidatorModel::stringType($aArgs, ['login']);
 
         $aEntities = DatabaseModel::select([
             'select'    => ['entities.id', 'users_entities.entity_id', 'entities.entity_label', 'users_entities.user_role', 'users_entities.primary_entity'],
             'table'     => ['users_entities, entities'],
             'where'     => ['users_entities.entity_id = entities.entity_id', 'users_entities.user_id = ?'],
-            'data'      => [$aArgs['userId']],
+            'data'      => [$aArgs['login']],
             'order_by'  => ['users_entities.primary_entity DESC']
         ]);
 
@@ -544,7 +544,7 @@ abstract class UserModelAbstract
         ValidatorModel::stringType($aArgs, ['entityId']);
 
         $user = UserModel::getById(['id' => $aArgs['id'], 'select' => ['user_id']]);
-        $entities = UserModel::getEntitiesById(['userId' => $user['user_id']]);
+        $entities = UserModel::getEntitiesByLogin(['login' => $user['user_id']]);
         foreach ($entities as $value) {
             if ($value['entity_id'] == $aArgs['entityId']) {
                 return true;
diff --git a/src/core/controllers/CoreController.php b/src/core/controllers/CoreController.php
index 38ace5ddefe..f6851428b2d 100755
--- a/src/core/controllers/CoreController.php
+++ b/src/core/controllers/CoreController.php
@@ -83,7 +83,7 @@ class CoreController
     {
         $user = UserModel::getByLogin(['login' => $GLOBALS['userId'], 'select' => ['id', 'user_id', 'firstname', 'lastname']]);
         $user['groups'] = UserModel::getGroupsByLogin(['login' => $GLOBALS['userId']]);
-        $user['entities'] = UserModel::getEntitiesById(['userId' => $GLOBALS['userId']]);
+        $user['entities'] = UserModel::getEntitiesByLogin(['login' => $GLOBALS['userId']]);
 
         if ($GLOBALS['userId'] == 'superadmin') {
             $menu = ServiceModel::getApplicationServicesByXML(['type' => 'menu']);
-- 
GitLab