From 679f4ed979d09cdf0fb2c2f258fec306bef8d700 Mon Sep 17 00:00:00 2001
From: Damien <damien.burel@maarch.org>
Date: Mon, 23 Mar 2020 17:52:43 +0100
Subject: [PATCH] FEAT #11902 TIME 4:20 Reconcile action + pre process

---
 modules/export_seda/Purge.php                 |   8 +-
 rest/index.php                                |   1 +
 .../controllers/ActionMethodController.php    | 141 ++++++++++++++----
 .../PreProcessActionController.php            |  50 +++++++
 src/app/resource/models/ResModelAbstract.php  |  15 +-
 .../app/resource/ResControllerTest.php        |   2 +-
 .../UserFollowedResourceControllerTest.php    |   2 +-
 7 files changed, 176 insertions(+), 43 deletions(-)

diff --git a/modules/export_seda/Purge.php b/modules/export_seda/Purge.php
index 272a70a34c1..cdf84af62bb 100755
--- a/modules/export_seda/Purge.php
+++ b/modules/export_seda/Purge.php
@@ -80,13 +80,9 @@ Class Purge{
 
     private function purgeResource($resId)
     {
-        $aArgs = [
-            'resId'         => $resId,
-        ];
+        \Resource\models\ResModel::update(['set' => ['status' => 'DEL'], 'where' => ['res_id = ?'], 'data' => [$resId]]);
 
-        $response = \Resource\models\ResModel::delete($aArgs);
-
-        return $response;
+        return true;
     }
 
     private function purgeContact($contactId)
diff --git a/rest/index.php b/rest/index.php
index 0405f1cfaa9..eca11fa86a7 100755
--- a/rest/index.php
+++ b/rest/index.php
@@ -420,6 +420,7 @@ $app->post('/resourcesList/users/{userId}/groups/{groupId}/baskets/{basketId}/ac
 $app->post('/resourcesList/users/{userId}/groups/{groupId}/baskets/{basketId}/actions/{actionId}/checkRejectVisa', \Action\controllers\PreProcessActionController::class . ':checkRejectVisa');
 $app->post('/resourcesList/users/{userId}/groups/{groupId}/baskets/{basketId}/actions/{actionId}/checkInterruptResetVisa', \Action\controllers\PreProcessActionController::class . ':checkInterruptResetVisa');
 $app->post('/resourcesList/users/{userId}/groups/{groupId}/baskets/{basketId}/actions/{actionId}/checkCloseWithFieldsAction', \Action\controllers\PreProcessActionController::class . ':checkCloseWithFieldsAction');
+$app->post('/resourcesList/users/{userId}/groups/{groupId}/baskets/{basketId}/actions/{actionId}/checkReconcile', \Action\controllers\PreProcessActionController::class . ':checkReconcile');
 
 //Search
 $app->get('/search', \Search\controllers\SearchController::class . ':get');
diff --git a/src/app/action/controllers/ActionMethodController.php b/src/app/action/controllers/ActionMethodController.php
index 0420d9968eb..ff7a9a24377 100644
--- a/src/app/action/controllers/ActionMethodController.php
+++ b/src/app/action/controllers/ActionMethodController.php
@@ -18,6 +18,10 @@ use Action\models\BasketPersistenceModel;
 use Action\models\ResMarkAsReadModel;
 use Attachment\controllers\AttachmentController;
 use Attachment\models\AttachmentModel;
+use Convert\controllers\ConvertPdfController;
+use Convert\models\AdrModel;
+use Docserver\controllers\DocserverController;
+use Docserver\models\DocserverModel;
 use Entity\controllers\ListInstanceController;
 use Entity\models\EntityModel;
 use Entity\models\ListInstanceModel;
@@ -28,6 +32,7 @@ use MessageExchange\controllers\MessageExchangeReviewController;
 use Note\models\NoteEntityModel;
 use Note\models\NoteModel;
 use Resource\controllers\ResController;
+use Resource\controllers\StoreController;
 use Resource\models\ResModel;
 use Respect\Validation\Validator;
 use SrcCore\models\CoreConfigModel;
@@ -42,32 +47,33 @@ class ActionMethodController
     use ExternalSignatoryBookTrait;
 
     const COMPONENTS_ACTIONS = [
-        'confirmAction'                          => null,
-        'closeMailAction'                        => 'closeMailAction',
-        'closeMailWithAttachmentsOrNotesAction'  => 'closeMailWithAttachmentsOrNotesAction',
-        'redirectAction'                         => 'redirect',
-        'closeAndIndexAction'                    => 'closeMailAction',
-        'updateDepartureDateAction'              => 'updateDepartureDateAction',
-        'enabledBasketPersistenceAction'         => 'enabledBasketPersistenceAction',
-        'disabledBasketPersistenceAction'        => 'disabledBasketPersistenceAction',
-        'resMarkAsReadAction'                    => 'resMarkAsReadAction',
-        'sendExternalSignatoryBookAction'        => 'sendExternalSignatoryBookAction',
-        'sendExternalNoteBookAction'             => 'sendExternalNoteBookAction',
-        'createAcknowledgementReceiptsAction'    => 'createAcknowledgementReceipts',
-        'updateAcknowledgementSendDateAction'    => 'updateAcknowledgementSendDateAction',
-        'sendShippingAction'                     => 'createMailevaShippings',
-        'sendSignatureBookAction'                => 'sendSignatureBook',
-        'continueVisaCircuitAction'              => 'continueVisaCircuit',
-        'redirectInitiatorEntityAction'          => 'redirectInitiatorEntityAction',
-        'rejectVisaBackToPreviousAction'         => 'rejectVisaBackToPrevious',
-        'resetVisaAction'                        => 'resetVisa',
-        'interruptVisaAction'                    => 'interruptVisa',
-        'sendToParallelOpinion'                  => 'sendToParallelOpinion',
-        'sendToOpinionCircuitAction'             => 'sendToOpinionCircuit',
-        'continueOpinionCircuitAction'           => 'continueOpinionCircuit',
-        'giveOpinionParallelAction'              => 'giveOpinionParallel',
-        'validateParallelOpinionDiffusionAction' => 'validateParallelOpinionDiffusion',
-        'noConfirmAction'                        => null
+        'confirmAction'                             => null,
+        'closeMailAction'                           => 'closeMailAction',
+        'closeMailWithAttachmentsOrNotesAction'     => 'closeMailWithAttachmentsOrNotesAction',
+        'redirectAction'                            => 'redirect',
+        'closeAndIndexAction'                       => 'closeMailAction',
+        'updateDepartureDateAction'                 => 'updateDepartureDateAction',
+        'enabledBasketPersistenceAction'            => 'enabledBasketPersistenceAction',
+        'disabledBasketPersistenceAction'           => 'disabledBasketPersistenceAction',
+        'resMarkAsReadAction'                       => 'resMarkAsReadAction',
+        'sendExternalSignatoryBookAction'           => 'sendExternalSignatoryBookAction',
+        'sendExternalNoteBookAction'                => 'sendExternalNoteBookAction',
+        'createAcknowledgementReceiptsAction'       => 'createAcknowledgementReceipts',
+        'updateAcknowledgementSendDateAction'       => 'updateAcknowledgementSendDateAction',
+        'sendShippingAction'                        => 'createMailevaShippings',
+        'sendSignatureBookAction'                   => 'sendSignatureBook',
+        'continueVisaCircuitAction'                 => 'continueVisaCircuit',
+        'redirectInitiatorEntityAction'             => 'redirectInitiatorEntityAction',
+        'rejectVisaBackToPreviousAction'            => 'rejectVisaBackToPrevious',
+        'resetVisaAction'                           => 'resetVisa',
+        'interruptVisaAction'                       => 'interruptVisa',
+        'sendToParallelOpinion'                     => 'sendToParallelOpinion',
+        'sendToOpinionCircuitAction'                => 'sendToOpinionCircuit',
+        'continueOpinionCircuitAction'              => 'continueOpinionCircuit',
+        'giveOpinionParallelAction'                 => 'giveOpinionParallel',
+        'validateParallelOpinionDiffusionAction'    => 'validateParallelOpinionDiffusion',
+        'reconcileAction'                           => 'reconcile',
+        'noConfirmAction'                           => null
     ];
 
     public static function terminateAction(array $args)
@@ -877,4 +883,87 @@ class ActionMethodController
 
         return true;
     }
+
+    public static function reconcile(array $args)
+    {
+        ValidatorModel::notEmpty($args, ['resId', 'data']);
+        ValidatorModel::intVal($args, ['resId']);
+        ValidatorModel::arrayType($args, ['data']);
+
+        $resource = ResModel::getById(['select' => ['docserver_id', 'path', 'filename', 'format', 'subject'], 'resId' => $args['resId']]);
+        if (empty($resource['filename'])) {
+            return ['errors' => ['Document has no file']];
+        }
+        $docserver = DocserverModel::getByDocserverId(['docserverId' => $resource['docserver_id'], 'select' => ['path_template']]);
+        if (empty($docserver['path_template'])) {
+            return ['errors' => ['Docserver does not exist']];
+        }
+        $pathToDocument = $docserver['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $resource['path']) . $resource['filename'];
+        if (!is_file($pathToDocument)) {
+            return ['errors' => ['Document not found on docserver']];
+        }
+
+        $targetResource = ResModel::getById(['select' => ['category_id', 'filename', 'version'], 'resId' => $args['data']['resId']]);
+        if (empty($targetResource)) {
+            return ['errors' => ['Target resource does not exist']];
+        } elseif ($targetResource['category_id'] == 'outgoing' && empty($targetResource['filename'])) {
+            return ['errors' => ['Target resource has no file']];
+        }
+
+        if ($targetResource['category_id'] == 'outgoing') {
+            $storeResult = DocserverController::storeResourceOnDocServer([
+                'collId'            => 'letterbox_coll',
+                'docserverTypeId'   => 'DOC',
+                'encodedResource'   => base64_encode(file_get_contents($pathToDocument)),
+                'format'            => 'pdf'
+            ]);
+            if (!empty($storeResult['errors'])) {
+                return ['errors' => ["[storeResourceOnDocServer] {$storeResult['errors']}"]];
+            }
+            AdrModel::createDocumentAdr([
+                'resId'         => $args['data']['resId'],
+                'type'          => 'SIGN',
+                'docserverId'   => $storeResult['docserver_id'],
+                'path'          => $storeResult['directory'],
+                'filename'      => $storeResult['file_destination_name'],
+                'version'       => $targetResource['version'],
+                'fingerprint'   => $storeResult['fingerPrint']
+            ]);
+
+        } else {
+            $id = StoreController::storeAttachment([
+                'encodedFile'   => base64_encode(file_get_contents($pathToDocument)),
+                'type'          => 'response_project',
+                'resIdMaster'   => $args['data']['resId'],
+                'title'         => $resource['subject']
+            ]);
+            if (empty($id) || !empty($id['errors'])) {
+                return ['errors' => ['[storeAttachment] ' . $id['errors']]];
+            }
+            ConvertPdfController::convert([
+                'resId'     => $id,
+                'collId'    => 'attachments_coll'
+            ]);
+
+            $id = StoreController::storeAttachment([
+                'encodedFile'   => base64_encode(file_get_contents($pathToDocument)),
+                'type'          => 'signed_response',
+                'resIdMaster'   => $args['data']['resId'],
+                'title'         => $resource['subject'],
+                'originId'      => $id
+            ]);
+            if (empty($id) || !empty($id['errors'])) {
+                return ['errors' => ['[storeAttachment] ' . $id['errors']]];
+            }
+            ConvertPdfController::convert([
+                'resId'     => $id,
+                'collId'    => 'attachments_coll'
+            ]);
+        }
+
+        ResModel::delete(['where' => ['res_id = ?'], 'data' => [$args['resId']]]);
+        AdrModel::deleteDocumentAdr(['where' => ['res_id = ?'], 'data' => [$args['resId']]]);
+
+        return true;
+    }
 }
diff --git a/src/app/action/controllers/PreProcessActionController.php b/src/app/action/controllers/PreProcessActionController.php
index 02630637d3c..92eae072566 100755
--- a/src/app/action/controllers/PreProcessActionController.php
+++ b/src/app/action/controllers/PreProcessActionController.php
@@ -1460,6 +1460,56 @@ class PreProcessActionController
         return $response->withJson(['errors' => $emptyFields, 'success' => $canClose]);
     }
 
