Files
ludikevent_crm/src/Controller/SignatureController.php
Serreau Jovann 6656d56111 ```
 feat(reservation/contrat): Ajoute la gestion complète des contrats
```
2026-01-22 20:15:21 +01:00

209 lines
9.8 KiB
PHP

<?php
namespace App\Controller;
use App\Entity\Account;
use App\Entity\AccountResetPasswordRequest;
use App\Entity\Devis;
use App\Entity\ProductReserve;
use App\Form\RequestPasswordConfirmType;
use App\Form\RequestPasswordRequestType;
use App\Logger\AppLogger;
use App\Repository\ContratsRepository;
use App\Repository\DevisRepository;
use App\Service\Mailer\Mailer;
use App\Service\ResetPassword\Event\ResetPasswordConfirmEvent;
use App\Service\ResetPassword\Event\ResetPasswordEvent;
use App\Service\Signature\Client;
use Doctrine\ORM\EntityManagerInterface;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class SignatureController extends AbstractController
{
#[Route('/signature/complete', name: 'app_sign_complete')]
public function appSignComplete(
Client $client,
DevisRepository $devisRepository,
ContratsRepository $contratsRepository,
EntityManagerInterface $entityManager,
Request $request,
Mailer $mailer,
): Response {
if ($request->get('type') === "contrat") {
$contrats = $contratsRepository->find($request->get('id'));
if (!$contrats) {
throw $this->createNotFoundException("Contrat introuvable.");
}
// On évite de retraiter un devis déjà marqué comme signé
if ($contrats->isSigned()) {
return $this->render('sign/contrat_sign_success.twig', ['contrat' => $contrats]);
}
$submiter = $client->getSubmiter($contrats->getSignID());
$submission = $client->getSubmition($submiter['submission_id']);
if ($submission['status'] === "completed") {
$contrats->setIsSigned(true);
$auditUrl = $submission['audit_log_url'];
$signedDocUrl = $submission['documents'][0]['url'];
try {
// 1. Gestion du PDF SIGNÉ
$tmpSigned = sys_get_temp_dir() . '/sign_' . uniqid() . '.pdf';
$signedContent = file_get_contents($signedDocUrl);
file_put_contents($tmpSigned, $signedContent);
// On utilise UploadedFile pour simuler un upload propre pour VichUploader
$contrats->setDevisSignFile(new UploadedFile($tmpSigned, "sign-" . $contrats->getNumReservation() . ".pdf", "application/pdf", null, true));
// 2. Gestion de l'AUDIT LOG
$tmpAudit = sys_get_temp_dir() . '/audit_' . uniqid() . '.pdf';
$auditContent = file_get_contents($auditUrl);
file_put_contents($tmpAudit, $auditContent);
$contrats->setDevisAuditFile(new UploadedFile($tmpAudit, "audit-" . $contrats->getNumReservation() . ".pdf", "application/pdf", null, true));
// 3. Préparation des pièces jointes pour le mail (Le PDF signé est le plus important)
$attachments = [
new DataPart($signedContent, "Contrat -" . $contrats->getNumReservation() . "-Signe.pdf", "application/pdf"),
new DataPart($auditContent, "Certificat-Signature-" . $contrats->getNumReservation() . ".pdf", "application/pdf"),
];
$entityManager->persist($contrats);
$entityManager->flush();
// 5. Envoi du mail de confirmation avec le récapitulatif
$mailer->send(
$contrats->getCustomer()->getEmail(),
$contrats->getCustomer()->getName() . " " . $contrats->getCustomer()->getSurname(),
"[Ludikevent] Confirmation de signature - Contrat " . $contrats->getNumReservation(),
"mails/sign/signed_contrat.twig",
[
'contrats' => $contrats // Correction ici : passage de l'objet, pas d'un string
],
$attachments
);
$mailer->send(
"contact@ludikevent.fr",
"Ludikevent",
"[Intranet Ludikevent] Confirmation signature d'un client pour - Contrat " . $contrats->getNumReservation(),
"mails/sign/signed_contrat_notification.twig",
[
'contrats' => $contrats // Correction ici : passage de l'objet, pas d'un string
],
$attachments
);
} catch (\Exception $e) {
return new Response("Erreur lors de la récupération ou de l'envoi des documents : " . $e->getMessage(), 500);
}
}
return $this->render('sign/contrat_sign_success.twig', ['contrat' => $contrats]);
}
if ($request->get('type') === "devis") {
$devis = $devisRepository->find($request->get('id'));
if (!$devis) {
throw $this->createNotFoundException("Devis introuvable.");
}
// On évite de retraiter un devis déjà marqué comme signé
if ($devis->getState() === 'signed') {
return $this->render('sign/sign_success.twig', ['devis' => $devis]);
}
$submiter = $client->getSubmiter($devis->getSignatureId());
$submission = $client->getSubmition($submiter['submission_id']);
if ($submission['status'] === "completed") {
$devis->setState("signed");
$auditUrl = $submission['audit_log_url'];
$signedDocUrl = $submission['documents'][0]['url'];
try {
// 1. Gestion du PDF SIGNÉ
$tmpSigned = sys_get_temp_dir() . '/sign_' . uniqid() . '.pdf';
$signedContent = file_get_contents($signedDocUrl);
file_put_contents($tmpSigned, $signedContent);
// On utilise UploadedFile pour simuler un upload propre pour VichUploader
$devis->setDevisSignFile(new UploadedFile($tmpSigned, "sign-" . $devis->getNum() . ".pdf", "application/pdf", null, true));
// 2. Gestion de l'AUDIT LOG
$tmpAudit = sys_get_temp_dir() . '/audit_' . uniqid() . '.pdf';
$auditContent = file_get_contents($auditUrl);
file_put_contents($tmpAudit, $auditContent);
$devis->setDevisAuditFile(new UploadedFile($tmpAudit, "audit-" . $devis->getNum() . ".pdf", "application/pdf", null, true));
// 3. Préparation des pièces jointes pour le mail (Le PDF signé est le plus important)
$attachments = [
new DataPart($signedContent, "Devis-" . $devis->getNum() . "-Signe.pdf", "application/pdf"),
new DataPart($auditContent, "Certificat-Signature-" . $devis->getNum() . ".pdf", "application/pdf"),
];
// 4. Sauvegarde en base de données
$devis->setUpdateAt(new \DateTimeImmutable());
foreach ($devis->getDevisLines() as $line) {
$product = $line->getProduct();
$productReserve = new ProductReserve();
$productReserve->setProduct($product);
$productReserve->setCustomer($devis->getCustomer());
$productReserve->setStartAt($devis->getStartAt());
$productReserve->setEndAt($devis->getEndAt());
$productReserve->setDevis($devis);
$entityManager->persist($productReserve);
}
$entityManager->persist($devis);
$entityManager->flush();
// 5. Envoi du mail de confirmation avec le récapitulatif
$mailer->send(
$devis->getCustomer()->getEmail(),
$devis->getCustomer()->getName() . " " . $devis->getCustomer()->getSurname(),
"[Ludikevent] Confirmation de signature - Devis " . $devis->getNum(),
"mails/sign/signed.twig",
[
'devis' => $devis // Correction ici : passage de l'objet, pas d'un string
],
$attachments
);
$mailer->send(
"contact@ludikevent.fr",
"Ludikevent",
"[Intranet Ludikevent] Confirmation signature d'un client pour - Devis " . $devis->getNum(),
"mails/sign/signed_notification.twig",
[
'devis' => $devis // Correction ici : passage de l'objet, pas d'un string
],
$attachments
);
} catch (\Exception $e) {
return new Response("Erreur lors de la récupération ou de l'envoi des documents : " . $e->getMessage(), 500);
}
}
}
return $this->render('sign/sign_success.twig', [
'devis' => $devis ?? null
]);
}
}