<?php
declare(strict_types=1);
namespace App\Controller\Website;
use App\Client\ErpClient;
use App\Form\Website\Type\PurchaseQuoteRequest\DddPurchaseQuoteRequestType;
use App\Helper\Partner\PartnerHelper;
use App\Repository\Cabin\CabinCategoryRepository;
use App\Service\Ddd\DddPageContext;
use App\Service\Ddd\DddPageContextBuilder;
use App\Service\Ddd\DddQuoteRequestPayloadFactory;
use App\Service\Ddd\DddStepContext;
use App\Service\Ddd\DddStepContextResolver;
use Croisiland\CommonBundle\Model\ProspectRequestModel;
use Doctrine\ORM\NonUniqueResultException;
use Exception;
use Sulu\Component\Content\Compat\StructureInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class DddController extends BaseWebsiteController
{
public function __construct(
private readonly DddPageContextBuilder $dddPageContextBuilder,
private readonly DddStepContextResolver $dddStepContextResolver,
private readonly DddQuoteRequestPayloadFactory $dddQuoteRequestPayloadFactory,
private readonly RequestStack $requestStack,
private readonly PartnerHelper $partnerHelper,
private readonly CabinCategoryRepository $cabinCategoryRepository,
private readonly ErpClient $erpClient,
) {
}
public function indexAction(StructureInterface $structure, $preview = false, $partial = false)
{
$templateVars = array_merge($this->getSharedLayoutFormViews(), [
'quoteRequestForm' => $this->createForm(DddPurchaseQuoteRequestType::class)->createView(),
]);
$request = $this->requestStack->getCurrentRequest();
if ($request !== null) {
$pageContext = $this->dddPageContextBuilder->buildFromCruiseId(
$request->query->getInt('croisiere', 0)
);
if ($pageContext !== null) {
$templateVars = array_merge($templateVars, $pageContext->toTemplateVars());
}
if ($request->request->get('ddd') !== null) {
$quoteRequestForm = $this->createForm(
DddPurchaseQuoteRequestType::class
);
$quoteRequestForm->handleRequest($request);
}
}
return $this->renderStructure(
$structure,
$templateVars,
$preview,
$partial
);
}
#[Route('/ddd/quote-request/form', name: 'website_ddd_quote_request_form', methods: ['POST'])]
public function quoteFormAction(Request $request): Response
{
$cruiseId = $request->query->getInt('croisiere', 0);
if ($cruiseId <= 0) {
return new Response('Missing cruise id', Response::HTTP_BAD_REQUEST);
}
$pageContext = $this->dddPageContextBuilder->buildFromCruiseId($cruiseId);
if ($pageContext === null) {
return new Response('Cruise not found', Response::HTTP_NOT_FOUND);
}
$this->dddStepContextResolver->resolve($request, 4, $pageContext->cruise);
$success = false;
$form = $this->createForm(
DddPurchaseQuoteRequestType::class
);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$this->erpClient->createQuoteRequest($form->getData());
$success = true;
}
catch (Exception $exception) {
if ($exception->getCode() === Response::HTTP_NOT_ACCEPTABLE) {
$form->addError(new FormError($exception->getMessage()));
}
else {
$form->addError(new FormError("Une erreur est survenue lors du traitement de votre demande. Merci de réessayer plus tard."));
}
}
}
if (!$request->isXmlHttpRequest()) {
$referer = $request->headers->get('Referer');
if (is_string($referer) && $referer !== '') {
if ($success) {
$separator = str_contains($referer, '?') ? '&' : '?';
return $this->redirect($referer.$separator.'quoteConfirmation=1');
}
return $this->redirect($referer);
}
}
if ($success) {
$payload = $this->dddQuoteRequestPayloadFactory->createFromValidatedForm(
$form,
$request,
$cruiseId
);
return $this->render('pages/_includes/ddd/_quote_form_ajax_fragment.html.twig', [
'success' => true,
]);
}
$formQueryParams = array_filter([
'croisiere' => $cruiseId,
'type' => $request->query->get('type'),
'subtype' => $request->query->get('subtype'),
'atmosphere' => $request->query->get('atmosphere'),
'category' => $request->query->get('category'),
'cabin' => $request->query->get('cabin'),
'price' => $request->query->get('price'),
], static fn ($value) => $value !== null && $value !== '');
return $this->render('pages/_includes/ddd/_quote_form.html.twig', [
'quoteRequestForm' => $form->createView(),
'formQueryParams' => $formQueryParams,
]);
}
#[Route('/ddd/fragments/step/{step}', name: 'website_ddd_step_fragment', methods: ['GET'])]
public function stepFragmentAction(Request $request, int $step): JsonResponse
{
$cruiseId = $request->query->getInt('croisiere', 0);
if ($cruiseId <= 0) {
return new JsonResponse([
'success' => false,
'error' => 'Missing cruise id',
], Response::HTTP_BAD_REQUEST);
}
$pageContext = $this->dddPageContextBuilder->buildFromCruiseId($cruiseId);
if ($pageContext === null) {
return new JsonResponse([
'success' => false,
'error' => 'Cruise not found',
], Response::HTTP_NOT_FOUND);
}
$templateByStep = [
1 => 'pages/_includes/ddd/steps/_step_subtype_cabin.html.twig',
2 => 'pages/_includes/ddd/steps/_step_atmosphere.html.twig',
3 => 'pages/_includes/ddd/steps/_step_category_cabin.html.twig',
4 => 'pages/_includes/ddd/steps/_step_quote_form.html.twig',
];
if (!isset($templateByStep[$step])) {
return new JsonResponse([
'success' => false,
'error' => 'Step not implemented yet',
'step' => $step,
], Response::HTTP_NOT_IMPLEMENTED);
}
$dddContext = $this->dddStepContextResolver->resolve($request, $step, $pageContext->cruise);
$templateVars = [
...$pageContext->toTemplateVars(),
'dddContext' => $dddContext,
...$dddContext->toTemplateVars(),
];
if ($step === 4) {
$quoteRequestForm = $this->createForm(
DddPurchaseQuoteRequestType::class,
$this->buildQuoteFormInitialData($request, $dddContext, $pageContext)
);
$quoteRequestForm->handleRequest($request);
$templateVars['quoteRequestForm'] = $quoteRequestForm->createView();
}
$html = $this->renderView($templateByStep[$step], $templateVars);
return new JsonResponse([
'success' => true,
'step' => $step,
'context' => [
'cruiseId' => $dddContext->cruiseId,
'cabinTypeId' => $dddContext->cabinTypeId,
'cabinSubTypeId' => $dddContext->cabinSubTypeId,
'atmosphereId' => $dddContext->atmosphereId,
'categoryId' => $dddContext->categoryId,
'cabinCode' => $dddContext->cabinCode,
],
'html' => $html,
]);
}
/**
* @param Request $request
* @param DddStepContext $dddContext
* @param DddPageContext $pageContext
* @return ProspectRequestModel
* @throws NonUniqueResultException
*/
private function buildQuoteFormInitialData(Request $request, DddStepContext $dddContext, DddPageContext $pageContext): ProspectRequestModel
{
$price = $request->query->get('price');
return (new ProspectRequestModel())
->setCruise($pageContext->cruise)
->setPartner($this->partnerHelper->getCurrentPartner())
->setPrice((float) $price)
->setCabinCategory(
$this->cabinCategoryRepository->find($dddContext->categoryId)
)
;
}
}