feat: improved mutability checks for personal data in edit or create mode

This commit is contained in:
Björn Fromme
2025-10-28 15:34:09 +01:00
parent 51dbf20118
commit 5021f414d1
27 changed files with 435 additions and 233 deletions
@@ -10,38 +10,44 @@ use App\Form\Service\Contract\FieldConditionInterface;
/**
* Condition that determines if personal data fields should be hidden for authenticated users.
*
* When a participant is linked to an existing BPN account (has personId),
* their personal data should not be editable during the booking process. Changes to
* master personal data should only happen through the dedicated personal data management
* interface to prevent:
* - Creating duplicate customer records in BPN
* - Disconnecting bookings from the user's account
* - Data inconsistencies between booking and account data
* ⚠️ IMPORTANT: This condition is used in CREATE MODE ONLY to protect authenticated
* applicant data during booking creation. It is NOT used in edit mode.
*
* Note: In edit mode, the BPN API may not return addressId in booking responses,
* so we rely on personId alone to identify authenticated users. The personId is
* sufficient to link a participant to an existing BPN account.
* In CREATE mode:
* - When a logged-in user creates a booking, their personal data is prepopulated from
* their BPN account (including personId).
* - Their personal data fields should be hidden and displayed as static text to prevent
* modifications that could:
* - Create duplicate customer records in BPN
* - Disconnect bookings from the user's account
* - Cause data inconsistencies between booking and account data
*
* In EDIT mode:
* - DO NOT use this condition. Edit mode uses PersonalDataMutabilityCondition instead,
* which respects the BPN API's per-participant `mutable` flag (aenderungmoeglich).
* - The mutability flag determines editability for ALL participants uniformly in edit mode.
*
* When this condition is satisfied (returns true), the template should:
* - Hide the form fields for personal data
* - Display the values as static, read-only text
*
* This follows the same pattern as bulk insurance booking.
* - Display the values as static, read-only text via the field_or_static macro
*/
class AuthenticatedUserPersonalDataCondition implements FieldConditionInterface
{
/**
* Evaluates if personal data fields should be hidden (not editable).
* Evaluates if personal data fields should be hidden (not editable) in CREATE mode.
*
* Returns true when the participant has both addressId and personId set,
* indicating they are linked to an existing BPN account. When true,
* personal data fields should be hidden and displayed as static text.
* Returns true when the participant has a personId set, indicating they are
* a logged-in user whose data was prepopulated from their BPN account.
* When true, personal data fields should be hidden and displayed as static text.
*
* @param BookingDto $bookingDto The current booking data
* This condition is only used during booking creation, not in edit mode.
* Edit mode uses PersonalDataMutabilityCondition to respect BPN's mutability flag.
*
* @param BookingDto $bookingDto The current booking data (create flow)
* @param int $participantIndex The index of the participant being evaluated
* @param array<string, mixed> $formData Current form data (unused)
*
* @return bool True if fields should be hidden (participant linked to BPN account)
* @return bool True if fields should be hidden (authenticated user in create mode)
*/
public function evaluate(BookingDto $bookingDto, int $participantIndex, array $formData): bool
{
@@ -50,17 +56,16 @@ class AuthenticatedUserPersonalDataCondition implements FieldConditionInterface
return false;
}
// Hide personal data fields if participant has BPN person ID
// In edit mode, bookings may not include addressId, so we check personId only
// The personId alone is sufficient to identify a participant linked to a BPN account
// Hide personal data fields if participant has BPN person ID (authenticated user in create mode)
// The personId is set during prepopulation when a logged-in user starts creating a booking
return null !== $participant->personId;
}
/**
* Returns field names that this condition depends on.
*
* This condition is based on addressId/personId which are set during prepopulation
* and don't change during the form interaction, so no field dependencies.
* This condition is based on personId which is set during prepopulation
* and doesn't change during form interaction, so no field dependencies.
*
* @return string[] Empty array - no field dependencies
*/
@@ -76,6 +81,6 @@ class AuthenticatedUserPersonalDataCondition implements FieldConditionInterface
*/
public function getDescription(): string
{
return 'Personal data is not editable when participant is linked to BPN account (prevents duplicate records)';
return 'Personal data is not editable for authenticated users in create mode (prevents duplicate records)';
}
}