Commit 7030ae75 authored by Stephane Bouvry's avatar Stephane Bouvry
Browse files

Signature/Document : Le déclenchement des procédure de signature a été...

Signature/Document : Le déclenchement des procédure de signature a été dissocié du type de document (en cours)
parent 6f8cd7ee
Loading
Loading
Loading
Loading
Loading
+1 −1
Changes for module/Oscar/config/module.config.php: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -252,7 +252,7 @@ return array(
                // DOCUMENTS
                [
                    'controller' => 'ContractDocument', // --- Upload
                    'action' => ['upload', 'delete', 'changeType', 'index', 'show', 'download', 'process'],
                    'action' => ['upload', 'delete', 'changeType', 'index', 'show', 'download', 'process', 'signDocument'],
                    'roles' => ['user']
                ],

+6 −0
Changes for module/Oscar/config/routes.yml: 6 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -1256,6 +1256,12 @@ contractdocument:
        route: /document-change-type
        defaults:
          action: changeType
    signdocument:
      type: segment
      options:
        route: /signature-document
        defaults:
          action: signDocument
    upload:
      type: segment
      options:
+14 −0
Changes for module/Oscar/src/Oscar/Controller/AbstractOscarController.php: 14 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@ use Oscar\Traits\UseOscarConfigurationService;
use Oscar\Traits\UseOscarConfigurationServiceTrait;
use Oscar\Traits\UseOscarUserContextService;
use Oscar\Traits\UseOscarUserContextServiceTrait;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use Symfony\Component\Yaml\Parser;
use UnicaenAuth\Service\UserContext;
use Laminas\Http\Request;
@@ -41,6 +44,17 @@ class AbstractOscarController extends AbstractActionController implements UseOsc
    use UseOscarConfigurationServiceTrait, UseOscarUserContextServiceTrait, UseLoggerServiceTrait, UseEntityManagerTrait, UseActivityLogServiceTrait;


    /**
     * @throws OscarException
     */
    protected function getService(ContainerInterface $container, string $id){
        try {
            return $container->get($id);
        } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) {
            $this->getLoggerService()->critical("Service Not Found '$id' : " . $e->getMessage());
            throw new OscarException("Erreur de service critique '$id'");
        }
    }
    /**
     * Retourne le format de la requête sous la forme d'une chaîne.
     * NB:  Pour le moment, sert uniquement à detecter le format JSON.
+80 −49
Changes for module/Oscar/src/Oscar/Controller/ContractDocumentController.php: 80 added lines, 49 removed lines.
Original line number Diff line number Diff line
<?php
/**
 * @author Stéphane Bouvry<stephane.bouvry@unicaen.fr>
 * @date: 26/10/15 09:32
 * @copyright Certic (c) 2015
 */

namespace Oscar\Controller;

use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Exception;
use Oscar\Entity\ContractDocument;
use Oscar\Entity\Person;
@@ -21,18 +14,14 @@ use Oscar\Provider\Privileges;
use Oscar\Service\ActivityLogService;
use Oscar\Service\ContractDocumentService;
use Oscar\Service\NotificationService;
use Oscar\Service\OscarUserContext;
use Oscar\Service\ProjectGrantService;
use Oscar\Service\VersionnedDocumentService;
use Oscar\Strategy\Upload\conventionSignee;
use Oscar\Strategy\Upload\ServiceContextUpload;
use Oscar\Traits\UseServiceContainer;
use Oscar\Traits\UseServiceContainerTrait;
use Oscar\Utils\FileSystemUtils;
use Oscar\Utils\UnicaenDoctrinePaginator;
use Psr\Container\ContainerInterface;
use Laminas\Http\Request;
use Laminas\Json\Server\Exception\HttpException;
use Laminas\View\Model\JsonModel;


