From 145f7de7810b97c893f95cf2872874025489ae57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Tue, 23 Jun 2026 15:24:10 +0200 Subject: [PATCH] fix: make personal data editable in bookings as permitted by bpn --- .../PersonalDataMutabilityCondition.php | 45 +++++-------------- src/Form/Service/EditFieldStateProvider.php | 21 ++++----- 2 files changed, 19 insertions(+), 47 deletions(-) diff --git a/src/Form/Service/Condition/PersonalDataMutabilityCondition.php b/src/Form/Service/Condition/PersonalDataMutabilityCondition.php index 6f3cdfd..74b5d3e 100644 --- a/src/Form/Service/Condition/PersonalDataMutabilityCondition.php +++ b/src/Form/Service/Condition/PersonalDataMutabilityCondition.php @@ -8,44 +8,23 @@ use App\Form\Model\BookingDto; use App\Form\Service\Contract\FieldConditionInterface; /** - * Condition that determines if personal data fields should be hidden based on BPN mutability flag. + * Condition that determines if personal data fields should be hidden based on the + * booking-level MOEGLICHEAENDERUNGEN/teilnehmerdaten flag. * - * This condition respects the BPN API's per-participant mutability flag (`aenderungmoeglich`). - * When a participant's data is not mutable (mutable=false), personal data fields should be - * hidden and displayed as static text. + * Uses Travel::participantDataMutable (defaults to true) which is populated from the + * MOEGLICHEAENDERUNGEN API endpoint. When BPN marks participant data as not changeable + * for a booking, all core personal data fields are rendered as static text. * - * This condition is combined with FirstParticipantReadOnlyCondition via OR in edit mode. - * FirstParticipantReadOnlyCondition handles agency-based read-only logic for first participant, - * while this condition applies BPN mutability rules to all participants. - * - * Exception: For internal agency bookings (agency code 0004), the BPN mutability flag - * is ignored for all participants. Agency staff need full control over participant data - * regardless of BPN's mutability restrictions. - * - * In edit mode, BPN determines mutability based on business rules (e.g., payment status, - * booking state, etc.). We must respect this flag to prevent users from attempting to - * modify data that BPN will reject. - * - * When this condition is satisfied (returns true), the template renders fields as - * static text via the `field_or_static` macro instead of form inputs. + * Exception: internal agency bookings always allow editing regardless of this flag. */ class PersonalDataMutabilityCondition implements FieldConditionInterface { /** - * Evaluates if personal data fields should be hidden (not editable). - * - * Returns true when the participant's mutable flag is false, indicating - * that BPN does not allow modifications to this participant's data. - * When true, personal data fields should be hidden and displayed as static text. - * - * Exception: For internal agency bookings, always returns false to allow - * editing all participants regardless of BPN's mutability flag. - * * @param BookingDto $bookingDto The current booking data * @param int $participantIndex The index of the participant being evaluated * @param array $formData Current form data (unused) * - * @return bool True if fields should be hidden (participant data not mutable) + * @return bool True if fields should be shown as static text (BPN disallows changes) */ public function evaluate(BookingDto $bookingDto, int $participantIndex, array $formData): bool { @@ -55,13 +34,9 @@ class PersonalDataMutabilityCondition implements FieldConditionInterface return false; } - $participant = $bookingDto->getParticipant($participantIndex); - if (null === $participant) { - return false; - } - - // Hide personal data fields if BPN indicates participant is not mutable - return false === $participant->mutable; + // Use the booking-level teilnehmerdaten flag from MOEGLICHEAENDERUNGEN. + // Defaults to true (editable) when the endpoint is unavailable. + return false === $bookingDto->travel->participantDataMutable; } /** diff --git a/src/Form/Service/EditFieldStateProvider.php b/src/Form/Service/EditFieldStateProvider.php index e6084e3..26635d9 100644 --- a/src/Form/Service/EditFieldStateProvider.php +++ b/src/Form/Service/EditFieldStateProvider.php @@ -65,23 +65,20 @@ class EditFieldStateProvider extends AbstractFieldStateProvider $personalDataMutabilityCondition ); - // Render all personal data fields as static text if first participant in non-internal agency OR BPN indicates not mutable - // Using 'static_text' state (not 'hidden') so template renders values as static text - $personalDataFields = [ - 'firstName', - 'lastName', - 'dateOfBirth', - 'gender', - 'nationality', - 'email', - 'mobile', - ]; - foreach ($personalDataFields as $field) { + // Core identity fields: static text if first participant in non-internal agency OR BPN indicates not mutable + foreach (['firstName', 'lastName', 'dateOfBirth', 'gender', 'nationality'] as $field) { $this->fieldStateConditions[$field] = [ 'static_text' => $personalDataHiddenCondition, ]; } + // Contact fields: only the applicant (index 0) is read-only — participants can always update email/phone + foreach (['email', 'mobile'] as $field) { + $this->fieldStateConditions[$field] = [ + 'static_text' => $firstParticipantReadOnlyCondition, + ]; + } + // Address fields - render as static text if first participant in non-internal agency OR participant not mutable $this->fieldStateConditions['address'] = [ 'static_text' => $personalDataHiddenCondition,