src/Controller/Shop/Json/PriceCalculatorJsonController.php line 256

Open in your IDE?
  1. <?php
  2. /**
  3.  * Created by Elements.at New Media Solutions GmbH
  4.  *
  5.  */
  6. namespace App\Controller\Shop\Json;
  7. use App\Controller\AbstractController;
  8. use App\Service\Shop\JsonDataService;
  9. use App\Service\Shop\ProductService;
  10. use App\Service\Shop\ShopService;
  11. use App\Service\Shop\SmartPricerService;
  12. use App\Service\SiteConfigService;
  13. use App\Twig\LinkGeneratorExtension;
  14. use Carbon\Carbon;
  15. use Elements\Bundle\RecurringDatesTypeBundle\Templating\RecurringDatesHelper;
  16. use Pimcore\Model\DataObject\ShopTicketCatalog;
  17. use Pimcore\Model\DataObject\TicketConsumerCategory;
  18. use Symfony\Component\HttpFoundation\Request;
  19. use Symfony\Component\HttpFoundation\Response;
  20. use Symfony\Component\Routing\Annotation\Route;
  21. use Symfony\Contracts\Translation\TranslatorInterface;
  22. /**
  23.  * @Route("/{_locale}/shop/pricecalculator")
  24.  */
  25. class PriceCalculatorJsonController extends AbstractController
  26. {
  27.     /**
  28.      * @Route("/basic-info", name="json_priceCalculator_basic_info", methods={"GET"})
  29.      *
  30.      * @param Request $request
  31.      * @param ProductService $productService
  32.      * @param TranslatorInterface $translator
  33.      *
  34.      * @return Response
  35.      */
  36.     public function basicInfoJson(Request $requestProductService $productServiceTranslatorInterface $translator): Response
  37.     {
  38.         $catalogs = new ShopTicketCatalog\Listing();
  39.         $catalogs->addConditionParam('hideInListing IS NULL OR hideInListing = ""');
  40.         $data $productService->getAvailableCategoryInterests($catalogs);
  41.         // interests
  42.         $interests = [
  43.             'title' => $translator->trans('shop.pricecalculator.basicinfos.interests'),
  44.             'type' => 'radio',
  45.             'data' => [],
  46.         ];
  47.         foreach ($data['interests'] as $interest) {
  48.             $interests['data'][] = [
  49.                 'id' => strval($interest->getId()),
  50.                 'label' => $interest->getName() ?? '',
  51.                 'categories' => array_map('strval'$data['categoriesPerInterest'][$interest->getId()]),
  52.             ];
  53.         }
  54.         // categories
  55.         $categories = [
  56.             'title' => $translator->trans('shop.pricecalculator.basicinfos.categories'),
  57.             'type' => 'checkbox',
  58.             'data' => [],
  59.         ];
  60.         foreach ($data['categories'] as $category) {
  61.             $categories['data'][] = [
  62.                 'id' => strval($category->getId()),
  63.                 'label' => $category->getName() ?? '',
  64.             ];
  65.         }
  66.         // price groups
  67.         $priceGroups = [
  68.             'title' => $translator->trans('shop.pricecalculator.basicinfos.pricegroups'),
  69.             'type' => 'checkbox',
  70.             'data' => [],
  71.         ];
  72.         $consumerCategories = new TicketConsumerCategory\Listing();
  73.         $consumerCategories->setOrderKey('order');
  74.         $consumerCategories->setOrder('desc');
  75.         foreach ($consumerCategories as $consumerCategory) {
  76.             if (!$consumerCategory->hasChildren()) {
  77.                 continue;
  78.             }
  79.             $priceGroups['data'][] = [
  80.                 'id' => strval($consumerCategory->getId()),
  81.                 'label' => $consumerCategory->getName() ?? '',
  82.                 'labelPlural' => $consumerCategory->getName() ?? '',
  83.             ];
  84.         }
  85.         $json = [
  86.           'success' => true,
  87.           'interests' => $interests,
  88.           'categories' => $categories,
  89.           'priceGroups' => $priceGroups,
  90.         ];
  91.         return $this->json($json);
  92.     }
  93.     /**
  94.      * @Route("/calendar", name="json_priceCalculator_calendar", methods={"GET"})
  95.      *
  96.      * @param Request $request
  97.      * @param ShopService $shopHelper
  98.      * @param SmartPricerService $smartPricerService
  99.      * @param SiteConfigService $siteConfigService
  100.      * @param ProductService $productService
  101.      * @param RecurringDatesHelper $recurringDatesHelper
  102.      *
  103.      * @return Response
  104.      */
  105.     public function calendarJson(
  106.         Request $request,
  107.         ShopService $shopHelper,
  108.         SmartPricerService $smartPricerService,
  109.         SiteConfigService $siteConfigService,
  110.         ProductService $productService,
  111.         RecurringDatesHelper $recurringDatesHelper): Response
  112.     {
  113.         $interestId $shopHelper->extractIdsFromString($request->get('selectedInterestIDs'), true);
  114.         $categoryIds $shopHelper->extractIdsFromString($request->get('selectedCategoryIDs'));
  115.         $priceGroupIds $shopHelper->extractIdsFromString($request->get('selectedPriceGroupIDs'));
  116.         $dateRange $shopHelper->getDatesForPriceCalculator($request);
  117.         $startDate $dateRange['startDate'];
  118.         $endDate $dateRange['endDate'];
  119.         $date $startDate->copy();
  120.         $seasonDates $shopHelper->modifySeasonDates($siteConfigService->getSiteConfig()->getPriceCalculatorSeasons());
  121.         // preparation for demand pressure
  122.         $pressures = [];
  123.         foreach ($smartPricerService->getDemandPressureEntries($startDate->copy(), $endDate->copy()) as $pressureEntry) {
  124.             $pressures[$pressureEntry['pointInTime']] = $pressureEntry['score'];
  125.         }
  126.         $isFirstLoad = !($interestId && $categoryIds && $priceGroupIds);
  127.         $selectableValidities = [];
  128.         if (!$isFirstLoad) {
  129.             $catalogs = new ShopTicketCatalog\Listing();
  130.             $catalogs->addConditionParam('hideInListing IS NULL OR hideInListing = ""');
  131.             $catalogs $productService->getFilteredCatalogs($catalogs$interestId$categoryIds$priceGroupIds);
  132.             $catalogs $catalogs->load();
  133.             /** @var \App\Model\Shop\Ticket\ShopTicketCatalog $catalog */
  134.             foreach ($catalogs as $catalog) {
  135.                 $selectableValidities array_merge($selectableValidities$catalog->getValidityDaysNumeric());
  136.             }
  137.             $selectableValidities array_unique($selectableValidities);
  138.             sort($selectableValidities);
  139.             /** @var \App\Model\Shop\Ticket\ShopTicketCatalog[] $catalogs */
  140.             [$recurringDates$useNextDayForAll$minSelectableDates$maxSelectableDates$minSelectableDays$maxSelectableDays] =
  141.                 $productService->getPriceCalculatorData($catalogs);
  142.             $lowestFromDate $shopHelper->getMinValidityDate($recurringDates);
  143.             $minDate $lowestFromDate->gt(Carbon::today())
  144.                 ? $lowestFromDate->copy()
  145.                 : ($useNextDayForAll && Carbon::now()->hour 15 Carbon::tomorrow() : Carbon::today());
  146.             $maxDate $shopHelper->getMaxValidityDate($recurringDates) ?: $endDate->copy();
  147.         } else {
  148.             $minDate Carbon::now()->hour 15 Carbon::tomorrow() : Carbon::today();
  149.             $maxDate $endDate->copy();
  150.         }
  151.         $json = [
  152.             'success' => true,
  153.             'calendarConfiguration' => [
  154.                 'minDate' => $minDate->toDateTimeLocalString(),
  155.                 'maxDate' => $maxDate->toDateTimeLocalString(),
  156.                 'minSelectableDays' => $isFirstLoad $minSelectableDays,
  157.                 'maxSelectableDays' => $isFirstLoad 30 $maxSelectableDays,
  158.                 'selectableValidities' => $selectableValidities,
  159.                 'minSelectableDates' => $isFirstLoad $minSelectableDates,
  160.                 'maxSelectableDates' => $isFirstLoad $maxSelectableDates,
  161.             ],
  162.             'calendarDates' => $shopHelper->buildCalendarData($date$endDate$minDate$seasonDates$pressures),
  163.         ];
  164.         return $this->json($json);
  165.     }
  166.     /**
  167.      * @Route("/price-groups", name="json_priceCalculator_price_groups", methods={"GET"})
  168.      *
  169.      * @param Request $request
  170.      * @param ProductService $productService
  171.      * @param TranslatorInterface $translator
  172.      * @param ShopService $shopHelper
  173.      *
  174.      * @return Response
  175.      */
  176.     public function priceGroupsJson(
  177.         Request $request,
  178.         ProductService $productService,
  179.         TranslatorInterface $translator,
  180.         ShopService $shopHelper): Response
  181.     {
  182.         $interestId $shopHelper->extractIdsFromString($request->get('selectedInterestIDs'), true);
  183.         $categoryIds $shopHelper->extractIdsFromString($request->get('selectedCategoryIDs'));
  184.         $catalogs = new ShopTicketCatalog\Listing();
  185.         $catalogs->addConditionParam('hideInListing IS NULL OR hideInListing = ""');
  186.         $data $productService->getFilteredPriceGroups($catalogs$interestId$categoryIds);
  187.         $priceGroups = [
  188.             'title' => $translator->trans('shop.pricecalculator.basicinfos.pricegroups'),
  189.             'type' => 'checkbox',
  190.             'data' => [],
  191.         ];
  192.         /** @var TicketConsumerCategory $priceGroup */
  193.         foreach ($data as $priceGroup) {
  194.             $priceGroups['data'][] = [
  195.                 'id' => strval($priceGroup->getId()),
  196.                 'label' => $priceGroup->getName() ?? '',
  197.                 'labelPlural' => $priceGroup->getName() ?? '',
  198.             ];
  199.         }
  200.         return $this->json([
  201.             'success' => true,
  202.             'priceGroups' => $priceGroups,
  203.         ]);
  204.     }
  205.     /**
  206.      * @Route("/tickets", name="json_priceCalculator_tickets", methods={"GET"})
  207.      *
  208.      * @param Request $request
  209.      *
  210.      * @return Response
  211.      */
  212.     public function ticketsJson(
  213.         Request $request,
  214.         ShopService $shopHelper,
  215.         ProductService $productService,
  216.         JsonDataService $jsonDataService,
  217.         LinkGeneratorExtension $linkGenerator
  218.     ): Response {
  219.         $interestId $shopHelper->extractIdsFromString($request->get('selectedInterestIDs'), true);
  220.         $categoryIds $shopHelper->extractIdsFromString($request->get('selectedCategoryIDs'));
  221.         $priceGroupIds $shopHelper->extractIdsFromString($request->get('selectedPriceGroupIDs'));
  222.         $startDate $request->get('startDate') ? Carbon::parse($request->get('startDate')) : null;
  223.         $endDate $request->get('endDate') ? Carbon::parse($request->get('endDate')) : $startDate->copy();
  224.         $catalogs = new ShopTicketCatalog\Listing();
  225.         $catalogs->addConditionParam('hideInListing IS NULL OR hideInListing = ""');
  226.         $catalogs->setOrderKey('sort');
  227.         $catalogs->setOrder('desc');
  228.         $catalogs $productService->getFilteredCatalogs($catalogs$interestId$categoryIds$priceGroupIds);
  229.         $catalogs $catalogs->load();
  230.         $data = [];
  231.         /** @var \App\Model\Shop\Ticket\ShopTicketCatalog $catalog */
  232.         foreach ($catalogs as $catalog) {
  233.             if (!$catalog->isAvailableInDateRange($startDate$endDate)) {
  234.                 continue;
  235.             }
  236.             // for normal tickets without upgrades
  237.             $allowedConsumerIds $shopHelper->getCorrectAllowedConsumerIds($catalog$priceGroupIds);
  238.             $availability $catalog->getAvailabilityForDateRangeWithPriceGroup($allowedConsumerIds$startDate$endDatetrue);
  239.             if (!$availability->hasAvailability() || $catalog->getIgnoreTicketsInPriceCalculator()) {
  240.                 // $finalPriceGroups = array_map(fn ($id) => TicketConsumerCategory::getById($id), $priceGroupIds);
  241.                 $catalog $catalog->getBaseCatalog();
  242.                 $data[] = [
  243.                     'catalogTitle' => $catalog->getName(),
  244.                     'tickets' => [
  245.                         [
  246.                             'ticketTitle' => $catalog->getName(),
  247.                             'startDate' => $startDate->toDateTimeLocalString(),
  248.                             'endDate' => $endDate->toDateTimeLocalString(),
  249.                             'ticketId' => strval($catalog->getId()),
  250.                             'isAnnualPass' => $catalog->getIsAnnualCatalog() ?? false,
  251.                             'isNotBookable' => true// important for showing the link to the detail page
  252.                             'pathToDetailPage' => $linkGenerator->getDetailLink($catalog),
  253.                             'data' => [],
  254.                         ],
  255.                     ],
  256.                 ];
  257.                 continue;
  258.             }
  259.             $tickets = []; // all tickets per catalog
  260.             foreach ($availability->getTicketAvailability() as $ticket) {
  261.                 $tickets[] = $jsonDataService->getTicketData($catalog$ticket$startDate$endDate); // normal ticket without upgrades
  262.                 if ($catalog->getUpgrades()) {
  263.                     $tickets array_merge(
  264.                         $tickets,
  265.                         $jsonDataService->getTicketUpgradeData($catalog$startDate$endDate$ticket$priceGroupIds)
  266.                     );
  267.                 }
  268.             }
  269.             $data[] = [
  270.                 'catalogTitle' => $catalog->getName(),
  271.                 'tickets' => $tickets,
  272.             ];
  273.         }
  274.         $json = [
  275.             'success' => true,
  276.             'data' => $data,
  277.         ];
  278.         return $this->json($json);
  279.     }
  280. }