feat: pre-flight check of agency bookings
addresses #869bqxr4q
This commit is contained in:
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\Tests\Form\Model;
|
||||
|
||||
use App\BusProNet\Model\Travel;
|
||||
use App\BusProNet\Model\Address;
|
||||
use App\Form\Model\BookingDto;
|
||||
use App\Form\Model\ParticipantDto;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
@@ -87,4 +88,44 @@ class BookingDtoTest extends TestCase
|
||||
$this->assertSame('75', $restored->participants[0]->weight);
|
||||
$this->assertSame('43', $restored->participants[0]->shoeSize);
|
||||
}
|
||||
|
||||
public function testUnserializeNormalizesLegacyParticipantStringsOnLoad(): void
|
||||
{
|
||||
$travel = new Travel();
|
||||
$travel->id = 42;
|
||||
$travel->dateFrom = new \DateTimeImmutable('2025-06-01');
|
||||
$travel->dateTo = new \DateTimeImmutable('2025-06-08');
|
||||
|
||||
$participant = new ParticipantDto();
|
||||
$participant->firstName = ' Max ';
|
||||
$participant->lastName = ' Mustermann ';
|
||||
$participant->email = ' [email protected] ';
|
||||
$participant->remarksRoom = ' ';
|
||||
$participant->licensePlate = ' B-AB 123 ';
|
||||
$participant->purchaseVoucherCode = ' ABC-123 ';
|
||||
$participant->promoVoucherCode = ' PROMO ';
|
||||
$participant->address = new Address();
|
||||
$participant->address->street = ' Test Street 1 ';
|
||||
$participant->address->postCode = ' 12345 ';
|
||||
$participant->address->city = ' Test City ';
|
||||
$participant->address->country = ' DE ';
|
||||
|
||||
$dto = new BookingDto($travel, 1);
|
||||
$dto->participants = [$participant];
|
||||
|
||||
$restored = unserialize(serialize($dto));
|
||||
|
||||
$this->assertInstanceOf(BookingDto::class, $restored);
|
||||
$this->assertSame('Max', $restored->participants[0]->firstName);
|
||||
$this->assertSame('Mustermann', $restored->participants[0]->lastName);
|
||||
$this->assertSame('[email protected]', $restored->participants[0]->email);
|
||||
$this->assertNull($restored->participants[0]->remarksRoom);
|
||||
$this->assertSame('B-AB 123', $restored->participants[0]->licensePlate);
|
||||
$this->assertSame('ABC-123', $restored->participants[0]->purchaseVoucherCode);
|
||||
$this->assertSame('PROMO', $restored->participants[0]->promoVoucherCode);
|
||||
$this->assertSame('Test Street 1', $restored->participants[0]->address->street);
|
||||
$this->assertSame('12345', $restored->participants[0]->address->postCode);
|
||||
$this->assertSame('Test City', $restored->participants[0]->address->city);
|
||||
$this->assertSame('DE', $restored->participants[0]->address->country);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,6 +597,51 @@ class ParticipantEditDtoTest extends TestCase
|
||||
$this->assertCount(0, $skiPassViolations, 'Ski pass validation should be skipped in edit mode');
|
||||
}
|
||||
|
||||
public function testEditSubmissionValidatesApplicantAddressOnlyForFirstParticipant(): void
|
||||
{
|
||||
$travel = new Travel();
|
||||
$travel->dateFrom = new \DateTimeImmutable('2025-06-01');
|
||||
$travel->dateTo = new \DateTimeImmutable('2025-06-08');
|
||||
|
||||
$bookingDto = new BookingDto($travel, 1);
|
||||
$bookingDto->booking = new Booking();
|
||||
$bookingDto->agencyCode = AgencyLoader::INTERNAL_AGENCY_CODE;
|
||||
|
||||
$participant0 = $this->createAdultParticipant('[email protected]');
|
||||
$participant0->index = 0;
|
||||
$participant0->address = null;
|
||||
|
||||
$participant1 = $this->createAdultParticipant('[email protected]');
|
||||
$participant1->index = 1;
|
||||
$participant1->address = null;
|
||||
|
||||
$bookingDto->participants = [$participant0, $participant1];
|
||||
|
||||
$wrapper0 = new ParticipantEditDto(
|
||||
participant: $bookingDto->participants[0],
|
||||
bookingContext: $bookingDto,
|
||||
);
|
||||
$wrapper1 = new ParticipantEditDto(
|
||||
participant: $bookingDto->participants[1],
|
||||
bookingContext: $bookingDto,
|
||||
);
|
||||
|
||||
$violations0 = $this->validator->validate($wrapper0, null, ['booking_edit', 'strict_required']);
|
||||
$addressViolations0 = array_filter(
|
||||
iterator_to_array($violations0),
|
||||
fn ($v) => 'address' === $v->getPropertyPath() || 'participant.address' === $v->getPropertyPath()
|
||||
);
|
||||
|
||||
$violations1 = $this->validator->validate($wrapper1, null, ['booking_edit', 'strict_required']);
|
||||
$addressViolations1 = array_filter(
|
||||
iterator_to_array($violations1),
|
||||
fn ($v) => 'address' === $v->getPropertyPath() || 'participant.address' === $v->getPropertyPath()
|
||||
);
|
||||
|
||||
$this->assertCount(1, $addressViolations0, 'Applicant address should still be required in edit submission');
|
||||
$this->assertCount(0, $addressViolations1, 'Non-applicant address should not be required in edit submission');
|
||||
}
|
||||
|
||||
public function testSkiPassAgeCalculatedAtTravelDate(): void
|
||||
{
|
||||
$travel = new Travel();
|
||||
@@ -635,6 +680,54 @@ class ParticipantEditDtoTest extends TestCase
|
||||
$this->assertCount(0, $skiPassViolations, 'Age should be calculated at travel date for baby exemption');
|
||||
}
|
||||
|
||||
public function testDependentWithoutInsurancePassesWhenApplicantUsesBulkInsurance(): void
|
||||
{
|
||||
$applicant = $this->createAdultParticipant('[email protected]');
|
||||
$applicant->bulkInsuranceBooking = true;
|
||||
|
||||
$dependent = $this->createAdultParticipant('[email protected]');
|
||||
$dependent->insurance = null;
|
||||
|
||||
$bookingDto = $this->createBookingDtoWithParticipants([$applicant, $dependent]);
|
||||
|
||||
$wrapper = new ParticipantEditDto(
|
||||
participant: $bookingDto->participants[1],
|
||||
bookingContext: $bookingDto,
|
||||
);
|
||||
|
||||
$violations = $this->validator->validate($wrapper, null, ['strict_required']);
|
||||
$insuranceViolations = array_filter(
|
||||
iterator_to_array($violations),
|
||||
fn ($v) => 'participant.insurance' === $v->getPropertyPath()
|
||||
);
|
||||
|
||||
$this->assertCount(0, $insuranceViolations);
|
||||
}
|
||||
|
||||
public function testDependentWithoutInsuranceFailsWhenApplicantDoesNotUseBulkInsurance(): void
|
||||
{
|
||||
$applicant = $this->createAdultParticipant('[email protected]');
|
||||
$applicant->bulkInsuranceBooking = false;
|
||||
|
||||
$dependent = $this->createAdultParticipant('[email protected]');
|
||||
$dependent->insurance = null;
|
||||
|
||||
$bookingDto = $this->createBookingDtoWithParticipants([$applicant, $dependent]);
|
||||
|
||||
$wrapper = new ParticipantEditDto(
|
||||
participant: $bookingDto->participants[1],
|
||||
bookingContext: $bookingDto,
|
||||
);
|
||||
|
||||
$violations = $this->validator->validate($wrapper, null, ['strict_required']);
|
||||
$insuranceViolations = array_filter(
|
||||
iterator_to_array($violations),
|
||||
fn ($v) => 'participant.insurance' === $v->getPropertyPath()
|
||||
);
|
||||
|
||||
$this->assertCount(1, $insuranceViolations);
|
||||
}
|
||||
|
||||
private function createBookingDtoWithParticipants(array $participants): BookingDto
|
||||
{
|
||||
$travel = new Travel();
|
||||
|
||||
Reference in New Issue
Block a user