Merge branch 'master' into develop

This commit is contained in:
Björn Fromme
2025-06-02 13:30:58 +02:00
21 changed files with 527 additions and 156 deletions
@@ -28,6 +28,7 @@ namespace EP\EpProducts\Controller;
use EP\EpProducts\Domain\Model\Dto\GroupsPriceInquiry; use EP\EpProducts\Domain\Model\Dto\GroupsPriceInquiry;
use EP\EpProducts\Domain\Model\GroupsPriceBoard; use EP\EpProducts\Domain\Model\GroupsPriceBoard;
use EP\EpProducts\Domain\Model\GroupsPriceOption;
use EP\EpProducts\Domain\Model\Hotel; use EP\EpProducts\Domain\Model\Hotel;
use EP\EpProducts\Domain\Repository\GroupsPriceOptionRepository; use EP\EpProducts\Domain\Repository\GroupsPriceOptionRepository;
use EP\EpProducts\Service\EmailService; use EP\EpProducts\Service\EmailService;
@@ -69,6 +70,9 @@ class AjaxGroupsPriceController extends ActionController
public function processFormAction(Hotel $hotel, GroupsPriceInquiry $groupsPriceInquiry) public function processFormAction(Hotel $hotel, GroupsPriceInquiry $groupsPriceInquiry)
{ {
$mode = $groupsPriceInquiry->getMode(); $mode = $groupsPriceInquiry->getMode();
$country = $hotel->getCountry()->getCode();
$effectivePax = $groupsPriceInquiry->getEffectivePax();
$nights = $groupsPriceInquiry->getNights();
if (false === in_array($mode, [GroupsPriceInquiry::MODE_BOOKING, GroupsPriceInquiry::MODE_INQUIRY])) { if (false === in_array($mode, [GroupsPriceInquiry::MODE_BOOKING, GroupsPriceInquiry::MODE_INQUIRY])) {
$mode = GroupsPriceInquiry::MODE_BOOKING; $mode = GroupsPriceInquiry::MODE_BOOKING;
@@ -86,10 +90,25 @@ class AjaxGroupsPriceController extends ActionController
'templateName' => 'GroupsPrice', 'templateName' => 'GroupsPrice',
]; ];
$optionPrice = function (GroupsPriceOption $option) use ($country, $effectivePax, $nights) {
$price = 'CH' === $country ? $option->getPriceChf() : $option->getPrice();
$currency = 'CH' === $country ? 'CHF' : '€';
if (GroupsPriceOption::TYPE_PER_PAX === $option->getType()) {
$price = $price * $effectivePax;
} elseif (GroupsPriceOption::TYPE_PER_NIGHT === $option->getType()) {
$price = $price * $nights;
} elseif (GroupsPriceOption::TYPE_PER_PAX_AND_NIGHT === $option->getType()) {
$price = $price * $nights * $effectivePax;
}
return $price.' '.$currency;
};
try { try {
$options = $this->groupsPriceOptionRepository->findByUids($groupsPriceInquiry->getOptions()); $options = $this->groupsPriceOptionRepository->findByUids($groupsPriceInquiry->getOptions());
$selectedOptions = array_map(function ($option) { $selectedOptions = array_map(function ($option) use ($optionPrice) {
return $option->getTitle(); return $option->getTitle().': '.$optionPrice($option);
}, $options); }, $options);
} }
catch (InvalidQueryException $e) { catch (InvalidQueryException $e) {
@@ -101,13 +120,20 @@ class AjaxGroupsPriceController extends ActionController
'hotel' => $hotel, 'hotel' => $hotel,
'name' => $groupsPriceInquiry->getName(), 'name' => $groupsPriceInquiry->getName(),
'group' => $groupsPriceInquiry->getGroup(), 'group' => $groupsPriceInquiry->getGroup(),
'address' => $groupsPriceInquiry->getAddress(), 'street' => $groupsPriceInquiry->getStreet(),
'postcode' => $groupsPriceInquiry->getPostcode(),
'city' => $groupsPriceInquiry->getCity(),
'email' => $groupsPriceInquiry->getEmail(), 'email' => $groupsPriceInquiry->getEmail(),
'phone' => $groupsPriceInquiry->getPhone(), 'phone' => $groupsPriceInquiry->getPhone(),
'remarks' => $groupsPriceInquiry->getRemarks(), 'remarks' => $groupsPriceInquiry->getRemarks(),
'dateFrom' => $groupsPriceInquiry->getDateFrom(), 'dateFrom' => $groupsPriceInquiry->getDateFrom(),
'dateTo' => $groupsPriceInquiry->getDateTo(), 'dateTo' => $groupsPriceInquiry->getDateTo(),
'nights' => $groupsPriceInquiry->getNights(),
'pax' => $groupsPriceInquiry->getPax(), 'pax' => $groupsPriceInquiry->getPax(),
'children' => $groupsPriceInquiry->getChildren(),
'minors' => $groupsPriceInquiry->getMinors(),
'adolescents' => $groupsPriceInquiry->getAdolescents(),
'adolescentsAge' => $hotel->getGroupsPriceAdolescentsAge(),
'options' => $selectedOptions, 'options' => $selectedOptions,
'board' => $groupsPriceInquiry->getBoard(), 'board' => $groupsPriceInquiry->getBoard(),
'summary' => $groupsPriceInquiry->getSummary(), 'summary' => $groupsPriceInquiry->getSummary(),
@@ -124,8 +150,7 @@ class AjaxGroupsPriceController extends ActionController
protected function errorAction() { protected function errorAction() {
$formErrors = []; $formErrors = [];
if ($this->arguments->validate()->hasErrors()) { if ($this->arguments->validate()->hasErrors()) {
foreach ($this->arguments->validate()->getFlattenedErrors() as $key => $errors) foreach ($this->arguments->validate()->getFlattenedErrors() as $key => $errors) {
{
$parts = explode('.', $key); $parts = explode('.', $key);
$fieldName = array_pop($parts); $fieldName = array_pop($parts);
$errorsRaw = []; $errorsRaw = [];
@@ -62,5 +62,6 @@ class GroupsPriceController extends ActionController
$this->view->assign('options', json_encode($hotel->getGroupsPriceOptions()->toArray(), JSON_HEX_APOS)); $this->view->assign('options', json_encode($hotel->getGroupsPriceOptions()->toArray(), JSON_HEX_APOS));
$this->view->assign('mainSeasonFrom', $mainSeasonFrom); $this->view->assign('mainSeasonFrom', $mainSeasonFrom);
$this->view->assign('mainSeasonTo', $mainSeasonTo); $this->view->assign('mainSeasonTo', $mainSeasonTo);
$this->view->assign('adolescentsAge', $hotel->getGroupsPriceAdolescentsAge() ?? 0);
} }
} }
@@ -60,7 +60,19 @@ class GroupsPriceInquiry
* @var string * @var string
* @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
*/ */
protected $address; protected $street;
/**
* @var string
* @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
*/
protected $postcode;
/**
* @var string
* @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
*/
protected $city;
/** /**
* @var string * @var string
@@ -92,6 +104,11 @@ class GroupsPriceInquiry
*/ */
protected $dateTo; protected $dateTo;
/**
* @var string
*/
protected $nights;
/** /**
* @var string * @var string
*/ */
@@ -102,6 +119,16 @@ class GroupsPriceInquiry
*/ */
protected $children; protected $children;
/**
* @var string
*/
protected $minors;
/**
* @var string
*/
protected $adolescents;
/** /**
* @var array * @var array
*/ */
@@ -109,6 +136,7 @@ class GroupsPriceInquiry
/** /**
* @var GroupsPriceBoard * @var GroupsPriceBoard
* @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
*/ */
protected $board; protected $board;
@@ -191,21 +219,53 @@ class GroupsPriceInquiry
/** /**
* @return string * @return string
*/ */
public function getAddress() public function getStreet()
{ {
return $this->address; return $this->street;
} }
/** /**
* @param string $address * @param string $street
*/ */
public function setAddress($address) public function setStreet($street)
{ {
$this->address = $address; $this->street = $street;
return $this; return $this;
} }
/**
* @return string
*/
public function getPostcode()
{
return $this->postcode;
}
/**
* @param string $postcode
*/
public function setPostcode($postcode)
{
$this->postcode = $postcode;
}
/**
* @return string
*/
public function getCity()
{
return $this->city;
}
/**
* @param string $city
*/
public function setCity($city)
{
$this->city = $city;
}
/** /**
* @return string * @return string
*/ */
@@ -286,6 +346,22 @@ class GroupsPriceInquiry
$this->dateTo = $dateTo; $this->dateTo = $dateTo;
} }
/**
* @return string
*/
public function getNights()
{
return $this->nights;
}
/**
* @param string $nights
*/
public function setNights($nights)
{
$this->nights = $nights;
}
/** /**
* @return string * @return string
*/ */
@@ -318,6 +394,46 @@ class GroupsPriceInquiry
$this->children = $children; $this->children = $children;
} }
/**
* @return string
*/
public function getMinors()
{
return $this->minors;
}
/**
* @param string $minors
*/
public function setMinors($minors)
{
$this->minors = $minors;
}
/**
* @return string
*/
public function getAdolescents()
{
return $this->adolescents;
}
/**
* @param string $adolescents
*/
public function setAdolescents($adolescents)
{
$this->adolescents = $adolescents;
}
/**
* @return int
*/
public function getEffectivePax()
{
return max(30, $this->getPax() - $this->getChildren());
}
/** /**
* @return array * @return array
*/ */
@@ -265,6 +265,16 @@ class Hotel extends AbstractEntity implements TeaserInterface
*/ */
protected $groupsPriceBoards; protected $groupsPriceBoards;
/**
* @var int
*/
protected $groupsPriceAdolescentsAge;
/**
* @var string
*/
protected $groupsPriceTaxLabel;
/** /**
* @var \DateTime * @var \DateTime
*/ */
@@ -1054,6 +1064,26 @@ class Hotel extends AbstractEntity implements TeaserInterface
$this->groupsPriceBoards = $groupsPriceBoards; $this->groupsPriceBoards = $groupsPriceBoards;
} }
public function getGroupsPriceAdolescentsAge()
{
return $this->groupsPriceAdolescentsAge;
}
public function setGroupsPriceAdolescentsAge($groupsPriceAdolescentsAge)
{
$this->groupsPriceAdolescentsAge = $groupsPriceAdolescentsAge;
}
public function getGroupsPriceTaxLabel()
{
return $this->groupsPriceTaxLabel;
}
public function setGroupsPriceTaxLabel($groupsPriceTaxLabel)
{
$this->groupsPriceTaxLabel = $groupsPriceTaxLabel;
}
public function getMainSeasonFrom() public function getMainSeasonFrom()
{ {
return $this->mainSeasonFrom; return $this->mainSeasonFrom;
@@ -358,7 +358,8 @@ class ProductRepository extends AbstractRepository
'date.bus_pro_id as dateBusProId', 'date.hotel_bus_pro_id as hotelBusProId', 'date.bus_pro_id as dateBusProId', 'date.hotel_bus_pro_id as hotelBusProId',
'date.date_end as dateEnd', 'date.hotel as hotelUid', 'date.hotel_name as hotelName', 'date.date_end as dateEnd', 'date.hotel as hotelUid', 'date.hotel_name as hotelName',
'date.hotel_header_title as hotelTitle', 'date.hotel_category as hotelCategory', 'date.hotel_header_title as hotelTitle', 'date.hotel_category as hotelCategory',
'room.pax as roomPax', 'room.price as roomPrice', 'room.available as available', 'room.name as roomName', 'room.pax as roomPax', 'room.price as roomPrice',
'room.available as available',
'hotel.detail_page as hotelDetailPageUid', 'hotel.short_name as hotelShortName', 'hotel.detail_page as hotelDetailPageUid', 'hotel.short_name as hotelShortName',
'hotel.show_as_teaser as hotelShowAsTeaser' 'hotel.show_as_teaser as hotelShowAsTeaser'
) )
@@ -384,6 +384,8 @@ class DateService implements SingletonInterface
} }
$entry =& $priceTable[$categoryUid][$hotelUid]['rooms']; $entry =& $priceTable[$categoryUid][$hotelUid]['rooms'];
$isUndersubscription = 1 === preg_match('/mit \d{1,2} Personen/', $row['roomName']);
// Add new entry or replace possible existing entry that is not // Add new entry or replace possible existing entry that is not
// bookable with current record in case of matching category // bookable with current record in case of matching category
// and pax // and pax
@@ -391,7 +393,7 @@ class DateService implements SingletonInterface
$entry[$roomPax] = [ $entry[$roomPax] = [
'price' => $row['roomPrice'], 'price' => $row['roomPrice'],
'available' => $row['available'] && $row['roomPrice'], 'available' => $row['available'] && $row['roomPrice'],
'undersubscription' => $isUndersubscription,
] ; ] ;
} else { } else {
$lastEntry = $entry[$roomPax]; $lastEntry = $entry[$roomPax];
@@ -399,6 +401,7 @@ class DateService implements SingletonInterface
$entry[$roomPax] = [ $entry[$roomPax] = [
'price' => $row['roomPrice'], 'price' => $row['roomPrice'],
'available' => $row['available'] && $row['roomPrice'], 'available' => $row['available'] && $row['roomPrice'],
'undersubscription' => $isUndersubscription,
]; ];
} }
} }
@@ -44,6 +44,7 @@ return [
['LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', -1], ['LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', -1],
['LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.default_value', 0] ['LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.default_value', 0]
], ],
'default' => -1,
], ],
], ],
'l10n_parent' => [ 'l10n_parent' => [
@@ -45,6 +45,7 @@ return [
['LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', -1], ['LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', -1],
['LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.default_value', 0] ['LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.default_value', 0]
], ],
'default' => -1,
], ],
], ],
'l10n_parent' => [ 'l10n_parent' => [
@@ -30,7 +30,8 @@ return [
--div--;Texte, teaser, description, features, room_types, additional_information, --div--;Texte, teaser, description, features, room_types, additional_information,
--div--;Verknüpfungen, facts, teamer, additional_codes, --div--;Verknüpfungen, facts, teamer, additional_codes,
--div--;Bilder/Dateien, teaser_images, header_images, images, reseller_images, --div--;Bilder/Dateien, teaser_images, header_images, images, reseller_images,
--div--;Gruppenhaus Preise, --palette--;;season, groups_price_configs, groups_price_boards, groups_price_options', --div--;Gruppenhaus Preise, --palette--;;season,--palette--;;others, groups_price_configs,
groups_price_boards, groups_price_options',
], ],
], ],
'palettes' => [ 'palettes' => [
@@ -41,6 +42,7 @@ return [
'name' => ['showitem' => 'name,short_name,--linebreak--,header_title,header_subtitle,--linebreak--,headline'], 'name' => ['showitem' => 'name,short_name,--linebreak--,header_title,header_subtitle,--linebreak--,headline'],
'categories' => ['showitem' => 'type,category'], 'categories' => ['showitem' => 'type,category'],
'season' => ['showitem' => 'main_season_from, main_season_to'], 'season' => ['showitem' => 'main_season_from, main_season_to'],
'others' => ['showitem' => 'season,groups_price_tax_label, groups_price_adolescents_age']
], ],
'columns' => [ 'columns' => [
@@ -658,6 +660,7 @@ return [
'type' => 'inline', 'type' => 'inline',
'foreign_table' => 'tx_epproducts_domain_model_groupspriceboard', 'foreign_table' => 'tx_epproducts_domain_model_groupspriceboard',
'foreign_field' => 'hotel', 'foreign_field' => 'hotel',
'foreign_table_where' => 'ORDER BY price ASC',
'maxitems' => 99, 'maxitems' => 99,
'minitems' => 0, 'minitems' => 0,
'appearance' => [ 'appearance' => [
@@ -691,6 +694,25 @@ return [
], ],
], ],
], ],
'groups_price_tax_label' => [
'exclude' => 0,
'label' => 'Text Ortstaxe',
'config' => [
'type' => 'input',
'size' => 50,
'eval' => 'trim',
'default' => 'zzgl. vor Ort zu entrichtender Ortstaxe',
],
],
'groups_price_adolescents_age' => [
'exclude' => 0,
'label' => 'Altersgrenze Jugendliche (6-X Jahre)',
'config' => [
'type' => 'input',
'size' => 50,
'eval' => 'int',
],
],
'main_season_from' => [ 'main_season_from' => [
'exclude' => false, 'exclude' => false,
'label' => 'Hauptsaison von', 'label' => 'Hauptsaison von',
+64 -62
View File
@@ -213,72 +213,74 @@ CREATE TABLE tx_epproducts_domain_model_date
CREATE TABLE tx_epproducts_domain_model_hotel CREATE TABLE tx_epproducts_domain_model_hotel
( (
uid int(11) NOT NULL auto_increment, uid int(11) NOT NULL auto_increment,
pid int(11) DEFAULT '0' NOT NULL, pid int(11) DEFAULT '0' NOT NULL,
earlybird tinyint(4) unsigned DEFAULT '0' NOT NULL, earlybird tinyint(4) unsigned DEFAULT '0' NOT NULL,
new tinyint(4) unsigned DEFAULT '0' NOT NULL, new tinyint(4) unsigned DEFAULT '0' NOT NULL,
low_contingent tinyint(4) unsigned DEFAULT '0' NOT NULL, low_contingent tinyint(4) unsigned DEFAULT '0' NOT NULL,
show_as_teaser tinyint(4) unsigned DEFAULT '0' NOT NULL, show_as_teaser tinyint(4) unsigned DEFAULT '0' NOT NULL,
detail_page varchar(255) DEFAULT '' NOT NULL, detail_page varchar(255) DEFAULT '' NOT NULL,
name varchar(255) DEFAULT '' NOT NULL, name varchar(255) DEFAULT '' NOT NULL,
short_name varchar(255) DEFAULT '' NOT NULL, short_name varchar(255) DEFAULT '' NOT NULL,
headline varchar(255) DEFAULT '' NOT NULL, headline varchar(255) DEFAULT '' NOT NULL,
description text NOT NULL, description text NOT NULL,
keywords text NOT NULL, keywords text NOT NULL,
features text NOT NULL, features text NOT NULL,
room_types text NOT NULL, room_types text NOT NULL,
additional_information text NOT NULL, additional_information text NOT NULL,
teaser text NOT NULL, teaser text NOT NULL,
header_title varchar(255) DEFAULT '' NOT NULL, header_title varchar(255) DEFAULT '' NOT NULL,
header_subtitle varchar(255) DEFAULT '' NOT NULL, header_subtitle varchar(255) DEFAULT '' NOT NULL,
teaser_images int(11) unsigned NOT NULL default '0', teaser_images int(11) unsigned NOT NULL default '0',
header_images int(11) unsigned NOT NULL default '0', header_images int(11) unsigned NOT NULL default '0',
images int(11) unsigned NOT NULL default '0', images int(11) unsigned NOT NULL default '0',
reseller_images int(11) unsigned NOT NULL default '0', reseller_images int(11) unsigned NOT NULL default '0',
code varchar(255) DEFAULT '' NOT NULL, code varchar(255) DEFAULT '' NOT NULL,
external_link varchar(255) DEFAULT '' NOT NULL, external_link varchar(255) DEFAULT '' NOT NULL,
path_segment varchar(255) DEFAULT '' NOT NULL, path_segment varchar(255) DEFAULT '' NOT NULL,
type varchar(255) DEFAULT '' NOT NULL, type varchar(255) DEFAULT '' NOT NULL,
category int(11) DEFAULT '0' NOT NULL, category int(11) DEFAULT '0' NOT NULL,
country int(11) unsigned DEFAULT '0', country int(11) unsigned DEFAULT '0',
region int(11) unsigned DEFAULT '0', region int(11) unsigned DEFAULT '0',
city int(11) unsigned DEFAULT '0', city int(11) unsigned DEFAULT '0',
teamer int(11) unsigned DEFAULT '0' NOT NULL, teamer int(11) unsigned DEFAULT '0' NOT NULL,
products int(11) unsigned DEFAULT '0' NOT NULL, products int(11) unsigned DEFAULT '0' NOT NULL,
rooms int(11) unsigned DEFAULT '0' NOT NULL, rooms int(11) unsigned DEFAULT '0' NOT NULL,
facts int(11) unsigned DEFAULT '0' NOT NULL, facts int(11) unsigned DEFAULT '0' NOT NULL,
additional_codes int(11) unsigned DEFAULT '0' NOT NULL, additional_codes int(11) unsigned DEFAULT '0' NOT NULL,
address varchar(255) DEFAULT '' NOT NULL, address varchar(255) DEFAULT '' NOT NULL,
latitude varchar(255) DEFAULT '' NOT NULL, latitude varchar(255) DEFAULT '' NOT NULL,
longitude varchar(255) DEFAULT '' NOT NULL, longitude varchar(255) DEFAULT '' NOT NULL,
groups_price_configs int(11) unsigned NOT NULL default '0', groups_price_configs int(11) unsigned NOT NULL default '0',
groups_price_options int(11) unsigned NOT NULL default '0', groups_price_options int(11) unsigned NOT NULL default '0',
groups_price_boards int(11) unsigned NOT NULL default '0', groups_price_boards int(11) unsigned NOT NULL default '0',
main_season_from date DEFAULT NULL, groups_price_adolescents_age int(11) unsigned NOT NULL default '0',
main_season_to date DEFAULT NULL, groups_price_tax_label varchar(255) DEFAULT '' NOT NULL,
main_season_from date DEFAULT NULL,
main_season_to date DEFAULT NULL,
tstamp int(11) unsigned DEFAULT '0' NOT NULL, tstamp int(11) unsigned DEFAULT '0' NOT NULL,
crdate int(11) unsigned DEFAULT '0' NOT NULL, crdate int(11) unsigned DEFAULT '0' NOT NULL,
cruser_id int(11) unsigned DEFAULT '0' NOT NULL, cruser_id int(11) unsigned DEFAULT '0' NOT NULL,
deleted tinyint(4) unsigned DEFAULT '0' NOT NULL, deleted tinyint(4) unsigned DEFAULT '0' NOT NULL,
hidden tinyint(4) unsigned DEFAULT '0' NOT NULL, hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
starttime int(11) unsigned DEFAULT '0' NOT NULL, starttime int(11) unsigned DEFAULT '0' NOT NULL,
endtime int(11) unsigned DEFAULT '0' NOT NULL, endtime int(11) unsigned DEFAULT '0' NOT NULL,
t3ver_oid int(11) DEFAULT '0' NOT NULL, t3ver_oid int(11) DEFAULT '0' NOT NULL,
t3ver_id int(11) DEFAULT '0' NOT NULL, t3ver_id int(11) DEFAULT '0' NOT NULL,
t3ver_wsid int(11) DEFAULT '0' NOT NULL, t3ver_wsid int(11) DEFAULT '0' NOT NULL,
t3ver_label varchar(255) DEFAULT '' NOT NULL, t3ver_label varchar(255) DEFAULT '' NOT NULL,
t3ver_state tinyint(4) DEFAULT '0' NOT NULL, t3ver_state tinyint(4) DEFAULT '0' NOT NULL,
t3ver_stage int(11) DEFAULT '0' NOT NULL, t3ver_stage int(11) DEFAULT '0' NOT NULL,
t3ver_count int(11) DEFAULT '0' NOT NULL, t3ver_count int(11) DEFAULT '0' NOT NULL,
t3ver_tstamp int(11) DEFAULT '0' NOT NULL, t3ver_tstamp int(11) DEFAULT '0' NOT NULL,
t3ver_move_id int(11) DEFAULT '0' NOT NULL, t3ver_move_id int(11) DEFAULT '0' NOT NULL,
sys_language_uid int(11) DEFAULT '0' NOT NULL, sys_language_uid int(11) DEFAULT '0' NOT NULL,
l10n_parent int(11) DEFAULT '0' NOT NULL, l10n_parent int(11) DEFAULT '0' NOT NULL,
l10n_diffsource mediumblob, l10n_diffsource mediumblob,
PRIMARY KEY (uid), PRIMARY KEY (uid),
KEY parent (pid), KEY parent (pid),
@@ -43,9 +43,48 @@
v-model.number="childrenCount" v-model.number="childrenCount"
@change="onPaxUpdated()" @change="onPaxUpdated()"
v-show="nightsCount > 0"/> v-show="nightsCount > 0"/>
<p class="text-sm italic"> <p class="text-sm italic"
Kinder werden nur bei Strom- und Abfallgebühren berücksichtigt v-show="nightsCount === 0">
Bitte zuerst einen Zeitraum wählen
</p> </p>
<p class="text-sm italic"
v-show="nightsCount > 0">
Kinder werden nur bei Strom- und Abfallgebühren berücksichtigt.
</p>
</div>
<div>
<label class="mb-2 font-bold">
davon Kinder 3-5 Jahre*
</label>
<input type="number"
class="form-field"
min="0"
v-model.number="childrenCount3to5"
@change="onPaxUpdated()"
v-show="nightsCount > 0"/>
<p class="text-sm italic"
v-show="nightsCount === 0">
Bitte zuerst einen Zeitraum wählen
</p>
</div>
<div v-if="adolescentsAge > 0">
<label class="mb-2 font-bold">
davon Kinder 6-{{ adolescentsAge }} Jahre*
</label>
<input type="number"
class="form-field"
min="0"
v-model.number="adolescentsCount"
@change="onPaxUpdated()"
v-show="nightsCount > 0"/>
<p class="text-sm italic"
v-show="nightsCount === 0">
Bitte zuerst einen Zeitraum wählen
</p>
</div>
<div class="sm:col-span-2 text-sm">
*Die Kosten für Essen und Kurtaxe werden wir entsprechend der Altersstruktur der Gäste in der Rechnung
anpassen.
</div> </div>
</div> </div>
<div class="mb-8" <div class="mb-8"
@@ -68,18 +107,21 @@
<div class="mb-8" <div class="mb-8"
v-show="boards.length > 0 && !submitted"> v-show="boards.length > 0 && !submitted">
<label class="mb-2 font-bold"> <label class="mb-2 font-bold">
Optionale Verpflegungsleistungen Verpflegungsleistungen
</label> </label>
<select class="form-field" <select class="form-field"
v-model="selectedBoard" v-model="selectedBoard"
v-if="selectedPax >= 30"> v-if="selectedPax >= 30">
<option :value="null">Keine Auswahl</option> <option :value="null" disabled>bitte auswählen</option>
<option v-for="board of boards" <option v-for="board of boards"
:value="board" :value="board"
:key="board.uid"> :key="board.uid">
{{ board.title }} ({{ formatCurrency(board.price) }} pro Person und Nacht) {{ board.title }} ({{ formatCurrency(board.price) }} pro Person und Nacht)
</option> </option>
</select> </select>
<div class="text-sm text-red-600 mt-1"
v-show="formErrors.board"
v-html="formErrors.board"></div>
<div v-show="selectedPax < 30"> <div v-show="selectedPax < 30">
<span class="text-red-600">Erst ab 30 Personen buchbar.</span> <span class="text-red-600">Erst ab 30 Personen buchbar.</span>
</div> </div>
@@ -128,8 +170,8 @@
<td>{{ formatCurrency(priceBoard) }}</td> <td>{{ formatCurrency(priceBoard) }}</td>
</tr> </tr>
<tr class="odd:bg-zinc-100" <tr class="odd:bg-zinc-100"
v-if="pricePax.undersubscription.EUR > 0 || pricePax.undersubscription.CHF > 0"> v-if="(priceBoard.EUR > 0 || priceBoard.CHF > 0) && (pricePax.undersubscription.EUR > 0 || pricePax.undersubscription.CHF > 0)">
<th class="text-left py-2">Kleingruppen-Verpflegungszuschlag</th> <th class="text-left py-2">Verpflegungs-Aufschlag für Gruppen unter 50 Personen</th>
<td>{{ formatCurrency(pricePax.undersubscription) }}</td> <td>{{ formatCurrency(pricePax.undersubscription) }}</td>
</tr> </tr>
<tr class="odd:bg-zinc-100" <tr class="odd:bg-zinc-100"
@@ -142,7 +184,7 @@
<td> <td>
<strong>{{ formatCurrency(priceTotal) }}</strong> <strong>{{ formatCurrency(priceTotal) }}</strong>
<br> <br>
<small>zzgl. vor Ort zu entrichtender Ortstaxe</small> <small>{{ taxLabel }}</small>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -180,17 +222,38 @@
v-show="formErrors.name" v-show="formErrors.name"
v-html="formErrors.name"></div> v-html="formErrors.name"></div>
</div> </div>
<div :class="{ 'has-error': formErrors.address }"> <div :class="{ 'has-error': formErrors.street }">
<label class="font-bold mb-2"> <label class="font-bold mb-2">
Adresse* Strasse, Nr.*
</label> </label>
<textarea class="form-field" <input type="text"
cols="30" class="form-field"
rows="3" v-model="street">
v-model="address"/>
<div class="text-sm text-red-600 mt-1" <div class="text-sm text-red-600 mt-1"
v-show="formErrors.address" v-show="formErrors.street"
v-html="formErrors.address"></div> v-html="formErrors.street"></div>
</div>
<div :class="{ 'has-error': formErrors.postcode }">
<label class="font-bold mb-2">
Postleitzahl*
</label>
<input type="text"
class="form-field"
v-model="postcode">
<div class="text-sm text-red-600 mt-1"
v-show="formErrors.postcode"
v-html="formErrors.postcode"></div>
</div>
<div :class="{ 'has-error': formErrors.city }">
<label class="font-bold mb-2">
Ort*
</label>
<input type="text"
class="form-field"
v-model="city">
<div class="text-sm text-red-600 mt-1"
v-show="formErrors.city"
v-html="formErrors.city"></div>
</div> </div>
<div :class="{ 'has-error': formErrors.group }"> <div :class="{ 'has-error': formErrors.group }">
<label class="font-bold mb-2"> <label class="font-bold mb-2">
@@ -239,7 +302,7 @@
<input type="checkbox" v-model="confirmation" name="confirmation" id="confirmation"> <input type="checkbox" v-model="confirmation" name="confirmation" id="confirmation">
<span class="block ml-2"> <span class="block ml-2">
Durch Anklicken des Buttons 'Buchung abschicken' bestätige ich, dass ich die Durch Anklicken des Buttons 'Buchung abschicken' bestätige ich, dass ich die
<a href="https://www.ep-reisen.de/reisen-fuer-gruppen/infos-zusatzleistungen/reiseinfos/agbs/" <a :href="termsUrls[countryCode]"
class="text-ep-primary" target="_blank"> class="text-ep-primary" target="_blank">
Allgemeinen Geschäftsbedingungen (AGB) Allgemeinen Geschäftsbedingungen (AGB)
</a> gelesen habe und damit einverstanden bin, dass eine </a> gelesen habe und damit einverstanden bin, dass eine
@@ -367,6 +430,14 @@ export default {
type: Number, type: Number,
default: 5, default: 5,
}, },
taxLabel: {
type: String,
default: 'zzgl. vor Ort zu entrichtender Ortstaxe',
},
adolescentsAge: {
type: Number,
default: 0,
}
}, },
data() { data() {
return { return {
@@ -382,16 +453,25 @@ export default {
selectedRange: [], selectedRange: [],
selectedPax: 30, selectedPax: 30,
childrenCount: 0, childrenCount: 0,
childrenCount3to5: 0,
adolescentsCount: 0,
selectedOptions: [], selectedOptions: [],
selectedBoard: null, selectedBoard: null,
name: null, name: '',
email: null, email: '',
phone: null, phone: '',
remarks: null, remarks: '',
group: null, group: '',
address: null, street: '',
postcode: '',
city: '',
mode: 'booking', mode: 'booking',
confirmation: false, confirmation: false,
termsUrls: {
AT: 'https://www.ep-reisen.de/fileadmin/user_upload/allgemein/AGB_Gruppen/AGB_Gruppen_CLLT_Touristik_GmbH.pdf',
CH: 'https://www.ep-reisen.de/fileadmin/user_upload/allgemein/AGB_Gruppen/AVB_Gruppen_AlpineVacation_GmbH.pdf',
IT: 'https://www.ep-reisen.de/fileadmin/user_upload/allgemein/AGB_Gruppen/AGB_Gruppen_E_P_Reisen.pdf',
}
} }
}, },
methods: { methods: {
@@ -487,14 +567,19 @@ export default {
'tx_epproducts_ajax[groupsPriceInquiry][confirmation]': confirmation ? '1' : '0', 'tx_epproducts_ajax[groupsPriceInquiry][confirmation]': confirmation ? '1' : '0',
'tx_epproducts_ajax[groupsPriceInquiry][name]': this.name ? this.name : '', 'tx_epproducts_ajax[groupsPriceInquiry][name]': this.name ? this.name : '',
'tx_epproducts_ajax[groupsPriceInquiry][group]': this.group ? this.group : '', 'tx_epproducts_ajax[groupsPriceInquiry][group]': this.group ? this.group : '',
'tx_epproducts_ajax[groupsPriceInquiry][address]': this.address ? this.address : '', 'tx_epproducts_ajax[groupsPriceInquiry][street]': this.street ? this.street : '',
'tx_epproducts_ajax[groupsPriceInquiry][postcode]': this.postcode ? this.postcode : '',
'tx_epproducts_ajax[groupsPriceInquiry][city]': this.city ? this.city : '',
'tx_epproducts_ajax[groupsPriceInquiry][email]': this.email? this.email : '', 'tx_epproducts_ajax[groupsPriceInquiry][email]': this.email? this.email : '',
'tx_epproducts_ajax[groupsPriceInquiry][phone]': this.phone ? this.phone : '', 'tx_epproducts_ajax[groupsPriceInquiry][phone]': this.phone ? this.phone : '',
'tx_epproducts_ajax[groupsPriceInquiry][remarks]': this.remarks, 'tx_epproducts_ajax[groupsPriceInquiry][remarks]': this.remarks,
'tx_epproducts_ajax[groupsPriceInquiry][dateFrom]': this.selectedFrom.format('DD.MM.YYYY'), 'tx_epproducts_ajax[groupsPriceInquiry][dateFrom]': this.selectedFrom.format('DD.MM.YYYY'),
'tx_epproducts_ajax[groupsPriceInquiry][dateTo]': this.selectedTo.format('DD.MM.YYYY'), 'tx_epproducts_ajax[groupsPriceInquiry][dateTo]': this.selectedTo.format('DD.MM.YYYY'),
'tx_epproducts_ajax[groupsPriceInquiry][nights]': this.nightsCount,
'tx_epproducts_ajax[groupsPriceInquiry][pax]': this.selectedPax, 'tx_epproducts_ajax[groupsPriceInquiry][pax]': this.selectedPax,
'tx_epproducts_ajax[groupsPriceInquiry][children]': this.childrenCount, 'tx_epproducts_ajax[groupsPriceInquiry][children]': this.childrenCount,
'tx_epproducts_ajax[groupsPriceInquiry][minors]': this.childrenCount3to5,
'tx_epproducts_ajax[groupsPriceInquiry][adolescents]': this.adolescentsCount,
'tx_epproducts_ajax[groupsPriceInquiry][summary][paxBase]': this.formatCurrency(this.pricePax.base), 'tx_epproducts_ajax[groupsPriceInquiry][summary][paxBase]': this.formatCurrency(this.pricePax.base),
'tx_epproducts_ajax[groupsPriceInquiry][summary][paxAdditional]': this.formatCurrency(this.pricePax.additional), 'tx_epproducts_ajax[groupsPriceInquiry][summary][paxAdditional]': this.formatCurrency(this.pricePax.additional),
'tx_epproducts_ajax[groupsPriceInquiry][summary][undersubscription]': this.formatCurrency(this.pricePax.undersubscription), 'tx_epproducts_ajax[groupsPriceInquiry][summary][undersubscription]': this.formatCurrency(this.pricePax.undersubscription),
@@ -531,6 +616,17 @@ export default {
}, },
}, },
computed: { computed: {
isSelfCatering() {
let selectedBoard = this.selectedBoard
if (null === selectedBoard) {
return false
}
if ('CH' === this.countryCode) {
return selectedBoard.price.CHF === 0
} else {
return selectedBoard.price.EUR === 0
}
},
paxCount() { paxCount() {
// subtract number of children from pax for price calculation, but minimum 30 pax // subtract number of children from pax for price calculation, but minimum 30 pax
return Math.max(this.selectedPax - this.childrenCount, 30) return Math.max(this.selectedPax - this.childrenCount, 30)
@@ -567,18 +663,18 @@ export default {
base.EUR += config.price.EUR base.EUR += config.price.EUR
base.CHF += config.price.CHF base.CHF += config.price.CHF
let included = config.personsIncluded let included = config.personsIncluded
let additionalPax = this.paxCount - included if (this.paxCount > included) {
if (this.selectedPax > included) { let additionalPax = this.paxCount - included
additional.EUR += additionalPax * config.priceAdditionalPerson.EUR additional.EUR += additionalPax * config.priceAdditionalPerson.EUR
additional.CHF += additionalPax * config.priceAdditionalPerson.CHF additional.CHF += additionalPax * config.priceAdditionalPerson.CHF
} }
} }
} }
} }
if (this.selectedBoard && this.paxCount < 40) { if (false === this.isSelfCatering && this.paxCount < 40) {
undersubscription.EUR = this.paxCount * this.undersubscription30Eur * this.selectedRange.length undersubscription.EUR = this.paxCount * this.undersubscription30Eur * this.selectedRange.length
undersubscription.CHF = this.paxCount * this.undersubscription30Chf * this.selectedRange.length undersubscription.CHF = this.paxCount * this.undersubscription30Chf * this.selectedRange.length
} else if (this.selectedBoard && this.paxCount < 50) { } else if (false === this.isSelfCatering && this.paxCount < 50) {
undersubscription.EUR = this.paxCount * this.undersubscription40Eur * this.selectedRange.length undersubscription.EUR = this.paxCount * this.undersubscription40Eur * this.selectedRange.length
undersubscription.CHF = this.paxCount * this.undersubscription40Chf * this.selectedRange.length undersubscription.CHF = this.paxCount * this.undersubscription40Chf * this.selectedRange.length
} }
@@ -87,12 +87,21 @@
<trans-unit id="tx_eptheme.message.group.1221560718"> <trans-unit id="tx_eptheme.message.group.1221560718">
<source>Bitte angeben</source> <source>Bitte angeben</source>
</trans-unit> </trans-unit>
<trans-unit id="tx_eptheme.message.address.1221560718"> <trans-unit id="tx_eptheme.message.street.1221560718">
<source>Bitte angeben</source>
</trans-unit>
<trans-unit id="tx_eptheme.message.postcode.1221560718">
<source>Bitte angeben</source>
</trans-unit>
<trans-unit id="tx_eptheme.message.city.1221560718">
<source>Bitte angeben</source> <source>Bitte angeben</source>
</trans-unit> </trans-unit>
<trans-unit id="tx_eptheme.message.phone.1221560718"> <trans-unit id="tx_eptheme.message.phone.1221560718">
<source>Bitte angeben</source> <source>Bitte angeben</source>
</trans-unit> </trans-unit>
<trans-unit id="tx_eptheme.message.board.1221560910">
<source>Bitte auswählen</source>
</trans-unit>
<trans-unit id="tx_eptheme.message.contactForm.firstName.1221560718"> <trans-unit id="tx_eptheme.message.contactForm.firstName.1221560718">
<source>Bitte angeben</source> <source>Bitte angeben</source>
</trans-unit> </trans-unit>
@@ -264,6 +264,10 @@
font-weight:normal; font-weight:normal;
text-decoration:underline; text-decoration:underline;
} }
table.data th,
table.data td {
vertical-align: top;
}
@media only screen and (min-width:768px){ @media only screen and (min-width:768px){
.templateContainer { .templateContainer {
width:600px !important; width:600px !important;
@@ -7,7 +7,7 @@
<f:link.typolink parameter="{f:if(condition: settings.logoLink, then: settings.logoLink, else: settings.defaultHomeUid)}" <f:link.typolink parameter="{f:if(condition: settings.logoLink, then: settings.logoLink, else: settings.defaultHomeUid)}"
class="block lg:pb-4" class="block lg:pb-4"
title="zur Startseite"> title="zur Startseite">
<f:image src="Logo" <f:image src="{settings.logoImage}"
class="block w-auto {ep:themeClasses(classes: '{ep: \'h-10 lg:h-12\', sbw: \'h-14 lg:h-24\', snz: \'h-14 lg:h-24\', suz: \'h-14 lg:h-24\', uch: \'h-12 lg:h-20\', ser: \'h-10 lg:h-12\'}', key: settings.themekey)}" class="block w-auto {ep:themeClasses(classes: '{ep: \'h-10 lg:h-12\', sbw: \'h-14 lg:h-24\', snz: \'h-14 lg:h-24\', suz: \'h-14 lg:h-24\', uch: \'h-12 lg:h-20\', ser: \'h-10 lg:h-12\'}', key: settings.themekey)}"
alt="Logo"/> alt="Logo"/>
</f:link.typolink> </f:link.typolink>
@@ -24,7 +24,7 @@
data-lightbox-url-value="{f:uri.action(action: 'index', controller: 'GroupsPrice', arguments: '{hotel: hotel}', pageUid: settings.groupsPricePopupPageUid, absolute: 1)}" data-lightbox-url-value="{f:uri.action(action: 'index', controller: 'GroupsPrice', arguments: '{hotel: hotel}', pageUid: settings.groupsPricePopupPageUid, absolute: 1)}"
data-lightbox-type-value="external" data-lightbox-type-value="external"
data-action="lightbox#open"> data-action="lightbox#open">
Preisberechnung &amp; direkt buchen Preisrechner/Buchungstool
</button> </button>
</div> </div>
</f:if> </f:if>
@@ -4,23 +4,27 @@
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers"> xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<div class="odd:bg-zinc-50 p-4" data-rte-content> <div class="odd:bg-zinc-50 p-4" data-rte-content>
<h3>
Eigenanreise
</h3>
{journey.byCar -> f:format.html()}
<f:if condition="{journey.image}">
<ep:lazyLoadImage image="{journey.image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="770"
height="430c+100"
alt="{journey.image.alternative}" />
</f:if>
<f:if condition="{journey.byBus}"> <f:if condition="{journey.byBus}">
<h3> <h3>
Busanreise Busanreise
</h3> </h3>
{journey.byBus -> f:format.html()} <div class="pb-8">
{journey.byBus -> f:format.html()}
</div>
</f:if>
<f:if condition="{journey.byCar}">
<h3>
Eigenanreise
</h3>
{journey.byCar -> f:format.html()}
<f:if condition="{journey.image}">
<ep:lazyLoadImage image="{journey.image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="770"
height="430c+100"
alt="{journey.image.alternative}" />
</f:if>
</f:if> </f:if>
</div> </div>
@@ -12,7 +12,7 @@
data-lightbox-url-value="{f:uri.action(action: 'index', controller: 'GroupsPrice', arguments: '{hotel: hotel}', pageUid: settings.groupsPricePopupPageUid, absolute: 1)}" data-lightbox-url-value="{f:uri.action(action: 'index', controller: 'GroupsPrice', arguments: '{hotel: hotel}', pageUid: settings.groupsPricePopupPageUid, absolute: 1)}"
data-lightbox-type-value="external" data-lightbox-type-value="external"
data-action="lightbox#open"> data-action="lightbox#open">
Preisberechnung &amp; direkt buchen Preisrechner/Buchungstool
</button> </button>
</div> </div>
</f:if> </f:if>
@@ -20,12 +20,12 @@
<f:section name="Table"> <f:section name="Table">
<div class="w-full max-w-full overflow-x-scroll md:overflow-x-auto"> <div class="w-full max-w-full overflow-x-scroll md:overflow-x-auto">
<table class="min-w-full border border-zinc-200 border-collapse mb-8"> <table class="min-w-full border border-zinc-200 border-collapse mb-2">
<f:for each="{categories}" as="category" key="categoryKey"> <f:for each="{categories}" as="category" key="categoryKey">
<f:if condition="{v:variable.get(name: 'pricetable.{categoryKey}', useRawKeys: 1) -> f:count()} > 0"> <f:if condition="{v:variable.get(name: 'pricetable.{categoryKey}', useRawKeys: 1) -> f:count()} > 0">
<tr class="text-white {ep:themeClasses(classes: '{sbw: \'bg-sbw-primary\', snz: \'bg-snz-primary\', uch: \'bg-uch-primary\'}', key: themekey)}"> <tr class="text-white {ep:themeClasses(classes: '{sbw: \'bg-sbw-primary\', snz: \'bg-snz-primary\', uch: \'bg-uch-primary\'}', key: themekey)}">
<td class="px-2 py-1 font-bold border border-zinc-200"> <td class="px-2 py-1 font-bold border border-zinc-200">
Apartments {category} {category}
</td> </td>
<f:for each="{roomTypesLabels}" as="type"> <f:for each="{roomTypesLabels}" as="type">
<td class="px-2 py-1 border border-zinc-200"> <td class="px-2 py-1 border border-zinc-200">
@@ -36,33 +36,34 @@
<f:for each="{pricetable.{categoryKey}}" as="row"> <f:for each="{pricetable.{categoryKey}}" as="row">
<tr> <tr>
<td class="px-2 py-1 border border-zinc-200"> <td class="px-2 py-1 border border-zinc-200">
<f:if condition="{row.hotelShortName}"> <f:link.typolink parameter="{row.hotelUri}" class="underline">
<f:then> <f:if condition="{row.hotelShortName}">
{row.hotelShortName} <f:then>
</f:then> {row.hotelShortName}
<f:else> </f:then>
<f:if condition="{row.hotelTitle}"> <f:else>
<f:then> <f:if condition="{row.hotelTitle}">
{row.hotelTitle} <f:then>
</f:then> {row.hotelTitle}
<f:else> </f:then>
{row.hotelName} <f:else>
</f:else> {row.hotelName}
</f:if> </f:else>
</f:else> </f:if>
</f:if> </f:else>
</f:if>
</f:link.typolink>
</td> </td>
<f:for each="{roomTypesPax}" as="type"> <f:for each="{roomTypesPax}" as="type">
<td class="px-2 py-1 border border-zinc-200"> <td class="px-2 py-1 border border-zinc-200">
<f:if condition="{row.rooms.{type}.available}"> <f:if condition="{row.rooms.{type}.available}">
<f:then> <f:then>
<a class="{ep:themeClasses(classes: '{sbw: \'text-sbw-primary\', snz: \'text-snz-primary\', uch: \'text-uch-primary\'}', key: settings.themekey)}" <f:link.typolink
data-controller="datalayer" data-datalayer-event-value="ZurBuchung" data-action="datalayer#trigger" parameter="{row.hotelUri}"
href="{row.bookingUrl}" class="whitespace-nowrap {ep:themeClasses(classes: '{sbw: \'text-sbw-primary\', snz: \'text-snz-primary\', uch: \'text-uch-primary\'}', key: settings.themekey)}">
title="Jetzt buchen"
target="_blank">
{row.rooms.{type}.price} {row.rooms.{type}.price}
</a> {f:if(condition: '{row.rooms.{type}.undersubscription}', then: '*')}
</f:link.typolink>
</f:then> </f:then>
<f:else> <f:else>
<f:if condition="{row.rooms.{type}.available}"> <f:if condition="{row.rooms.{type}.available}">
@@ -79,6 +80,7 @@
</f:if> </f:if>
</f:for> </f:for>
</table> </table>
<p class="text-sm mb-8">* Preis kommt durch eine Unterbelegung zustande.</p>
</div> </div>
</f:section> </f:section>
@@ -13,7 +13,7 @@
<h1>Anfrage Gruppenhaus vom <f:format.date date="now" format="d.m.y" /></h1> <h1>Anfrage Gruppenhaus vom <f:format.date date="now" format="d.m.y" /></h1>
</f:else> </f:else>
</f:if> </f:if>
<table> <table class="data">
<tr> <tr>
<th> <th>
Art Art
@@ -35,8 +35,16 @@
<td>{group}</td> <td>{group}</td>
</tr> </tr>
<tr> <tr>
<th>Adresse</th> <th>Straße</th>
<td>{address -> f:format.nl2br()}</td> <td>{street}</td>
</tr>
<tr>
<th>Postleitzahl</th>
<td>{postcode}</td>
</tr>
<tr>
<th>Ort</th>
<td>{city}</td>
</tr> </tr>
<tr> <tr>
<th>E-Mail</th> <th>E-Mail</th>
@@ -50,6 +58,10 @@
<th>Zeitraum</th> <th>Zeitraum</th>
<td>{dateFrom} - {dateTo}</td> <td>{dateFrom} - {dateTo}</td>
</tr> </tr>
<tr>
<th>Nächte</th>
<td>{nights}</td>
</tr>
<tr> <tr>
<th>Anzahl der Personen</th> <th>Anzahl der Personen</th>
<td>{pax -> v:or(alternative: '-')}</td> <td>{pax -> v:or(alternative: '-')}</td>
@@ -58,6 +70,16 @@
<th>Anzahl Kinder 0-3 Jahre</th> <th>Anzahl Kinder 0-3 Jahre</th>
<td>{children -> v:or(alternative: '-')}</td> <td>{children -> v:or(alternative: '-')}</td>
</tr> </tr>
<tr>
<th>Anzahl Kinder 3-5 Jahre</th>
<td>{minors -> v:or(alternative: '-')}</td>
</tr>
<f:if condition="{adolescentsAge}">
<tr>
<th>Anzahl Kinder 6-{adolescentsAge} Jahre</th>
<td>{adolescents -> v:or(alternative: '-')}</td>
</tr>
</f:if>
<tr> <tr>
<th>Verpflegung</th> <th>Verpflegung</th>
<td> <td>
@@ -82,25 +104,55 @@
</f:for> </f:for>
</ul> </ul>
</f:then> </f:then>
<f:else>
-
</f:else>
</f:if> </f:if>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Kostenübersicht</th> <th>Kostenübersicht</th>
<td> <td>
Grundpreis: {summary.paxBase}<br> <ul>
Aufpreis Personen: {summary.paxAdditional -> v:or(alternative: '-')}<br> <li>
Verpflegung: {summary.board -> v:or(alternative: '-')}<br> Grundpreis: {summary.paxBase}
Kleingruppen-Verpflegungszuschlag: {summary.undersubscription -> v:or(alternative: '-')}<br> </li>
Aufpreis Kurzzeit: {summary.shortTerm -> v:or(alternative: '-')}<br> <li>
Zusatzleistungen: {summary.options}<br> Aufpreis Personen: {summary.paxAdditional -> v:or(alternative: '-')}
Strom- und Abfallgebühren: {summary.runningCosts -> v:or(alternative: '-')}<br> </li>
<strong>Gesamtpreis: {summary.total}</strong> <li>
Verpflegung: {summary.board -> v:or(alternative: '-')}
</li>
<li>
Kleingruppen-Verpflegungszuschlag: {summary.undersubscription -> v:or(alternative: '-')}
</li>
<li>
Aufpreis Kurzzeit: {summary.shortTerm -> v:or(alternative: '-')}
</li>
<li>
Zusatzleistungen: {summary.options}
</li>
<li>
Strom- und Abfallgebühren: {summary.runningCosts -> v:or(alternative: '-')}
</li>
<li>
<strong>Gesamtpreis: {summary.total}</strong>
</li>
</ul>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Bemerkungen/Wünsche</th> <th>Bemerkungen/Wünsche</th>
<td>{remarks -> f:format.nl2br()}</td> <td>
<f:if condition="{remarks}">
<f:then>
{remarks -> f:format.nl2br()}
</f:then>
<f:else>
-
</f:else>
</f:if>
</td>
</tr> </tr>
</table> </table>
</f:section> </f:section>
@@ -26,6 +26,8 @@
logo-at="{f:uri.image(src: 'fileadmin/user_upload/Logos_Banner/Cllt_Touristik_frei_gestellt.jpg')}" logo-at="{f:uri.image(src: 'fileadmin/user_upload/Logos_Banner/Cllt_Touristik_frei_gestellt.jpg')}"
main-season-from="{mainSeasonFrom}" main-season-from="{mainSeasonFrom}"
main-season-to="{mainSeasonTo}" main-season-to="{mainSeasonTo}"
tax-label="{hotel.groupsPriceTaxLabel -> v:or(alternative: 'zzgl. vor Ort zu entrichtender Ortstaxe')}"
adolescents-age="{adolescentsAge}"
> >
</groups-price-calculator> </groups-price-calculator>
</f:format.raw> </f:format.raw>
@@ -339,7 +339,7 @@
data-lightbox-type-value="external" data-lightbox-type-value="external"
data-lightbox-height-value="85vh" data-lightbox-height-value="85vh"
data-action="lightbox#open"> data-action="lightbox#open">
Preisberechnung &amp; direkt buchen Preisrechner/Buchungstool
</button> </button>
</f:if> </f:if>
<div class="bg-zinc-50 p-4 flex flex-col space-y-2 relative mb-8"> <div class="bg-zinc-50 p-4 flex flex-col space-y-2 relative mb-8">