Merge branch 'feature/price-calculator-currencies' into develop

This commit is contained in:
Björn Fromme
2025-02-25 09:52:19 +01:00
11 changed files with 482 additions and 109 deletions
@@ -41,7 +41,11 @@ class GroupsPriceController extends ActionController
}); });
$this->view->assign('hotel', $hotel); $this->view->assign('hotel', $hotel);
$this->view->assign('runningCosts', $this->settings['runningCosts']); $this->view->assign('runningCostsEUR', $this->settings['runningCostsEUR']);
$this->view->assign('runningCostsCHF', $this->settings['runningCostsCHF']);
$this->view->assign('undersubscriptionEUR', $this->settings['undersubscriptionEUR']);
$this->view->assign('undersubscriptionCHF', $this->settings['undersubscriptionCHF']);
$this->view->assign('countryCode', $hotel->getCountry()->getCode());
$this->view->assign('configs', json_encode(array_values($configs), JSON_HEX_APOS)); $this->view->assign('configs', json_encode(array_values($configs), JSON_HEX_APOS));
$this->view->assign('boards', json_encode($hotel->getGroupsPriceBoards()->toArray(), JSON_HEX_APOS)); $this->view->assign('boards', json_encode($hotel->getGroupsPriceBoards()->toArray(), JSON_HEX_APOS));
$this->view->assign('options', json_encode($hotel->getGroupsPriceOptions()->toArray(), JSON_HEX_APOS)); $this->view->assign('options', json_encode($hotel->getGroupsPriceOptions()->toArray(), JSON_HEX_APOS));
@@ -41,6 +41,11 @@ class GroupsPriceBoard extends AbstractEntity implements \JsonSerializable
*/ */
protected $price; protected $price;
/**
* @var float
*/
protected $priceChf;
/** /**
* @return string * @return string
*/ */
@@ -73,15 +78,34 @@ class GroupsPriceBoard extends AbstractEntity implements \JsonSerializable
$this->price = $price; $this->price = $price;
} }
/**
* @return float
*/
public function getPriceChf(): ?float
{
return $this->priceChf;
}
/**
* @param float $price
*/
public function setPriceChf(float $price): void
{
$this->priceChf = $price;
}
/** /**
* @return array * @return array
*/ */
public function jsonSerialize() public function jsonSerialize(): array
{ {
return [ return [
'uid' => $this->getUid(), 'uid' => $this->getUid(),
'title' => $this->getTitle(), 'title' => $this->getTitle(),
'price' => $this->getPrice(), 'price' => [
'EUR' => $this->getPrice(),
'CHF' => $this->getPriceChf(),
],
]; ];
} }
} }
@@ -51,26 +51,51 @@ class GroupsPriceConfig extends AbstractEntity implements \JsonSerializable
*/ */
protected $price; protected $price;
/**
* @var float
*/
protected $priceChf;
/** /**
* @var float * @var float
*/ */
protected $priceAdditionalPerson; protected $priceAdditionalPerson;
/**
* @var float
*/
protected $priceAdditionalPersonChf;
/** /**
* @var float * @var float
*/ */
protected $priceAdditionalPersonGroup1; protected $priceAdditionalPersonGroup1;
/**
* @var float
*/
protected $priceAdditionalPersonGroup1Chf;
/** /**
* @var float * @var float
*/ */
protected $priceAdditionalPersonGroup2; protected $priceAdditionalPersonGroup2;
/**
* @var float
*/
protected $priceAdditionalPersonGroup2Chf;
/** /**
* @var float * @var float
*/ */
protected $priceAdditionalPersonGroup3; protected $priceAdditionalPersonGroup3;
/**
* @var float
*/
protected $priceAdditionalPersonGroup3Chf;
/** /**
* @var bool * @var bool
*/ */
@@ -140,6 +165,22 @@ class GroupsPriceConfig extends AbstractEntity implements \JsonSerializable
$this->price = $price; $this->price = $price;
} }
/**
* @return float
*/
public function getPriceChf(): ?float
{
return $this->priceChf;
}
/**
* @param float $price
*/
public function setPriceChf(float $price): void
{
$this->priceChf = $price;
}
/** /**
* @return float * @return float
*/ */
@@ -156,6 +197,22 @@ class GroupsPriceConfig extends AbstractEntity implements \JsonSerializable
$this->priceAdditionalPerson = $priceAdditionalPerson; $this->priceAdditionalPerson = $priceAdditionalPerson;
} }
/**
* @return float
*/
public function getPriceAdditionalPersonChf(): ?float
{
return $this->priceAdditionalPersonChf;
}
/**
* @param float $priceAdditionalPerson
*/
public function setPriceAdditionalPersonChf(float $priceAdditionalPerson): void
{
$this->priceAdditionalPersonChf = $priceAdditionalPerson;
}
/** /**
* @return float * @return float
*/ */
@@ -172,6 +229,22 @@ class GroupsPriceConfig extends AbstractEntity implements \JsonSerializable
$this->priceAdditionalPersonGroup1 = $priceAdditionalPersonGroup1; $this->priceAdditionalPersonGroup1 = $priceAdditionalPersonGroup1;
} }
/**
* @return float
*/
public function getPriceAdditionalPersonGroup1Chf(): ?float
{
return $this->priceAdditionalPersonGroup1Chf;
}
/**
* @param float $priceAdditionalPersonGroup1
*/
public function setPriceAdditionalPersonGroup1Chf(float $priceAdditionalPersonGroup1): void
{
$this->priceAdditionalPersonGroup1Chf = $priceAdditionalPersonGroup1;
}
/** /**
* @return float * @return float
*/ */
@@ -188,6 +261,22 @@ class GroupsPriceConfig extends AbstractEntity implements \JsonSerializable
$this->priceAdditionalPersonGroup2 = $priceAdditionalPersonGroup2; $this->priceAdditionalPersonGroup2 = $priceAdditionalPersonGroup2;
} }
/**
* @return float
*/
public function getPriceAdditionalPersonGroup2Chf(): ?float
{
return $this->priceAdditionalPersonGroup2Chf;
}
/**
* @param float $priceAdditionalPersonGroup2
*/
public function setPriceAdditionalPersonGroup2Chf(float $priceAdditionalPersonGroup2): void
{
$this->priceAdditionalPersonGroup2Chf = $priceAdditionalPersonGroup2;
}
/** /**
* @return float * @return float
*/ */
@@ -204,6 +293,22 @@ class GroupsPriceConfig extends AbstractEntity implements \JsonSerializable
$this->priceAdditionalPersonGroup3 = $priceAdditionalPersonGroup3; $this->priceAdditionalPersonGroup3 = $priceAdditionalPersonGroup3;
} }
/**
* @return float
*/
public function getPriceAdditionalPersonGroup3Chf(): ?float
{
return $this->priceAdditionalPersonGroup3Chf;
}
/**
* @param float $priceAdditionalPersonGroup3
*/
public function setPriceAdditionalPersonGroup3Chf(float $priceAdditionalPersonGroup3): void
{
$this->priceAdditionalPersonGroup3Chf = $priceAdditionalPersonGroup3;
}
/** /**
* @return bool * @return bool
*/ */
@@ -223,19 +328,34 @@ class GroupsPriceConfig extends AbstractEntity implements \JsonSerializable
/** /**
* @return array * @return array
*/ */
public function jsonSerialize() public function jsonSerialize(): array
{ {
return [ return [
'uid' => $this->getUid(), 'uid' => $this->getUid(),
'dateFrom' => $this->getDateFrom()->format('Y-m-d'), 'dateFrom' => $this->getDateFrom()->format('Y-m-d'),
'dateTo' => $this->getDateTo()->format('Y-m-d'), 'dateTo' => $this->getDateTo()->format('Y-m-d'),
'personsIncluded' => $this->getPersonsIncluded(), 'personsIncluded' => $this->getPersonsIncluded(),
'price' => $this->getPrice(), 'price' => [
'priceAdditionalPerson' => $this->getPriceAdditionalPerson(), 'EUR' => $this->getPrice(),
'CHF' => $this->getPriceChf(),
],
'priceAdditionalPerson' => [
'EUR' => $this->getPriceAdditionalPerson(),
'CHF' => $this->getPriceAdditionalPersonChf(),
],
'priceAdditionalPersonByGroup' => [ 'priceAdditionalPersonByGroup' => [
1 => $this->getPriceAdditionalPersonGroup1(), 1 => [
2 => $this->getPriceAdditionalPersonGroup2(), 'EUR' => $this->getPriceAdditionalPersonGroup1(),
3 => $this->getPriceAdditionalPersonGroup3(), 'CHF' => $this->getPriceAdditionalPersonGroup1Chf(),
],
2 => [
'EUR' => $this->getPriceAdditionalPersonGroup2(),
'CHF' => $this->getPriceAdditionalPersonGroup2Chf(),
],
3 => [
'EUR' => $this->getPriceAdditionalPersonGroup3(),
'CHF' => $this->getPriceAdditionalPersonGroup3Chf(),
],
], ],
'bonusCardIncluded' => $this->isBonusCardIncluded(), 'bonusCardIncluded' => $this->isBonusCardIncluded(),
]; ];
@@ -46,6 +46,11 @@ class GroupsPriceOption extends AbstractEntity implements \JsonSerializable
*/ */
protected $price; protected $price;
/**
* @var float
*/
protected $priceChf;
/** /**
* @var int * @var int
*/ */
@@ -88,6 +93,22 @@ class GroupsPriceOption extends AbstractEntity implements \JsonSerializable
$this->price = $price; $this->price = $price;
} }
/**
* @return float
*/
public function getPriceChf(): ?float
{
return $this->priceChf;
}
/**
* @param float $price
*/
public function setPriceChf(float $price): void
{
$this->priceChf = $price;
}
/** /**
* @return int * @return int
*/ */
@@ -123,12 +144,15 @@ class GroupsPriceOption extends AbstractEntity implements \JsonSerializable
/** /**
* @return array * @return array
*/ */
public function jsonSerialize() public function jsonSerialize(): array
{ {
return [ return [
'uid' => $this->getUid(), 'uid' => $this->getUid(),
'title' => $this->getTitle(), 'title' => $this->getTitle(),
'price' => $this->getPrice(), 'price' => [
'EUR' => $this->getPrice(),
'CHF' => $this->getPriceChf(),
],
'type' => $this->getType(), 'type' => $this->getType(),
'ignoreWithBoard' => $this->isIgnoreWithBoard(), 'ignoreWithBoard' => $this->isIgnoreWithBoard(),
]; ];
@@ -10,17 +10,50 @@
</TCEforms> </TCEforms>
<type>array</type> <type>array</type>
<el> <el>
<settings.runningCosts> <settings.runningCostsEUR>
<TCEforms> <TCEforms>
<exclude>0</exclude> <exclude>0</exclude>
<label>Strom- und Entsorgungspauschale</label> <label>Strom- und Entsorgungspauschale EUR</label>
<config> <config>
<type>input</type> <type>input</type>
<default>1.7</default> <default>2.5</default>
<eval>double2,required</eval> <eval>double2,required</eval>
</config> </config>
</TCEforms> </TCEforms>
</settings.runningCosts> </settings.runningCostsEUR>
<settings.runningCostsCHF>
<TCEforms>
<exclude>0</exclude>
<label>Strom- und Entsorgungspauschale CHF</label>
<config>
<type>input</type>
<default>2.9</default>
<eval>double2,required</eval>
</config>
</TCEforms>
</settings.runningCostsCHF>
<settings.undersubscriptionEUR>
<TCEforms>
<exclude>0</exclude>
<label>Unterbelegung EUR</label>
<config>
<type>input</type>
<default>5.0</default>
<eval>double2,required</eval>
</config>
</TCEforms>
</settings.undersubscriptionEUR>
<settings.undersubscriptionCHF>
<TCEforms>
<exclude>0</exclude>
<label>Unterbelegung CHF</label>
<config>
<type>input</type>
<default>5.0</default>
<eval>double2,required</eval>
</config>
</TCEforms>
</settings.undersubscriptionCHF>
</el> </el>
</ROOT> </ROOT>
</sDEF> </sDEF>
@@ -25,7 +25,7 @@ return [
], ],
'types' => [ 'types' => [
'1' => [ '1' => [
'showitem' => 'title, price', 'showitem' => 'title, price, price_chf',
], ],
], ],
'palettes' => [ 'palettes' => [
@@ -130,6 +130,15 @@ return [
'eval' => 'double2,required', 'eval' => 'double2,required',
] ]
], ],
'price_chf' => [
'exclude' => false,
'label' => 'Preis pro Person/Nacht in CHF',
'config' => [
'type' => 'input',
'size' => 8,
'eval' => 'double2',
]
],
'sorting' => [ 'sorting' => [
'config' => [ 'config' => [
'type' => 'passthrough' 'type' => 'passthrough'
@@ -31,9 +31,10 @@ return [
'palettes' => [ 'palettes' => [
'dates' => ['showitem' => 'date_from, date_to'], 'dates' => ['showitem' => 'date_from, date_to'],
'included' => ['showitem' => 'bonus_card_included, persons_included'], 'included' => ['showitem' => 'bonus_card_included, persons_included'],
'prices' => ['showitem' => 'price, price_additional_person'], 'prices' => ['showitem' => 'price, price_chf, price_additional_person, price_additional_person_chf'],
'prices_groups' => ['showitem' => 'price_additional_person_group_1, price_additional_person_group_2, 'prices_groups' => ['showitem' => 'price_additional_person_group_1, price_additional_person_group_1_chf,
--linebreak--, price_additional_person_group_3'], --linebreak--, price_additional_person_group_2, price_additional_person_group_2_chf,
--linebreak--, price_additional_person_group_3, price_additional_person_group_3_chf'],
], ],
'columns' => [ 'columns' => [
@@ -156,6 +157,15 @@ return [
'eval' => 'double2,required', 'eval' => 'double2,required',
] ]
], ],
'price_chf' => [
'exclude' => false,
'label' => 'Preis pro Nacht in CHF',
'config' => [
'type' => 'input',
'size' => 8,
'eval' => 'double2',
]
],
'price_additional_person' => [ 'price_additional_person' => [
'exclude' => false, 'exclude' => false,
'label' => 'Preis weitere Person', 'label' => 'Preis weitere Person',
@@ -166,6 +176,16 @@ return [
'eval' => 'double2', 'eval' => 'double2',
] ]
], ],
'price_additional_person_chf' => [
'exclude' => false,
'label' => 'Preis weitere Person',
'description' => 'ohne Jokercard, alle Altersgruppen',
'config' => [
'type' => 'input',
'size' => 8,
'eval' => 'double2',
]
],
'price_additional_person_group_1' => [ 'price_additional_person_group_1' => [
'exclude' => false, 'exclude' => false,
'label' => 'Preis weitere Person', 'label' => 'Preis weitere Person',
@@ -176,6 +196,16 @@ return [
'eval' => 'double2', 'eval' => 'double2',
] ]
], ],
'price_additional_person_group_1_chf' => [
'exclude' => false,
'label' => 'Preis weitere Person in CHF',
'description' => 'mit Jokercard, 4-6 Jahre',
'config' => [
'type' => 'input',
'size' => 8,
'eval' => 'double2',
]
],
'price_additional_person_group_2' => [ 'price_additional_person_group_2' => [
'exclude' => false, 'exclude' => false,
'label' => 'Preis weitere Person', 'label' => 'Preis weitere Person',
@@ -186,6 +216,16 @@ return [
'eval' => 'double2', 'eval' => 'double2',
] ]
], ],
'price_additional_person_group_2_chf' => [
'exclude' => false,
'label' => 'Preis weitere Person in CHF',
'description' => 'mit Jokercard, 7-14 Jahre',
'config' => [
'type' => 'input',
'size' => 8,
'eval' => 'double2',
]
],
'price_additional_person_group_3' => [ 'price_additional_person_group_3' => [
'exclude' => false, 'exclude' => false,
'label' => 'Preis weitere Person', 'label' => 'Preis weitere Person',
@@ -196,6 +236,16 @@ return [
'eval' => 'double2', 'eval' => 'double2',
] ]
], ],
'price_additional_person_group_3_chf' => [
'exclude' => false,
'label' => 'Preis weitere Person',
'description' => 'mit Jokercard, ab 15 Jahre',
'config' => [
'type' => 'input',
'size' => 8,
'eval' => 'double2',
]
],
'bonus_card_included' => [ 'bonus_card_included' => [
'exclude' => 0, 'exclude' => 0,
'label' => 'Jokercard inklusive', 'label' => 'Jokercard inklusive',
@@ -29,7 +29,7 @@ return [
], ],
], ],
'palettes' => [ 'palettes' => [
'priceconfig' => ['showitem' => 'price, type, ignore_with_board'], 'priceconfig' => ['showitem' => 'price, price_chf, type, ignore_with_board'],
], ],
'columns' => [ 'columns' => [
@@ -131,6 +131,15 @@ return [
'eval' => 'double2,required', 'eval' => 'double2,required',
] ]
], ],
'price_chf' => [
'exclude' => false,
'label' => 'Preis in CHF',
'config' => [
'type' => 'input',
'size' => 8,
'eval' => 'double2',
]
],
'type' => [ 'type' => [
'exclude' => false, 'exclude' => false,
'label' => 'Typ', 'label' => 'Typ',
@@ -296,10 +296,15 @@ CREATE TABLE tx_epproducts_domain_model_groupspriceconfig
date_to int(11) unsigned DEFAULT '0' NOT NULL, date_to int(11) unsigned DEFAULT '0' NOT NULL,
persons_included int(11) unsigned DEFAULT '0' NOT NULL, persons_included int(11) unsigned DEFAULT '0' NOT NULL,
price float(8) unsigned DEFAULT '0' NOT NULL, price float(8) unsigned DEFAULT '0' NOT NULL,
price_chf float(8) unsigned DEFAULT '0' NOT NULL,
price_additional_person float(8) unsigned DEFAULT '0' NOT NULL, price_additional_person float(8) unsigned DEFAULT '0' NOT NULL,
price_additional_person_chf float(8) unsigned DEFAULT '0' NOT NULL,
price_additional_person_group_1 float(8) unsigned DEFAULT '0' NOT NULL, price_additional_person_group_1 float(8) unsigned DEFAULT '0' NOT NULL,
price_additional_person_group_1_chf float(8) unsigned DEFAULT '0' NOT NULL,
price_additional_person_group_2 float(8) unsigned DEFAULT '0' NOT NULL, price_additional_person_group_2 float(8) unsigned DEFAULT '0' NOT NULL,
price_additional_person_group_2_chf float(8) unsigned DEFAULT '0' NOT NULL,
price_additional_person_group_3 float(8) unsigned DEFAULT '0' NOT NULL, price_additional_person_group_3 float(8) unsigned DEFAULT '0' NOT NULL,
price_additional_person_group_3_chf float(8) unsigned DEFAULT '0' NOT NULL,
bonus_card_included tinyint(4) unsigned DEFAULT '0' NOT NULL, bonus_card_included tinyint(4) unsigned DEFAULT '0' NOT NULL,
hotel int(11) unsigned DEFAULT '0', hotel int(11) unsigned DEFAULT '0',
@@ -343,6 +348,7 @@ CREATE TABLE tx_epproducts_domain_model_groupspriceoption
title varchar(255) DEFAULT '' NOT NULL, title varchar(255) DEFAULT '' NOT NULL,
price float(8) unsigned DEFAULT '0' NOT NULL, price float(8) unsigned DEFAULT '0' NOT NULL,
price_chf float(8) unsigned DEFAULT '0' NOT NULL,
type tinyint(4) unsigned DEFAULT '0' NOT NULL, type tinyint(4) unsigned DEFAULT '0' NOT NULL,
ignore_with_board tinyint(4) unsigned DEFAULT '0' NOT NULL, ignore_with_board tinyint(4) unsigned DEFAULT '0' NOT NULL,
hotel int(11) unsigned DEFAULT '0', hotel int(11) unsigned DEFAULT '0',
@@ -388,6 +394,7 @@ CREATE TABLE tx_epproducts_domain_model_groupspriceboard
title varchar(255) DEFAULT '' NOT NULL, title varchar(255) DEFAULT '' NOT NULL,
price float(8) unsigned DEFAULT '0' NOT NULL, price float(8) unsigned DEFAULT '0' NOT NULL,
price_chf float(8) unsigned DEFAULT '0' NOT NULL,
hotel int(11) unsigned DEFAULT '0', hotel int(11) unsigned DEFAULT '0',
sorting int(11) DEFAULT '0' NOT NULL, sorting int(11) DEFAULT '0' NOT NULL,
@@ -103,12 +103,12 @@
<td>{{ formatCurrency(pricePax.base) }}</td> <td>{{ formatCurrency(pricePax.base) }}</td>
</tr> </tr>
<tr class="odd:bg-zinc-100" <tr class="odd:bg-zinc-100"
v-if="pricePax.additional > 0"> v-if="pricePax.additional.EUR > 0">
<th class="text-left py-2">Aufpreis Personenzahl</th> <th class="text-left py-2">Aufpreis Personenzahl</th>
<td>{{ formatCurrency(pricePax.additional) }}</td> <td>{{ formatCurrency(pricePax.additional) }}</td>
</tr> </tr>
<tr class="odd:bg-zinc-100" <tr class="odd:bg-zinc-100"
v-if="priceShortTerm > 0"> v-if="priceShortTerm.EUR > 0">
<th class="text-left py-2">Aufpreis Kurzzeit</th> <th class="text-left py-2">Aufpreis Kurzzeit</th>
<td>{{ formatCurrency(priceShortTerm) }}</td> <td>{{ formatCurrency(priceShortTerm) }}</td>
</tr> </tr>
@@ -127,17 +127,17 @@
<td>{{ formatCurrency(priceOptions) }}</td> <td>{{ formatCurrency(priceOptions) }}</td>
</tr> </tr>
<tr class="odd:bg-zinc-100" <tr class="odd:bg-zinc-100"
v-if="priceBoard > 0"> v-if="priceBoard.EUR > 0">
<th class="text-left py-2">Verpflegung</th> <th class="text-left py-2">Verpflegung</th>
<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 > 0"> v-if="pricePax.undersubscription.EUR > 0">
<th class="text-left py-2">Kleingruppen-Verpflegungszuschlag</th> <th class="text-left py-2">Kleingruppen-Verpflegungszuschlag</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"
v-if="priceRunningCosts > 0"> v-if="priceRunningCosts.EUR > 0">
<th class="text-left py-2">Strom- und Abfallgebühren</th> <th class="text-left py-2">Strom- und Abfallgebühren</th>
<td>{{ formatCurrency(priceRunningCosts) }}</td> <td>{{ formatCurrency(priceRunningCosts) }}</td>
</tr> </tr>
@@ -250,6 +250,10 @@
<div class="py-8 text-xl text-center font-bold" v-show="submitted"> <div class="py-8 text-xl text-center font-bold" v-show="submitted">
Vielen Dank für Deine {{ mode === 'booking' ? 'Buchung' : 'Anfrage' }}. Wir werden diese schnellstmöglich bearbeiten. Vielen Dank für Deine {{ mode === 'booking' ? 'Buchung' : 'Anfrage' }}. Wir werden diese schnellstmöglich bearbeiten.
</div> </div>
<div>
<img :src="logoAt" alt="" v-if="countryCode === 'AT'" class="block w-full h-auto max-w-24">
<img :src="logoCh" alt="" v-if="countryCode === 'CH'" class="block w-full h-auto max-w-24">
</div>
<div class="fixed top-0 left-0 inset-0 bg-white/85 flex items-center justify-center" v-show="processing"> <div class="fixed top-0 left-0 inset-0 bg-white/85 flex items-center justify-center" v-show="processing">
<img :src="loaderUri" alt="Loading..."> <img :src="loaderUri" alt="Loading...">
</div> </div>
@@ -274,6 +278,12 @@ export default {
type: String, type: String,
required: true required: true
}, },
logoAt: {
type: String,
},
logoCh: {
type: String,
},
configsJson: { configsJson: {
type: String, type: String,
required: true required: true
@@ -286,9 +296,25 @@ export default {
type: String, type: String,
required: true required: true
}, },
runningCostsFactor: { runningCostsFactorEur: {
type: Number, type: Number,
default: 1.7, default: 2.5,
},
runningCostsFactorChf: {
type: Number,
default: 2.9,
},
undersubscriptionEur: {
type: Number,
default: 5.0,
},
undersubscriptionChf: {
type: Number,
default: 5.0,
},
countryCode: {
type: String,
required: true
}, },
shortTermFactors: { shortTermFactors: {
type: Array, type: Array,
@@ -323,28 +349,33 @@ export default {
email: null, email: null,
phone: null, phone: null,
remarks: null, remarks: null,
group: null,
address: null,
mode: 'inquiry', mode: 'inquiry',
} }
}, },
methods: { methods: {
formatCurrency(value) { formatCurrency({ EUR, CHF }) {
if (0 === value) { let price = parseFloat(EUR).toFixed(2).replace(/\./, ',') + ' €'
return '-';
if ('CH' === this.countryCode && 0 < CHF) {
price += `/${parseFloat(CHF).toFixed(2).replace(/\./, ',')} CHF`
} }
return parseFloat(value).toFixed(2).replace(/\./, ',') + ' €';
return price
}, },
formatOptionPriceType(option) { formatOptionPriceType(option) {
if (2 === option.type) { if (2 === option.type) {
return ' (' + this.formatCurrency(option.price) + ' pro Person)'; return ` (${this.formatCurrency(option.price)} pro Person)`
} }
if (3 === option.type) { if (3 === option.type) {
return ' (' + this.formatCurrency(option.price) + ' pro Nacht)'; return ` (${this.formatCurrency(option.price)} pro Nacht)`
} }
if (4 === option.type) { if (4 === option.type) {
return ' (' + this.formatCurrency(option.price) + ' pro Person und Nacht)'; return ` (${this.formatCurrency(option.price)} pro Person und Nacht)`
} }
return ' (' + this.formatCurrency(option.price) + ')'; return ` (${this.formatCurrency(option.price)})`
}, },
initSelectableRanges() { initSelectableRanges() {
let enabledDates = []; let enabledDates = [];
@@ -425,7 +456,7 @@ export default {
.finally(() => { .finally(() => {
this.processing = false this.processing = false
}) })
} },
}, },
computed: { computed: {
nightsCount() { nightsCount() {
@@ -455,33 +486,47 @@ export default {
return included return included
}, },
pricePax() { pricePax() {
let base = 0 let base = {
let additional = 0 EUR: 0,
let undersubscription = 0 CHF: 0,
}
let additional = {
EUR: 0,
CHF: 0,
}
let undersubscription = {
EUR: 0,
CHF: 0,
}
for (let date of this.selectedRange) { for (let date of this.selectedRange) {
for (let config of this.configs) { for (let config of this.configs) {
if (date >= dayjs(config.dateFrom) && date < dayjs(config.dateTo)) { if (date >= dayjs(config.dateFrom) && date < dayjs(config.dateTo)) {
base += config.price base.EUR += config.price.EUR
base.CHF += config.price.CHF
if (this.totalPax > config.personsIncluded) { if (this.totalPax > config.personsIncluded) {
if (false === config.bonusCardIncluded) { if (false === config.bonusCardIncluded) {
additional += (this.selectedPax - config.personsIncluded) * config.priceAdditionalPerson; additional.EUR += (this.selectedPax - config.personsIncluded) * config.priceAdditionalPerson.EUR;
additional.CHF += (this.selectedPax - config.personsIncluded) * config.priceAdditionalPerson.CHF;
} else { } else {
// Distribute additional persons costs by group // Distribute additional persons costs by group
let included = config.personsIncluded let included = config.personsIncluded
if (this.selectedPaxGroup3 <= included) { if (this.selectedPaxGroup3 <= included) {
included -= this.selectedPaxGroup3 included -= this.selectedPaxGroup3
} else { } else {
additional += (this.selectedPaxGroup3 - included) * config.priceAdditionalPersonByGroup[3] additional.EUR += (this.selectedPaxGroup3 - included) * config.priceAdditionalPersonByGroup[3].EUR
additional.CHF += (this.selectedPaxGroup3 - included) * config.priceAdditionalPersonByGroup[3].EUR
included = 0 included = 0
} }
if (this.selectedPaxGroup2 <= included) { if (this.selectedPaxGroup2 <= included) {
included -= this.selectedPaxGroup2 included -= this.selectedPaxGroup2
} else { } else {
additional += (this.selectedPaxGroup2 - included) * config.priceAdditionalPersonByGroup[2] additional.EUR += (this.selectedPaxGroup2 - included) * config.priceAdditionalPersonByGroup[2].EUR
additional.CHF += (this.selectedPaxGroup2 - included) * config.priceAdditionalPersonByGroupCHF[2].CHF
included = 0 included = 0
} }
if (this.selectedPaxGroup1 > included) { if (this.selectedPaxGroup1 > included) {
additional += (this.selectedPaxGroup1 - included) * config.priceAdditionalPersonByGroup[1] additional.EUR += (this.selectedPaxGroup1 - included) * config.priceAdditionalPersonByGroup[1].EUR
additional.CHF += (this.selectedPaxGroup1 - included) * config.priceAdditionalPersonByGroupCHF[1].CHF
} }
} }
} }
@@ -489,66 +534,108 @@ export default {
} }
} }
if (this.selectedBoard && this.totalPax < 50) { if (this.selectedBoard && this.totalPax < 50) {
undersubscription = this.totalPax * 5 * this.selectedRange.length undersubscription.EUR = this.totalPax * this.undersubscriptionEur * this.selectedRange.length
undersubscription.CHF = this.totalPax * this.undersubscriptionChf * this.selectedRange.length
} }
return {base, additional, undersubscription};
return {base, additional, undersubscription}
}, },
totalPax() { totalPax() {
return this.includesBonusCard ? this.selectedPaxGroup1 + this.selectedPaxGroup2 + this.selectedPaxGroup3 : this.selectedPax return this.includesBonusCard ?
this.selectedPaxGroup1 + this.selectedPaxGroup2 + this.selectedPaxGroup3 : this.selectedPax
}, },
priceOptions() { priceOptions() {
let price = 0; let price = {
EUR: 0,
CHF: 0,
};
for (let option of this.selectedOptions) { for (let option of this.selectedOptions) {
let optionPriceEUR = option.price.EUR
let optionPriceCHF = option.price.CHF
if (true === option.ignoreWithBoard && this.selectedBoard) { if (true === option.ignoreWithBoard && this.selectedBoard) {
continue; optionPriceEUR = -optionPriceEUR
optionPriceCHF = -optionPriceCHF
} }
if (1 === option.type) { if (1 === option.type) {
price += option.price; price.EUR += optionPriceEUR;
price.CHF += optionPriceCHF;
} else if (2 === option.type) { } else if (2 === option.type) {
price += option.price * this.totalPax; price.EUR += optionPriceEUR * this.totalPax;
price.CHF += optionPriceCHF * this.totalPax;
} else if (3 === option.type) { } else if (3 === option.type) {
price += option.price * this.nightsCount; price.EUR += optionPriceEUR * this.nightsCount;
price.CHF += optionPriceCHF * this.nightsCount;
} else if (4 === option.type) { } else if (4 === option.type) {
price += option.price * this.nightsCount * this.totalPax; price.EUR += optionPriceEUR * this.nightsCount * this.totalPax;
price.CHF += optionPriceCHF * this.nightsCount * this.totalPax;
} }
} }
return price; return price;
}, },
priceBoard() { priceBoard() {
let price = 0; let price = {
if (this.selectedBoard) { EUR: 0,
price = this.selectedBoard.price * this.nightsCount * this.totalPax; CHF: 0,
} }
return price; if (this.selectedBoard) {
price.EUR = this.selectedBoard.price.EUR * this.nightsCount * this.totalPax;
price.CHF = this.selectedBoard.price.CHF * this.nightsCount * this.totalPax;
}
return price
}, },
priceShortTerm() { priceShortTerm() {
let price = 0; let price = {
const totalPricePax = this.pricePax.base + this.pricePax.additional; EUR: 0,
CHF: 0,
}
const totalPricePax = this.pricePax.base.EUR + this.pricePax.additional.EUR;
const totalPricePaxCHF = this.pricePax.base.CHF + this.pricePax.additional.CHF;
const shorTermFactor = this.shortTermFactors.find(element => element.nights === this.nightsCount); const shorTermFactor = this.shortTermFactors.find(element => element.nights === this.nightsCount);
if (undefined !== shorTermFactor) { if (undefined !== shorTermFactor) {
price = totalPricePax * shorTermFactor.factor; price.EUR = totalPricePax * shorTermFactor.factor;
price.CHF = totalPricePaxCHF * shorTermFactor.factor;
} }
return price; return price
}, },
priceRunningCosts() { priceRunningCosts() {
// if (this.selectedBoard) { let CHF = 0
// return 0;
// } // calculate CHF price when pax price in CHF is available since CHF prices may not be provided via CMS yet
return this.nightsCount * this.totalPax * this.runningCostsFactor; if (0 < this.pricePax.base.CHF) {
CHF = this.nightsCount * this.totalPax * this.runningCostsFactorChf
}
return {
EUR: this.nightsCount * this.totalPax * this.runningCostsFactorEur,
CHF
}
}, },
priceTotal() { priceTotal() {
return this.pricePax.base + this.pricePax.additional + this.pricePax.undersubscription + this.priceOptions let totalEUR = this.pricePax.base.EUR
+ this.priceBoard + this.priceShortTerm + this.priceRunningCosts; + this.pricePax.additional.EUR
}, + this.pricePax.undersubscription.EUR
priceSummary() { + this.priceOptions.EUR
+ this.priceBoard.EUR
+ this.priceShortTerm.EUR
+ this.priceRunningCosts.EUR
let totalCHF = 0
// calculate CHF price when pax price in CHF is available since CHF prices may not be provided via CMS yet
if (0 < this.pricePax.base.CHF) {
totalCHF = this.pricePax.base.CHF
+ this.pricePax.additional.CHF
+ this.pricePax.undersubscription.CHF
+ this.priceOptions.CHF
+ this.priceBoard.CHF
+ this.priceShortTerm.CHF
+ this.priceRunningCosts.CHF
}
return { return {
paxBase: this.formatCurrency(this.pricePax.base), EUR: totalEUR,
paxAdditional: this.formatCurrency(this.pricePax.additional), CHF: totalCHF,
shortTerm: this.formatCurrency(this.priceShortTerm),
options: this.formatCurrency(this.priceOptions),
board: this.formatCurrency(this.priceBoard),
runningCosts: this.formatCurrency(this.priceRunningCosts),
total: this.formatCurrency(this.priceTotal)
} }
} }
}, },
@@ -13,9 +13,15 @@
configs-json='{configs}' configs-json='{configs}'
boards-json='{boards}' boards-json='{boards}'
options-json='{options}' options-json='{options}'
running-costs-factor="{runningCosts}" running-costs-factor-eur="{runningCostsEUR}"
running-costs-factor-chf="{runningCostsCHF}"
undersubscription-eur="{undersubscriptionEUR}"
undersubscription-chf="{undersubscriptionCHF}"
country-code="{countryCode}"
endpoint="{ep:uri.ajax(action: 'processForm', controller: 'AjaxGroupsPrice', pageUid: settings.defaultAjaxUid, arguments: '{hotel: hotel}')}" endpoint="{ep:uri.ajax(action: 'processForm', controller: 'AjaxGroupsPrice', pageUid: settings.defaultAjaxUid, arguments: '{hotel: hotel}')}"
loader-uri="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/ajax-loader-white.gif')}" loader-uri="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/ajax-loader-white.gif')}"
logo-at="{f:uri.image(src: 'fileadmin/user_upload/Logos_Banner/Alpinevacation.jpg')}"
logo-ch="{f:uri.image(src: 'fileadmin/user_upload/Logos_Banner/Cllt_Touristik_frei_gestellt.jpg')}"
> >
</groups-price-calculator> </groups-price-calculator>
</f:format.raw> </f:format.raw>