feat: split booking between participants and applicant
addresses #869f2q1vu
This commit is contained in:
1 parent
2d49212b08
commit
1ff293f41f
44 files changed
+2024
-316
No files matched your search
@@ -254,7 +254,11 @@ class BookingPayloadBuilder
|
||||
*/
|
||||
public function buildCreatePayload(BookingDto $bookingDto, string $bookingType): array
|
||||
{
|
||||
$firstParticipant = $bookingDto->participants[0];
|
||||
// The applicant is participant[0] on an ordinary booking, and a person of their own
|
||||
// when they do not travel along.
|
||||
$applicantSource = $bookingDto->applicantTravels
|
||||
? $bookingDto->participants[0]
|
||||
: ($bookingDto->applicant ?? $bookingDto->participants[0]);
|
||||
|
||||
$payload = [
|
||||
'buchungsart' => $bookingType,
|
||||
@@ -264,36 +268,10 @@ class BookingPayloadBuilder
|
||||
'idagentur' => $bookingDto->agencyId,
|
||||
];
|
||||
|
||||
// Add applicant (first participant data)
|
||||
$payload['anmelder'] = [
|
||||
'name' => $firstParticipant->lastName,
|
||||
'vorname' => $firstParticipant->firstName,
|
||||
'geschlecht' => $firstParticipant->gender ?? '',
|
||||
'nationalitaet' => $firstParticipant->nationality ?? '',
|
||||
];
|
||||
|
||||
// DO NOT include personId or addressId in create mode
|
||||
// BPN will automatically match existing customers by exact personal data (name, DOB, address)
|
||||
// Including IDs would prevent automatic matching and could cause data inconsistencies
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
$payload['anmelder'] = $this->buildPersonalDataPayload($applicantSource);
|
||||
|
||||
// Determine if this is an inquiry booking for voucher handling
|
||||
$isInquiryBooking = 'A' === $bookingDto->bookingStatus;
|
||||
@@ -301,42 +279,13 @@ class BookingPayloadBuilder
|
||||
// Add participants
|
||||
$payload['teilnehmerliste']['teilnehmer'] = [];
|
||||
foreach ($bookingDto->participants as $index => $participant) {
|
||||
$participantData = [
|
||||
'@id' => $index + 1,
|
||||
'status' => self::DEFAULT_PARTICIPANT_STATUS,
|
||||
'name' => $participant->lastName,
|
||||
'vorname' => $participant->firstName,
|
||||
'geschlecht' => $participant->gender ?? '',
|
||||
'nationalitaet' => $participant->nationality ?? '',
|
||||
];
|
||||
|
||||
// DO NOT include personId or addressId in create mode
|
||||
// BPN will automatically match existing customers by exact personal data (name, DOB, address)
|
||||
// Including IDs would prevent automatic matching and could cause data inconsistencies
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
$participantData = [
|
||||
'@id' => $index + 1,
|
||||
'status' => self::DEFAULT_PARTICIPANT_STATUS,
|
||||
] + $this->buildPersonalDataPayload($participant, $applicantSource->email, true);
|
||||
|
||||
// Add body dimensions
|
||||
if (null !== $participant->height) {
|
||||
@@ -434,6 +383,61 @@ class BookingPayloadBuilder
|
||||
return $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps one person's personal data onto the payload shape shared by anmelder and teilnehmer.
|
||||
*
|
||||
* @param ParticipantDto $person The applicant or participant to map
|
||||
* @param string|null $fallbackEmail Used when the person has none of their own. BusPro
|
||||
* requires a Mail-Adresse for every participant once
|
||||
* a room is present and rejects the Anfrage with 650
|
||||
* otherwise, but accepts one shared with the Anmelder
|
||||
* @param bool $alwaysIncludeAddress Participants always carry the anschrift structure
|
||||
* even when empty; the anmelder only when set
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function buildPersonalDataPayload(ParticipantDto $person, ?string $fallbackEmail = null, bool $alwaysIncludeAddress = false): array
|
||||
{
|
||||
$data = [
|
||||
'name' => $person->lastName,
|
||||
'vorname' => $person->firstName,
|
||||
'geschlecht' => $person->gender ?? '',
|
||||
'nationalitaet' => $person->nationality ?? '',
|
||||
];
|
||||
|
||||
if (null !== $person->dateOfBirth) {
|
||||
$data['geburtsdatum'] = $person->dateOfBirth->format('d.m.Y');
|
||||
}
|
||||
|
||||
if (null !== $person->address) {
|
||||
$data['anschrift'] = $person->address->toPayload();
|
||||
} elseif ($alwaysIncludeAddress) {
|
||||
$data['anschrift'] = [
|
||||
'strasse' => null,
|
||||
'plz' => null,
|
||||
'ort' => null,
|
||||
'ortsteil' => null,
|
||||
'land' => null,
|
||||
];
|
||||
}
|
||||
|
||||
$email = null !== $person->email && '' !== trim($person->email)
|
||||
? $person->email
|
||||
: $fallbackEmail;
|
||||
|
||||
if (null !== $email || null !== $person->mobile) {
|
||||
$data['kommunikation'] = [];
|
||||
if (null !== $email) {
|
||||
$data['kommunikation']['email'] = $email;
|
||||
}
|
||||
if (null !== $person->mobile) {
|
||||
$data['kommunikation']['telefonmobil'] = $person->mobile;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds services from a mapping to the payload.
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user