191 lines
6.4 KiB
Markdown
191 lines
6.4 KiB
Markdown
# 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:
|
|
```php
|
|
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):
|
|
```php
|
|
// Add address for applicant
|
|
if (null !== $firstParticipant->address) {
|
|
$payload['anmelder']['anschrift'] = $firstParticipant->address->toPayload();
|
|
}
|
|
```
|
|
|
|
**Participant list** (lines 481-488):
|
|
```php
|
|
// 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:**
|
|
```xml
|
|
<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)
|
|
```php
|
|
$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)
|
|
```php
|
|
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:
|
|
- [x] Applicant address required (all fields) - ✅ PASSED
|
|
- [x] Dependent participant address optional - ✅ PASSED
|
|
- [x] Country dropdown shows DE, AT, CH first - ✅ PASSED
|
|
- [x] Address appears in XML for applicant - ✅ PASSED
|
|
- [x] Address appears in XML for all participants (empty if not provided) - ✅ PASSED
|
|
- [x] Email is mandatory for all participants - ✅ PASSED
|
|
- [x] Insurance selection works for dependent participants - ✅ PASSED
|
|
- [x] 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.
|