feat: additional currency CHF in price calculator for Swiss hotels

closes #8697b8j20
This commit is contained in:
Björn Fromme
2025-02-12 09:24:42 +01:00
parent f5ef4168d5
commit 1bd61e8807
11 changed files with 457 additions and 109 deletions
@@ -103,12 +103,12 @@
<td>{{ formatCurrency(pricePax.base) }}</td>
</tr>
<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>
<td>{{ formatCurrency(pricePax.additional) }}</td>
</tr>
<tr class="odd:bg-zinc-100"
v-if="priceShortTerm > 0">
v-if="priceShortTerm.EUR > 0">
<th class="text-left py-2">Aufpreis Kurzzeit</th>
<td>{{ formatCurrency(priceShortTerm) }}</td>
</tr>
@@ -127,17 +127,17 @@
<td>{{ formatCurrency(priceOptions) }}</td>
</tr>
<tr class="odd:bg-zinc-100"
v-if="priceBoard > 0">
v-if="priceBoard.EUR > 0">
<th class="text-left py-2">Verpflegung</th>
<td>{{ formatCurrency(priceBoard) }}</td>
</tr>
<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>
<td>{{ formatCurrency(pricePax.undersubscription) }}</td>
</tr>
<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>
<td>{{ formatCurrency(priceRunningCosts) }}</td>
</tr>
@@ -286,9 +286,25 @@ export default {
type: String,
required: true
},
runningCostsFactor: {
runningCostsFactorEur: {
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: {
type: Array,
@@ -323,28 +339,33 @@ export default {
email: null,
phone: null,
remarks: null,
group: null,
address: null,
mode: 'inquiry',
}
},
methods: {
formatCurrency(value) {
if (0 === value) {
return '-';
formatCurrency({ EUR, CHF }) {
let price = parseFloat(EUR).toFixed(2).replace(/\./, ',') + ' €'
if ('CH' === this.countryCode && null !== CHF) {
price += `/${parseFloat(CHF).toFixed(2).replace(/\./, ',')} CHF`
}
return parseFloat(value).toFixed(2).replace(/\./, ',') + ' €';
return price
},
formatOptionPriceType(option) {
if (2 === option.type) {
return ' (' + this.formatCurrency(option.price) + ' pro Person)';
return ` (${this.formatCurrency(option.price)} pro Person)`
}
if (3 === option.type) {
return ' (' + this.formatCurrency(option.price) + ' pro Nacht)';
return ` (${this.formatCurrency(option.price)} pro Nacht)`
}
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() {
let enabledDates = [];
@@ -425,7 +446,7 @@ export default {
.finally(() => {
this.processing = false
})
}
},
},
computed: {
nightsCount() {
@@ -455,33 +476,47 @@ export default {
return included
},
pricePax() {
let base = 0
let additional = 0
let undersubscription = 0
let base = {
EUR: 0,
CHF: 0,
}
let additional = {
EUR: 0,
CHF: 0,
}
let undersubscription = {
EUR: 0,
CHF: 0,
}
for (let date of this.selectedRange) {
for (let config of this.configs) {
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 (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 {
// Distribute additional persons costs by group
let included = config.personsIncluded
if (this.selectedPaxGroup3 <= included) {
included -= this.selectedPaxGroup3
} 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
}
if (this.selectedPaxGroup2 <= included) {
included -= this.selectedPaxGroup2
} 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
}
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 +524,95 @@ export default {
}
}
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() {
return this.includesBonusCard ? this.selectedPaxGroup1 + this.selectedPaxGroup2 + this.selectedPaxGroup3 : this.selectedPax
return this.includesBonusCard ?
this.selectedPaxGroup1 + this.selectedPaxGroup2 + this.selectedPaxGroup3 : this.selectedPax
},
priceOptions() {
let price = 0;
let price = {
EUR: 0,
CHF: 0,
};
for (let option of this.selectedOptions) {
let optionPriceEUR = option.price.EUR
let optionPriceCHF = option.price.CHF
if (true === option.ignoreWithBoard && this.selectedBoard) {
continue;
optionPriceEUR = -optionPriceEUR
optionPriceCHF = -optionPriceCHF
}
if (1 === option.type) {
price += option.price;
price.EUR += optionPriceEUR;
price.CHF += optionPriceCHF;
} 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) {
price += option.price * this.nightsCount;
price.EUR += optionPriceEUR * this.nightsCount;
price.CHF += optionPriceCHF * this.nightsCount;
} 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;
},
priceBoard() {
let price = 0;
if (this.selectedBoard) {
price = this.selectedBoard.price * this.nightsCount * this.totalPax;
let price = {
EUR: 0,
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() {
let price = 0;
const totalPricePax = this.pricePax.base + this.pricePax.additional;
let price = {
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);
if (undefined !== shorTermFactor) {
price = totalPricePax * shorTermFactor.factor;
price.EUR = totalPricePax * shorTermFactor.factor;
price.CHF = totalPricePaxCHF * shorTermFactor.factor;
}
return price;
return price
},
priceRunningCosts() {
// if (this.selectedBoard) {
// return 0;
// }
return this.nightsCount * this.totalPax * this.runningCostsFactor;
return {
EUR: this.nightsCount * this.totalPax * this.runningCostsFactorEur,
CHF: this.nightsCount * this.totalPax * this.runningCostsFactorChf
}
},
priceTotal() {
return this.pricePax.base + this.pricePax.additional + this.pricePax.undersubscription + this.priceOptions
+ this.priceBoard + this.priceShortTerm + this.priceRunningCosts;
},
priceSummary() {
let totalEUR = this.pricePax.base.EUR
+ this.pricePax.additional.EUR
+ this.pricePax.undersubscription.EUR
+ this.priceOptions.EUR
+ this.priceBoard.EUR
+ this.priceShortTerm.EUR
+ this.priceRunningCosts.EUR
let 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 {
paxBase: this.formatCurrency(this.pricePax.base),
paxAdditional: this.formatCurrency(this.pricePax.additional),
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)
EUR: totalEUR,
CHF: totalCHF,
}
}
},
@@ -13,7 +13,11 @@
configs-json='{configs}'
boards-json='{boards}'
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}')}"
loader-uri="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/ajax-loader-white.gif')}"
>