diff --git a/src/app/action/controllers/ExternalSignatoryBookTrait.php b/src/app/action/controllers/ExternalSignatoryBookTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..80062692cc740f00a8e46e994c15107f88674a46 --- /dev/null +++ b/src/app/action/controllers/ExternalSignatoryBookTrait.php @@ -0,0 +1,98 @@ +<?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 ExternalSignatoryBookTrait +* @author dev <dev@maarch.org> +* @ingroup core +*/ + +namespace Action\controllers; + +use SrcCore\models\ValidatorModel; +use Attachment\models\AttachmentModel; +use ExternalSignatoryBook\controllers\XParaphController; +use Resource\models\ResModel; +use SrcCore\models\CoreConfigModel; + +trait ExternalSignatoryBookTrait +{ + public static function sendExternalSignatoryBookAction(array $args) + { + ValidatorModel::notEmpty($args, ['resId']); + ValidatorModel::intVal($args, ['resId']); + + $loadedXml = CoreConfigModel::getXmlLoaded(['path' => 'modules/visa/xml/remoteSignatoryBooks.xml']); + $config = []; + + if (!empty($loadedXml)) { + $config['id'] = (string)$loadedXml->signatoryBookEnabled; + foreach ($loadedXml->signatoryBook as $value) { + if ($value->id == $config['id']) { + $config['data'] = (array)$value; + break; + } + } + + if ($config['id'] == 'ixbus') { + // TODO + } elseif ($config['id'] == 'iParapheur') { + // TODO + } elseif ($config['id'] == 'fastParapheur') { + // TODO + } elseif ($config['id'] == 'maarchParapheur') { + // TODO + } elseif ($config['id'] == 'xParaph') { + $attachmentToFreeze = XParaphController::sendDatas([ + 'config' => $config, + 'resIdMaster' => $args['resId'] + ]); + } + } + + if (!empty($attachmentToFreeze)) { + if (!empty($attachmentToFreeze['letterbox_coll'])) { + ResModel::update([ + 'set' => ['external_signatory_book_id' => $attachmentToFreeze['letterbox_coll'][$res_id]], + 'where' => ['res_id = ?'], + 'data' => [$res_id] + ]); + } else { + if (!empty($attachmentToFreeze['attachments_coll'])) { + foreach ($attachmentToFreeze['attachments_coll'] as $resId => $externalId) { + AttachmentModel::freezeAttachment([ + 'resId' => $resId, + 'table' => 'res_attachments', + 'externalId' => $externalId + ]); + } + } + if (!empty($attachmentToFreeze['attachments_version_coll'])) { + foreach ($attachmentToFreeze['attachments_version_coll'] as $resId => $externalId) { + AttachmentModel::freezeAttachment([ + 'resId' => $resId, + 'table' => 'res_version_attachments', + 'externalId' => $externalId + ]); + } + } + } + + // $stmt = $db->query('SELECT status FROM res_letterbox WHERE res_id = ?', array($res_id)); + // $resource = $stmt->fetchObject(); + + // if ($resource->status == 'EVIS' || $resource->status == 'ESIG') { + // $sequence = $circuit_visa->getCurrentStep($res_id, $coll_id, 'VISA_CIRCUIT'); + // $stepDetails = array(); + // $stepDetails = $circuit_visa->getStepDetails($res_id, $coll_id, 'VISA_CIRCUIT', $sequence); + + // $message = $circuit_visa->processVisaWorkflow(['stepDetails' => $stepDetails, 'res_id' => $res_id]); + // } + } + + return true; + } +} diff --git a/src/app/external/externalSignatoryBook/controllers/XParaphController.php b/src/app/external/externalSignatoryBook/controllers/XParaphController.php new file mode 100755 index 0000000000000000000000000000000000000000..0b9dfb48b0db55c1a341b5bd74d9372b54f6717d --- /dev/null +++ b/src/app/external/externalSignatoryBook/controllers/XParaphController.php @@ -0,0 +1,103 @@ +<?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 XParaph Controller +* @author dev@maarch.org +*/ + +namespace ExternalSignatoryBook\controllers; + +use Attachment\models\AttachmentModel; +use Convert\controllers\ConvertPdfController; +use Docserver\models\DocserverModel; +use SrcCore\models\CurlModel; + +class XParaphController +{ + public static function sendDatas($aArgs) + { + $attachments = AttachmentModel::getOnView([ + 'select' => [ + 'res_id', 'res_id_version', 'title', 'identifier', 'attachment_type', + 'status', 'typist', 'docserver_id', 'path', 'filename', 'creation_date', + 'validation_date', 'relation', 'attachment_id_master', 'filesize' + ], + 'where' => ["res_id_master = ?", "attachment_type not in (?)", "status not in ('DEL', 'OBS', 'FRZ', 'TMP')", "in_signature_book = 'true'"], + 'data' => [$aArgs['resIdMaster'], ['converted_pdf', 'incoming_mail_attachment', 'print_folder', 'signed_response']] + ]); + + $attachmentToFreeze = []; + + foreach ($attachments as $value) { + if (!empty($value['res_id'])) { + $resId = $value['res_id']; + $collId = 'attachments_coll'; + $is_version = false; + } else { + $resId = $value['res_id_version']; + $collId = 'attachments_version_coll'; + $is_version = true; + } + $adrInfo = ConvertPdfController::getConvertedPdfById(['resId' => $resId, 'collId' => $collId, 'isVersion' => $is_version]); + $docserverInfo = DocserverModel::getByDocserverId(['docserverId' => $adrInfo['docserver_id']]); + $filePath = $docserverInfo['path_template'] . str_replace('#', '/', $adrInfo['path']) . $adrInfo['filename']; + $fileContent = file_get_contents($filePath); + + $xmlPostString = '<?xml version="1.0" encoding="utf-8"?> + <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:parafwsdl" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> + <soapenv:Header/> + <soapenv:Body> + <urn:XPRF_Deposer soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> + <params xsi:type="urn:XPRF_Deposer_Param"> + <reponse xsi:type="xsd:string">SOAP</reponse> + <siret xsi:type="xsd:string">'.$aArgs['config']['data']['siret'].'</siret> + <login xsi:type="xsd:string">'.$aArgs['config']['data']['login'].'</login> + <password xsi:type="xsd:string">'.$aArgs['config']['data']['password'].'</password> + <docutype xsi:type="xsd:string">'.$aArgs['config']['data']['docutype'].'</docutype> + <docustype xsi:type="xsd:string">'.$aArgs['config']['data']['docustype'].'</docustype> + <objet xsi:type="xsd:string">'.$value['title'].'</objet> + <contenu xsi:type="xsd:base64Binary">'.base64_encode($fileContent).'</contenu> + <nom xsi:type="xsd:string">'.$value['title'].'</nom> + <taille xsi:type="xsd:int">'.$value['filesize'].'</taille> + <pml xsi:type="xsd:string">0</pml> + </params> + </urn:XPRF_Deposer> + </soapenv:Body> + </soapenv:Envelope>'; + + $response = CurlModel::execSOAP([ + 'soapAction' => 'urn:parafwsdl#paraf', + 'url' => $aArgs['config']['data']['url'], + 'xmlPostString' => $xmlPostString, + 'options' => [CURLOPT_SSL_VERIFYPEER => false] + ]); + + $isError = $response['response']->children('http://schemas.xmlsoap.org/soap/envelope/')->Body; + if (!empty($isError->Fault[0])) { + $error = $response['response']->children('http://schemas.xmlsoap.org/soap/envelope/')->Body->Fault[0]->children()->detail; + return $error; + } else { + // $response = $response['response']->children('http://schemas.xmlsoap.org/soap/envelope/')->Body->children('http://sei.ws.fast.cdc.com/')->downloadResponse->children()->return; + // $returnedDocumentId = (string) $response->documentId; + // if ($aArgs['documentId'] !== $returnedDocumentId) { + // // TODO gestion d'une potentiel erreur + // return false; + // } else { + // $b64FileContent = $response->content; + // return ['b64FileContent' => (string)$b64FileContent, 'documentId' => $returnedDocumentId]; + // } + } + + // $attachmentToFreeze[$collId][$resId] = (string)$response; + } + + return $attachmentToFreeze; + } +} diff --git a/src/app/external/externalSignatoryBook/models/MessageExchangeModel.php b/src/app/external/externalSignatoryBook/models/MessageExchangeModel.php new file mode 100755 index 0000000000000000000000000000000000000000..b3db9181390fabdec3d559eef97cfad7cdb74238 --- /dev/null +++ b/src/app/external/externalSignatoryBook/models/MessageExchangeModel.php @@ -0,0 +1,19 @@ +<?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 Message Exchange Model +* @author dev@maarch.org +*/ + +namespace MessageExchange\models; + +class MessageExchangeModel extends MessageExchangeModelAbstract +{ +} diff --git a/src/app/external/externalSignatoryBook/models/MessageExchangeModelAbstract.php b/src/app/external/externalSignatoryBook/models/MessageExchangeModelAbstract.php new file mode 100755 index 0000000000000000000000000000000000000000..577190e2ed4d6be4ed99dc1cb8af14038a88683b --- /dev/null +++ b/src/app/external/externalSignatoryBook/models/MessageExchangeModelAbstract.php @@ -0,0 +1,197 @@ +<?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 User Model + * @author dev@maarch.org + */ + +namespace MessageExchange\models; + +use SrcCore\models\DatabaseModel; +use SrcCore\models\ValidatorModel; +use Docserver\models\DocserverModel; +use Docserver\models\DocserverTypeModel; +use Resource\controllers\StoreController; +use Docserver\controllers\DocserverController; + +abstract class MessageExchangeModelAbstract +{ + public static function getMessageByReference($aArgs = []) + { + ValidatorModel::notEmpty($aArgs, ['reference']); + + $aReturn = DatabaseModel::select( + [ + 'select' => empty($aArgs['select']) ? ['*'] : $aArgs['select'], + 'table' => ['message_exchange'], + 'where' => ['reference = ?'], + 'data' => [$aArgs['reference']] + ] + ); + + if (empty($aReturn[0])) { + return []; + } + + return $aReturn; + } + + public static function getMessageByIdentifier($aArgs = []) + { + ValidatorModel::notEmpty($aArgs, ['messageId']); + + $aReturn = DatabaseModel::select( + [ + 'select' => empty($aArgs['select']) ? ['*'] : $aArgs['select'], + 'table' => ['message_exchange'], + 'where' => ['message_id = ?'], + 'data' => [$aArgs['messageId']] + ] + ); + + if (empty($aReturn[0])) { + return []; + } + + return $aReturn; + } + + public static function updateStatusMessage(array $aArgs) + { + ValidatorModel::notEmpty($aArgs, ['status','reference']); + + DatabaseModel::update([ + 'table' => 'message_exchange', + 'set' => [ + 'status' => $aArgs['status'] + ], + 'where' => ['reference = ?'], + 'data' => [$aArgs['reference']] + ]); + + return true; + } + + /*** Generates a local unique identifier + @return string The unique id*/ + public static function generateUniqueId() + { + $parts = explode('.', microtime(true)); + $sec = $parts[0]; + if (!isset($parts[1])) { + $msec = 0; + } else { + $msec = $parts[1]; + } + $uniqueId = str_pad(base_convert($sec, 10, 36), 6, '0', STR_PAD_LEFT) . str_pad(base_convert($msec, 10, 16), 4, '0', STR_PAD_LEFT); + $uniqueId .= str_pad(base_convert(mt_rand(), 10, 36), 6, '0', STR_PAD_LEFT); + + return $uniqueId; + } + + public static function insertMessage($args = []) + { + $messageObject = $args['data']; + $type = $args['type']; + $aArgs = $args['dataExtension']; + $userId = $args['userId']; + + if (empty($messageObject->messageId)) { + $messageObject->messageId = self::generateUniqueId(); + } + + if (empty($aArgs['status'])) { + $status = "sent"; + } else { + $status = $aArgs['status']; + } + + if (empty($aArgs['fullMessageObject'])) { + $messageObjectToSave = $messageObject; + } else { + $messageObjectToSave = $aArgs['fullMessageObject']; + } + + if (empty($aArgs['resIdMaster'])) { + $resIdMaster = null; + } else { + $resIdMaster = $aArgs['resIdMaster']; + } + + if (empty($aArgs['filePath'])) { + $filePath = null; + } else { + $filePath = $aArgs['filePath']; + $filesize = filesize($filePath); + + //Store resource on docserver + $resource = file_get_contents($filePath); + $pathInfo = pathinfo($filePath); + $storeResult = DocserverController::storeResourceOnDocServer([ + 'collId' => 'archive_transfer_coll', + 'docserverTypeId' => 'ARCHIVETRANSFER', + 'encodedResource' => base64_encode($resource), + 'format' => $pathInfo['extension'] + ]); + + if (!empty($storeResult['errors'])) { + var_dump($storeResult['errors']); + } + $docserverId = $storeResult['docserver_id']; + $filepath = $storeResult['destination_dir']; + $filename = $storeResult['file_destination_name']; + $docserver = DocserverModel::getByDocserverId(['docserverId' => $docserverId]); + + $docserverType = DocserverTypeModel::getById([ + 'id' => $docserver['docserver_type_id'] + ]); + + $fingerprint = StoreController::getFingerPrint([ + 'filePath' => $filePath, + 'mode' => $docserverType['fingerprint_mode'], + ]); + } + + try { + DatabaseModel::insert([ + 'table' => 'message_exchange', + 'columnsValues' => [ + 'message_id' => $messageObject->messageId, + 'schema' => "2.1", + 'type' => $type, + 'status' => $status, + 'date' => $messageObject->date, + 'reference' => $messageObject->MessageIdentifier->value, + 'account_id' => $userId, + 'sender_org_identifier' => $messageObject->TransferringAgency->Identifier->value, + 'sender_org_name' => $aArgs['SenderOrgNAme'], + 'recipient_org_identifier' => $messageObject->ArchivalAgency->Identifier->value, + 'recipient_org_name' => $aArgs['RecipientOrgNAme'], + 'archival_agreement_reference' => $messageObject->ArchivalAgreement->value, + 'reply_code' => $messageObject->ReplyCode, + 'size' => '0', + 'data' => json_encode($messageObjectToSave), + 'active' => "TRUE", + 'archived' => "FALSE", + 'res_id_master' => $resIdMaster, + 'docserver_id' => $docserverId, + 'path' => $filepath, + 'filename' => $filename, + 'fingerprint' => $fingerprint, + 'filesize' => $filesize + ] + ]); + } catch (Exception $e) { + return false; + } + + return $messageObject->messageId; + } +} diff --git a/src/frontend/app/actions/send-external-signatory-book-action/send-external-signatory-book-action.component.html b/src/frontend/app/actions/send-external-signatory-book-action/send-external-signatory-book-action.component.html new file mode 100644 index 0000000000000000000000000000000000000000..4318fb10adbff639d337fa3dc64a562de6002758 --- /dev/null +++ b/src/frontend/app/actions/send-external-signatory-book-action/send-external-signatory-book-action.component.html @@ -0,0 +1,26 @@ +<h1 mat-dialog-title>{{data.action.label_action}}</h1> +<div mat-dialog-content > + <div *ngIf="loading" class="loading" style="display:flex;height:100%;"> + <mat-spinner style="margin:auto;"></mat-spinner> + </div> + <mat-sidenav-container autosize style="height:100%;"> + <mat-sidenav-content style="background: white;"> + <div class="row" style="margin: 0;"> + <div class="col-md-12"> + {{lang.makeActionOn}} + <b *ngIf="data.contextMode" color="primary" class="highlight">{{data.contextChrono}}</b> + <b *ngIf="!data.contextMode" color="primary" class="highlight">{{data.selectedRes.length}} + {{lang.elements}}</b> ? + </div> + <div class="col-md-12"> + <app-note-editor #noteEditor [resIds]="data.selectedRes"></app-note-editor> + </div> + </div> + </mat-sidenav-content> + </mat-sidenav-container> +</div> +<div mat-dialog-actions class="actions"> + <button mat-raised-button mat-button color="primary" + (click)="onSubmit()">{{lang.validate}}</button> + <button mat-raised-button mat-button [mat-dialog-close]="">{{lang.cancel}}</button> +</div> \ No newline at end of file diff --git a/src/frontend/app/actions/send-external-signatory-book-action/send-external-signatory-book-action.component.scss b/src/frontend/app/actions/send-external-signatory-book-action/send-external-signatory-book-action.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..9424211bb4af9027d454165e7417bf86fb23c6eb --- /dev/null +++ b/src/frontend/app/actions/send-external-signatory-book-action/send-external-signatory-book-action.component.scss @@ -0,0 +1,128 @@ +@import '../../../css/vars.scss'; + +.fullHeight { + height: 70vh; +} + +.fullWidth { + width: 70vw; +} + +.highlight { + font-size: 110%; +} + +.loading { + display: flex; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: #ffffffb3; + z-index: 2; + overflow: hidden; +} + +.mailList { + ul { + font-size: 12px; + max-height: 100px; + overflow: auto; + padding-left: 25px; + padding-right: 5px; + padding-bottom: 10px; + margin-top: 10px; + } + + p { + //font-size: 18px; + margin: 0; + text-decoration: underline; + } + + b { + font-size: 120%; + } +} + +.formType { + align-items: center; + display: flex; + margin: 10px; + border-radius: 4px; + border: solid 1px #ccc; + position: relative; + padding: 10px; + + &-title { + white-space: pre; + overflow: hidden; + max-width: 85%; + text-overflow: ellipsis; + z-index: 1; + font-size: 10px; + font-weight: bold; + background: white; + position: absolute; + top: -7px; + left: 10px; + padding: 0px; + margin: 0px; + color: #135f7f; + } + + ::ng-deep.mat-form-field-suffix { + color: $secondary; + font-size: 15px; + top: 0; + } + + ::ng-deep.mat-form-field-wrapper { + padding: 0; + } +} + +.priceContent { + display: flex; + align-items: center; + justify-content: flex-end; + width: 100%; + + &-label { + text-align: right; + color: $primary; + flex: 1; + justify-content: flex-end; + display: flex; + padding-right: 10px; + } + + .mat-form-field { + width: 90px !important; + + input { + font-weight: bold; + user-select: none; + } + } +} + +.priceInfo { + padding-right: 20px; + font-size: 10px; + opacity: 0.5; + width: 100%; +} + +.pjList { + display: flex; + width: 100%; + overflow: auto; + flex-direction: column; + background: #666; + + img { + margin: 10px; + } +} \ No newline at end of file diff --git a/src/frontend/app/actions/send-external-signatory-book-action/send-external-signatory-book-action.component.ts b/src/frontend/app/actions/send-external-signatory-book-action/send-external-signatory-book-action.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..ba63ab58a9e390163f767ac2a93497b731f6076f --- /dev/null +++ b/src/frontend/app/actions/send-external-signatory-book-action/send-external-signatory-book-action.component.ts @@ -0,0 +1,56 @@ +import { Component, OnInit, Inject, ViewChild } from '@angular/core'; +import { LANG } from '../../translate.component'; +import { NotificationService } from '../../notification.service'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; +import { HttpClient } from '@angular/common/http'; +import { NoteEditorComponent } from '../../notes/note-editor.component'; + +@Component({ + templateUrl: "send-external-signatory-book-action.component.html", + styleUrls: ['send-external-signatory-book-action.component.scss'], + providers: [NotificationService], +}) +export class sendExternalSignatoryBookActionComponent implements OnInit { + + lang: any = LANG; + loading: boolean = false; + + @ViewChild('noteEditor') noteEditor: NoteEditorComponent; + + constructor(public http: HttpClient, private notify: NotificationService, public dialogRef: MatDialogRef<sendExternalSignatoryBookActionComponent>, @Inject(MAT_DIALOG_DATA) public data: any) { } + + ngOnInit(): void { + this.loading = false; + + // this.http.post('../../rest/resourcesList/users/' + this.data.currentBasketInfo.ownerId + '/groups/' + this.data.currentBasketInfo.groupId + '/baskets/' + this.data.currentBasketInfo.basketId + '/actions/' + this.data.action.id + '/checkShippings', { resources: this.data.selectedRes }) + // .subscribe((data: any) => { + // this.shippings = data.shippingTemplates; + // this.mailsNotSend = data.canNotSend; + // this.entitiesList = data.entities; + // this.attachList = data.resources; + // this.loading = false; + // }, (err: any) => { + // this.notify.handleErrors(err); + // this.loading = false; + // }); + } + + onSubmit(): void { + this.loading = false; + + this.http.put('../../rest/resourcesList/users/' + this.data.currentBasketInfo.ownerId + '/groups/' + this.data.currentBasketInfo.groupId + '/baskets/' + this.data.currentBasketInfo.basketId + '/actions/' + this.data.action.id, { resources: this.data.selectedRes, note: this.noteEditor.getNoteContent() }) + .subscribe((data: any) => { + if (data && data.data != null) { + this.dialogRef.close('success'); + } + if (data && data.errors != null) { + this.notify.error(data.errors); + } + this.loading = false; + }, (err: any) => { + this.notify.handleErrors(err); + this.loading = false; + }); + } + +}