From 42d588765dfbf213f666b690bf73d48a248e6491 Mon Sep 17 00:00:00 2001 From: Serreau Jovann Date: Fri, 23 Jan 2026 13:10:42 +0100 Subject: [PATCH] =?UTF-8?q?```=20=E2=9C=A8=20feat(Contrats):=20Ajoute=20la?= =?UTF-8?q?=20gestion=20de=20l'=C3=A9tat=20de=20la=20caution=20(restitu?= =?UTF-8?q?=C3=A9e/encaiss=C3=A9e).=20```?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- migrations/Version20260123115335.php | 32 ++++++ .../Dashboard/ContratsController.php | 36 ++++++ src/Entity/Contrats.php | 15 +++ src/Service/Stripe/Client.php | 32 ++++++ templates/dashboard/contrats/view.twig | 108 ++++++++++++------ 5 files changed, 189 insertions(+), 34 deletions(-) create mode 100644 migrations/Version20260123115335.php diff --git a/migrations/Version20260123115335.php b/migrations/Version20260123115335.php new file mode 100644 index 0000000..960ec54 --- /dev/null +++ b/migrations/Version20260123115335.php @@ -0,0 +1,32 @@ +addSql('ALTER TABLE contrats ADD caution_state VARCHAR(255) DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE contrats DROP caution_state'); + } +} diff --git a/src/Controller/Dashboard/ContratsController.php b/src/Controller/Dashboard/ContratsController.php index 37f4e92..5f4c6d9 100644 --- a/src/Controller/Dashboard/ContratsController.php +++ b/src/Controller/Dashboard/ContratsController.php @@ -5,6 +5,7 @@ namespace App\Controller\Dashboard; use App\Entity\Contrats; use App\Entity\ContratsLine; use App\Entity\ContratsOption; +use App\Entity\ContratsPayments; use App\Entity\Devis; use App\Event\Signature\ContratEvent; use App\Form\Type\ContratsType; @@ -79,6 +80,7 @@ class ContratsController extends AbstractController EntityManagerInterface $entityManager, Request $request, Client $client, + \App\Service\Stripe\Client $stripeClient, DevisRepository $devisRepository, AppLogger $appLogger, EventDispatcherInterface $eventDispatcher, @@ -128,6 +130,40 @@ class ContratsController extends AbstractController $solde = $totalHt - $dejaPaye; + + if($request->query->has('act') && $request->query->get('act') === 'cautionCapture') { + $amount = $request->query->get('amountToCapture'); + $paiementCaution = $entityManager->getRepository(ContratsPayments::class)->findOneBy([ + 'contrat' => $contrat, + 'type' => 'caution', + ]); + $result = $stripeClient->capture($paiementCaution->getPaymentId()); + if($result['state']) { + $contrat->setCautionState("recover"); + $entityManager->persist($contrat); + $entityManager->flush(); + $this->addFlash("success","Caution restitué"); + } else { + $this->addFlash("error",$result['message']); + } + } + if($request->query->has('act') && $request->query->get('act') === 'cautionRelease') { + + $paiementCaution = $entityManager->getRepository(ContratsPayments::class)->findOneBy([ + 'contrat' => $contrat, + 'type' => 'caution', + ]); + $result = $stripeClient->cancelPayment($paiementCaution->getPaymentId()); + if($result['state']) { + $contrat->setCautionState("restitue"); + $entityManager->persist($contrat); + $entityManager->flush(); + $this->addFlash("success","Caution restitué"); + } else { + $this->addFlash("error",$result['message']); + } + } + return $this->render('dashboard/contrats/view.twig', [ 'contrat' => $contrat, 'days' => $days, diff --git a/src/Entity/Contrats.php b/src/Entity/Contrats.php index 4451ad2..9c1fa03 100644 --- a/src/Entity/Contrats.php +++ b/src/Entity/Contrats.php @@ -140,6 +140,9 @@ class Contrats #[ORM\OneToOne(mappedBy: 'contrat', cascade: ['persist', 'remove'])] private ?Facture $facture = null; + #[ORM\Column(length: 255, nullable: true)] + private ?string $cautionState = null; + public function __construct() { $this->contratsPayments = new ArrayCollection(); @@ -815,6 +818,18 @@ class Contrats return $this; } + public function getCautionState(): ?string + { + return $this->cautionState; + } + + public function setCautionState(?string $cautionState): static + { + $this->cautionState = $cautionState; + + return $this; + } + } diff --git a/src/Service/Stripe/Client.php b/src/Service/Stripe/Client.php index 52c09be..ffe15b0 100644 --- a/src/Service/Stripe/Client.php +++ b/src/Service/Stripe/Client.php @@ -572,4 +572,36 @@ class Client return $newSession; } + + public function cancelPayment(?string $getPaymentId) + { + $session = $this->client->checkout->sessions->retrieve($getPaymentId); + $paymentIntent = $this->client->paymentIntents->retrieve($session->payment_intent); + if($paymentIntent->status == "requires_capture") { + $this->client->paymentIntents->cancel($paymentIntent->id); + return [ + 'state' => true + ]; + } + return [ + 'state' => false, + 'message' => 'Impossible d\'annuler la caution' + ]; + } + + public function capture(?string $getPaymentId) + { + $session = $this->client->checkout->sessions->retrieve($getPaymentId); + $paymentIntent = $this->client->paymentIntents->retrieve($session->payment_intent); + if($paymentIntent->status == "requires_capture") { + $this->client->paymentIntents->capture($paymentIntent->id); + return [ + 'state' => true + ]; + } + return [ + 'state' => false, + 'message' => 'Impossible de récupérer la caution' + ]; + } } diff --git a/templates/dashboard/contrats/view.twig b/templates/dashboard/contrats/view.twig index 430f917..2ec9d57 100644 --- a/templates/dashboard/contrats/view.twig +++ b/templates/dashboard/contrats/view.twig @@ -11,9 +11,36 @@ - Télécharger Contrat PDF + Télécharger Devis PDF {% endif %} + {% if contrat.signed %} + + + + + Télécharger Contrat Signée PDF + + + + + + Télécharger Audit Signée PDF + + {% else %} + + + + + Télécharger Contrat PDF + + {% endif %} {% endblock %} @@ -64,54 +91,67 @@ {# 3. CAUTION (MODE ADMINISTRATION) #}
+ {# Icône dynamique : Pulse si non déposée, fixe si OK #}
+

Garantie (Caution)

{% if not cautionOk %} - {# Affichage simple du statut sans lien #} + {# ÉTAT 1 : ATTENTE DE DÉPÔT #}
-

- Non Déposée -

+

Non Déposée

Attendu : {{ totalCaution|number_format(2, ',', ' ') }}€

{% else %} - {# État : Caution déposée - Actions d'administration #} -
-

Empreinte active

-
- {# ACTION LIBÉRER #} - - Libérer la caution - + {# ÉTAT 2 : CAUTION DÉPOSÉE #} + {% if contrat.cautionState == null %} + {# ACTIONS DISPONIBLES #} +
+

Empreinte active

+
+ {# LIBÉRER #} + + Libérer la caution + - {# ACTION ENCAISSER #} -
- -
- - -
-
+ {# ENCAISSER #} +
+ +
+ + +
+
+
-
+ {% else %} + {# ÉTAT 3 : ARCHIVÉ (RESTITUÉ OU RÉCUPÉRÉ) #} +
+ {% if contrat.cautionState == 'restitue' %} + + Restituée + + {% elseif contrat.cautionState == 'recover' %} + + Encaissée + + {% else %} + {{ contrat.cautionState }} + {% endif %} +
+ {% endif %} {% endif %}