+    public function checkReconcile(Request $request, Response $response, array $args)
+    {
+        $body = $request->getParsedBody();
+
+        if (!Validator::arrayType()->notEmpty()->validate($body['resources'])) {
+            return $response->withStatus(400)->withJson(['errors' => 'Body resources is empty or not an array']);
+        }
+
+        $errors = ResourceListController::listControl(['groupId' => $args['groupId'], 'userId' => $args['userId'], 'basketId' => $args['basketId'], 'currentUserId' => $GLOBALS['id']]);
+        if (!empty($errors['errors'])) {
+            return $response->withStatus($errors['code'])->withJson(['errors' => $errors['errors']]);
+        }
+
+        $body['resources'] = array_slice($body['resources'], 0, 500);
+        if (!ResController::hasRightByResId(['resId' => $body['resources'], 'userId' => $GLOBALS['id']])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
+        }
+        $body['resources'] = PreProcessActionController::getNonLockedResources(['resources' => $body['resources'], 'userId' => $GLOBALS['id']]);
+
+        $targetResource = ResModel::getById(['select' => ['category_id', 'filename'], 'resId' => $body['data']['resId']]);
+        if ($targetResource['category_id'] == 'outgoing' && empty($targetResource['filename'])) {
+            return $response->withJson(['fatalError' => 'Target resource has no file', 'reason' => 'targetResourceHasNoFile']);
+        }
+
+        $resourcesInformation = [];
+        foreach ($body['resources'] as $resId) {
+            $resource = ResModel::getById(['resId' => $resId, 'select' => ['alt_identifier', 'filename']]);
+
+            if (empty($resource['alt_identifier'])) {
+                $resource['alt_identifier'] = _UNDEFINED;
+            }
+
+            if (empty($resource['filename'])) {
+                $resourcesInformation['error'][] = ['alt_identifier' => $resource['alt_identifier'], 'res_id' => $resId, 'reason' => 'noFilename'];
+                continue;
+            }
+
+            $targetResource = ResModel::getById(['select' => ['category_id', 'filename'], 'resId' => $body['data']['resId']]);
+            if (empty($targetResource)) {
+                return ['errors' => ['Target resource does not exist']];
+            } elseif ($targetResource['category_id'] == 'outgoing' && empty($targetResource['filename'])) {
+                return ['errors' => ['Target resource has no file']];
+            }
+
+            $resourcesInformation['success'][] = ['alt_identifier' => $resource['alt_identifier'], 'res_id' => $resId];
+        }
+
+        return $response->withJson(['resourcesInformations' => $resourcesInformation]);
+    }
+
     private static function getNonLockedResources(array $args)
     {
         ValidatorModel::notEmpty($args, ['resources', 'userId']);
diff --git a/src/app/resource/models/ResModelAbstract.php b/src/app/resource/models/ResModelAbstract.php
index f3fafa46276..1af3f4bcab7 100755
--- a/src/app/resource/models/ResModelAbstract.php
+++ b/src/app/resource/models/ResModelAbstract.php
@@ -107,18 +107,15 @@ abstract class ResModelAbstract
         return true;
     }
 
