Files
myep/docs/ADDRESS_FIELDS_IMPLEMENTATION.md
T

6.4 KiB

Address Fields Implementation

Date: 2025-10-06 Status: TESTED SUCCESSFULLY (2025-10-06)

Overview

Added participant address collection to the booking create flow. Address is mandatory for the applicant (first participant) and optional for others.

Implementation

1. Models

ParticipantDto (src/Form/Model/ParticipantDto.php):

  • Added Address $address property
  • Made email field required (@Assert\NotBlank)
  • Added constructor to initialize Address object
  • Removed @Assert\NotNull constraint (validation handled by ParticipantValidator)

Address (src/BusProNet/Model/Address.php):

  • Already had toPayload() method for XML generation
  • Properties: street, postCode, city, district, country
  • No changes needed (existing model worked perfectly)

2. Forms

AddressType (src/Form/AddressType.php) - NEW:

class AddressType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('street', TextType::class, [...])
            ->add('postCode', TextType::class, [...])
            ->add('city', TextType::class, [...])
            ->add('country', CountryType::class, [
                'property' => 'country',
                'preferred_choices' => ['DE', 'AT', 'CH'],
            ]);
    }
}

BookingParticipantType (src/Form/BookingParticipantType.php):

  • Added address field after mobile field
  • required => 0 === $participantIndex (mandatory for applicant)
  • Added 'address' to $baseFields array for rebuild handling

3. Validation

ParticipantValidator (src/Validator/Constraints/ParticipantValidator.php):

  • Added assertApplicantAddressValid() method
  • Validates street, postCode, city, country for applicant only
  • Uses $participant->isApplicant() to check if validation should run
  • Error messages: "Bitte angeben" for each missing field

4. Payload Generation

BookingDataProcessor (src/BusProNet/DataProcessor/BookingDataProcessor.php):

Applicant section (lines 451-454):

// Add address for applicant
if (null !== $firstParticipant->address) {
    $payload['anmelder']['anschrift'] = $firstParticipant->address->toPayload();
}

Participant list (lines 481-488):

// Add address (always include structure, even if empty)
$participantData['anschrift'] = $participant->address?->toPayload() ?? [
    'strasse' => null,
    'plz' => null,
    'ort' => null,
    'ortsteil' => null,
    'land' => null,
];

XML Output:

<anmelder>
    <anschrift>
        <strasse>Gablonzer Straße 32</strasse>
        <plz>53359</plz>
        <ort>Rheinbach</ort>
        <ortsteil />
        <land>D</land>
    </anschrift>
</anmelder>

<teilnehmerliste>
    <teilnehmer id="1">
        <anschrift>
            <strasse>Gablonzer Straße 32</strasse>
            <plz>53359</plz>
            <ort>Rheinbach</ort>
            <ortsteil />
            <land>D</land>
        </anschrift>
    </teilnehmer>
</teilnehmerliste>

Bug Fixes (Same Session)

1. Room Quantity Fix

Issue: Room @anzahl was set to participant count instead of room quantity Fix: Use roomSelections[].quantity from step 1 (lines 576-603)

$roomQuantities = [];
foreach ($bookingDto->roomSelections as $selection) {
    if ($selection->quantity > 0) {
        $roomQuantities[$selection->roomId] = $selection->quantity;
    }
}
$quantity = $roomQuantities[$roomId] ?? 1;

2. Insurance Selection for Dependent Participants

Issue: ParticipantBulkInsuranceFieldHandler cleared independent selections on every form submit Fix: Added wasBulkInsurancePreviouslyEnabled() check (lines 90, 144-176)

if (false === $isBulkEnabled && $this->wasBulkInsurancePreviouslyEnabled($bookingDto)) {
    $this->clearDependentParticipantsInsurance($bookingDto);
}

Files Modified

  1. src/Form/Model/ParticipantDto.php - Added address property, constructor, required email
  2. src/Form/AddressType.php - NEW form type
  3. src/Form/BookingParticipantType.php - Added address field
  4. src/Validator/Constraints/ParticipantValidator.php - Added address validation
  5. src/BusProNet/DataProcessor/BookingDataProcessor.php - Address in payload, room quantity fix, isApplicant() usage
  6. src/Form/Service/ParticipantBulkInsuranceFieldHandler.php - Insurance clearing fix

Testing

Manual Testing Checklist:

  • Applicant address required (all fields) - PASSED
  • Dependent participant address optional - PASSED
  • Country dropdown shows DE, AT, CH first - PASSED
  • Address appears in XML for applicant - PASSED
  • Address appears in XML for all participants (empty if not provided) - PASSED
  • Email is mandatory for all participants - PASSED
  • Insurance selection works for dependent participants - PASSED
  • Room quantity matches selection from step 1 - PASSED

Expected XML:

  • Applicant: Full address in <anmelder><anschrift>
  • All participants: Address structure in <teilnehmer><anschrift> (may be empty)
  • Room quantity: Matches quantity selected in step 1, not participant count

Notes

  • Address object initialized in ParticipantDto constructor
  • Uses existing Address::toPayload() method for XML generation
  • CountryType provides nationality dropdown with German country codes
  • Validation runs via existing ParticipantValidator constraint
  • Template integration happens automatically via Symfony form system

Implementation Status: TESTED SUCCESSFULLY Code Quality: PHP-CS-Fixer validated Test Date: 2025-10-06

Test Results

Test Date: 2025-10-06 Environment: DDEV sandbox with BusProNet API

Validated Features:

  • Applicant address validation (all fields mandatory)
  • Dependent participant address optional
  • Country dropdown with preferred choices (DE, AT, CH)
  • Address correctly included in XML payload for applicant
  • Address structure included for all participants (empty nodes for optional)
  • Email mandatory validation working for all participants
  • Mobile mandatory validation working for applicant only

Validated Bug Fixes:

  • Room quantity using correct value from step 1 selections
  • Insurance selection working correctly for dependent participants
  • Pickup locations included with correct quantities

Result: All address field requirements working correctly in production-like environment.