222 lines
7.4 KiB
PHP
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;
|
|
}
|
|
}
|