diff --git a/public/typo3conf/ext/ep_products/Classes/Controller/AjaxGroupsPriceController.php b/public/typo3conf/ext/ep_products/Classes/Controller/AjaxGroupsPriceController.php
new file mode 100644
index 00000000..4f8c54ea
--- /dev/null
+++ b/public/typo3conf/ext/ep_products/Classes/Controller/AjaxGroupsPriceController.php
@@ -0,0 +1,91 @@
+, dreipunktnull
+ *
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use EP\EpProducts\Domain\Model\Hotel;
+use EP\EpProducts\Service\GroupsPriceService;
+use League\Period\Period;
+use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
+
+class AjaxGroupsPriceController extends ActionController
+{
+ /**
+ * @var GroupsPriceService
+ */
+ protected $groupsPriceService;
+
+ public function __construct(GroupsPriceService $groupsPriceService)
+ {
+ parent::__construct();
+
+ $this->groupsPriceService = $groupsPriceService;
+ }
+
+ /**
+ * @param Hotel $hotel
+ * @return string
+ */
+ public function configsAction(Hotel $hotel)
+ {
+ return json_encode([
+ 'configs' => $hotel->getGroupsPriceConfigs()->toArray(),
+ 'boards' => $hotel->getGroupsPriceBoards()->toArray(),
+ 'options' => $hotel->getGroupsPriceOptions()->toArray(),
+ ], JSON_THROW_ON_ERROR, 512);
+ }
+
+ public function initializePriceAction()
+ {
+ if ($this->request->hasArgument('dateFrom')) {
+ $dateFrom = new \DateTime($this->request->getArgument('dateFrom'));
+ $this->request->setArgument('dateFrom', $dateFrom);
+ }
+ if ($this->request->hasArgument('dateTo')) {
+ $dateTo = new \DateTime($this->request->getArgument('dateTo'));
+ $this->request->setArgument('dateTo', $dateTo);
+ }
+ }
+
+ /**
+ * @param Hotel $hotel
+ * @param \DateTime $dateFrom
+ * @param \DateTime $dateTo
+ * @param int $pax
+ * @return string
+ * @throws \League\Period\Exception
+ */
+ public function priceAction(Hotel $hotel, \DateTime $dateFrom, \DateTime $dateTo, $pax)
+ {
+ $period = new Period($dateFrom, $dateTo);
+ $price = $this->groupsPriceService->calculateHotelPrice($hotel, $period, $pax);
+
+ return json_encode([
+ 'price' => $price,
+ ], JSON_THROW_ON_ERROR, 512);
+ }
+}
diff --git a/public/typo3conf/ext/ep_products/Classes/Service/GroupsPriceService.php b/public/typo3conf/ext/ep_products/Classes/Service/GroupsPriceService.php
new file mode 100644
index 00000000..f44deadf
--- /dev/null
+++ b/public/typo3conf/ext/ep_products/Classes/Service/GroupsPriceService.php
@@ -0,0 +1,80 @@
+getConfigs($hotel);
+
+ // Create periods in configs to simplify following steps
+ $this->patchConfigPeriods($configs);
+
+ $price = 0;
+
+ // Iterate over all days in provided period
+ foreach ($period->getDatePeriod('1 DAY') as $day) {
+
+ // Iterate over all configs
+ foreach ($configs as $config) {
+
+ // Skip config if current day is not contained
+ if (false === $config['period']->contains($day)) {
+ continue;
+ }
+
+ // Calculate base price
+ $price += $config['price'];
+
+ // Add costs for not-included number of persons
+ if ($pax > $config['persons_included']) {
+ $price += $config['price_additional_person'] * ($pax - $config['persons_included']);
+ }
+ }
+ }
+
+ return $price;
+ }
+
+ protected function patchConfigPeriods(array &$configs)
+ {
+ foreach ($configs as $idx => $config) {
+ $configDateFrom = (new \DateTimeImmutable())->setTimestamp($config['date_from']);
+ $configDateTo = (new \DateTimeImmutable())->setTimestamp($config['date_to']);
+ $configs[$idx]['period'] = new Period($configDateFrom, $configDateTo);
+ }
+ }
+
+ /**
+ * @param Hotel $hotel
+ * @return array
+ */
+ protected function getConfigs(Hotel $hotel)
+ {
+ $qb = $this->getQueryBuilder();
+
+ return $qb
+ ->select('*')
+ ->from('tx_epproducts_domain_model_groupspriceconfig')
+ ->where($qb->expr()->eq('hotel', $qb->createNamedParameter($hotel->getUid())))
+ ->orderBy('date_from')
+ ->execute()
+ ->fetchAll()
+ ;
+ }
+
+ protected function getQueryBuilder()
+ {
+ /** @var ConnectionPool $connectionPool */
+ $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
+
+ return $connectionPool->getQueryBuilderForTable('tx_epproducts_domain_model_groupspriceconfig');
+ }
+}
\ No newline at end of file
diff --git a/public/typo3conf/ext/ep_products/Configuration/TypoScript/setup.typoscript b/public/typo3conf/ext/ep_products/Configuration/TypoScript/setup.typoscript
index 7f1e426c..5be9ade7 100644
--- a/public/typo3conf/ext/ep_products/Configuration/TypoScript/setup.typoscript
+++ b/public/typo3conf/ext/ep_products/Configuration/TypoScript/setup.typoscript
@@ -133,6 +133,10 @@ tx_epproducts_ajax_json {
AjaxWatchlist {
1 = list
}
+ AjaxGroupsPrice {
+ 1 = configs
+ 2 = price
+ }
}
features.requireCHashArgumentForActionArguments = 0
settings =< plugin.tx_epproducts.settings
diff --git a/public/typo3conf/ext/ep_products/ext_localconf.php b/public/typo3conf/ext/ep_products/ext_localconf.php
index b32051ff..83c46f2d 100644
--- a/public/typo3conf/ext/ep_products/ext_localconf.php
+++ b/public/typo3conf/ext/ep_products/ext_localconf.php
@@ -345,6 +345,7 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\EP\EpProducts\T
'AjaxTable' => 'pricetable,pricetableHtml,eventPricetable',
'AjaxCalendar' => 'range,contingents,availableRooms',
'AjaxWatchlist' => 'list',
+ 'AjaxGroupsPrice' => 'configs,price',
],
[
'AjaxSearch' => 'searchresult',
@@ -355,6 +356,7 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\EP\EpProducts\T
'AjaxTable' => 'pricetable,pricetableHtml,eventPricetable',
'AjaxCalendar' => 'range,contingents,availableRooms',
'AjaxWatchlist' => 'list',
+ 'AjaxGroupsPrice' => 'configs,price',
]
);
@@ -382,6 +384,7 @@ $GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash']['excludedParameters'][] = 'tx_epp
$GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash']['excludedParameters'][] = 'tx_epproducts_ajax[months]';
$GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash']['excludedParameters'][] = 'tx_epproducts_ajax[month]';
$GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash']['excludedParameters'][] = 'tx_epproducts_ajax[year]';
+$GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash']['excludedParameters'][] = 'tx_epproducts_ajax[hotel]';
$GLOBALS['TYPO3_CONF_VARS']['LOG']['EP']['EpProducts']['Controller']['writerConfiguration'] = [
\TYPO3\CMS\Core\Log\LogLevel::INFO => [
diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/GroupsPriceCalculator.vue b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/GroupsPriceCalculator.vue
new file mode 100644
index 00000000..ee647cad
--- /dev/null
+++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/GroupsPriceCalculator.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/ProductDetail.vue b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/ProductDetail.vue
index cbc22ec8..dbd0234b 100644
--- a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/ProductDetail.vue
+++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/ProductDetail.vue
@@ -11,6 +11,7 @@
import DaterangeSelect from './DaterangeSelect.vue'
import AjaxContent from './AjaxContent.vue'
import Calendar from './Calendar.vue'
+ import GroupsPriceCalculator from './GroupsPriceCalculator.vue';
import FacebookPixel from './FacebookPixel.vue'
import WatchlistToggle from './WatchlistToggle.vue'
import OsmMap from './OsmMap.vue'
@@ -28,6 +29,7 @@
DaterangeSelect,
AjaxContent,
Calendar,
+ GroupsPriceCalculator,
FacebookPixel,
WatchlistToggle,
OsmMap,
diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Templates/Product/Detail.html b/public/typo3conf/ext/ep_theme/Resources/Private/Templates/Product/Detail.html
index 52e4e8ed..c2b101a1 100644
--- a/public/typo3conf/ext/ep_theme/Resources/Private/Templates/Product/Detail.html
+++ b/public/typo3conf/ext/ep_theme/Resources/Private/Templates/Product/Detail.html
@@ -248,6 +248,9 @@
+