Travail sur le tunnel de reservation etape final
This commit is contained in:
@@ -28,9 +28,45 @@ use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
|
||||
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
|
||||
class ReserverController extends AbstractController
|
||||
{
|
||||
private KernelInterface $kernel;
|
||||
private ?array $simplifiedCommunes = null;
|
||||
|
||||
public function __construct(KernelInterface $kernel)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
}
|
||||
|
||||
private function loadSimplifiedCommunes(): array
|
||||
{
|
||||
if ($this->simplifiedCommunes !== null) {
|
||||
return $this->simplifiedCommunes;
|
||||
}
|
||||
|
||||
$filePath = $this->kernel->getProjectDir() . '/public/simplified_communes_by_zip.json';
|
||||
if (!file_exists($filePath)) {
|
||||
// Log an error or throw an exception if the file doesn't exist
|
||||
// For now, return an empty array if file is missing
|
||||
return [];
|
||||
}
|
||||
|
||||
$content = file_get_contents($filePath);
|
||||
if ($content === false) {
|
||||
// Log an error or throw an exception if reading fails
|
||||
return [];
|
||||
}
|
||||
|
||||
$this->simplifiedCommunes = json_decode($content, true);
|
||||
if ($this->simplifiedCommunes === null && json_last_error() !== JSON_ERROR_NONE) {
|
||||
// Log JSON decoding error
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->simplifiedCommunes;
|
||||
}
|
||||
#[Route('/robots.txt', name: 'robots_txt', defaults: ['_format' => 'txt'])]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
@@ -98,6 +134,76 @@ class ReserverController extends AbstractController
|
||||
return new JsonResponse(['dispo' => $isAvailable]);
|
||||
}
|
||||
|
||||
#[Route('/produit/check/basket', name: 'produit_check_basket', methods: ['POST'])]
|
||||
public function productCheckBasket(Request $request, ProductReserveRepository $productReserveRepository, ProductRepository $productRepository): JsonResponse
|
||||
{
|
||||
$data = json_decode($request->getContent(), true);
|
||||
$ids = $data['ids'] ?? [];
|
||||
$startStr = $data['start'] ?? null;
|
||||
$endStr = $data['end'] ?? null;
|
||||
|
||||
if (!is_array($ids) || empty($ids) || !$startStr || !$endStr) {
|
||||
return new JsonResponse(['available' => false, 'message' => 'Missing or invalid parameters'], Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$availability = $this->_checkProductsAvailability($ids, $startStr, $endStr, $productRepository, $productReserveRepository);
|
||||
|
||||
if (!$availability['allProductsAvailable']) {
|
||||
return new JsonResponse([
|
||||
'available' => false,
|
||||
'message' => 'Certains produits de votre panier ne sont pas disponibles aux dates sélectionnées.',
|
||||
'unavailable_products_ids' => $availability['unavailableProductIds']
|
||||
]);
|
||||
}
|
||||
|
||||
return new JsonResponse(['available' => true, 'message' => 'Tous les produits sont disponibles.']);
|
||||
}
|
||||
|
||||
private function _checkProductsAvailability(
|
||||
array $ids,
|
||||
?string $startStr,
|
||||
?string $endStr,
|
||||
ProductRepository $productRepository,
|
||||
ProductReserveRepository $productReserveRepository
|
||||
): array {
|
||||
$allProductsAvailable = true;
|
||||
$unavailableProductIds = [];
|
||||
|
||||
if (empty($ids) || !$startStr || !$endStr) {
|
||||
return ['allProductsAvailable' => false, 'unavailableProductIds' => $ids];
|
||||
}
|
||||
|
||||
try {
|
||||
$start = new \DateTimeImmutable($startStr);
|
||||
$end = new \DateTimeImmutable($endStr);
|
||||
} catch (\Exception $e) {
|
||||
return ['allProductsAvailable' => false, 'unavailableProductIds' => $ids];
|
||||
}
|
||||
|
||||
foreach ($ids as $productId) {
|
||||
$product = $productRepository->find($productId);
|
||||
if (!$product) {
|
||||
$allProductsAvailable = false;
|
||||
$unavailableProductIds[] = $productId;
|
||||
continue;
|
||||
}
|
||||
|
||||
$reserve = new ProductReserve();
|
||||
$reserve->setProduct($product);
|
||||
$reserve->setStartAt($start);
|
||||
$reserve->setEndAt($end);
|
||||
|
||||
$isAvailable = $productReserveRepository->checkAvailability($reserve);
|
||||
|
||||
if (!$isAvailable) {
|
||||
$allProductsAvailable = false;
|
||||
$unavailableProductIds[] = $productId;
|
||||
}
|
||||
}
|
||||
|
||||
return ['allProductsAvailable' => $allProductsAvailable, 'unavailableProductIds' => $unavailableProductIds];
|
||||
}
|
||||
|
||||
#[Route('/web-vitals', name: 'reservation_web-vitals', methods: ['POST'])]
|
||||
public function webVitals(Request $request, EntityManagerInterface $em): Response
|
||||
{
|
||||
@@ -238,13 +344,87 @@ class ReserverController extends AbstractController
|
||||
AuthenticationUtils $authenticationUtils,
|
||||
OrderSessionRepository $repository,
|
||||
ProductRepository $productRepository,
|
||||
UploaderHelper $uploaderHelper
|
||||
UploaderHelper $uploaderHelper,
|
||||
ProductReserveRepository $productReserveRepository
|
||||
): Response {
|
||||
$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;
|
||||
|
||||
// Check product availability
|
||||
$availability = $this->_checkProductsAvailability($ids, $startStr, $endStr, $productRepository, $productReserveRepository);
|
||||
|
||||
if (!$availability['allProductsAvailable']) {
|
||||
$this->addFlash('danger', 'Certains produits de votre panier ne sont plus disponibles. Veuillez vérifier votre réservation.');
|
||||
return $this->redirectToRoute('reservation_flow', ['sessionId' => $sessionId]);
|
||||
}
|
||||
|
||||
// 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_confirmed.twig', [
|
||||
'session' => $session,
|
||||
'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}', name: 'reservation_flow', methods: ['GET', 'POST'])]
|
||||
@@ -253,7 +433,8 @@ class ReserverController extends AbstractController
|
||||
AuthenticationUtils $authenticationUtils,
|
||||
OrderSessionRepository $repository,
|
||||
ProductRepository $productRepository,
|
||||
UploaderHelper $uploaderHelper
|
||||
UploaderHelper $uploaderHelper,
|
||||
ProductReserveRepository $productReserveRepository // Added dependency
|
||||
): 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.
|
||||
@@ -267,6 +448,14 @@ class ReserverController extends AbstractController
|
||||
$startStr = $sessionData['start'] ?? null;
|
||||
$endStr = $sessionData['end'] ?? null;
|
||||
|
||||
// Check product availability
|
||||
$availability = $this->_checkProductsAvailability($ids, $startStr, $endStr, $productRepository, $productReserveRepository);
|
||||
|
||||
if (!$availability['allProductsAvailable']) {
|
||||
$this->addFlash('danger', 'Certains produits de votre panier ne sont plus disponibles. Veuillez vérifier votre sélection.');
|
||||
return $this->redirectToRoute('reservation');
|
||||
}
|
||||
|
||||
// Calcul de la durée
|
||||
$duration = 1;
|
||||
if ($startStr && $endStr) {
|
||||
@@ -682,6 +871,26 @@ class ReserverController extends AbstractController
|
||||
return $this->render('revervation/legal.twig');
|
||||
}
|
||||
|
||||
#[Route('/cities/lookup', name: 'api_cities_lookup', methods: ['POST'])]
|
||||
public function getCityByZipCode(Request $request): JsonResponse
|
||||
{
|
||||
$data = json_decode($request->getContent(), true);
|
||||
$zipCode = $data['zipCode'] ?? null;
|
||||
|
||||
if (!$zipCode) {
|
||||
return new JsonResponse(['error' => 'Missing zipCode parameter'], Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$simplifiedCommunes = $this->loadSimplifiedCommunes();
|
||||
$cities = $simplifiedCommunes[$zipCode] ?? [];
|
||||
|
||||
if (!empty($cities)) {
|
||||
return new JsonResponse(['cities' => $cities]);
|
||||
}
|
||||
|
||||
return new JsonResponse(['cities' => [], 'message' => 'City not found for this zip code'], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
#[Route('/rgpd', name: 'reservation_rgpd')]
|
||||
public function revervationRgpd(): Response
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user