wip: submit booking to api
This commit is contained in:
@@ -4,7 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\BusProNet\DataProcessor;
|
||||
|
||||
use App\BusProNet\Constants;
|
||||
use App\BusProNet\Model\Communication;
|
||||
use App\Form\Model\BookingCreateDto;
|
||||
use App\Form\Model\BookingEditDto;
|
||||
|
||||
/**
|
||||
@@ -408,4 +410,365 @@ class BookingDataProcessor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a booking request payload for new bookings (inquiry or final booking).
|
||||
*
|
||||
* Generates the array payload structure for creating new bookings through the BusProNet API.
|
||||
* This includes all participant data, room selections, services (including insurance), and
|
||||
* payment information. The booking type determines whether this is an inquiry validation
|
||||
* ('Anfrage') or a final booking commit ('Buchung').
|
||||
*
|
||||
* @param BookingCreateDto $bookingDto The booking creation form data
|
||||
* @param string $bookingType Either 'Anfrage' (inquiry) or 'Buchung' (final booking)
|
||||
*
|
||||
* @return array The structured payload array for BusProNet API submission
|
||||
*/
|
||||
public function createBookingRequestPayload(BookingCreateDto $bookingDto, string $bookingType): array
|
||||
{
|
||||
$firstParticipant = $bookingDto->participants[0];
|
||||
|
||||
$payload = [
|
||||
'buchungsart' => $bookingType,
|
||||
'status' => 'F',
|
||||
'idreise' => $bookingDto->travel->id,
|
||||
'idpartner' => $bookingDto->travel->hotelId,
|
||||
'idagentur' => $bookingDto->agencyId,
|
||||
];
|
||||
|
||||
// Add applicant (first participant data)
|
||||
$payload['anmelder'] = [
|
||||
'name' => $firstParticipant->lastName,
|
||||
'vorname' => $firstParticipant->firstName,
|
||||
'geschlecht' => $firstParticipant->gender ?? '',
|
||||
'nationalitaet' => $firstParticipant->nationality ?? '',
|
||||
];
|
||||
|
||||
if (null !== $firstParticipant->dateOfBirth) {
|
||||
$payload['anmelder']['geburtsdatum'] = $firstParticipant->dateOfBirth->format('d.m.Y');
|
||||
}
|
||||
|
||||
// Add address for applicant
|
||||
if (null !== $firstParticipant->address) {
|
||||
$payload['anmelder']['anschrift'] = $firstParticipant->address->toPayload();
|
||||
}
|
||||
|
||||
if (null !== $firstParticipant->email || null !== $firstParticipant->mobile) {
|
||||
$payload['anmelder']['kommunikation'] = [];
|
||||
if (null !== $firstParticipant->email) {
|
||||
$payload['anmelder']['kommunikation']['email'] = $firstParticipant->email;
|
||||
}
|
||||
if (null !== $firstParticipant->mobile) {
|
||||
$payload['anmelder']['kommunikation']['telefonmobil'] = $firstParticipant->mobile;
|
||||
}
|
||||
}
|
||||
|
||||
// Add participants
|
||||
$payload['teilnehmerliste']['teilnehmer'] = [];
|
||||
foreach ($bookingDto->participants as $index => $participant) {
|
||||
$participantData = [
|
||||
'@id' => $index + 1,
|
||||
'name' => $participant->lastName,
|
||||
'vorname' => $participant->firstName,
|
||||
'geschlecht' => $participant->gender ?? '',
|
||||
'nationalitaet' => $participant->nationality ?? '',
|
||||
];
|
||||
|
||||
if (null !== $participant->dateOfBirth) {
|
||||
$participantData['geburtsdatum'] = $participant->dateOfBirth->format('d.m.Y');
|
||||
}
|
||||
|
||||
// Add address (always include structure, even if empty)
|
||||
$participantData['anschrift'] = $participant->address?->toPayload() ?? [
|
||||
'strasse' => null,
|
||||
'plz' => null,
|
||||
'ort' => null,
|
||||
'ortsteil' => null,
|
||||
'land' => null,
|
||||
];
|
||||
|
||||
// Add contact info for all participants
|
||||
if (null !== $participant->email || null !== $participant->mobile) {
|
||||
$participantData['kommunikation'] = [];
|
||||
if (null !== $participant->email) {
|
||||
$participantData['kommunikation']['email'] = $participant->email;
|
||||
}
|
||||
if (null !== $participant->mobile) {
|
||||
$participantData['kommunikation']['telefonmobil'] = $participant->mobile;
|
||||
}
|
||||
}
|
||||
|
||||
// Add wishes (room remarks and license plate)
|
||||
if (null !== $participant->remarksRoom || null !== $participant->licensePlate) {
|
||||
$participantData['wünsche'] = [];
|
||||
if (null !== $participant->remarksRoom && '' !== trim($participant->remarksRoom)) {
|
||||
$participantData['wünsche']['unterbringungswunsch'] = $participant->remarksRoom;
|
||||
}
|
||||
if (null !== $participant->licensePlate && '' !== trim($participant->licensePlate)) {
|
||||
$participantData['wünsche']['beförderungswunsch'] = $participant->licensePlate;
|
||||
}
|
||||
}
|
||||
|
||||
$payload['teilnehmerliste']['teilnehmer'][] = $participantData;
|
||||
}
|
||||
|
||||
// Collect and group all services by ID with participant mappings
|
||||
$serviceMap = $this->collectServiceMappings($bookingDto);
|
||||
$transportationMap = $this->collectTransportationMappings($bookingDto);
|
||||
$roomMap = $this->collectRoomMappings($bookingDto);
|
||||
$pickupMap = $this->collectPickupMappings($bookingDto);
|
||||
$insuranceMap = $this->collectInsuranceMappings($bookingDto);
|
||||
|
||||
// Add services using reusable helper methods
|
||||
$this->addServicesFromMap($payload, 'beförderungen', 'beförderung', '@idleistung', $transportationMap);
|
||||
$this->addRoomMappingsToPayload($payload, $roomMap, $bookingDto);
|
||||
$this->addServicesFromMap($payload, 'zusatzleistungen', 'zusatzleistung', '@idleistung', $serviceMap);
|
||||
$this->addServicesFromMap($payload, 'zustiege', 'zustieg', '@idzustieg', $pickupMap);
|
||||
$this->addServicesFromMap($payload, 'versicherungen', 'versicherung', '@idversicherung', $insuranceMap);
|
||||
|
||||
// Add payment information
|
||||
$payload['zahlung'] = [
|
||||
'@idzahlungsart' => Constants::PAYMENT_METHOD_DEBIT === $bookingDto->paymentMethod
|
||||
? Constants::PAYMENT_TYPE_ID_DEBIT
|
||||
: Constants::PAYMENT_TYPE_ID_TRANSFER,
|
||||
'@art' => Constants::PAYMENT_METHOD_DEBIT === $bookingDto->paymentMethod ? 'EINZUG' : 'UEBERWEISUNG',
|
||||
];
|
||||
|
||||
if (Constants::PAYMENT_METHOD_DEBIT === $bookingDto->paymentMethod && null !== $bookingDto->bankAccount) {
|
||||
$payload['zahlung']['bankverbindung'] = [
|
||||
'@iban' => $bookingDto->bankAccount->iban,
|
||||
'@kontoinhaber' => $bookingDto->bankAccount->accountHolder,
|
||||
];
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds services from a mapping to the payload.
|
||||
*
|
||||
* Generic helper method that converts service ID => participant IDs mappings
|
||||
* into XML payload structure.
|
||||
*
|
||||
* @param array $payload The payload array to modify
|
||||
* @param string $sectionKey The section key (e.g., 'beförderungen', 'versicherungen')
|
||||
* @param string $itemKey The item key (e.g., 'beförderung', 'versicherung')
|
||||
* @param string $idAttributeName The ID attribute name (e.g., '@idleistung', '@idversicherung')
|
||||
* @param array $serviceMap Map of service ID to participant IDs
|
||||
*/
|
||||
private function addServicesFromMap(
|
||||
array &$payload,
|
||||
string $sectionKey,
|
||||
string $itemKey,
|
||||
string $idAttributeName,
|
||||
array $serviceMap,
|
||||
): void {
|
||||
if (false === empty($serviceMap)) {
|
||||
$payload[$sectionKey][$itemKey] = [];
|
||||
foreach ($serviceMap as $serviceId => $participantIds) {
|
||||
$payload[$sectionKey][$itemKey][] = [
|
||||
$idAttributeName => $serviceId,
|
||||
'@anzahl' => count($participantIds),
|
||||
'@zuordnung' => implode(',', $participantIds),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds room mappings with detailed attributes to the payload.
|
||||
*
|
||||
* Rooms require special attributes beyond simple service mapping:
|
||||
* - kategorie (room category code)
|
||||
* - idverpflegung (board type ID)
|
||||
* - anreise (arrival date)
|
||||
* - abreise (departure date)
|
||||
* - anzahl (number of rooms of this type booked)
|
||||
*
|
||||
* @param array $payload The payload array to modify
|
||||
* @param array $roomMap Map of room ID to participant IDs
|
||||
* @param BookingCreateDto $bookingDto The booking data for accessing room details and quantities
|
||||
*/
|
||||
private function addRoomMappingsToPayload(array &$payload, array $roomMap, BookingCreateDto $bookingDto): void
|
||||
{
|
||||
if (empty($roomMap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$availableRooms = $bookingDto->travel->getAvailableRooms();
|
||||
$payload['ferienzielunterbringungen']['ferienzielunterbringung'] = [];
|
||||
|
||||
// Build room selection quantity lookup
|
||||
$roomQuantities = [];
|
||||
foreach ($bookingDto->roomSelections as $selection) {
|
||||
if ($selection->quantity > 0) {
|
||||
$roomQuantities[$selection->roomId] = $selection->quantity;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($roomMap as $roomId => $participantIds) {
|
||||
$room = $availableRooms[$roomId] ?? null;
|
||||
if (null === $room) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$quantity = $roomQuantities[$roomId] ?? 1;
|
||||
|
||||
$payload['ferienzielunterbringungen']['ferienzielunterbringung'][] = [
|
||||
'@idzimmer' => $room->id,
|
||||
'@kategorie' => $room->category,
|
||||
'@idverpflegung' => $room->boardId,
|
||||
'@anreise' => $bookingDto->travel->dateFrom->format('d.m.Y'),
|
||||
'@abreise' => $bookingDto->travel->dateTo->format('d.m.Y'),
|
||||
'@anzahl' => $quantity,
|
||||
'@zuordnung' => implode(',', $participantIds),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects room mappings.
|
||||
*
|
||||
* Groups participants by their assigned room ID.
|
||||
*
|
||||
* @return array<string, array<int>> Map of room ID to participant IDs
|
||||
*/
|
||||
private function collectRoomMappings(BookingCreateDto $bookingDto): array
|
||||
{
|
||||
$roomMap = [];
|
||||
|
||||
foreach ($bookingDto->participants as $index => $participant) {
|
||||
$participantId = $index + 1;
|
||||
|
||||
if (null !== $participant->assignedRoomId) {
|
||||
$roomMap[$participant->assignedRoomId][] = $participantId;
|
||||
}
|
||||
}
|
||||
|
||||
return $roomMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects service mappings for the booking request.
|
||||
*
|
||||
* Groups board, ski passes, rentals, rental insurance, courses, parking, and additional services
|
||||
* by service ID with their participant assignments (1-based).
|
||||
*
|
||||
* @return array<string, array<int>> Map of service ID to participant IDs
|
||||
*/
|
||||
private function collectServiceMappings(BookingCreateDto $bookingDto): array
|
||||
{
|
||||
$serviceMap = [];
|
||||
|
||||
foreach ($bookingDto->participants as $index => $participant) {
|
||||
$participantId = $index + 1;
|
||||
|
||||
// Board services
|
||||
foreach ($participant->board as $board) {
|
||||
$serviceMap[$board->id][] = $participantId;
|
||||
}
|
||||
|
||||
// Ski pass
|
||||
if (null !== $participant->skiPass) {
|
||||
$serviceMap[$participant->skiPass->id][] = $participantId;
|
||||
}
|
||||
|
||||
// Rentals
|
||||
foreach ($participant->rentals as $rental) {
|
||||
$serviceMap[$rental->id][] = $participantId;
|
||||
}
|
||||
|
||||
// Rental insurance
|
||||
if (null !== $participant->rentalInsurance) {
|
||||
$serviceMap[$participant->rentalInsurance->id][] = $participantId;
|
||||
}
|
||||
|
||||
// Courses
|
||||
foreach ($participant->courses as $course) {
|
||||
$serviceMap[$course->id][] = $participantId;
|
||||
}
|
||||
|
||||
// Parking service (for self-organized transportation)
|
||||
if (true === $participant->parking && null !== $participant->parkingService) {
|
||||
$serviceMap[$participant->parkingService->id][] = $participantId;
|
||||
}
|
||||
|
||||
// Additional services
|
||||
foreach ($participant->additionalServices as $service) {
|
||||
$serviceMap[$service->id][] = $participantId;
|
||||
}
|
||||
}
|
||||
|
||||
return $serviceMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects transportation service mappings.
|
||||
*
|
||||
* @return array<string, array<int>> Map of transportation service ID to participant IDs
|
||||
*/
|
||||
private function collectTransportationMappings(BookingCreateDto $bookingDto): array
|
||||
{
|
||||
$transportationMap = [];
|
||||
|
||||
foreach ($bookingDto->participants as $index => $participant) {
|
||||
$participantId = $index + 1;
|
||||
|
||||
if (null !== $participant->transportationOutbound) {
|
||||
$transportationMap[$participant->transportationOutbound->id][] = $participantId;
|
||||
}
|
||||
|
||||
if (null !== $participant->transportationInbound) {
|
||||
$transportationMap[$participant->transportationInbound->id][] = $participantId;
|
||||
}
|
||||
}
|
||||
|
||||
return $transportationMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects pickup location mappings.
|
||||
*
|
||||
* Only collects outbound pickups as the API doesn't support different pickups
|
||||
* for inbound direction. Both directions use the same pickup location.
|
||||
*
|
||||
* @return array<string, array<int>> Map of pickup ID to participant IDs
|
||||
*/
|
||||
private function collectPickupMappings(BookingCreateDto $bookingDto): array
|
||||
{
|
||||
$pickupMap = [];
|
||||
|
||||
foreach ($bookingDto->participants as $index => $participant) {
|
||||
$participantId = $index + 1;
|
||||
|
||||
// Only use outbound pickups (inbound uses same location)
|
||||
if (null !== $participant->pickupOutbound) {
|
||||
$pickupMap[$participant->pickupOutbound->id][] = $participantId;
|
||||
}
|
||||
}
|
||||
|
||||
return $pickupMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects insurance mappings.
|
||||
*
|
||||
* CRITICAL: Insurance data is only included in CREATE flow, not in UPDATE flow.
|
||||
*
|
||||
* @return array<string, array<int>> Map of insurance ID to participant IDs
|
||||
*/
|
||||
private function collectInsuranceMappings(BookingCreateDto $bookingDto): array
|
||||
{
|
||||
$insuranceMap = [];
|
||||
|
||||
foreach ($bookingDto->participants as $index => $participant) {
|
||||
$participantId = $index + 1;
|
||||
|
||||
if (null !== $participant->insurance) {
|
||||
$insuranceMap[$participant->insurance->id][] = $participantId;
|
||||
}
|
||||
}
|
||||
|
||||
return $insuranceMap;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user