feat(revervation): [Ajoute la création de session de réservation et le flow]
🐛 fix(PurgeCommandTest): [Utilise addCommand au lieu de add pour les commandes]
📝 chore(deps): [Mise à jour des dépendances Composer et corrections]
🐛 fix(KeycloakAuthenticator): [Corrige le type nullable de l'exception start]
 feat(Customer): [Ajoute les sessions de commandes aux entités Customer]
♻️ refactor(AppLogger): [Refactorise l'AppLogger pour obtenir l'UserAgent]
 feat(FlowReserve): [Ajoute une action de validation du panier]
```
This commit is contained in:
Serreau Jovann
2026-01-31 13:49:25 +01:00
parent 4227c3d3b0
commit 0be752c145
117 changed files with 8798 additions and 2645 deletions

View File

@@ -10,6 +10,7 @@ use App\Entity\SitePerformance;
use App\Repository\CustomerRepository;
use App\Repository\CustomerTrackingRepository;
use App\Repository\FormulesRepository;
use App\Repository\OrderSessionRepository;
use App\Repository\ProductRepository;
use App\Repository\ProductReserveRepository;
use App\Service\Mailer\Mailer;
@@ -60,9 +61,9 @@ class ReserverController extends AbstractController
#[Route('/produit/check', name: 'produit_check', methods: ['GET', 'POST'])]
public function productCheck(Request $request, ProductReserveRepository $productReserveRepository, ProductRepository $productRepository): Response
{
$productId = $request->get('id');
$startStr = $request->get('start');
$endStr = $request->get('end');
$productId = $request->query->get('id');
$startStr = $request->query->get('start');
$endStr = $request->query->get('end');
if (!$productId && $request->isMethod('POST')) {
$payload = $request->getPayload();
@@ -197,6 +198,160 @@ class ReserverController extends AbstractController
]);
}
#[Route('/reservation/session', name: 'reservation_session_create', methods: ['POST'])]
public function createSession(Request $request, EntityManagerInterface $em, OrderSessionRepository $sessionRepository): Response
{
$data = json_decode($request->getContent(), true);
$existingUuid = $request->getSession()->get('order_session_uuid');
$session = null;
if ($existingUuid) {
$session = $sessionRepository->findOneBy(['uuid' => $existingUuid]);
}
if (!$session) {
$session = new \App\Entity\OrderSession();
$session->setUuid(\Symfony\Component\Uid\Uuid::v4()->toRfc4122());
$session->setState('created');
}
$session->setProducts($data ?? []);
$user = $this->getUser();
if ($user instanceof Customer) {
$session->setCustomer($user);
}
$em->persist($session);
$em->flush();
$request->getSession()->set('order_session_uuid', $session->getUuid());
return new JsonResponse([
'flowUrl' => $this->generateUrl('reservation_flow', ['sessionId' => $session->getUuid()])
]);
}
#[Route('/flow/{sessionId}', name: 'reservation_flow', methods: ['GET', 'POST'])]
public function flowLogin(
string $sessionId,
AuthenticationUtils $authenticationUtils,
OrderSessionRepository $repository,
ProductRepository $productRepository,
UploaderHelper $uploaderHelper
): Response {
// This is the POST target for the login form, but also the GET page.
// The authenticator handles the POST. For GET, we just render the page.
$session = $repository->findOneBy(['uuid' => $sessionId]);
if (!$session) {
return $this->render('revervation/session_lost.twig');
}
$sessionData = $session->getProducts();
$ids = $sessionData['ids'] ?? [];
$startStr = $sessionData['start'] ?? null;
$endStr = $sessionData['end'] ?? null;
// Calcul de la durée
$duration = 1;
if ($startStr && $endStr) {
try {
$start = new \DateTimeImmutable($startStr);
$end = new \DateTimeImmutable($endStr);
if ($end >= $start) {
$duration = $start->diff($end)->days + 1;
}
} catch (\Exception $e) {
$duration = 1;
}
}
$products = [];
if (!empty($ids)) {
$products = $productRepository->findBy(['id' => $ids]);
}
$items = [];
$totalHT = 0;
$tvaEnabled = isset($_ENV['TVA_ENABLED']) && $_ENV['TVA_ENABLED'] === "true";
$tvaRate = $tvaEnabled ? 0.20 : 0;
foreach ($products as $product) {
$price1Day = $product->getPriceDay();
$priceSup = $product->getPriceSup() ?? 0.0;
// Calcul du coût total pour ce produit selon la durée
$productTotalHT = $price1Day + ($priceSup * max(0, $duration - 1));
$productTotalTTC = $productTotalHT * (1 + $tvaRate);
$items[] = [
'product' => $product,
'image' => $uploaderHelper->asset($product, 'imageFile'),
'price1Day' => $price1Day,
'priceSup' => $priceSup,
'totalPriceHT' => $productTotalHT,
'totalPriceTTC' => $productTotalTTC,
];
$totalHT += $productTotalHT;
}
$totalTva = $totalHT * $tvaRate;
$totalTTC = $totalHT + $totalTva;
return $this->render('revervation/flow.twig', [
'session' => $session,
'last_username' => $authenticationUtils->getLastUsername(),
'error' => $authenticationUtils->getLastAuthenticationError(),
'cart' => [
'items' => $items,
'startDate' => $startStr ? new \DateTimeImmutable($startStr) : null,
'endDate' => $endStr ? new \DateTimeImmutable($endStr) : null,
'duration' => $duration,
'totalHT' => $totalHT,
'totalTva' => $totalTva,
'totalTTC' => $totalTTC,
'tvaEnabled' => $tvaEnabled,
]
]);
}
#[Route('/flow/{sessionId}/update', name: 'reservation_flow_update', methods: ['POST'])]
public function flowUpdate(
string $sessionId,
Request $request,
OrderSessionRepository $repository,
EntityManagerInterface $em
): Response {
$session = $repository->findOneBy(['uuid' => $sessionId]);
if (!$session) {
return $this->redirectToRoute('reservation');
}
$session->setBillingAddress($request->request->get('billingAddress'));
$session->setBillingZipCode($request->request->get('billingZipCode'));
$session->setBillingTown($request->request->get('billingTown'));
$session->setAdressEvent($request->request->get('adressEvent'));
$session->setAdress2Event($request->request->get('adress2Event'));
$session->setZipCodeEvent($request->request->get('zipCodeEvent'));
$session->setTownEvent($request->request->get('townEvent'));
$session->setType($request->request->get('type'));
$session->setDetails($request->request->get('details'));
$session->setTypeSol($request->request->get('typeSol'));
$session->setPente($request->request->get('pente'));
$session->setAccess($request->request->get('access'));
$distance = $request->request->get('distancePower');
if ($distance !== null && $distance !== '') {
$session->setDistancePower((float)$distance);
}
$em->flush();
return $this->redirectToRoute('reservation_flow', ['sessionId' => $sessionId]);
}
#[Route('/umami', name: 'reservation_umami', methods: ['POST'])]
public function umami(
Request $request,