feat: various adjustments in price calculator

addresses #8697b8j0m
This commit is contained in:
Björn Fromme
2025-05-15 15:28:49 +02:00
parent 8f846c4401
commit d42bf45a70
11 changed files with 157 additions and 31 deletions
@@ -101,12 +101,15 @@ 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(),
'options' => $selectedOptions, 'options' => $selectedOptions,
'board' => $groupsPriceInquiry->getBoard(), 'board' => $groupsPriceInquiry->getBoard(),
@@ -124,8 +127,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 = [];
@@ -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
*/ */
@@ -109,6 +126,7 @@ class GroupsPriceInquiry
/** /**
* @var GroupsPriceBoard * @var GroupsPriceBoard
* @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
*/ */
protected $board; protected $board;
@@ -191,21 +209,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 +336,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
*/ */
@@ -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' => [
@@ -658,6 +658,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' => [
@@ -68,18 +68,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 +131,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"
@@ -180,17 +183,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 +263,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
@@ -389,9 +413,16 @@ export default {
phone: null, phone: null,
remarks: null, remarks: null,
group: null, group: null,
address: null, street: null,
postcode: null,
city: null,
mode: 'booking', mode: 'booking',
confirmation: false, confirmation: false,
termsUrls: {
AT: 'https://www.ep-reisen.de/fileadmin/form_definitions/AGB_Gruppen/AGB_Gruppen_CLLT_Touristik_GmbH.pdf',
CH: 'https://www.ep-reisen.de/fileadmin/form_definitions/AGB_Gruppen/AVB_Gruppen_AlpineVacation_GmbH.pdf',
IT: 'https://www.ep-reisen.de/fileadmin/form_definitions/AGB_Gruppen/AGB_Gruppen_E_P_Reisen.pdf',
}
} }
}, },
methods: { methods: {
@@ -487,12 +518,15 @@ 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][summary][paxBase]': this.formatCurrency(this.pricePax.base), 'tx_epproducts_ajax[groupsPriceInquiry][summary][paxBase]': this.formatCurrency(this.pricePax.base),
@@ -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>
@@ -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>
@@ -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>
@@ -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>
@@ -100,7 +112,7 @@
</tr> </tr>
<tr> <tr>
<th>Bemerkungen/Wünsche</th> <th>Bemerkungen/Wünsche</th>
<td>{remarks -> f:format.nl2br()}</td> <td>{remarks -> v:or(alternative: '-') -> f:format.nl2br()}</td>
</tr> </tr>
</table> </table>
</f:section> </f:section>
@@ -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">