Files
kupshop/bundles/KupShop/ReservationBundle/Controller/ReservationController.php
2025-08-02 16:30:27 +02:00

222 lines
7.4 KiB
PHP

<?php
declare(strict_types=1);
namespace KupShop\ReservationBundle\Controller;
use KupShop\ContentBundle\View\Exception\ValidationException;
use KupShop\KupShopBundle\Context\UserContext;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\KupShopBundle\Views\View;
use KupShop\ReservationBundle\Util\ReservationUtil;
use KupShop\SellerBundle\Context\SellerContext;
use KupShop\SellerBundle\Utils\SellerMultiFetch;
use KupShop\SellerBundle\Utils\SellerUtil;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
class ReservationController extends AbstractController
{
private const SESSION_USER_DATA = 'reservation.userData';
protected SellerContext $sellerContext;
protected SellerUtil $sellerUtil;
protected SellerMultiFetch $sellerMultiFetch;
public function __construct(SellerContext $sellerContext, SellerUtil $sellerUtil, SellerMultiFetch $sellerMultiFetch)
{
$this->sellerContext = $sellerContext;
$this->sellerUtil = $sellerUtil;
$this->sellerMultiFetch = $sellerMultiFetch;
}
/**
* @Route("/_focus/reservation/create/")
*/
public function focusReservationCreate(Request $request, ReservationUtil $reservationUtil): Response
{
$view = (new View())
->setTemplate('focus/reservation/focus.reservation.tpl');
// ID produktu a varianty, ktere budu rezervovat
$productId = (int) $request->get('productId');
$variationId = $request->get('variationId');
$variationId = !empty($variationId) ? (int) $variationId : null;
if (!$productId) {
throw new NotFoundHttpException('Missing product ID!');
}
// ID vybrane prodejny
$selectedSellerId = null;
if (!$request->get('sellerChange')) {
$selectedSellerId = $request->get('sellerId');
}
// nactu si produkt
$product = \Variation::createProductOrVariation($productId, $variationId);
$product->createFromDB();
$selectedSeller = $this->getSelectedSeller((int) $selectedSellerId, $product);
$reservationReadyDate = $this->getReservationReadyDate($selectedSeller);
$vars = [
'product' => $product,
'seller' => $selectedSeller,
'reservationReadyDate' => $reservationReadyDate,
'reservationEndDate' => $this->getReservationEndDate($selectedSeller, $reservationReadyDate),
'userData' => [],
'error' => null,
];
// formular byl odeslan
if ($request->isMethod('POST')) {
try {
if (!($sellerId = $request->request->get('sellerId'))) {
throw new \InvalidArgumentException('Missing seller id');
}
// vytvorim rezervaci
$vars['reservation'] = $reservationUtil->createReservation(
[
'email' => $request->get('email'),
'name' => $request->get('name'),
'surname' => $request->get('surname'),
'phone' => $request->get('phone'),
],
$productId,
$variationId,
[
'sellerId' => (int) $sellerId,
]
);
// ulozim si vyplnene udaje do sessiony, abych to mohl u dalsich rezervaci uz predvyplnit
$request->getSession()->set(self::SESSION_USER_DATA, [
'email' => $request->get('email'),
'name' => $request->get('name'),
'surname' => $request->get('surname'),
'phone' => $request->get('phone'),
]);
// musi byt setovani po session set, protože pole porovnáva session data, chci zanechat strukturu a nesetovat session
// na zacatku metody
$vars['userData'] = $this->getUserData($request);
} catch (\Exception $e) {
$vars['error'] = translate('errorGeneric', 'reservations');
if ($e instanceof ValidationException) {
$vars['error'] = $e->getMessage();
}
if ($e instanceof \InvalidArgumentException) {
$vars['error'] = translate('errorInvalidArguments', 'reservations');
}
}
$vars['sent'] = true;
}
return $view->addBodyVariables($vars)
->getResponse();
}
protected function getUserData(Request $request): array
{
$userContext = Contexts::get(UserContext::class);
$userData = [];
/** @var \User $user */
if ($user = $userContext->getActive()) {
$userData = [
'email' => $user->email,
'name' => $user->invoice['name'] ?? '',
'surname' => $user->invoice['surname'] ?? '',
'phone' => $user->invoice['phone'] ?? '',
];
}
return array_merge($userData, $request->getSession()->get(self::SESSION_USER_DATA, []));
}
protected function getSelectedSeller(int $sellerId, \Product $product): array
{
$sellers = array_filter([$this->sellerContext->getSupported()[$sellerId] ?? null]);
$this->sellerMultiFetch->fetchSellersInStore($sellers, [$product->id => $product->variationId ?? null]);
$seller = reset($sellers);
return $seller ?: [];
}
protected function getReservationEndDate(array $seller, ?\DateTime $readyDate): ?\DateTime
{
if (empty($seller)) {
return null;
}
if (!$readyDate) {
return null;
}
$endDate = clone $readyDate;
$dbcfg = \Settings::getDefault();
if (!($reservationLength = $dbcfg->reservations['reservation_length'] ?? null)) {
return null;
}
$i = 0;
while ($reservationLength > 0) {
if ($i > 30) {
break;
}
$endDate->add(new \DateInterval('P1D'));
if (!$this->sellerUtil->isSellerClosed($seller, 0, $endDate)) {
$reservationLength--;
}
$i++;
}
return $endDate;
}
protected function getReservationReadyDate(array $seller): ?\DateTime
{
if (empty($seller)) {
return null;
}
$dbcfg = \Settings::getDefault();
$preparationTime = $dbcfg->reservations['preparation_time'] ?? 1;
$date = new \DateTime();
// pokud bude prodejna brzo zavirat
if ($this->sellerUtil->isSellerClosed($seller, ((int) $preparationTime) + 1)) {
// nactu si oteviraci dobu dalsiho dne
if ($hour = $this->sellerUtil->getClosingTime($seller, $date, 0)) {
$hourData = explode(':', $hour);
// aktualizuju datum
$date = new \DateTime('tomorrow');
$date->setTime((int) $hourData[0], (int) ($hourData[1] ?? 0));
}
}
$date->add(new \DateInterval('PT'.$preparationTime.'H'));
// prevedu minuty na ctvrt hodiny
$minutes = $date->format('i') - ($date->format('i') % 15);
$date->setTime((int) $date->format('H'), (int) $minutes);
return $date;
}
}