<?php
namespace App\Controller;
use AF\AdminBundle\Enum\WeekDaysEnum;
use AF\PHDatabase\Entity\PriceListCommodity;
use App\Repository\App\ConfigurationRepository;
use App\Repository\App\OfferTransRepository;
use App\Service\EventService;
use App\Service\PriceService;
use App\Service\SlackNotify;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
/**
* Obsługa cenników
*
* Zwraca najniższą kwotę dla standardu, który definiuje się w CMS (według założeń jest to DBL – najtańszy standard).
*
* @see PriceService Serwis wyliczający ceny per dzień
*/
class CalendarController extends AbstractController
{
public function __construct(private readonly OfferTransRepository $offerTransRepository,
private readonly EventService $eventService,
private readonly ConfigurationRepository $configurationRepository)
{
}
/**
* Zwraca najniższą kwotę per dzień
*
* Standard, dla którego będą pobierane cenniki definiuje się w CMS.
* Cenniki nie zostaną zwrócone, jeżeli standard nie zostanie prawidłowo zdefiniowany.
*
* @api {get} /api/v1/public/calendar/prices Cennik
* @apiDescription
* <p> Endpoint domyślnie zwraca kwotę per dzień, licząc od dnia aktualnego, aż do ostatniego dnia, dla którego
* został uzupełniony cennik. Istnieje możliwość przekazania własnego zakresu za pomocą parametrów
* "start" i "end" w formacie Y-m-d, np. api/v1/public/calendar/prices?start=2020-01-01&end=2021-01-01) </p>
* <p> Waluta kwoty to PLN, bez możliwości jej zmiany. </p>
*
* <b>Uwaga!</b>
* <p> Endpoint działa prawidłowo tylko wtedy, gdy zostały spełnione następujące warunki: </p>
* <ol>
* <li> Istnieje pokój, który został przypisany do shuum'owego standardu pokoju i ma aktywną flagę "Cena kalendarzowa" </li>
* <li> Wybrany standard pokoju ma uzupełniony cennik w SPAsofcie i zaznaczoną opcję "DostepPrzezWWW" w tabeli shuum.Cenniki </li>
* </ol>
* @apiSampleRequest /api/v1/public/calendar/prices
* @apiVersion 1.0.0
* @apiGroup Kalendarz
* @apiParam {String} start Początek zakresu
* @apiParam {String} end Koniec zakresu
* @apiSuccess {Array} meta Dodatkowe informacje
* @apiSuccess {String} meta.maxDate Maksymalny dostępny zakres
* @apiSuccess {Array} results Dostępne kwoty, zobacz przykład Success 200
* @apiError {Array} messages Opisy błędów
* @apiExample Success 200
* HTTP/1.1 200 OK
* {
* "meta": {
* "maxDate": "2021-01-03"
* },
* "results": {
* "2020": {
* "12": {
* "30": "900.00",
* "31": "900.00"
* }
* },
* "2021": {
* "1": {
* "1": "900.00"
* }
* }
* }
* }
*
* @apiExample Error 400
* HTTP/1.1 400 Bad Request
* {
* "messages": [
* "Brak pokoju odpowiadającego za ceny kalendarzowe."
* ]
* }
*
* @param Request $request Żądanie wysyłane do serwera
* @param ManagerRegistry $registry Obsługa baz danych
* @param PriceService $priceService Pobierania cenników
* @param SlackNotify $slackNotify Wysyłka notyfikacja na slacka
* @return JsonResponse
* @throws \Exception
*/
public function calendarPrices(
Request $request,
ManagerRegistry $registry,
PriceService $priceService,
SlackNotify $slackNotify
): JsonResponse
{
$config = $registry->getRepository('App\Entity\App\Configuration')->findOneByName('booking_calendar_price');
if ( $config === null || $config->getValue() === null ) {
$slackNotify->send(null, '[Kalendarz - cennik] Brak standardu', 'W CMS nie został
zdefiniowany standard, którego cennik miałby się pokazywać na kalendarzu.');
return new JsonResponse([
'messages' => [
'Wystąpił błąd podczas pobierania danych. Prosimy spróbować ponownie za chwilę.'
]
], 400);
}
if ( $request->query->has('start') ) {
$dateStart = new \DateTime($request->query->get('start'));
} else {
$dateStart = new \DateTime();
}
if ( $request->query->has('end') ) {
$dateEnd = new \DateTime($request->query->get('end'));
} else {
$dateEnd = null;
}
$prices = $registry->getRepository(PriceListCommodity::class)->getLowestPrice(
$dateStart,
$dateEnd,
$config->getValue()
);
$results = $priceService->getCalendarPrice($dateStart, $dateEnd, $prices);
$configs = $this->configurationRepository->getBookingConfig(['booking_score_hotel', 'description_engine_standard']);
$maxDate = $registry->getRepository(PriceListCommodity::class)->getMaxDate($config->getValue());
if ( $maxDate !== null ) {
$maxDate = $maxDate->getPriceList()->getAvailableUntil()->format('Y-m-d');
}
$offerResponse = [];
if($request->query->has('slug'))
{
$slug = $request->query->get('slug');
$offerTrans = $this->offerTransRepository->getOfferBySlug($slug);
if($offerTrans) {
$offer = $offerTrans->getOffer();
$offerResponse['offerId'] = $offer->getId();
$offerResponse['minDate'] = $offer->getArrivalPeriodFrom()->format('Y-m-d');
$offerResponse['maxDate'] = $offer->getArrivalPeriodTo()->format('Y-m-d');
$offerResponse['minDays'] = $offer->getMinDaysNumber();
$offerResponse['maxDays'] = $offer->getMaxDaysNumber();
$offerResponse['minGuests'] = $offer->getMinGuestsNumber();
$offerResponse['maxGuests'] = $offer->getMaxGuestsNumber();
$offerResponse['requiredDays'] = WeekDaysEnum::getCalendarKeysFromRequiredDays($offer->getWeekDays());
$offerResponse['requiredStartingDay'] = WeekDaysEnum::getCalendarKeysFromRequiredDays($offer->getWeekDaysStart());
$offerResponse['arrivalFrom'] = $offer->getArrivalFrom() ? $offer->getArrivalFrom()->format('Y-m-d') : null;
$offerResponse['arrivalTo'] = $offer->getArrivalFrom() ? $offer->getArrivalTo()->format('Y-m-d') : null;
$offerResponse['excludes'] = $offer->getExcludes() ? json_decode($offer->getExcludes(), true) : [];
$offerResponse['header'] = $offerTrans->getName();
$offerResponse['description'] = $offerTrans->getOfferDescription();
}
else
{
$offerResponse = null;
}
}
$results = $this->eventService->applyEventsIntoDates($results, $this->eventService->getBookingEvents($maxDate));
return new JsonResponse([
'meta' => [
'maxDate' => $maxDate,
'bookingPercent' => $configs['booking_score_hotel'] ? (int) $configs['booking_score_hotel']->getValue() : '',
'descriptionEngineStandard' => $configs['description_engine_standard'] ? $configs['description_engine_standard']->getValue() : ''
],
'results' => $results,
'offer' => !empty($offerResponse) ? $offerResponse : null
]);
}
}