wip: booking process, refactoring
This commit is contained in:
@@ -1,97 +1,236 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\BusProNet\DataProcessor;
|
||||
|
||||
use App\BusProNet\Model\Communication;
|
||||
use App\Form\Model\BookingEditDto;
|
||||
|
||||
/**
|
||||
* Processes booking form data and converts it into BusProNet API payload format.
|
||||
*
|
||||
* This processor handles the complex transformation of booking edit form data into the structured
|
||||
* array format required by the BusProNet API. It manages service mappings between participants
|
||||
* and various booking components like additional services, transportation, and accommodations.
|
||||
* The processor ensures data consistency by resetting and rebuilding participant-to-service
|
||||
* mappings based on form selections, while maintaining proper API payload structure.
|
||||
*/
|
||||
class BookingDataProcessor
|
||||
{
|
||||
/**
|
||||
* Creates an update request payload for the BusProNet API from booking form data.
|
||||
*
|
||||
* This method processes booking edit form data and transforms it into the structured array
|
||||
* format expected by the BusProNet XML API. It handles service mappings, participant data
|
||||
* updates, and generates the complete payload structure including booking metadata,
|
||||
* participant information, services, transportation, and accommodation details.
|
||||
*
|
||||
* The process involves:
|
||||
* - Resetting existing service-to-participant mappings
|
||||
* - Rebuilding mappings based on current form selections
|
||||
* - Adding new services from travel data when participants select them
|
||||
* - Removing services with no participant mappings
|
||||
* - Updating participant personal data from form input
|
||||
* - Synchronizing applicant data with first participant details
|
||||
* - Building the final API payload structure
|
||||
*
|
||||
* @param BookingEditDto|null $formData The booking edit form data containing updated participant and service selections
|
||||
*
|
||||
* @return array The structured payload array ready for BusProNet API submission
|
||||
*/
|
||||
public function createUpdateRequestPayload(?BookingEditDto $formData): array
|
||||
{
|
||||
$bookingData = $formData->booking;
|
||||
$travelData = $formData->travel;
|
||||
|
||||
// Reset mappings
|
||||
$this->resetServiceMappings($bookingData);
|
||||
|
||||
foreach ($formData->participants as $participant) {
|
||||
$this->processParticipantServices($participant, $bookingData, $travelData);
|
||||
}
|
||||
|
||||
$this->removeUnusedServices($bookingData);
|
||||
$this->updateParticipantPersonalData($formData->participants, $bookingData);
|
||||
$this->syncApplicantData($bookingData);
|
||||
|
||||
$payload = $this->buildBasePayload($bookingData);
|
||||
$this->addBankAccountToPayload($payload, $bookingData);
|
||||
$this->buildParticipantPayload($payload, $bookingData);
|
||||
$this->buildServicesPayload($payload, $bookingData);
|
||||
$this->buildPickupPayload($payload, $bookingData);
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all existing participant-to-service mappings to start with a clean slate.
|
||||
*
|
||||
* This ensures that service assignments are rebuilt from scratch based on current form selections.
|
||||
*
|
||||
* @param object $bookingData The booking data object containing services to reset
|
||||
*/
|
||||
private function resetServiceMappings(object $bookingData): void
|
||||
{
|
||||
$servicesToReset = [
|
||||
...$bookingData->additionalServices,
|
||||
...$bookingData->transportationServices,
|
||||
...$bookingData->pickupsTo,
|
||||
...$bookingData->pickupsFro,
|
||||
];
|
||||
|
||||
foreach ($servicesToReset as $service) {
|
||||
$service->mapping = [];
|
||||
}
|
||||
}
|
||||
|
||||
// Update mappings, add services and pickups
|
||||
foreach ($formData->participants as $participant) {
|
||||
// skip canceled participants
|
||||
if (true === $participant->isCanceled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$servicesToMap = [
|
||||
...$participant->courses,
|
||||
...$participant->additionalServices,
|
||||
...$participant->skiPass,
|
||||
...$participant->board,
|
||||
...$participant->rentals,
|
||||
];
|
||||
foreach ($servicesToMap as $service) {
|
||||
if (false === isset($this->additionalServices[$service->id])) {
|
||||
$serviceToAdd = $travelData->additionalServices[$service->id];
|
||||
if (null !== $serviceToAdd) {
|
||||
$bookingData->additionalServices[$service->id] = $serviceToAdd;
|
||||
$bookingData->additionalServices[$service->id]->individualPrice[$participant->index] = $serviceToAdd->price;
|
||||
}
|
||||
}
|
||||
$bookingData->additionalServices[$service->id]->mapping[] = $participant->index;
|
||||
}
|
||||
foreach ([$participant->transportationServiceTo, $participant->transportationServiceFro] as $service) {
|
||||
if (false === isset($this->transportationServices[$service->id])) {
|
||||
$serviceToAdd = $travelData->transportationServices[$service->id];
|
||||
if (null !== $serviceToAdd) {
|
||||
$bookingData->transportationServices[$service->id] = $serviceToAdd;
|
||||
$bookingData->transportationServices[$service->id]->individualPrice[$participant->index] = $serviceToAdd->price;
|
||||
}
|
||||
}
|
||||
$bookingData->transportationServices[$service->id]->mapping[] = $participant->index;
|
||||
}
|
||||
if ('BUS' === $participant->transportationServiceTo->subType && null !== $selectedPickup = $participant->pickup) {
|
||||
if (false === isset($bookingData->pickupsTo[$selectedPickup->id])) {
|
||||
$bookingData->pickupsTo[$selectedPickup->id] = $selectedPickup;
|
||||
}
|
||||
$bookingData->pickupsTo[$selectedPickup->id]->mapping[] = $participant->index;
|
||||
}
|
||||
/**
|
||||
* Processes all services for a single participant.
|
||||
*
|
||||
* This orchestrator method handles the complete service assignment workflow for one participant,
|
||||
* including additional services, transportation services, and pickup locations.
|
||||
*
|
||||
* @param object $participant The participant data from the form
|
||||
* @param object $bookingData The booking data object to update
|
||||
* @param object $travelData The travel data containing available services
|
||||
*/
|
||||
private function processParticipantServices(object $participant, object $bookingData, object $travelData): void
|
||||
{
|
||||
if (true === $participant->isCanceled()) {
|
||||
return;
|
||||
}
|
||||
// Remove services/pickups with empty mappings
|
||||
|
||||
$this->processAdditionalServices($participant, $bookingData, $travelData);
|
||||
$this->processTransportationServices($participant, $bookingData, $travelData);
|
||||
$this->processPickupLocations($participant, $bookingData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes additional services for a participant.
|
||||
*
|
||||
* Maps additional services (courses, ski passes, board options, rentals) to the participant.
|
||||
* Adds new services to the booking if they don't already exist and sets individual pricing.
|
||||
*
|
||||
* @param object $participant The participant data from the form
|
||||
* @param object $bookingData The booking data object to update
|
||||
* @param object $travelData The travel data containing available services
|
||||
*/
|
||||
private function processAdditionalServices(object $participant, object $bookingData, object $travelData): void
|
||||
{
|
||||
$servicesToMap = [
|
||||
...$participant->courses,
|
||||
...$participant->additionalServices,
|
||||
...$participant->skiPass,
|
||||
...$participant->board,
|
||||
...$participant->rentals,
|
||||
];
|
||||
|
||||
foreach ($servicesToMap as $service) {
|
||||
if (false === isset($bookingData->additionalServices[$service->id])) {
|
||||
$serviceToAdd = $travelData->additionalServices[$service->id] ?? null;
|
||||
if (null !== $serviceToAdd) {
|
||||
$bookingData->additionalServices[$service->id] = $serviceToAdd;
|
||||
$bookingData->additionalServices[$service->id]->individualPrice[$participant->index] = $serviceToAdd->price;
|
||||
}
|
||||
}
|
||||
$bookingData->additionalServices[$service->id]->mapping[] = $participant->index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes transportation services for a participant.
|
||||
*
|
||||
* Maps transportation services (both directions: to and from destination) to the participant.
|
||||
* Adds new transportation services to the booking if they don't already exist.
|
||||
*
|
||||
* @param object $participant The participant data from the form
|
||||
* @param object $bookingData The booking data object to update
|
||||
* @param object $travelData The travel data containing available services
|
||||
*/
|
||||
private function processTransportationServices(object $participant, object $bookingData, object $travelData): void
|
||||
{
|
||||
foreach ([$participant->transportationServiceTo, $participant->transportationServiceFro] as $service) {
|
||||
if (false === isset($bookingData->transportationServices[$service->id])) {
|
||||
$serviceToAdd = $travelData->transportationServices[$service->id] ?? null;
|
||||
if (null !== $serviceToAdd) {
|
||||
$bookingData->transportationServices[$service->id] = $serviceToAdd;
|
||||
$bookingData->transportationServices[$service->id]->individualPrice[$participant->index] = $serviceToAdd->price;
|
||||
}
|
||||
}
|
||||
$bookingData->transportationServices[$service->id]->mapping[] = $participant->index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes pickup locations for participants using bus transportation.
|
||||
*
|
||||
* Only processes pickup locations for bus transportation services and maps the participant
|
||||
* to their selected pickup location.
|
||||
*
|
||||
* @param object $participant The participant data from the form
|
||||
* @param object $bookingData The booking data object to update
|
||||
*/
|
||||
private function processPickupLocations(object $participant, object $bookingData): void
|
||||
{
|
||||
if ('BUS' === $participant->transportationServiceTo->subType && null !== $selectedPickup = $participant->pickup) {
|
||||
if (false === isset($bookingData->pickupsTo[$selectedPickup->id])) {
|
||||
$bookingData->pickupsTo[$selectedPickup->id] = $selectedPickup;
|
||||
}
|
||||
$bookingData->pickupsTo[$selectedPickup->id]->mapping[] = $participant->index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes services and pickups with no participant mappings.
|
||||
*
|
||||
* Cleans up unused services to prevent empty services from being sent to the API.
|
||||
* This includes additional services, transportation services, and pickup locations.
|
||||
*
|
||||
* @param object $bookingData The booking data object to clean up
|
||||
*/
|
||||
private function removeUnusedServices(object $bookingData): void
|
||||
{
|
||||
foreach ($bookingData->additionalServices as $service) {
|
||||
if (0 === count($service->mapping)) {
|
||||
unset($bookingData->additionalServices[$service->id]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($bookingData->transportationServices as $service) {
|
||||
if (0 === count($service->mapping)) {
|
||||
unset($bookingData->transportationServices[$service->id]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($bookingData->pickupsTo as $pickup) {
|
||||
if (0 === count($pickup->mapping)) {
|
||||
unset($bookingData->pickupsTo[$pickup->id]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($bookingData->pickupsFro as $pickup) {
|
||||
if (0 === count($pickup->mapping)) {
|
||||
unset($bookingData->pickupsFro[$pickup->id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update participants' personal data
|
||||
foreach ($formData->participants as $participant) {
|
||||
// skip canceled participants
|
||||
/**
|
||||
* Updates participant personal data from form input.
|
||||
*
|
||||
* Only processes participants with status 'F' (active/confirmed participants).
|
||||
* Updates all personal data fields and communication information.
|
||||
*
|
||||
* @param array $participants The participants array from the form
|
||||
* @param object $bookingData The booking data object to update
|
||||
*/
|
||||
private function updateParticipantPersonalData(array $participants, object $bookingData): void
|
||||
{
|
||||
foreach ($participants as $participant) {
|
||||
if ('F' !== $participant->status) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$bookingData->participants[$participant->index]->firstName = $participant->firstName;
|
||||
$bookingData->participants[$participant->index]->name = $participant->lastName;
|
||||
$bookingData->participants[$participant->index]->dateOfBirth = $participant->dateOfBirth;
|
||||
@@ -109,19 +248,40 @@ class BookingDataProcessor
|
||||
$bookingData->participants[$participant->index]->communication->mobile = $participant->mobile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update applicant's data with personal data of first participant
|
||||
/**
|
||||
* Synchronizes applicant data with first participant's physical characteristics.
|
||||
*
|
||||
* The applicant (booking holder) inherits physical data from the first participant.
|
||||
*
|
||||
* @param object $bookingData The booking data object to update
|
||||
*/
|
||||
private function syncApplicantData(object $bookingData): void
|
||||
{
|
||||
if (false !== $firstParticipant = reset($bookingData->participants)) {
|
||||
$bookingData->applicant->height = $firstParticipant->height;
|
||||
$bookingData->applicant->weight = $firstParticipant->weight;
|
||||
$bookingData->applicant->shoeSize = $firstParticipant->shoeSize;
|
||||
}
|
||||
}
|
||||
|
||||
$payload = [
|
||||
/**
|
||||
* Builds the base API payload structure with booking information.
|
||||
*
|
||||
* Creates the main structure that will be populated with detailed data sections.
|
||||
*
|
||||
* @param object $bookingData The booking data object
|
||||
*
|
||||
* @return array The base payload structure
|
||||
*/
|
||||
private function buildBasePayload(object $bookingData): array
|
||||
{
|
||||
return [
|
||||
'idbuchung' => $bookingData->id,
|
||||
'status' => $bookingData->status,
|
||||
'idagentur' => $bookingData->agencyId,
|
||||
'idreise' => $bookingData->travelId,
|
||||
'idreise' => $bookingData->dateId,
|
||||
'idpartner' => $bookingData->hotelId,
|
||||
'anmelder' => $bookingData->applicant->toPayload(),
|
||||
'zahlung' => [
|
||||
@@ -142,7 +302,18 @@ class BookingDataProcessor
|
||||
'ferienzielunterbringung' => [],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds bank account information to the payload if present.
|
||||
*
|
||||
* Bank account information is required for direct debit payments.
|
||||
*
|
||||
* @param array $payload The payload array to modify
|
||||
* @param object $bookingData The booking data object
|
||||
*/
|
||||
private function addBankAccountToPayload(array &$payload, object $bookingData): void
|
||||
{
|
||||
if (null !== $bookingData->bankAccount) {
|
||||
$payload['zahlung']['bankverbindung'] = [
|
||||
'@kreditinstitut' => $bookingData->bankAccount->bankName,
|
||||
@@ -151,7 +322,18 @@ class BookingDataProcessor
|
||||
'@kontoinhaber' => $bookingData->bankAccount->holder,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the participant list section of the payload.
|
||||
*
|
||||
* Includes status and personal data for each participant.
|
||||
*
|
||||
* @param array $payload The payload array to modify
|
||||
* @param object $bookingData The booking data object
|
||||
*/
|
||||
private function buildParticipantPayload(array &$payload, object $bookingData): void
|
||||
{
|
||||
foreach ($bookingData->participants as $index => $participant) {
|
||||
$payload['teilnehmerliste']['teilnehmer'][] = [
|
||||
'@id' => $index,
|
||||
@@ -159,7 +341,19 @@ class BookingDataProcessor
|
||||
...$participant->toPayload(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the services sections of the payload.
|
||||
*
|
||||
* Includes additional services, transportation services, and accommodation details
|
||||
* with participant mappings and quantities.
|
||||
*
|
||||
* @param array $payload The payload array to modify
|
||||
* @param object $bookingData The booking data object
|
||||
*/
|
||||
private function buildServicesPayload(array &$payload, object $bookingData): void
|
||||
{
|
||||
foreach ($bookingData->additionalServices as $service) {
|
||||
$payload['zusatzleistungen']['zusatzleistung'][] = [
|
||||
'@idleistung' => $service->id,
|
||||
@@ -187,7 +381,18 @@ class BookingDataProcessor
|
||||
'@zuordnung' => implode(',', $room->mapping),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the pickup locations section of the payload.
|
||||
*
|
||||
* Only included in payload if there are actual pickup assignments for bus transportation.
|
||||
*
|
||||
* @param array $payload The payload array to modify
|
||||
* @param object $bookingData The booking data object
|
||||
*/
|
||||
private function buildPickupPayload(array &$payload, object $bookingData): void
|
||||
{
|
||||
if (0 < count($bookingData->pickupsTo)) {
|
||||
$payload['zustiege']['zustieg'] = [];
|
||||
foreach ($bookingData->pickupsTo as $pickup) {
|
||||
@@ -198,7 +403,5 @@ class BookingDataProcessor
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user