diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..3ef543d3007f28b2af1dddec41659ceb37ff17ff --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,18 @@ +# CHANGELOG + +## 16 octobre 2024 + +### Général + + - Ajout de tests unitaires (intégrés dans Gitlab au push) + - Traitement des commentaires dans `SignRequestInfo` + - Ajout des messages de refus : mise à jour du champ information - non testé* - sur `SignatureRecipient` et ajout d'un champ pour le message d'erreur dans `Signature::refused_text` + +```sql +ALTER TABLE unicaen_signature_signature ADD refused_text TEXT DEFAULT NULL; + +``` + +### ESUP + - **Prise en charge des commentaires/Post-its ESUP** Cependant, la version actuelle d'ESUP ne permet pas de déterminer l'auteur du Post-it, donc ils seront traité de façon global + - Les commentaires/Post-its sont ignorés pour le moment \ No newline at end of file diff --git a/src/Entity/Db/ProcessStep.php b/src/Entity/Db/ProcessStep.php index 29b462ddda215c1be2972678493e78c72bedac31..f71c3be254f7ae3b871610590d091daaecb6ba57 100644 --- a/src/Entity/Db/ProcessStep.php +++ b/src/Entity/Db/ProcessStep.php @@ -194,6 +194,7 @@ class ProcessStep 'order' => $this->getOrder(), 'status' => $this->getStatus(), 'status_text' => $this->getStatusText(), + 'refused_text' => $this->getSignature()->getRefusedText(), 'allSignToComplete' => $this->getSignature()->getAllSignToComplete(), 'dateSignatureUpdate' => $this->getSignature()->getDateUpdate(), 'recipients' => $recipients, diff --git a/src/Entity/Db/Signature.php b/src/Entity/Db/Signature.php index ad678c77af31546a55640bf49d19592ddb80e053..928bde2d6b5539c8bbb7200672d6afb925d97b95 100644 --- a/src/Entity/Db/Signature.php +++ b/src/Entity/Db/Signature.php @@ -186,6 +186,14 @@ class Signature */ private ?string $context_long; + /** + * Message de refus + * + * @var ?string + * @ORM\Column (type="text", nullable=true) + */ + private ?string $refused_text; + /** * Clef permettant d'identifier le parapheur * @@ -326,6 +334,7 @@ class Signature /** * @param ProcessStep|null $processStep + * @return Signature */ public function setProcessStep(?ProcessStep $processStep): self { @@ -362,6 +371,7 @@ class Signature /** * @param DateTime|null $dateSend + * @return Signature */ public function setDateSend(?DateTime $dateSend): self { @@ -459,6 +469,17 @@ class Signature return $this; } + public function getRefusedText(): ?string + { + return $this->refused_text; + } + + public function setRefusedText(?string $refused_text): self + { + $this->refused_text = $refused_text; + return $this; + } + /** * @return SignatureRecipient[] */ diff --git a/src/Service/SignatureService.php b/src/Service/SignatureService.php index 92360169a4a5461312edad6b675488980dbc203d..821b02b50ef1e0e0e671d80cecffd6e124261aac 100644 --- a/src/Service/SignatureService.php +++ b/src/Service/SignatureService.php @@ -544,6 +544,7 @@ class SignatureService ): bool { $this->getLoggerService()->debug("### UPDATE STATUS '$signature'"); try { + if (!$signature->isFinished()) { $documentSrc = $this->getSignatureConfigurationService()->getDocumentsLocation() . DIRECTORY_SEPARATOR @@ -555,7 +556,6 @@ class SignatureService throw new SignatureException($err); } - $letterFileStrategy = $this->getLetterfileService()->getLetterFileStrategy( $signature->getLetterfileKey() ); @@ -598,6 +598,7 @@ class SignatureService if ($infos->isAccepted($recipient->getEmail()) && $updateRequired) { $this->getLoggerService()->debug("$recipient a signé"); $recipient->setStatus(Signature::STATUS_SIGNATURE_SIGNED, true); + $recipient->setInformations($infos->getCommentByFlat($recipient->getEmail())); $recipient->setDateFinished($infos->getDateDone($recipient->getEmail())); $events[] = [ 'spot' => 'recipient', @@ -608,6 +609,10 @@ class SignatureService } if ($infos->isRefused($recipient->getEmail()) && $updateRequired) { $recipient->setStatus(Signature::STATUS_SIGNATURE_REJECT, true); + $recipient->setInformations($infos->getRefusedCommentsByFlat($recipient->getEmail())); + $refusedText = $infos->getRefusedCommentsByFlat(); + $this->getLoggerService()->debug("COMMENTAIRE de REFUS : '$refusedText'"); + $signature->setRefusedText($refusedText); $this->getLoggerService()->debug("$recipient a REJETé"); $events[] = [ 'spot' => 'recipient', @@ -624,6 +629,7 @@ class SignatureService ->setDateUpdate(new \DateTime()); } } + $this->getObjectManager()->flush(); if ($signature->getStatus() == Signature::STATUS_SIGNATURE_SIGNED) { diff --git a/src/Strategy/Letterfile/Esup/EsupLetterfileStrategy.php b/src/Strategy/Letterfile/Esup/EsupLetterfileStrategy.php index c279c317fa9e7a0c6ea4b4dfd2b76bccc97775fc..3baa19ab22ace71b75fa1bedc272e365c9b82128 100644 --- a/src/Strategy/Letterfile/Esup/EsupLetterfileStrategy.php +++ b/src/Strategy/Letterfile/Esup/EsupLetterfileStrategy.php @@ -9,6 +9,7 @@ use UnicaenSignature\Exception\SignatureDataMissingException; use UnicaenSignature\Service\LoggerServiceAwareTrait; use UnicaenSignature\Service\ServiceContainerAwareTrait; use UnicaenSignature\Service\SignatureConfigurationServiceAwareTrait; +use UnicaenSignature\Strategy\Letterfile\Esup\Response\SignRequestInfo; use UnicaenSignature\Strategy\Letterfile\ILetterfileStrategy; use UnicaenSignature\Strategy\Letterfile\ISignRequest; use UnicaenSignature\Strategy\Letterfile\Tools\CurlAccess; @@ -350,68 +351,8 @@ class EsupLetterfileStrategy implements ILetterfileStrategy throw new Exception("La signature n'existe plus dans Esup"); } - $responseInfos = new ResponseInfos(); + return SignRequestInfo::getFromSignRequestGetId($returned); - // On regarde si une personne a refusée - if (array_key_exists('recipientHasSigned', $returned)) { - foreach ($returned['recipientHasSigned'] as $item) { - if (array_key_exists('actionType', $item) && $item['actionType'] == 'refused') { - $responseInfos->setForceRefuse(true); - } - } - } - - // La clef auditTrail permet d'obtenir les personnes qui ont signées - if ($returned['auditTrail'] != null && array_key_exists('auditSteps', $returned['auditTrail'])) { - foreach ($returned['auditTrail']['auditSteps'] as $auditStep) { - $email = $auditStep['email']; - $date = $auditStep['timeStampDate']; - $dateAccepted = new \DateTime($date); - $responseInfos->addAccepted($email, $dateAccepted); - } - } - - // Récupération des emails qui ont réagit - if (array_key_exists('parentSignBook', $returned) - && array_key_exists('liveWorkflow', $returned['parentSignBook']) - && array_key_exists('currentStep', $returned['parentSignBook']['liveWorkflow']) - && array_key_exists('recipients', $returned['parentSignBook']['liveWorkflow']['currentStep']) - ) { - $allSignToComplete = $returned['parentSignBook']['liveWorkflow']['currentStep']['allSignToComplete']; - $responseInfos->setAllSignToComplete($allSignToComplete); - - foreach ($returned['parentSignBook']['liveWorkflow']['currentStep']['recipients'] as $recipient) { - $signed = $recipient['signed']; - $email = $recipient['user']['email']; - $recipients[] = $email; - $responseInfos->addRecipient($email); - if ($signed) { - if (!$responseInfos->isAccepted($email)) { - $responseInfos->addRefused($email); - } - } - else { - $responseInfos->addNone($email); - } - } - } - - - // Commentaires - foreach ($returned['comments'] as $com) { - var_dump($com); - $responseInfos->addComment("unknow", $email); - } - - // Status - $status_remote = $returned['status']; - $responseInfos->setStatusRemote($status_remote); - - // Suppression dans le parapheur - if ($status_remote == 'deleted') { - $responseInfos->setStatus(Signature::STATUS_SIGNATURE_DELETE); - } - return $responseInfos; } catch (Exception $e) { $msg = "Impossible de charger les informations de la SignRequest '$id' dans ESUP"; $this->getLoggerService()->critical( diff --git a/src/Strategy/Letterfile/Esup/Response/SignRequestInfo.php b/src/Strategy/Letterfile/Esup/Response/SignRequestInfo.php index d66101afc757ea34b6348c817060c22643b462be..e2dbcc1002e57c9ee233ed98daaeff782302019f 100644 --- a/src/Strategy/Letterfile/Esup/Response/SignRequestInfo.php +++ b/src/Strategy/Letterfile/Esup/Response/SignRequestInfo.php @@ -11,9 +11,6 @@ use UnicaenSignature\Strategy\Letterfile\Tools\ResponseInfos; */ class SignRequestInfo { - /** - * @throws \DateMalformedStringException - */ public static function getFromSignRequestGetId($returned) :ResponseInfos { $responseInfos = new ResponseInfos(); @@ -33,7 +30,7 @@ class SignRequestInfo $email = $auditStep['email']; $date = $auditStep['timeStampDate']; $dateAccepted = new \DateTime($date); - $responseInfos->addAccepted($email, $dateAccepted); + $responseInfos->addAccepted($email, null, $dateAccepted); } } @@ -49,11 +46,11 @@ class SignRequestInfo foreach ($returned['parentSignBook']['liveWorkflow']['currentStep']['recipients'] as $recipient) { $signed = $recipient['signed']; $email = $recipient['user']['email']; - $recipients[] = $email; + $comment = null; $responseInfos->addRecipient($email); if ($signed) { if (!$responseInfos->isAccepted($email)) { - $responseInfos->addRefused($email); + $responseInfos->addRefused($email, $comment); } } else { @@ -76,9 +73,13 @@ class SignRequestInfo $text = $com['text']; // Dans ESUP, pas d'infos sur l'auteur du commentaire/postit - $author = 'unknown'; - - $responseInfos->addComment($author, $text, $dateCreated); + $author = ResponseInfos::COMMENT_NO_AUTHOR; + $isRefused = $com['postitColor'] == '#FF7EB9'; + if( $isRefused ){ + $responseInfos->addCommentRefused($author, $text, $dateCreated); + } else { + $responseInfos->addComment($author, $text, $dateCreated); + } } // Status diff --git a/src/Strategy/Letterfile/Tools/ResponseInfos.php b/src/Strategy/Letterfile/Tools/ResponseInfos.php index de898b06cace22c6f980be5b9ec6f2af581e5816..8e14daf61f4cbb8aa2aab2543587d88a4884d501 100644 --- a/src/Strategy/Letterfile/Tools/ResponseInfos.php +++ b/src/Strategy/Letterfile/Tools/ResponseInfos.php @@ -9,6 +9,8 @@ use UnicaenSignature\Entity\Db\Signature; */ class ResponseInfos { + // Clef utilisée pour ranger les commentaires sans auteurs + const COMMENT_NO_AUTHOR = 'unknow'; private string $status_remote; private ?int $status = null; @@ -67,6 +69,12 @@ class ResponseInfos */ private array $comments; + /** + * Messages de refus + * @var array + */ + private array $refusedComments; + public function __construct() { $this->allSignToComplete = true; @@ -77,6 +85,7 @@ class ResponseInfos $this->recipients_refused = array(); $this->recipients_none = array(); $this->comments = array(); + $this->refusedComments = array(); } /** @@ -208,20 +217,27 @@ class ResponseInfos } } - public function addAccepted(string $email, \DateTime $date = new \DateTime()): void + public function addAccepted(string $email, ?string $comment = null, \DateTime $date = new \DateTime()): void { $this->addRecipient($email); if (!in_array($email, $this->recipients_accepted)) { $this->recipients_accepted[] = $email; $this->recipients_response_dates[$email] = $date; + if ($comment) { + $this->addComment($email, $comment, $date); + } } } - public function addRefused(string $email): void + public function addRefused(string $email, ?string $comment = null, \DateTime $date = new \DateTime()): void { $this->addRecipient($email); if (!in_array($email, $this->recipients_refused)) { $this->recipients_refused[] = $email; + $this->recipients_response_dates[$email] = $date; + if ($comment !== null) { + $this->addCommentRefused($email, $comment); + } } } @@ -233,38 +249,127 @@ class ResponseInfos } } - public function addComment(string $email, string $comment, ?\DateTime $date = null): void + public function addComment(?string $email, string $comment, ?\DateTime $date = null): void { - if ($date === null) { - $date = new \DateTime(); - } + $this->comment($email, $date, $comment, $this->comments); + } + + public function addCommentRefused(?string $email, string $comment, ?\DateTime $date = null): void + { + $this->comment($email, $date, $comment, $this->refusedComments); + } + + /** + * @param string|null $email + * @param \DateTime|null $date + * @param string $comment + * @param array $comments + * @return void + */ + private function comment(?string $email, ?\DateTime $date, string $comment, array &$comments): void + { + $key = $email !== null ? $email : self::COMMENT_NO_AUTHOR; + $date = $date !== null ? $date : new \DateTime(); + $dateStr = $date->format('Y-m-d H:i:s'); - if (!array_key_exists($email, $this->comments)) { - $this->comments[$email] = []; + if (!array_key_exists($key, $comments)) { + $comments[$key] = []; } - $this->comments[$email][$dateStr] = $comment; + + $comments[$key][] = [ + 'date' => $dateStr, + 'text' => $comment + ]; } - public function getComment(string $email): ?string + /** + * Applati un tableau de commentaire pour retourner une chaine + * + * @param array $comments + * @return string|null + */ + private function flatComments(array $comments): ?string { - if (array_key_exists($email, $this->comments)) { - return implode(' / ', $this->comments[$email]); + if (count($comments) === 0) { + return null; + } + else { + $separator = ' / '; + $out = []; + foreach ($comments as $comment) { + $out[] = $comment['text']; + } + return implode($separator, $out); + } + } + + /** + * @param string $email + * @return array|null + */ + public function getCommentsBy(string $email = self::COMMENT_NO_AUTHOR): ?array + { + return array_key_exists($email, $this->comments) ? $this->comments[$email] : null; + } + + public function getCommentsByFlat(string $email = self::COMMENT_NO_AUTHOR): ?string + { + $comments = $this->getCommentsBy($email); + if ($comments !== null) { + return $this->flatComments($comments); + } + return null; + } + + public function getRefusedComments(): array + { + return $this->refusedComments; + } + + /** + * Retourne la liste des commentaires de refus de la personne. + * + * @param string $mailAuthor + * @return array|null + */ + public function getRefusedCommentsBy(string $mailAuthor = self::COMMENT_NO_AUTHOR): ?array + { + if (array_key_exists($mailAuthor, $this->refusedComments)) { + return $this->refusedComments[$mailAuthor]; + } + else { + return null; + } + } + + /** + * Retourne la liste des commentaires de la personne sous la forme d'une chaine. + * + * @param string $mailAuthor + * @return string|null + */ + public function getRefusedCommentsByFlat(string $mailAuthor = self::COMMENT_NO_AUTHOR): ?string + { + $comments = $this->getRefusedCommentsBy($mailAuthor); + if ($comments !== null) { + return $this->flatComments($comments); } return null; } - public function getAllComments(): array + public function getRefusedCommentsFlat(): ?string { $out = []; - foreach ($this->comments as $comments) { + foreach ($this->getRefusedComments() as $comments) { foreach ($comments as $comment) { $out[] = $comment; } } - return $out; + return $this->flatComments($out); } + public function isAccepted(string $email): bool { return in_array($email, $this->recipients_accepted); @@ -291,7 +396,7 @@ class ResponseInfos $dateDone = $this->recipients_response_dates[$email]; } - if( $dateDone === null && $throw ) { + if ($dateDone === null && $throw) { throw new \Exception('Unknown date done'); } @@ -328,20 +433,21 @@ class ResponseInfos { // Return $out = [ - "status" => $this->getStatus(), - "status_text" => Signature::getStatusLabel($this->getStatus()), - "status_remote" => $this->status_remote, - "accepted" => $this->recipients_accepted, - "response_date" => $this->recipients_response_dates, - "refused" => $this->recipients_refused, - "none" => $this->recipients_none, - "recipients" => $this->recipients, - "comments" => $this->comments + "status" => $this->getStatus(), + "status_text" => Signature::getStatusLabel($this->getStatus()), + "status_remote" => $this->status_remote, + "accepted" => $this->recipients_accepted, + "response_date" => $this->recipients_response_dates, + "refused" => $this->recipients_refused, + "none" => $this->recipients_none, + "recipients" => $this->recipients, + "comments" => $this->comments, + "comments_refused" => $this->refusedComments, ]; return $out; } - public function isWaiting() + public function isWaiting(): bool { return $this->getStatus() == Signature::STATUS_SIGNATURE_WAIT; } diff --git a/test/datas/json-datas-add-signature.json b/test/datas/json-datas-add-signature.json deleted file mode 100644 index a890679fb759c2d1f161b928c00a5c3676bc5920..0000000000000000000000000000000000000000 --- a/test/datas/json-datas-add-signature.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "level": "validation", - "recipients": [ - { - "firstname": "Jean-Pierre", - "lastname": "Afeuh", - "email": "jeanpierre.afeuh@test-signature.org" - } - ] -} \ No newline at end of file diff --git a/tests/ESUP/SignRequestsGetTest.php b/tests/ESUP/SignRequestsGetTest.php index 9ddba2cb2d5361f54a34c14c9f6a6a45b5c334cc..eaad29d97d7a95eb750e1aa27f384f014dfd7336 100644 --- a/tests/ESUP/SignRequestsGetTest.php +++ b/tests/ESUP/SignRequestsGetTest.php @@ -3,6 +3,35 @@ namespace ESUP; class SignRequestsGetTest extends \PHPUnit\Framework\TestCase { + public function testSignRequestsGetPostIts() + { + $datas = $this->getJsonData('esup-retour-refused-post-it-comments.json'); + $this->assertTrue($datas !== null); + + $esupSignRequest = \UnicaenSignature\Strategy\Letterfile\Esup\Response\SignRequestInfo::getFromSignRequestGetId($datas); + + $this->assertTrue( + $esupSignRequest->getStatus() === \UnicaenSignature\Entity\Db\Signature::STATUS_SIGNATURE_REJECT + ); + + $this->assertTrue( + $esupSignRequest->isAccepted('karin.fery@unicaen.fr') + ); + $this->assertTrue( + $esupSignRequest->isAccepted('jean-baptiste.oellers@unicaen.fr') + ); + + $this->assertEquals( + "Commentaire de REFUS à récupérer", + $esupSignRequest->getRefusedCommentsByFlat() + ); + + $this->assertEquals( + (new \DateTime('2024-10-15 10:05:34'))->format('Y-m-d H:i:s'), + $esupSignRequest->getDateDone(null, false)->format('Y-m-d H:i:s') + ); + } + public function testSignRequestsGetWaiting1of3() { $datas = $this->getJsonData('esup-retour-waiting-signed-2-of-3.json'); @@ -52,9 +81,8 @@ class SignRequestsGetTest extends \PHPUnit\Framework\TestCase $esupSignRequest->getDateDone(null, false)->format('Y-m-d H:i:s') ); - $comments = $esupSignRequest->getAllComments(); $this->assertEquals( - $esupSignRequest->getAllComments()[0], "Commentaire de refus à récupérer" + $esupSignRequest->getRefusedCommentsByFlat(), "Commentaire de refus à récupérer" ); } @@ -74,7 +102,7 @@ class SignRequestsGetTest extends \PHPUnit\Framework\TestCase ); $this->assertEquals( - $esupSignRequest->getAllComments()[0], "Il y'a un problème dans ce document" + $esupSignRequest->getRefusedCommentsByFlat(), "Il y'a un problème dans ce document" ); $this->assertEquals( @@ -87,7 +115,7 @@ class SignRequestsGetTest extends \PHPUnit\Framework\TestCase { $file_path = __DIR__.'/../datas/' . $filename; if( !file_exists($file_path) ){ - throw new Exception($file_path.' n\'existe pas'); + throw new \Exception($file_path.' n\'existe pas'); } $content = file_get_contents($file_path); return json_decode($content, true);