Skip to content
Snippets Groups Projects
Commit 6a4578e1 authored by Stephane Bouvry's avatar Stephane Bouvry
Browse files

- Ajout du commentaire de refus dans l'objet Signature

 - Traitement des Post-its côté ESUP pour isoler les commentaires de refus et les ajouter dans les Signatures
parent 5a5702c0
Branches
Tags
No related merge requests found
Pipeline #31653 passed
# 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
......@@ -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,
......
......@@ -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[]
*/
......
......@@ -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) {
......
......@@ -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(
......
......@@ -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
......
......@@ -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;
}
......
{
"level": "validation",
"recipients": [
{
"firstname": "Jean-Pierre",
"lastname": "Afeuh",
"email": "jeanpierre.afeuh@test-signature.org"
}
]
}
\ No newline at end of file
......@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment