From 46c3e82ffc197fc796976d58a1be0a03a9e922a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bjo=CC=88rn=20Fromme?= Date: Fri, 5 Oct 2018 08:54:51 +0200 Subject: [PATCH] Correctly validate selected date range --- .../Controller/AjaxContingentController.php | 4 +-- .../Repository/ContingentRepository.php | 3 +- .../Classes/Service/ContingentDataService.php | 24 +++++++++++++ .../Assets/js/components/DateSelect.vue | 36 ++++++++++++------- 4 files changed, 52 insertions(+), 15 deletions(-) diff --git a/web/typo3conf/ext/ep_products/Classes/Controller/AjaxContingentController.php b/web/typo3conf/ext/ep_products/Classes/Controller/AjaxContingentController.php index 0df8bd88..3884e824 100644 --- a/web/typo3conf/ext/ep_products/Classes/Controller/AjaxContingentController.php +++ b/web/typo3conf/ext/ep_products/Classes/Controller/AjaxContingentController.php @@ -79,9 +79,9 @@ class AjaxContingentController extends ActionController */ public function listAction(Hotel $hotel, Product $product) { - $enabled = $this->contingentRepository->getAvailableContingents($hotel, $product); + $enabled = $this->contingentDataService->getAvailableContingents($hotel, $product); - return json_encode($enabled); + return \json_encode($enabled); } /** diff --git a/web/typo3conf/ext/ep_products/Classes/Domain/Repository/ContingentRepository.php b/web/typo3conf/ext/ep_products/Classes/Domain/Repository/ContingentRepository.php index 4adf6c53..d26179a5 100644 --- a/web/typo3conf/ext/ep_products/Classes/Domain/Repository/ContingentRepository.php +++ b/web/typo3conf/ext/ep_products/Classes/Domain/Repository/ContingentRepository.php @@ -106,13 +106,14 @@ class ContingentRepository extends AbstractRepository implements ProviderInterfa $qb = $this->getDbConnection()->createQueryBuilder(); $qb - ->select('c.date as date') + ->select('c.date as date', 'c.min_nights as minNights') ->addSelectLiteral('SUM(c.available) as total') ->from('tx_epproducts_domain_model_contingent', 'c') ->innerJoin('c', 'tx_epproducts_domain_model_date', 'd', 'c.date = d.date_start AND c.hotel_code = d.hotel_code') ->where('c.hotel = :hotelUid') ->andWhere('d.product = :productUid') ->andWhere('c.available > 0') + ->andWhere('c.min_price > 0') ->setParameters([ 'hotelUid' => $hotel->getUid(), 'productUid' => $product->getUid(), diff --git a/web/typo3conf/ext/ep_products/Classes/Service/ContingentDataService.php b/web/typo3conf/ext/ep_products/Classes/Service/ContingentDataService.php index 43566ad3..94bfb7a6 100644 --- a/web/typo3conf/ext/ep_products/Classes/Service/ContingentDataService.php +++ b/web/typo3conf/ext/ep_products/Classes/Service/ContingentDataService.php @@ -47,6 +47,30 @@ class ContingentDataService $this->contingentRepository = $contingentRepository; } + /** + * @param Hotel $hotel + * @param Product $product + * @return array + * @throws \Doctrine\DBAL\DBALException + */ + public function getAvailableContingents(Hotel $hotel, Product $product) + { + $data = $this->contingentRepository->getAvailableContingents($hotel, $product); + + $contingents = []; + + foreach ($data as $row) + { + $contingents[$row['date']] = [ + 'date' => $row['date'], + 'minNights' => $row['minNights'], + 'total' => $row['total'], + ]; + } + + return $contingents; + } + /** * @param \DateTime $dateFrom * @param \DateTime $dateTo diff --git a/web/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/DateSelect.vue b/web/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/DateSelect.vue index 9838638c..b7b53dc1 100644 --- a/web/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/DateSelect.vue +++ b/web/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/DateSelect.vue @@ -142,6 +142,16 @@ } return this.selectedTo.diff(this.selectedFrom, 'days'); }, + minNightsForSelectedDate () { + if (this.selectedFrom === null) { + return 0; + } + const key = this.selectedFrom.format('YYYY-MM-DD'); + if (!key in this.availableDates) { + return 0; + } + return this.availableDates[key].minNights; + }, message () { if (this.loading) { return ''; @@ -149,6 +159,10 @@ if (this.selectedFrom === null || this.selectedTo === null) { return 'Bitte einen Zeitraum auswählen.'; } + const minNights = this.minNightsForSelectedDate; + if (this.selectedNumberOfDays < minNights) { + return 'Bitte mindestens ' + minNights + ' Nächte auswählen.'; + } if (this.availableRooms.length === 0) { return 'Im gewählten Zeitraum sind leider keine Zimmer verfügbar.'; } @@ -166,11 +180,13 @@ this.loading = true; $.post(this.contingentEndpointUri, query, (json) => { this.loading = false; - this.availableDates = json; - const enabledDates = []; - if (json.length) { - for (const entry of this.availableDates) { - enabledDates.push(entry.date); + if (json) { + this.availableDates = json; + const enabledDates = []; + for (const date in this.availableDates) { + if (this.availableDates.hasOwnProperty(date)) { + enabledDates.push(this.availableDates[date].date); + } } this.picker.set('enable', enabledDates); this.picker.set('minDate', enabledDates[0]); @@ -212,20 +228,16 @@ if (selectedDates.length === 2) { this.selectedFrom = dayjs(selectedDates[0]); this.selectedTo = dayjs(selectedDates[1]); - if (this.selectedNumberOfDays > 1) { + if (this.selectedNumberOfDays >= this.minNightsForSelectedDate) { this.fetchAvailableRooms(); } } }, onDayCreate: (dObj, dStr, fp, dayElem) => { const day = dayjs(dayElem.dateObj).format('YYYY-MM-DD'); - for (const entry of this.availableDates) { - if (entry.date === day) { - dayElem.classList.add('available'); - return; - } + if (day in this.availableDates) { + dayElem.classList.add('available'); } - } }); Vue.nextTick(() => {