Skip to content
Snippets Groups Projects
ExportSEDATrait.php 23.3 KiB
Newer Older
<?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   ExportSEDATrait
* @author  dev <dev@maarch.org>
* @ingroup core
*/

namespace ExportSeda\controllers;

use Contact\controllers\ContactController;
use Docserver\models\DocserverModel;
use Docserver\models\DocserverTypeModel;
use Doctype\models\DoctypeModel;
use Entity\models\EntityModel;
use Entity\models\ListInstanceModel;
use ExportSeda\controllers\ExportSEDATrait;
use ExportSeda\controllers\SedaController;
use Folder\models\FolderModel;
use History\models\HistoryModel;
use MessageExchange\models\MessageExchangeModel;
use Note\controllers\NoteController;
use Resource\controllers\SummarySheetController;
use Resource\models\ResModel;
use setasign\Fpdi\Tcpdf\Fpdi;
use SrcCore\models\CoreConfigModel;
use SrcCore\models\CurlModel;
use User\models\UserModel;

trait ExportSEDATrait
{
    public static function sendToRecordManagement(array $args)
    {
        ValidatorModel::notEmpty($args, ['resId']);
        ValidatorModel::intVal($args, ['resId']);

        $resource = ResModel::getById(['resId' => $args['resId'], 'select' => ['res_id', 'destination', 'type_id', 'subject', 'linked_resources', 'alt_identifier', 'admission_date', 'creation_date', 'modification_date', 'doc_date', 'retention_frozen']]);
        if (empty($resource)) {
            return ['errors' => ['resource does not exists']];
        } elseif (empty($resource['destination'])) {
            return ['errors' => ['resource has no destination']];
        } elseif ($resource['retention_frozen']) {
            return ['errors' => ['retention rule is frozen']];
        }

        $doctype = DoctypeModel::getById(['id' => $resource['type_id'], 'select' => ['description', 'retention_rule', 'retention_final_disposition']]);
        if (empty($doctype['retention_rule']) || empty($doctype['retention_final_disposition'])) {
            return ['errors' => ['retention_rule or retention_final_disposition is empty for doctype']];
        }
        $entity = EntityModel::getByEntityId(['entityId' => $resource['destination'], 'select' => ['producer_service', 'entity_label']]);
        if (empty($entity['producer_service'])) {
            return ['errors' => ['producer_service is empty for this entity']];
        }

        $config = CoreConfigModel::getJsonLoaded(['path' => 'apps/maarch_entreprise/xml/config.json']);
        if (empty($config['exportSeda']['senderOrgRegNumber'])) {
            return ['errors' => ['No senderOrgRegNumber found in config.json']];
        }

        if (empty($args['data']['packageName'])) {
            return ['errors' => ['packageName is empty']];
        }
        if (empty($args['data']['archivalAgreement'])) {
            return ['errors' => ['archivalAgreement is empty']];
        }
        if (empty($args['data']['slipId'])) {
            return ['errors' => ['slipId is empty']];
        }
        if (empty($args['data']['entityArchiveRecipient'])) {
            return ['errors' => ['entityArchiveRecipient is empty']];
        }
        if (empty($args['data']['archiveDescriptionLevel'])) {
            return ['errors' => ['archiveDescriptionLevel is empty']];
        }

        foreach ($args['data']['archives'] as $archiveUnit) {
            if (empty($archiveUnit['id']) or empty($archiveUnit['descriptionLevel'])) {
                return ['errors' => ['Missing id or descriptionLevel for an archiveUnit']];
            }
        }

        $initData = SedaController::initArchivalData([
            'resource'           => $resource,
            'senderOrgRegNumber' => $config['exportSeda']['senderOrgRegNumber'],
            'entity'             => $entity,
            'doctype'            => $doctype,
            'getFile'            => true
        ]);

        if (!empty($initData['errors'])) {
            return ['errors' => $initData['errors']];
        } else {
            $initData = $initData['archivalData'];
        }

        $archivesAttachment = [];
        $initialArchiveUnits = $initData['archiveUnits'];
        foreach ($initialArchiveUnits as $archiveUnit) {
            $archiveFound = false;
            foreach ($args['data']['archives'] as $userArchiveUnit) {
                if ($userArchiveUnit['id'] == $archiveUnit['id']) {
                    $archiveUnit['descriptionLevel'] = $userArchiveUnit['descriptionLevel'];
                    $archivesAttachment[]             = $archiveUnit;
                    $archiveFound                    = true;
                    break;
                }
            }
            if (!$archiveFound) {
                $archiveUnit['descriptionLevel'] = 'Item';
                $archivesAttachment = $archiveUnit;
        $history = ExportSEDATrait::getHistory(['resId' => $resource['res_id']]);
        $folder  = ExportSEDATrait::getFolderPath(['selectedFolder' => $args['data']['folder'], 'folders' => $initData['additionalData']['folders']]);

        $dataObjectPackage = [
            'archiveId'                 => $initData['data']['slipInfo']['archiveId'],
            'chrono'                    => $resource['alt_identifier'],
            'originatorAgency'          => [
                'id'    => $entity['producer_service'],
                'label' => $entity['entity_label']
            ],
            'descriptionLevel'          => $args['data']['archiveDescriptionLevel'],
            'receivedDate'              => $resource['admission_date'],
            'documentDate'              => $resource['doc_date'],
            'creationDate'              => $resource['creation_date'],
            'modificationDate'          => $resource['modification_date'],
            'retentionRule'             => $initData['data']['doctype']['retentionRule'],
            'retentionFinalDisposition' => $initData['data']['doctype']['retentionFinalDisposition'],
            'accessRuleCode'            => $config['exportSeda']['accessRuleCode'],
            'history'                   => $history['history'],
            'contacts'                  => [
                'senders'    => ContactController::getParsedContacts(['resId' => $resource['res_id'], 'mode' => 'sender']),
                'recipients' => ContactController::getParsedContacts(['resId' => $resource['res_id'], 'mode' => 'recipient'])
            ],
            'attachments'               => $archivesAttachment,
            'folders'                   => $folder['folderPath'],
            'links'                     => $initData['additionalData']['linkedResources']
        ];

        $data = [
            'type' => 'ArchiveTransfer',
            'messageObject' => [
                'messageName '       => $args['data']['packageName'],
                'messageIdentifier'  => $initData['data']['slipInfo']['slipId'],
                'archivalAgreement'  => $args['data']['archivalAgreement'],
                'dataObjectPackage'  => $dataObjectPackage,
                'archivalAgency'     => $args['data']['entityArchiveRecipient'],
                'transferringAgency' => $initData['data']['entity']['senderArchiveEntity']
            ]
        ];
        $sedaPackage = ExportSEDATrait::generateSEDAPackage(['data' => $data]);
        if (!empty($sedaPackage['errors'])) {
            return ['errors' => [$sedaPackage['errors']]];
        $messageSaved = ExportSEDATrait::saveMessage(['messageObject' => $sedaPackage['messageObject']]);
        $elementSend  = ExportSEDATrait::sendSedaPackage([
            'messageId'       => $messageSaved['messageId'],
            'config'          => $config,
            'encodedFilePath' => $sedaPackage['encodedFilePath'],
            'messageFilename' => $sedaPackage['messageFilename'],
            'resId'           => $resource['res_id']
        ]);
        if (!empty($elementSend['errors'])) {
            return ['errors' => [$elementSend['errors']]];
        }
    private static function sendSedaPackage()
    {
        $bodyData = [
            'messageFile' => base64_encode(file_get_contents($args['encodedFilePath'])),
            'filename'    => $args['messageFilename'],
            'schema'      => 'seda2'
        ];
        $curlResponse = CurlModel::execSimple([
            'url'     => rtrim($args['config']['exportSeda']['urlSAEService'], '/') . '/medona/archiveTransfer',
            'method'  => 'POST',
            'cookie'  => 'LAABS-AUTH=' . urlencode($args['config']['exportSeda']['token']),
            'headers' => [
                'Accept: application/json',
                'Content-Type: application/json',
                'User-Agent: ' . $args['config']['exportSeda']['userAgent']
        ]);

        if (!empty($curlResponse['errors'])) {
            return ['errors' => 'Error returned by the route /medona/create : ' . $curlResponse['errors']];
        } elseif ($curlResponse['code'] != 200) {
            return ['errors' => 'Error returned by the route /medona/create : ' . $curlResponse['response']['message']];
        }

        // TODO GET XML

        $id = StoreController::storeAttachment([
            'encodedFile'   => base64_encode(file_get_contents($pathToDocument)),
            'type'          => 'acknowledgement_record_management',
            'resIdMaster'   => $args['resId'],
            'title'         => 'Accusé de réception',
            'format'        => 'xml',
            'status'        => 'TRA'
        ]);
        if (empty($id) || !empty($id['errors'])) {
            return ['errors' => ['[storeAttachment] ' . $id['errors']]];
        }

        return [];
    }

    public static function saveMessage($args = [])

        $data->messageId                             = $args['messageObject']->MessageIdentifier->value;
        $data->date                                  = $args['messageObject']->Date;

        $data->MessageIdentifier                     = new \stdClass();
        $data->MessageIdentifier->value              = $args['messageObject']->MessageIdentifier->value;

        $data->TransferringAgency                    = new \stdClass();
        $data->TransferringAgency->Identifier        = new \stdClass();
        $data->TransferringAgency->Identifier->value = $args['messageObject']->TransferringAgency->Identifier->value;

        $data->ArchivalAgency                        = new \stdClass();
        $data->ArchivalAgency->Identifier            = new \stdClass();
        $data->ArchivalAgency->Identifier->value     = $args['messageObject']->ArchivalAgency->Identifier->value;

        $data->ArchivalAgreement                     = new \stdClass();
        $data->ArchivalAgreement->value              = $args['messageObject']->ArchivalAgreement->value;

        $data->ReplyCode                             = $args['messageObject']->ReplyCode;

        $dataExtension                      = [];
        $dataExtension['fullMessageObject'] = $args['messageObject'];
        $dataExtension['SenderOrgNAme']     = '';
        $dataExtension['RecipientOrgNAme']  = '';

        $message = MessageExchangeModel::insertMessage([
            'data'          => $data,
            'type'          => 'ArchiveTransfer',
            'dataExtension' => $dataExtension,
            'userId'        => $GLOBALS['id']
        ]);

        return ['messageId' => $message['messageId']];
    }

    public static function getFolderPath($args = [])
    {
        $folderPath = null;
        if (!empty($args['selectedFolder'])) {
            foreach ($args['folders'] as $folder) {
                if ($folder['id'] == $args['selectedFolder']) {
                    $folderId   = explode("_", $folder['id'])[1];
                    $folderPath = FolderModel::getFolderPath(['id' => $folderId]);
                    break;
                }
            }
        }

        return ['folderPath' => $folderPath];
    }

    public static function getHistory($args = [])
    {
        $history = HistoryModel::get([
            'select'  => ['event_date', 'user_id', 'info', 'remote_ip'],
            'where'   => ['table_name in (?)', 'record_id = ?', 'event_type like ?'],
            'data'    => [['res_letterbox', 'res_view_letterbox'], $args['resId'], 'ACTION#%'],
            'orderBy' => ['event_date DESC']
        ]);

        foreach ($history as $key => $value) {
            $history[$key]['userLabel'] = UserModel::getLabelledUserById(['id' => $value['user_id']]);
        }

        return ['history' => $history];
    }

    public static function getAttachmentFilePath($args = [])
    {
        $document['docserver_id'] = $args['data']['docserver_id'];
        $document['path']         = $args['data']['path'];
        $document['filename']     = $args['data']['filename'];
        $document['fingerprint']  = $args['data']['fingerprint'];

        $docserver = DocserverModel::getByDocserverId(['docserverId' => $document['docserver_id'], 'select' => ['path_template', 'docserver_type_id']]);
        if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) {
            return ['errors' => 'Docserver does not exist'];
        }

        $pathToDocument = $docserver['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $document['path']) . $document['filename'];

        if (!file_exists($pathToDocument)) {
            return ['errors' => 'Attachment not found on docserver'];
        }

        $docserverType = DocserverTypeModel::getById(['id' => $docserver['docserver_type_id'], 'select' => ['fingerprint_mode']]);
        $fingerprint   = StoreController::getFingerPrint(['filePath' => $pathToDocument, 'mode' => $docserverType['fingerprint_mode']]);
        if (empty($document['fingerprint'])) {
            AttachmentModel::update(['set' => ['fingerprint' => $fingerprint], 'where' => ['res_id = ?'], 'data' => [$args['resId']]]);
            $document['fingerprint'] = $fingerprint;
        }

        if (!empty($document['fingerprint']) && $document['fingerprint'] != $fingerprint) {
            return ['errors' => 'Fingerprints do not match'];
        }

        $fileContent = file_exists($pathToDocument);
        if ($fileContent === false) {
            return ['errors' => 'Document not found on docserver'];
        }

        return ['filePath' => $pathToDocument];
    }

    public static function getNoteFilePath($args = [])
    {
        $encodedDocument = NoteController::getEncodedPdfByIds(['ids' => [$args['id']]]);

        $tmpPath  = CoreConfigModel::getTmpPath();
        $filePath = $tmpPath . 'note_' . $args['id'] . '.pdf';
        file_put_contents($filePath, base64_decode($encodedDocument['encodedDocument']));

        return ['filePath' => $filePath];
    }

    public static function getEmailFilePath($args = [])
    {
        $body   = str_replace('###', ';', $args['data']['body']);
        $sender = json_decode($args['data']['sender'], true);
        $data   = "Courriel n°" . $args['data']['id'] . "\nDe : " . $sender['email'] . "\nPour : " . implode(", ", json_decode($args['data']['recipients'], true)) . "\nObjet : " . $args['data']['object'] . "\n\n" . strip_tags(html_entity_decode($body));

        $pdf = new Fpdi('P', 'pt');
        $pdf->setPrintHeader(false);
        $pdf->AddPage();
        $pdf->MultiCell(0, 10, $data, 0, 'L');

        $tmpPath  = CoreConfigModel::getTmpPath();
        $filePath = $tmpPath . 'email_' . $args['data']['id'] . '.pdf';
        $pdf->Output($filePath, "F");

        return ['filePath' => $filePath];
    }

    public static function getSummarySheetFilePath($args = [])
    {
        $units   = [];
        $units[] = ['unit' => 'primaryInformations'];
        $units[] = ['unit' => 'secondaryInformations',       'label' => _SECONDARY_INFORMATION];
        $units[] = ['unit' => 'senderRecipientInformations', 'label' => _DEST_INFORMATION];
        $units[] = ['unit' => 'diffusionList',               'label' => _DIFFUSION_LIST];
        $units[] = ['unit' => 'visaWorkflow',                'label' => _VISA_WORKFLOW];
        $units[] = ['unit' => 'opinionWorkflow',             'label' => _AVIS_WORKFLOW];
        $units[] = ['unit' => 'notes',                       'label' => _NOTES_COMMENT];
        
        $tmpIds = [$args['resId']];
        $data   = [];
        foreach ($units as $unit) {
            if ($unit['unit'] == 'opinionWorkflow') {
                $data['listInstancesOpinion'] = ListInstanceModel::get([
                    'select'    => ['item_id', 'process_date', 'res_id'],
                    'where'     => ['difflist_type = ?', 'res_id in (?)'],
                    'data'      => ['AVIS_CIRCUIT', $tmpIds],
                    'orderBy'   => ['listinstance_id']
                ]);
            } elseif ($unit['unit'] == 'visaWorkflow') {
                $data['listInstancesVisa'] = ListInstanceModel::get([
                    'select'    => ['item_id', 'requested_signature', 'process_date', 'res_id'],
                    'where'     => ['difflist_type = ?', 'res_id in (?)'],
                    'data'      => ['VISA_CIRCUIT', $tmpIds],
                    'orderBy'   => ['listinstance_id']
                ]);
            } elseif ($unit['unit'] == 'diffusionList') {
                $data['listInstances'] = ListInstanceModel::get([
                    'select'  => ['item_id', 'item_type', 'item_mode', 'res_id'],
                    'where'   => ['difflist_type = ?', 'res_id in (?)'],
                    'data'    => ['entity_id', $tmpIds],
                    'orderBy' => ['listinstance_id']
                ]);
            }
        }

        $mainResource = ResModel::getOnView([
            'select' => ['process_limit_date', 'status', 'alt_identifier', 'subject', 'priority', 'res_id', 'admission_date', 'creation_date', 'doc_date', 'initiator', 'typist', 'type_label', 'destination', 'filename'],
            'where'  => ['res_id = ?'],
            'data'   => [$args['resId']]
        ]);

        $pdf = new Fpdi('P', 'pt');
        $pdf->setPrintHeader(false);
        SummarySheetController::createSummarySheet($pdf, ['resource' => $mainResource[0], 'units' => $units, 'login' => $GLOBALS['login'], 'data' => $data]);

        $tmpPath = CoreConfigModel::getTmpPath();
        $summarySheetFilePath = $tmpPath . "summarySheet_".$args['resId'] . "_" . $aArgs['userId'] . "_" . rand() . ".pdf";
        $pdf->Output($summarySheetFilePath, 'F');

        return ['filePath' => $summarySheetFilePath];
    }

    public static function generateSEDAPackage(array $args)
    {
        $encodedFile = '';
        
        return ['encodedFile' => $encodedFile];
    }

    public static function checkAcknowledgmentRecordManagement(array $args)
    {
        ValidatorModel::notEmpty($args, ['resId']);
        ValidatorModel::intVal($args, ['resId']);

        $acknowledgement = AttachmentModel::get([
            'select' => ['res_id_master', 'path', 'filename', 'docserver_id', 'fingerprint'],
            'where'  => ['res_id_master = ?', 'attachment_type = ?', 'status = ?'],
            'data'   => [$args['resId'], 'acknowledgement_record_management', 'TRA']
        ])[0];
        if (empty($acknowledgement)) {
            return ['errors' => ['No acknowledgement found']];
        }

        $docserver = DocserverModel::getByDocserverId(['docserverId' => $acknowledgement['docserver_id'], 'select' => ['path_template', 'docserver_type_id']]);
        if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) {
            return ['errors' => ['Docserver does not exists']];
        }

        $pathToDocument = $docserver['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $acknowledgement['path']) . $acknowledgement['filename'];
        if (!file_exists($pathToDocument)) {
            return ['errors' => ['File does not exists']];
        }

        $docserverType = DocserverTypeModel::getById(['id' => $docserver['docserver_type_id'], 'select' => ['fingerprint_mode']]);
        $fingerprint = StoreController::getFingerPrint(['filePath' => $pathToDocument, 'mode' => $docserverType['fingerprint_mode']]);
        if (!empty($acknowledgement['fingerprint']) && $acknowledgement['fingerprint'] != $fingerprint) {
            return ['errors' => ['Fingerprint does not match']];
        }
        
        $acknowledgementXml = @simplexml_load_file($pathToDocument);
        if (empty($acknowledgementXml)) {
            return ['errors' => ['Acknowledgement is not readable']];
        }

        $messageExchange = MessageExchangeModel::getMessageByReference(['select' => ['message_id'], 'reference' => (string)$acknowledgementXml->MessageReceivedIdentifier]);
        if (empty($messageExchange)) {
            return ['errors' => ['No acknowledgement found with this reference']];
        }

        $unitIdentifier = MessageExchangeModel::getUnitIdentifierByResId(['select' => ['message_id'], 'resId' => $args['resId']]);
        if ($unitIdentifier['message_id'] != $messageExchange['message_id']) {
            return ['errors' => ['Wrong acknowledgement']];
        }

        return true;
    }

    public static function checkReplyRecordManagement(array $args)
    {
        ValidatorModel::notEmpty($args, ['resId']);
        ValidatorModel::intVal($args, ['resId']);

        $reply = AttachmentModel::get([
            'select' => ['res_id_master', 'path', 'filename', 'docserver_id', 'fingerprint'],
            'where'  => ['res_id_master = ?', 'attachment_type = ?', 'status = ?'],
            'data'   => [$args['resId'], 'reply_record_management', 'TRA']
        ])[0];
        if (empty($reply)) {
            return ['errors' => ['No reply found']];
        }

        $docserver = DocserverModel::getByDocserverId(['docserverId' => $reply['docserver_id'], 'select' => ['path_template', 'docserver_type_id']]);
        if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) {
            return ['errors' => ['Docserver does not exists']];
        }

        $pathToDocument = $docserver['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $reply['path']) . $reply['filename'];
        if (!file_exists($pathToDocument)) {
            return ['errors' => ['File does not exists']];
        }

        $docserverType = DocserverTypeModel::getById(['id' => $docserver['docserver_type_id'], 'select' => ['fingerprint_mode']]);
        $fingerprint = StoreController::getFingerPrint(['filePath' => $pathToDocument, 'mode' => $docserverType['fingerprint_mode']]);
        if (!empty($reply['fingerprint']) && $reply['fingerprint'] != $fingerprint) {
            return ['errors' => ['Fingerprint does not match']];
        }
        
        $replyXml = @simplexml_load_file($pathToDocument);
        if (empty($replyXml)) {
            return ['errors' => ['Reply is not readable']];
        }

        $messageExchange = MessageExchangeModel::getMessageByReference(['select' => ['message_id'], 'reference' => (string)$replyXml->MessageReceivedIdentifier]);
        if (empty($messageExchange)) {
            return ['errors' => ['No reply found with this reference']];
        }

        $unitIdentifier = MessageExchangeModel::getUnitIdentifierByResId(['select' => ['message_id'], 'resId' => $args['resId']]);
        if ($unitIdentifier['message_id'] != $messageExchange['message_id']) {
            return ['errors' => ['Wrong reply']];
        }

        return true;
    }