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