<?php
namespace App\Controller;
use App\Service\TessituraBundle\AddNotAvailableException;
use App\Service\TessituraBundle\CartService;
use App\Service\TessituraBundle\CateringService;
use App\Service\TessituraBundle\CateringServiceException;
use App\Service\TessituraBundle\Entity\CateringItemPerformance;
use App\Service\TessituraBundle\Item\CartItemCatering;
use App\Service\TessituraBundle\Item\CateringItemPerformance as ItemCateringItemPerformance;
use App\Service\TessituraSDK\Entity\Remote\Performance;
use App\Service\TessituraSDK\Entity\Remote\ProductionSeason;
use App\Service\TessituraSDK\Resource\TXN\Performances;
use App\Service\TessituraSDK\Resource\TXN\ProductionSeasons;
use App\Service\TessituraSDK\TessituraClient;
use App\Service\TessituraSDK\TessituraClientException;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Validator\Constraints\DateTime;
class CateringController extends AbstractController
{
/**
* @var TessituraClient
*/
private $client;
/**
* @var Serializer
*/
private $serializer;
/**
* @var CacheItemPoolInterface|TagAwareAdapterInterface
*/
private $cache;
/**
* @var TranslatorInterface
*/
private $translator;
/**
* @var ParameterBagInterface
*/
private $params;
/**
* CartController constructor.
*
* @param TessituraClient $client
* @param SerializerInterface $serializer
* @param ContainerInterface $container
* @param TranslatorInterface $translator
* @param ParameterBagInterface $params
*/
public function __construct(
TessituraClient $client,
SerializerInterface $serializer,
ContainerInterface $container,
TranslatorInterface $translator,
ParameterBagInterface $params
) {
$this->setContainer($container);
$this->client = $client;
$this->serializer = $serializer;
$this->cache = $container->get('cache.app');
$this->translator = $translator;
$this->params = $params;
}
/**
* @Route(
* "/{_locale}/catering/{performanceId}/",
* name="catering-performance",
* defaults={
* "_locale": "fi"
* },
* requirements={
* "_locale": "fi|sv|en"
* }
* )
* @param Request $request
* @param CateringService $cateringService
* @param $performanceId
*
* @return \Symfony\Component\HttpFoundation\Response
* @throws TessituraClientException
*/
public function cateringPerformanceAction(Request $request, CateringService $cateringService, $performanceId)
{
$compiled = false;
try {
$performance = $cateringService->getPerformance($performanceId);
$items = $cateringService->getDefaultItems();
if ($items) {
$orderedItems = $cateringService->orderItems($items);
$compiled = $this->render('partial/catering-items-partial.html.twig', [
'ordered_items' => $orderedItems,
'items' => $items,
'disabled' => true
]);
}
} catch (TessituraClientException $exception) {
if ($exception->getCode() === TessituraClientException::TESSITURA_NOT_FOUND) {
throw $this->createNotFoundException();
}
throw $exception;
}
return $this->render('page/catering.html.twig', [
'items' => [],
'performance' => $performance,
'default_items' => $compiled instanceof Response ? $compiled->getContent() : ''
]);
}
/**
* @Route(
* "/{_locale}/catering/",
* name="catering",
* defaults={
* "_locale": "fi"
* },
* requirements={
* "_locale": "fi|sv|en"
* }
* )
* @param Request $request
* @param CateringService $cateringService
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function cateringAction(Request $request, CateringService $cateringService)
{
$compiled = false;
$items = $cateringService->getDefaultItems();
if ($items) {
$orderedItems = $cateringService->orderItems($items);
$compiled = $this->render('partial/catering-items-partial.html.twig', [
'ordered_items' => $orderedItems,
'items' => $items,
'disabled' => true
]);
}
return $this->render('page/catering.html.twig', [
'performance' => false,
'default_items' => $compiled instanceof Response ? $compiled->getContent() : ''
]);
}
/**
* @Route(
* "/{_locale}/catering/api/v1/catering-items/",
* name="get-api-catering-items",
* defaults={
* "_locale": "fi"
* },
* requirements={
* "_locale": "fi|sv|en"
* },
* methods={"GET"}
* )
* @param Request $request
* @param CateringService $cateringService
*
* @return JsonResponse
* @internal param CartService $cart
*/
public function getItemsAction(Request $request, CateringService $cateringService)
{
$performanceId = $request->get('performanceId');
$statuses = json_decode($request->get('statuses'));
$performance = $cateringService->getPerformance($performanceId);
$items = $cateringService->getAvailable($performanceId);
$orderedItems = $cateringService->orderItems($items);
$compiled = $this->render('partial/catering-items-partial.html.twig', [
'performance' => $performance,
'ordered_items' => $orderedItems,
'items' => $items,
'pre_status' => $cateringService->getCorrespondingCateringMessage($statuses->pre ?? 0),
'int1_status' => $cateringService->getCorrespondingCateringMessage($statuses->int1 ?? 0),
'int2_status' => $cateringService->getCorrespondingCateringMessage($statuses->int2 ?? 0),
'post_status' => $cateringService->getCorrespondingCateringMessage($statuses->post ?? 0),
]);
return new JsonResponse([
'success' => (bool)$items,
'html' => $compiled->getContent()
]);
}
/**
* @Route(
* "/{_locale}/cart/api/v1/catering-performances/",
* name="get-api-catering-performances",
* defaults={
* "_locale": "fi"
* },
* requirements={
* "_locale": "fi|sv|en"
* },
* methods={"GET"}
* )
* @param Request $request
* @param CateringService $cateringService
*
* @return JsonResponse
* @internal param CartService $cart
*/
public function getPerformancesAction(Request $request, CateringService $cateringService)
{
$date = $request->get('date');
$timestamp = strtotime($date);
$startDate = new \DateTime();
$startDate->setTimestamp($timestamp);
$endDate = new \DateTime();
$endDate->setTimestamp(strtotime('+1 day', $timestamp));
/** @var ItemCateringItemPerformance[] $performances */
$performances = $cateringService->getPerformancesCustom($startDate, $endDate);
$performances = array_values(
array_filter($performances, function ($performance) {
return !$performance->isOnnenpaikat();
})
);
if (!$performances) {
return new JsonResponse([
'success' => false,
'message' => $this->translator->trans('catering_no_performances')
]);
}
return new JsonResponse([
'success' => true,
'performances' => $this->serializer->normalize($performances, null, ['groups' => ['json']])
]);
}
/**
* @Route(
* "/{_locale}/cart/api/v1/catering-guests/",
* name="get-api-catering-guests",
* defaults={
* "_locale": "fi"
* },
* requirements={
* "_locale": "fi|sv|en"
* },
* methods={"GET"}
* )
* @param Request $request
* @param CateringService $cateringService
*
* @return JsonResponse
* @throws TessituraClientException
*/
public function getGuestsAction(Request $request, CateringService $cateringService)
{
$statuses = json_decode($request->get('statuses'));
$message = false;
try {
$validStatuses = $this->params->get('tessitura.catering_valid_performance_statuses');
} catch (\InvalidArgumentException $exception) {
$validStatuses = [];
}
$duplicatesRemoved = array_unique((array)$statuses);
$uniqueStatus = reset($duplicatesRemoved);
if (count($duplicatesRemoved) === 1 && !in_array($uniqueStatus, $validStatuses)) {
$message = $cateringService->getCorrespondingCateringMessage($uniqueStatus);
}
if ($message) {
return new JsonResponse([
'success' => false,
'message' => $message
]);
}
$count = $cateringService->getMaxBookingAvailable();
return new JsonResponse([
'success' => true,
'statuses' => json_encode($statuses),
'available' => $count
]);
}
/**
* @Route(
* "/{_locale}/cart/api/v1/catering-add/",
* name="post-api-catering-add",
* defaults={
* "_locale": "fi"
* },
* requirements={
* "_locale": "fi|sv|en"
* },
* methods={"POST"}
* )
* @param Request $request
* @param CartService $cartService
*
* @return JsonResponse
* @internal param CartService $cart
*/
public function addToCartAction(Request $request, CartService $cartService)
{
$priceType = (int)$this->params->get('tessitura.catering_default_pricetype');
$performanceId = (int)$request->get('performanceId');
$count = (int)$request->get('count');
$bookingPerformanceId = (int)$request->get('bookingPerformanceId');
$bookingGuests = (int)$request->get('bookingGuests');
$successMessage = "";
$collectItemsCountTotal = 0;
$collectItemsCount = 0;
try {
$cartService->evaluateFundsInCart(CartItemCatering::class);
} catch (AddNotAvailableException $exception) {
return new JsonResponse([
'success' => false,
'message' => $this->translator->trans('fund_in_cart_error')
]);
}
// If both vars are true -> This add to cart item shouldn't be collect item
if ($bookingPerformanceId && $bookingGuests) {
try {
$cartService->reserveCateringTableBooking($bookingPerformanceId, $bookingGuests, $priceType);
$successMessage = '';
} catch (CateringServiceException $exception) {
switch ($exception->getCode()) {
case CateringServiceException::TABLE_NOT_BOOKABLE:
return new JsonResponse([
'success' => false,
'message' => $this->translator->trans('catering_booking_failure')
]);
break;
case CateringServiceException::TABLE_ALL_READY_BOOKED:
// Not a problem
$successMessage = '';
break;
}
}
} else {
$collectItemsCount = $count;
}
// Calculate all collect items in cart
$collectItemsCountTotal = array_reduce($cartService->getCateringProducts(), function ($carry, $item) use ($performanceId) {
if ((int)$item->getRelatedCartPerformance()->getType()->getId() === $this->params->get('tessitura.performance_type_catering_collect')) {
$carry++;
}
return $carry;
}, 0);
// Add just added to the total count (when dealing with collect items)
$collectItemsCountTotal += (int)$collectItemsCount;
if ((int)$collectItemsCountTotal > $this->params->get('tessitura.catering_collect_max_booking')) {
return new JsonResponse([
'success' => false,
'message' => $this->translator->trans('catering_collect_too_many_failure')
]);
}
try {
$cartService->reserveCatering($performanceId, $count, $priceType);
} catch (TessituraClientException $exception) {
return new JsonResponse([
'success' => false,
'message' => $this->translator->trans('catering_cart_add_failure')
]);
}
return new JsonResponse([
'success' => true,
'message' => $successMessage
]);
}
}