-    public static function delete(array $aArgs)
+    public static function delete(array $args)
     {
-        ValidatorModel::notEmpty($aArgs, ['resId']);
-        ValidatorModel::intVal($aArgs, ['resId']);
+        ValidatorModel::notEmpty($args, ['where', 'data']);
+        ValidatorModel::arrayType($args, ['where', 'data']);
 
-        DatabaseModel::update([
+        DatabaseModel::delete([
             'table' => 'res_letterbox',
-            'set'   => [
-                'status'    => 'DEL'
-            ],
-            'where' => ['res_id = ?'],
-            'data'  => [$aArgs['resId']]
+            'where' => $args['where'],
+            'data'  => $args['data']
         ]);
 
         return true;
diff --git a/test/unitTests/app/resource/ResControllerTest.php b/test/unitTests/app/resource/ResControllerTest.php
index 6f05a9abf1d..585197fb264 100755
--- a/test/unitTests/app/resource/ResControllerTest.php
+++ b/test/unitTests/app/resource/ResControllerTest.php
@@ -321,7 +321,7 @@ class ResControllerTest extends TestCase
     public function testDelete()
     {
         //  DELETE
-        \Resource\models\ResModel::delete(['resId' => self::$id]);
+        \Resource\models\ResModel::update(['set' => ['status' => 'DEL'], 'where' => ['res_id = ?'], 'data' => [self::$id]]);
 
         //  READ
         $res = \Resource\models\ResModel::getById(['resId' => self::$id, 'select' => ['*']]);
diff --git a/test/unitTests/app/resource/UserFollowedResourceControllerTest.php b/test/unitTests/app/resource/UserFollowedResourceControllerTest.php
index 9c8e56ab2d0..52388dfc9ed 100644
--- a/test/unitTests/app/resource/UserFollowedResourceControllerTest.php
+++ b/test/unitTests/app/resource/UserFollowedResourceControllerTest.php
@@ -197,7 +197,7 @@ class UserFollowedResourceControllerTest extends TestCase
         $GLOBALS['id'] = $userInfo['id'];
 
         //  DELETE
-        \Resource\models\ResModel::delete(['resId' => self::$id]);
+        \Resource\models\ResModel::update(['set' => ['status' => 'DEL'], 'where' => ['res_id = ?'], 'data' => [self::$id]]);
 
         UserFollowedResourceModel::delete([
             'userId' => $GLOBALS['id'],
-- 
GitLab