> Map of room ID to participant IDs */ public function collectRoomMappings(BookingDto $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> Map of service ID to participant IDs */ public function collectServiceMappings(BookingDto $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> Map of transportation service ID to participant IDs */ public function collectTransportationMappings(BookingDto $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. * * Collects the unified pickup selection which applies to both directions. * The API receives this as outbound pickup data. * * @return array> Map of pickup ID to participant IDs */ public function collectPickupMappings(BookingDto $bookingDto): array { $pickupMap = []; foreach ($bookingDto->participants as $index => $participant) { $participantId = $index + 1; if (null !== $participant->pickup) { $pickupMap[$participant->pickup->id][] = $participantId; } } return $pickupMap; } /** * Collects insurance mappings. * * CRITICAL: Insurance data is only included in CREATE flow, not in UPDATE flow. * IMPORTANT: Excludes synthetic "no insurance" option from BPN transmission. * * @return array> Map of insurance ID to participant IDs */ public function collectInsuranceMappings(BookingDto $bookingDto): array { $insuranceMap = []; foreach ($bookingDto->participants as $index => $participant) { $participantId = $index + 1; // Exclude synthetic "keine Versicherung gewünscht" option from BPN XML if (null !== $participant->insurance && false === $participant->insurance->isNoInsurance()) { $insuranceMap[$participant->insurance->id][] = $participantId; } } return $insuranceMap; } /** * Collects all purchase vouchers from participants. * * Removes duplicates and empty values, returning unique redemption codes * for aggregation into the collection in the booking payload. * * IMPORTANT: Goodwill vouchers (Kulanz) are excluded from this collection. * They are added per participant as instead. * * @return string[] Array of unique redemption codes (excluding Kulanz) */ public function collectPurchaseVouchers(BookingDto $bookingDto): array { $vouchers = []; foreach ($bookingDto->participants as $participant) { if (null !== $participant->purchaseVoucherCode && '' !== trim($participant->purchaseVoucherCode)) { // Exclude goodwill vouchers if (false === $participant->hasGoodwillVoucher()) { $vouchers[] = trim($participant->purchaseVoucherCode); } } } // Remove duplicates (in case multiple participants enter same code) return array_unique($vouchers); } /** * Gets the aktionscode (promotional voucher code) for a participant. * * Returns the promotional voucher code if present. * Goodwill vouchers are handled separately via getGoodwillVoucherCodeForParticipant(). * * @return string|null The aktionscode to use, or null if none */ public function getPromoVoucherCodeForParticipant(ParticipantDto $participant): ?string { // Only return promotional voucher code (goodwill vouchers are handled separately) if (null !== $participant->promoVoucherCode && '' !== trim($participant->promoVoucherCode)) { return trim($participant->promoVoucherCode); } return null; } /** * Extracts goodwill voucher code for a participant. * * Goodwill vouchers are sent as per participant (not in aggregate), * allowing them to coexist with promotional codes. */ public function getGoodwillVoucherCodeForParticipant(ParticipantDto $participant): ?string { if ($participant->hasGoodwillVoucher() && null !== $participant->purchaseVoucherCode && '' !== trim($participant->purchaseVoucherCode)) { return trim($participant->purchaseVoucherCode); } return null; } }