createMock(InsuranceMatchingService::class); $this->processor = new BookingDataProcessor($insuranceMatchingService); } public function testCreateUpdateRequestPayloadWithCompleteData(): void { $formData = $this->createCompleteFormData(); $result = $this->processor->createUpdateRequestPayload($formData); $this->assertIsArray($result); $this->assertArrayHasKey('idbuchung', $result); $this->assertArrayHasKey('teilnehmerliste', $result); $this->assertArrayHasKey('zusatzleistungen', $result); $this->assertArrayHasKey('beförderungen', $result); $this->assertArrayHasKey('ferienzielunterbringungen', $result); $this->assertEquals(123, $result['idbuchung']); $this->assertEquals('ACTIVE', $result['status']); $this->assertCount(2, $result['teilnehmerliste']['teilnehmer']); } public function testCanceledParticipantsAreSkipped(): void { $formData = $this->createFormDataWithCanceledParticipant(); $result = $this->processor->createUpdateRequestPayload($formData); $this->assertCount(2, $result['teilnehmerliste']['teilnehmer']); $this->assertEquals(1, $result['teilnehmerliste']['teilnehmer'][0]['@id']); $this->assertEquals(2, $result['teilnehmerliste']['teilnehmer'][1]['@id']); } public function testAdditionalServicesProcessing(): void { $formData = $this->createFormDataWithAdditionalServices(); $result = $this->processor->createUpdateRequestPayload($formData); $this->assertNotEmpty($result['zusatzleistungen']['zusatzleistung']); $this->assertCount(2, $result['zusatzleistungen']['zusatzleistung']); $service = $result['zusatzleistungen']['zusatzleistung'][0]; $this->assertEquals(1, $service['@idleistung']); $this->assertEquals(1, $service['@anzahl']); $this->assertEquals('1', $service['@zuordnung']); } public function testTransportationServicesProcessing(): void { $formData = $this->createFormDataWithTransportation(); $result = $this->processor->createUpdateRequestPayload($formData); $this->assertNotEmpty($result['beförderungen']['beförderung']); $this->assertCount(2, $result['beförderungen']['beförderung']); } public function testBusPickupLocationsProcessing(): void { $formData = $this->createFormDataWithBusPickup(); $result = $this->processor->createUpdateRequestPayload($formData); $this->assertArrayHasKey('zustiege', $result); $this->assertNotEmpty($result['zustiege']['zustieg']); $this->assertEquals(1, $result['zustiege']['zustieg'][0]['@idzustieg']); } public function testNonBusTransportationSkipsPickup(): void { $formData = $this->createFormDataWithNonBusTransportation(); $result = $this->processor->createUpdateRequestPayload($formData); $this->assertArrayNotHasKey('zustiege', $result); } public function testUnusedServicesAreRemoved(): void { $formData = $this->createFormDataWithUnusedServices(); $result = $this->processor->createUpdateRequestPayload($formData); $this->assertEmpty($result['zusatzleistungen']['zusatzleistung']); $this->assertEmpty($result['beförderungen']['beförderung']); } public function testParticipantPersonalDataUpdate(): void { $formData = $this->createFormDataWithUpdatedPersonalData(); $this->processor->createUpdateRequestPayload($formData); $participant = $formData->booking->participants[0]; $this->assertEquals('Updated', $participant->firstName); $this->assertEquals('Participant', $participant->name); $this->assertEquals('test@example.com', $participant->communication->email); $this->assertEquals('+49123456789', $participant->communication->mobile); } public function testInactiveParticipantsPersonalDataNotUpdated(): void { $formData = $this->createFormDataWithInactiveParticipant(); $this->processor->createUpdateRequestPayload($formData); $participant = $formData->booking->participants[0]; $this->assertEquals('Original', $participant->firstName); $this->assertEquals('Name', $participant->name); } public function testApplicantDataSyncWithFirstParticipant(): void { $formData = $this->createFormDataForApplicantSync(); $this->processor->createUpdateRequestPayload($formData); $applicant = $formData->booking->applicant; $firstParticipant = $formData->booking->participants[0]; $this->assertEquals($firstParticipant->height, $applicant->height); $this->assertEquals($firstParticipant->weight, $applicant->weight); $this->assertEquals($firstParticipant->shoeSize, $applicant->shoeSize); } public function testBankAccountIncludedInPayload(): void { $formData = $this->createFormDataWithBankAccount(); $result = $this->processor->createUpdateRequestPayload($formData); $this->assertArrayHasKey('bankverbindung', $result['zahlung']); $this->assertEquals('Test Bank', $result['zahlung']['bankverbindung']['@kreditinstitut']); $this->assertEquals('DE89370400440532013000', $result['zahlung']['bankverbindung']['@iban']); } public function testBankAccountNotIncludedWhenNull(): void { $formData = $this->createFormDataWithoutBankAccount(); $result = $this->processor->createUpdateRequestPayload($formData); $this->assertArrayNotHasKey('bankverbindung', $result['zahlung']); } public function testAccommodationRoomsProcessing(): void { $formData = $this->createFormDataWithRooms(); $result = $this->processor->createUpdateRequestPayload($formData); $this->assertNotEmpty($result['ferienzielunterbringungen']['ferienzielunterbringung']); $room = $result['ferienzielunterbringungen']['ferienzielunterbringung'][0]; $this->assertEquals(1, $room['@idzimmer']); $this->assertEquals('DOUBLE', $room['@kategorie']); $this->assertEquals('01.01.2024', $room['@anreise']); $this->assertEquals('07.01.2024', $room['@abreise']); } public function testCommunicationObjectCreation(): void { $formData = $this->createFormDataWithoutExistingCommunication(); $this->processor->createUpdateRequestPayload($formData); $participant = $formData->booking->participants[0]; $this->assertInstanceOf(Communication::class, $participant->communication); $this->assertEquals('new@example.com', $participant->communication->email); } public function testEmptyPickupsToDoesNotCreateZustiegeSection(): void { $formData = $this->createFormDataWithoutPickups(); $result = $this->processor->createUpdateRequestPayload($formData); $this->assertArrayNotHasKey('zustiege', $result); } private function createCompleteFormData(): BookingDto { $bookingDto = new BookingDto($this->createMockTravel(), 1); $bookingDto->booking = $this->createMockBooking(); $bookingDto->participants = [ $this->createMockParticipantDto(0, 'F'), $this->createMockParticipantDto(1, 'F'), ]; return $bookingDto; } private function createFormDataWithCanceledParticipant(): BookingDto { $bookingDto = new BookingDto($this->createMockTravel(), 1); $bookingDto->booking = $this->createMockBooking(); $bookingDto->participants = [ $this->createMockParticipantDto(0, 'F'), $this->createMockParticipantDto(1, 'S'), // Canceled ]; return $bookingDto; } private function createFormDataWithAdditionalServices(): BookingDto { $formData = $this->createCompleteFormData(); $participant = $formData->participants[0]; $participant->courses = [$this->createMockService(1)]; $participant->additionalServices = [$this->createMockService(2)]; return $formData; } private function createFormDataWithTransportation(): BookingDto { $formData = $this->createCompleteFormData(); $participant = $formData->participants[0]; $participant->transportationOutbound = $this->createMockService(1); $participant->transportationInbound = $this->createMockService(2); return $formData; } private function createFormDataWithBusPickup(): BookingDto { $formData = $this->createCompleteFormData(); $participant = $formData->participants[0]; $busService = $this->createMockService(1); $busService->subType = 'BUS'; $participant->transportationOutbound = $busService; $participant->pickup = $this->createMockPickup(1); return $formData; } private function createFormDataWithNonBusTransportation(): BookingDto { $formData = $this->createCompleteFormData(); $participant = $formData->participants[0]; $trainService = $this->createMockService(1); $trainService->subType = 'TRAIN'; $participant->transportationOutbound = $trainService; return $formData; } private function createFormDataWithUnusedServices(): BookingDto { $formData = $this->createCompleteFormData(); // Remove all participants so services become unused $formData->participants = []; return $formData; } private function createFormDataWithUpdatedPersonalData(): BookingDto { $formData = $this->createCompleteFormData(); $participant = $formData->participants[0]; $participant->firstName = 'Updated'; $participant->lastName = 'Participant'; $participant->email = 'test@example.com'; $participant->mobile = '+49123456789'; return $formData; } private function createFormDataWithInactiveParticipant(): BookingDto { $formData = $this->createCompleteFormData(); $participant = $formData->participants[0]; $participant->status = 'C'; // Inactive status $participant->firstName = 'Updated'; $participant->lastName = 'Participant'; // Ensure original data remains unchanged $formData->booking->participants[0]->firstName = 'Original'; $formData->booking->participants[0]->name = 'Name'; return $formData; } private function createFormDataForApplicantSync(): BookingDto { $formData = $this->createCompleteFormData(); $firstParticipant = $formData->booking->participants[0]; $firstParticipant->height = '180'; $firstParticipant->weight = '75'; $firstParticipant->shoeSize = '42'; return $formData; } private function createFormDataWithBankAccount(): BookingDto { $formData = $this->createCompleteFormData(); $bankAccount = new BankAccount(); $bankAccount->bankName = 'Test Bank'; $bankAccount->iban = 'DE89370400440532013000'; $bankAccount->bic = 'COBADEFFXXX'; $bankAccount->holder = 'Test Holder'; $formData->booking->bankAccount = $bankAccount; return $formData; } private function createFormDataWithoutBankAccount(): BookingDto { $formData = $this->createCompleteFormData(); $formData->booking->bankAccount = null; return $formData; } private function createFormDataWithRooms(): BookingDto { $formData = $this->createCompleteFormData(); $room = new Room(); $room->id = 1; $room->category = 'DOUBLE'; $room->boardId = 1; $room->dateFrom = new \DateTimeImmutable('2024-01-01'); $room->dateTo = new \DateTimeImmutable('2024-01-07'); $room->totalCount = 2; $room->mapping = [0, 1]; $formData->booking->rooms = [$room]; return $formData; } private function createFormDataWithoutExistingCommunication(): BookingDto { $formData = $this->createCompleteFormData(); $participant = $formData->participants[0]; $participant->email = 'new@example.com'; $participant->mobile = '+49987654321'; $formData->booking->participants[0]->communication = new Communication(); return $formData; } private function createFormDataWithoutPickups(): BookingDto { $formData = $this->createCompleteFormData(); $formData->booking->pickupsOutbound = []; return $formData; } private function createMockBooking(): Booking { $booking = new Booking(); $booking->id = 123; $booking->status = 'ACTIVE'; $booking->agencyId = 1; $booking->dateId = 1; $booking->hotelId = 1; $booking->paymentId = '1'; $booking->paymentLabel = 'Credit Card'; $booking->paymentType = 'CC'; $booking->additionalServices = []; $booking->transportationServices = []; $booking->pickupsOutbound = []; $booking->pickupsInbound = []; $booking->participants = [ $this->createMockPersonalData('Participant0'), $this->createMockPersonalData('Participant1'), ]; $booking->participantsStatus = ['F', 'F']; $booking->applicant = $this->createMockPersonalData('Applicant'); $booking->bankAccount = null; $booking->rooms = []; return $booking; } private function createMockTravel(): Travel { $travel = new Travel(); $travel->additionalServices = [ 1 => $this->createMockService(1), 2 => $this->createMockService(2), ]; $travel->transportationServices = [ 1 => $this->createMockService(1), 2 => $this->createMockService(2), ]; return $travel; } private function createMockParticipantDto(int $index, string $status): ParticipantDto { $participant = new ParticipantDto(); $participant->index = $index; $participant->status = $status; $participant->firstName = "Participant{$index}"; $participant->lastName = 'LastName'; $participant->dateOfBirth = new \DateTimeImmutable('1990-01-01'); $participant->gender = 'M'; $participant->nationality = 'DE'; $participant->height = '175'; $participant->weight = '70'; $participant->shoeSize = '40'; $participant->email = null; $participant->mobile = null; $participant->courses = []; $participant->additionalServices = []; $participant->skiPass = null; $participant->board = []; $participant->rentals = []; $participant->transportationOutbound = $this->createMockService(1); $participant->transportationInbound = $this->createMockService(2); $participant->pickup = null; return $participant; } private function createMockPersonalData(string $firstName): PersonalData { $personalData = new PersonalData(); $personalData->firstName = $firstName; $personalData->name = 'LastName'; $personalData->dateOfBirth = new \DateTimeImmutable('1990-01-01'); $personalData->gender = 'M'; $personalData->nationality = 'DE'; $personalData->height = '175'; $personalData->weight = '70'; $personalData->shoeSize = '40'; $personalData->address = new Address(); $personalData->communication = new Communication(); return $personalData; } private function createMockService(int $id): Service { $service = new Service(); $service->id = $id; $service->price = 50.0; $service->mapping = []; $service->individualPrice = []; $service->subType = 'STANDARD'; return $service; } private function createMockPickup(int $id): Pickup { $pickup = new Pickup(); $pickup->id = $id; $pickup->mapping = []; return $pickup; } }