wip: submit booking to api
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user