@@ -45,70 +34,50 @@ class ContractDocumentController extends AbstractOscarController implements UseS

    use UseServiceContainerTrait;

    /**
     * @return ProjectGrantService
     */
    public function getActivityService()
    {
        return $this->getServiceContainer()->get(ProjectGrantService::class);
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////// SERVICES ACCESS

    /**
     * @return OscarUserContext
     * @return ProjectGrantService
     * @throws OscarException
     */
    public function getOscarUserContext()
    public function getActivityService(): ProjectGrantService
    {
        return $this->getOscarUserContextService();
        return $this->getService($this->getServiceContainer(), ProjectGrantService::class);
    }

    /**
     * @return ContainerInterface
     */
    public function getServiceLocator()
    public function getServiceLocator(): ContainerInterface
    {
        return $this->getServiceContainer();
    }

    /**
     * @return mixed
     * @return NotificationService
     * @throws OscarException
     */
    public function getNotificationService()
    public function getNotificationService(): NotificationService
    {
        return $this->getServiceContainer()->get(NotificationService::class);
        return $this->getService($this->getServiceContainer(), NotificationService::class);
    }

    public function getActivityLogService(): ActivityLogService
    {
        return $this->getServiceContainer()->get(ActivityLogService::class);
    }


    private $versionnedDocumentService;

    /**
     * Retourne l'emplacement où sont stoqués les documents depuis le fichier
     * de configuration local.php
     *
     * @param ContractDocument|null $document
     * @return mixed|string
     * @return ActivityLogService
     * @throws OscarException
     */
    protected function getDropLocation(ContractDocument $document = null)
    public function getActivityLogService(): ActivityLogService
    {
        if (!is_null($document)) {
            return $this->getOscarConfigurationService()->getDocumentRealpath($document);
        }
        else {
            return $this->getOscarConfigurationService()->getDocumentDropLocation();
        }
        return $this->getService($this->getServiceContainer(), ActivityLogService::class);
    }

    /**
     * @return ContractDocumentService
     * @throws OscarException
     */
    protected function getContractDocumentService()
    {
        return $this->getServiceContainer()->get(ContractDocumentService::class);
        return $this->getService($this->getServiceContainer(),ContractDocumentService::class);
    }

    /**
@@ -117,7 +86,12 @@ class ContractDocumentController extends AbstractOscarController implements UseS
     * @annotations Retourne le service pour gérer les documents
     */

    protected function getVersionnedDocumentService()
    private ?VersionnedDocumentService $versionnedDocumentService = null;

    /**
     * @throws OscarException
     */
    protected function getVersionnedDocumentService() :VersionnedDocumentService
    {
        if (null === $this->versionnedDocumentService) {
            $this->versionnedDocumentService = new VersionnedDocumentService(
@@ -128,6 +102,28 @@ class ContractDocumentController extends AbstractOscarController implements UseS
        }
        return $this->versionnedDocumentService;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////////////////////////////////////////////// USEFULL INFOS
    /**
     * Retourne l'emplacement où sont stoqués les documents depuis le fichier
     * de configuration local.php
     *
     * @param ContractDocument|null $document
     * @throws OscarException
     */
    protected function getDropLocation(ContractDocument $document = null) :string
    {
        if (!is_null($document)) {
            return $this->getOscarConfigurationService()->getDocumentRealpath($document);
        }
        else {
            return $this->getOscarConfigurationService()->getDocumentDropLocation();
        }
    }


    ////////////////////////////////////////////////////////////////////////////


@@ -312,7 +308,6 @@ class ContractDocumentController extends AbstractOscarController implements UseS
            }
        }


        if ($action == 'version') {
            try {
                $this->getContractDocumentService()->uploadContractDocument(
@@ -360,7 +355,8 @@ class ContractDocumentController extends AbstractOscarController implements UseS
            $flow = $this->params()->fromPost('flow');
            $flowDt = null;
            if($flow != 'false'){
                $flowDt = json_decode($flow, true);
                // DISABLED
                // $flowDt = json_decode($flow, true);
            }
            $this->getContractDocumentService()->uploadContractDocument(
                $_FILES['file'],
@@ -384,6 +380,41 @@ class ContractDocumentController extends AbstractOscarController implements UseS
        }
    }

    public function signDocumentAction() {
        try {
            // DOCUMENT et FLOWDT
            try {
                $document_id = $this->params()->fromPost('document_id', null);
                if( $document_id == null || $document_id <= 0 ){
                    throw new OscarException("ID de document non transmis");
                }
                $document = $this->getContractDocumentService()->getDocument($document_id);
            } catch (Exception $e){
                throw new OscarException("Impossible de trouver le document");
            }
            $activity = $this->getActivityService()->getActivityById($document->getActivity()->getId());

            // FLOW

            $flowDtPosted = $this->params()->fromPost('flow_datas', null);
            if( $flowDtPosted == null ){
                throw new OscarException("Aucune donnée de signature envoyée");
            }
            $flowDt = json_decode($flowDtPosted, true);

            if( !$flowDt ){
                throw new OscarException("Les données de signature envoyées sont invalides");
            }

            $this->getContractDocumentService()->applySignature($document->getId(), $flowDt['id'], $flowDt);

            return new JsonModel(['response' => 'ok']);
        } catch (Exception $e) {
            $this->getLoggerService()->critical("Erreur signature : " . $e->getMessage());
            return $this->jsonError("Un problème est survenu lors de la soumission pour signature : " . $e->getMessage());
        }
    }

    /**
     * Téléchargement d'un document.
     *
+52 −25
Changes for module/Oscar/src/Oscar/Controller/ProjectGrantController.php: 52 added lines, 25 removed lines.
Original line number Diff line number Diff line
@@ -1223,7 +1223,6 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif
    /** Export les données en CSV. */
    public function csvAction()
    {

        /** @var Request $request */
        $request = $this->getRequest();

@@ -1244,7 +1243,8 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif
            if (!$paramID) {
                return $this->getResponseBadRequest();
            }
        } else {
        }
        else {
            return $this->getResponseUnauthorized();
        };

@@ -1576,6 +1576,8 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif
        $rolesAppli = $this->getOscarUserContextService()->getBaseRoleId();
        $rolesMerged = array_merge($roles, $rolesAppli);

        $allowSign = $this->getOscarUserContextService()->hasPrivileges(SignaturePrivileges::SIGNATURE_CREATE, $entity);

        if ($this->getOscarUserContextService()->getAccessActivityDocument($entity)['read'] != true) {
            return $this->getResponseUnauthorized();
        }
@@ -1588,7 +1590,7 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif
                $tabId = $tabDocument->getId();
                $arrayTabs[$tabId] = $tabDocument->toJson();
                $arrayTabs[$tabId]["documents"] = [];
                $arrayTabs[$tabId]['manage'] = $access['write'] === true;
                $arrayTabs[$tabId]['manage'] = $access['write'] == true;
            }
        }

@@ -1631,9 +1633,13 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif
            }

            $manage = $this->getOscarUserContextService()->contractDocumentWrite($doc);
            $processTriggerable = ($doc->getProcess() == null && $allowSign);

            $docAdded = $doc->toJson();
            $docAdded['manage_process'] = $manageProcess;
            $docAdded['process_triggerable'] = $processTriggerable;


            if (is_null($doc->getTabDocument())) {
                if ($doc->isPrivate() === true) {
                    // Droits sur les documents privés utilisateur courant associé ou non au document
@@ -1722,24 +1728,30 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif
        $signatureFlowParams = [];
        $typesDocumentsDatas = $this->getActivityService()->getTypesDocuments(false);

        foreach ($this->getActivityService()->getTypesDocuments(false) as $typeDocument) {
            $typeDatas = $typeDocument->toArray();
            $typeDatas['flow'] = false;
            if ($typeDocument->getSignatureFlow()) {
                $signatureFlow = $typeDocument->getSignatureFlow();
                if (!array_key_exists($signatureFlow->getId(), $signatureFlowParams)) {
                    $signatureFlowParams[$signatureFlow->getId()] = $this->getSignatureService(
                    )->createSignatureFlowDatasById(
                        '',
                        $signatureFlow->getId(),
        // Signatures disponibles (avec les personnes associées dans le contexte de l'activité)
        $processDatas = [];
        foreach ($this->getSignatureService()->getSignatureFlows() as $flow) {
            $this->getLoggerService()->debug(
                "Chargement du flow " . $flow['label'] . " pour l'activité " . $entity->getLabel()
            );
            $flowId = $flow['id'];
            $signatureFlowDatas = $this->getSignatureService()->createSignatureFlowDatasById(
                "",
                $flowId,
                ['activity_id' => $entity->getId()]
            );

            $processDatas[] = $signatureFlowDatas['signatureflow'];
        }
                $typeDatas['flow'] = $signatureFlowParams[$signatureFlow->getId()];
            }

        // Types de document
        foreach ($typesDocumentsDatas as $typeDocument) {
            $typeDatas = $typeDocument->toArray();
            $typeDatas['flow'] = false;
            $typesDocuments[] = $typeDatas;
        }

        $out['process_datas'] = $processDatas;
        $out['tabsWithDocuments'] = $arrayTabs;
        $out['typesDocuments'] = $typesDocuments;
        $out['idCurrentPerson'] = $this->getCurrentPerson()->getId();
@@ -2849,6 +2861,8 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif
                        $parameters['search'] = $search;
                        $qb->andWhere('LOWER(c.codeEOTP) = LOWER(:search)');
                    }

                    // Motif clef=valeur
                    elseif (preg_match('/(.*)=(.*)/', $search, $result)) {
                        $key = $result[1];
                        $value = $result[2];
@@ -2860,7 +2874,9 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif
                        if (preg_match("/^[0-9]{4}SAIC.*/mi", $search)) {
                            $parameters['search'] = $search . '%';
                            $qb->andWhere('c.centaureNumConvention LIKE :search');
                        } // La saisie est un numéro OSCAR©
                        }

                        // La saisie est un numéro OSCAR©
                        elseif (preg_match("/^[0-9]{4}" . $oscarNumSeparator . ".*/mi", $search)) {
                            $parameters['search'] = $search . '%';
                            $qb->andWhere('c.oscarNum LIKE :search');
@@ -2868,15 +2884,18 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif
                        else {
                            try {
                                $filterIds = $this->getActivityService()->search($search);
                            } catch (\Zend_Search_Lucene_Exception $e) {
                            } catch (Exception $e) {
                                if (stripos($e->getMessage(), 'non-wildcard') > 0) {
                                    $this->getLoggerService()->error($e->getMessage());
                                    $error = "Les motifs de recherche doivent commencer par au moins 3 caractères non-wildcard.";
                                }
                                else {
                                    $error = "Motif de recherche incorrecte : " . $e->getMessage();
                                    $this->getLoggerService()->critical($e->getMessage());
                                    $error = "Erreur Elasticsearch (" . $e->getCode() . "): " . $e->getMessage();
                                }
                                $filterIds = [];
                            } catch (BadRequest400Exception $e) {
                                $this->getLoggerService()->error($e->getMessage());
                                $error = "Expression de recherche incorrecte";
                            }
                            if ($projectview == 'on') {
@@ -2977,8 +2996,8 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif
                        try {
                            if (!$value1 && !$value2) {
                                $crit['error'] = "Aucun critère pour ce filtre";
                            } else {

                            }
                            else {
                                $personIds = [];
                                $roleId = 0;
                                $role = null;
@@ -2991,7 +3010,10 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif
                                        $persons[$person->getId()] = $person;
                                        $crit['val1Label'] = $person->getDisplayName();
                                    } catch (Exception $e) {
                                        $this->getLoggerService()->error("Erreur filtre 'sur la personne/role, impossible de charger la personne '$value1'' : " . $e->getMessage());
                                        $this->getLoggerService()->error(
                                            "Erreur filtre 'sur la personne/role, impossible de charger la personne '$value1'' : " . $e->getMessage(
                                            )
                                        );
                                        $crit['error'] = "Impossible de trouver la personne";
                                    }
                                }
@@ -3004,17 +3026,21 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif
                                            $crit['val2Label'] = $role;
                                        }
                                    } catch (Exception $e) {
                                        $this->getLoggerService()->error("Erreur filtre 'sur la personne/role, impossible de charger le rôle '$value2'' : " . $e->getMessage());
                                        $this->getLoggerService()->error(
                                            "Erreur filtre 'sur la personne/role, impossible de charger le rôle '$value2'' : " . $e->getMessage(
                                            )
                                        );
                                        $crit['error'] = "Impossible de trouver le rôle";
                                    }
                                }

                                $ids = $this->getActivityService()->getActivityRepository()
                                    ->getIdsForPersonAndOrWithRole($personIds, $roleId);

                            }
                        } catch (Exception $e) {
                            $this->getLoggerService()->error("Erreur filtre 'sur la personne '$value1'/role '$roleId' : " . $e->getMessage());
                            $this->getLoggerService()->error(
                                "Erreur filtre 'sur la personne '$value1'/role '$roleId' : " . $e->getMessage()
                            );
                            $crit['error'] = "Impossible de filtrer sur la personne";
                        }
                        break;
@@ -3291,7 +3317,8 @@ class ProjectGrantController extends AbstractOscarController implements UseNotif

                    $qbIds = $qb->select('DISTINCT pr.id');
                    $idsProjects = array_map('current', $qbIds->getQuery()->getResult());
                } else {
                }
                else {
                    $qbIds = $qb->select('DISTINCT c.id');
                    $ids = array_map('current', $qbIds->getQuery()->getResult());
                    $idsExport = $ids;
Loading