fix: incorrect rules around family insurances

addresses #869dr80qj
This commit is contained in:
Björn Fromme
2026-08-05 15:11:37 +02:00
parent 736128476b
commit 8a46908856
15 changed files with 859 additions and 50 deletions
@@ -13,6 +13,7 @@ use App\BusProNet\Model\Address;
use App\BusProNet\Model\BankAccount;
use App\BusProNet\Model\Booking;
use App\BusProNet\Model\Communication;
use App\BusProNet\Model\Insurance;
use App\BusProNet\Model\PersonalData;
use App\BusProNet\Model\Pickup;
use App\BusProNet\Model\Room;
@@ -822,4 +823,106 @@ class BookingDataProcessorTest extends TestCase
return $participant;
}
/**
* Regression: family insurance covers the whole family under a single policy on the
* applicant, so dependents must never keep their own insurance selection - even when
* the applicant never checked the "book for everyone" (bulkInsuranceBooking) box.
*/
public function testFamilyInsuranceClearsDependentInsuranceWithoutBulkCheckbox(): void
{
$familyInsurance = new Insurance();
$familyInsurance->id = 'family-1';
$familyInsurance->familyInsurance = true;
$applicant = $this->createMockParticipantDto(0, 'F');
$applicant->bulkInsuranceBooking = false;
$applicant->insurance = $familyInsurance;
$dependentInsurance = new Insurance();
$dependentInsurance->id = 'dependent-own-1';
$dependentInsurance->familyInsurance = false;
$dependent = $this->createMockParticipantDto(1, 'F');
$dependent->insurance = $dependentInsurance;
$bookingDto = new BookingDto($this->createMockTravel(), 1);
$bookingDto->participants = [$applicant, $dependent];
$insuranceService = $this->createMock(InsuranceManager::class);
$insuranceService->method('getSelectableInsurances')->willReturn([]);
$insuranceService->method('batchAssignInsuranceToParticipants')->willReturn([
0 => $familyInsurance,
1 => null,
]);
$priceCalculatorService = $this->createMock(BookingPriceCalculator::class);
$priceCalculatorService->method('calculateIndividualParticipantPriceExcludingInsurance')->willReturn(0.0);
$payloadBuilder = $this->createMock(BookingPayloadBuilder::class);
$payloadBuilder->method('buildCreatePayload')->willReturn([]);
$processor = new BookingDataProcessor(
$insuranceService,
$priceCalculatorService,
new ServiceMappingCollector(),
new ParticipantServiceProcessor(new NullLogger()),
$payloadBuilder,
new PersonalDataSynchronizer(),
);
$processor->createBookingRequestPayload($bookingDto, 'ANFRAGE');
$this->assertSame($familyInsurance, $bookingDto->participants[0]->insurance);
$this->assertNull($bookingDto->participants[1]->insurance, 'Dependent must lose their own insurance once the applicant selects family insurance');
}
/**
* Regression: the edit-mode guard that protects an individually-locked non-family
* insurance from being overwritten must not also block clearing a dependent's
* pre-existing insurance when the applicant switches to family insurance.
*/
public function testFamilyInsuranceClearsDependentInsuranceInEditMode(): void
{
$familyInsurance = new Insurance();
$familyInsurance->id = 'family-1';
$familyInsurance->familyInsurance = true;
$formData = $this->createCompleteFormData();
$applicant = $formData->participants[0];
$applicant->bulkInsuranceBooking = false;
$applicant->insurance = $familyInsurance;
$dependentInsurance = new Insurance();
$dependentInsurance->id = 'dependent-own-1';
$dependentInsurance->familyInsurance = false;
$dependent = $formData->participants[1];
$dependent->insurance = $dependentInsurance;
$insuranceService = $this->createMock(InsuranceManager::class);
$insuranceService->method('getSelectableInsurances')->willReturn([]);
$insuranceService->method('batchAssignInsuranceToParticipants')->willReturn([
0 => $familyInsurance,
1 => null,
]);
$priceCalculatorService = $this->createMock(BookingPriceCalculator::class);
$priceCalculatorService->method('calculateIndividualParticipantPriceExcludingInsurance')->willReturn(0.0);
$processor = new BookingDataProcessor(
$insuranceService,
$priceCalculatorService,
new ServiceMappingCollector(),
new ParticipantServiceProcessor(new NullLogger()),
new BookingPayloadBuilder(new ServiceMappingCollector()),
new PersonalDataSynchronizer(),
);
$processor->createUpdateRequestPayload($formData);
$this->assertSame($familyInsurance, $formData->participants[0]->insurance);
$this->assertNull($formData->participants[1]->insurance, 'Dependent must lose their pre-existing individual insurance in edit mode once the applicant selects family insurance');
}
}