diff --git a/api/app/Listeners/FormBuilder/TriggerPersonIdentityMatchOnFormSubmit.php b/api/app/Listeners/FormBuilder/TriggerPersonIdentityMatchOnFormSubmit.php index 43f816c4..da006082 100644 --- a/api/app/Listeners/FormBuilder/TriggerPersonIdentityMatchOnFormSubmit.php +++ b/api/app/Listeners/FormBuilder/TriggerPersonIdentityMatchOnFormSubmit.php @@ -80,10 +80,22 @@ final class TriggerPersonIdentityMatchOnFormSubmit private function resolveStatus(FormSubmission $submission): string { - // Public submission without a person subject — mark pending so the - // portal shows the "we koppelen je gegevens zodra..." message. - // Real matching happens when the organiser attaches a person. if ($submission->subject_type !== 'person' || $submission->subject_id === null) { + // Post-WS-6 (RFC Q2): this path should be unreachable for + // event_registration submissions because ApplyBindingsOnFormSubmit + // provisions the Person synchronously before this listener fires. + // If we reach here, either: + // - ApplyBindings failed silently (check form_submission_action_failures) + // - Schema is misconfigured (no email binding, no identity-key) + // - Different purpose where subject genuinely is null + // Failsafe: preserve the existing 'pending' state so portal banner + // still renders sensibly, and surface the misconfiguration in logs. + Log::warning('form-builder.identity-match.no_person_subject_post_apply', [ + 'submission_id' => (string) $submission->id, + 'schema_id' => (string) $submission->form_schema_id, + 'subject_type' => $submission->subject_type, + ]); + return 'pending'; } diff --git a/api/tests/Feature/FormBuilder/Listeners/TriggerPersonIdentityMatchOnFormSubmitTest.php b/api/tests/Feature/FormBuilder/Listeners/TriggerPersonIdentityMatchOnFormSubmitTest.php index 236a0cd5..5123834a 100644 --- a/api/tests/Feature/FormBuilder/Listeners/TriggerPersonIdentityMatchOnFormSubmitTest.php +++ b/api/tests/Feature/FormBuilder/Listeners/TriggerPersonIdentityMatchOnFormSubmitTest.php @@ -84,9 +84,23 @@ final class TriggerPersonIdentityMatchOnFormSubmitTest extends TestCase public function test_public_event_registration_submission_is_marked_pending(): void { + // RFC Q2: this path is now a logged-warning failsafe. The pending + // state is preserved for portal banner rendering, but a misconfigured + // schema or silently-failed ApplyBindings should surface in logs. + // Spy mode (not strict mock) so other listeners' Log calls don't + // interfere — ApplyBindingsOnFormSubmit may also log error here. + $logSpy = \Illuminate\Support\Facades\Log::spy(); + $submission = $this->submit(); $this->assertSame('pending', $submission->identity_match_status); + + /** @var \Mockery\Expectation $expectation */ + $expectation = $logSpy->shouldHaveReceived('warning'); + $expectation->with( + 'form-builder.identity-match.no_person_subject_post_apply', + \Mockery::type('array'), + ); } public function test_linked_person_is_marked_matched(): void