feat(form-builder): add ApplyStatus, DismissalReasonType, BindingTargetType enums (WS-6)

DismissalReasonType has six values; manually_resolved is intentionally
absent because Resolve and Dismiss are separate workflows (RFC V2).

Refs: RFC-WS-6.md §3 (Q4 partial-status separation), §4 (V2 dismiss enum)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-25 22:36:10 +02:00
parent c033dc6cd2
commit 447511634d
6 changed files with 213 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace App\Enums\FormBuilder;
/**
* RFC-WS-6 §3 (Q4) apply-state of a FormSubmission's binding pipeline.
* Distinct from {@see \App\Models\FormBuilder\FormSubmission::$identity_match_status},
* which tracks identity resolution (RFC O1).
*/
enum ApplyStatus: string
{
case PENDING = 'pending';
case COMPLETED = 'completed';
case PARTIAL = 'partial';
case FAILED = 'failed';
public function isTerminal(): bool
{
return $this !== self::PENDING;
}
public function isOpen(): bool
{
return $this !== self::COMPLETED;
}
public function label(): string
{
return match ($this) {
self::PENDING => 'Wachtrij',
self::COMPLETED => 'Voltooid',
self::PARTIAL => 'Gedeeltelijk mislukt',
self::FAILED => 'Mislukt',
};
}
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace App\Enums\FormBuilder;
/**
* RFC-WS-6 §4 (V1) storage shape of a binding-target attribute, as
* declared by {@see \App\FormBuilder\Bindings\BindingTypeRegistry}.
*
* Source of truth for whether a target accepts the `Append` merge
* strategy (only COLLECTION does V1 rejects scalar-append).
*/
enum BindingTargetType: string
{
case SCALAR = 'scalar';
case COLLECTION = 'collection';
case RELATION = 'relation';
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace App\Enums\FormBuilder;
/**
* RFC-WS-6 §4 (V2) typed reason for dismissing a
* {@see \App\Models\FormBuilder\FormSubmissionActionFailure}.
*
* `manually_resolved` is intentionally absent Resolve and Dismiss are
* separate workflows (resolved_at + resolved_note vs. dismissed_at +
* dismissed_reason_type/note).
*/
enum DismissalReasonType: string
{
case SCHEMA_DELETED = 'schema_deleted';
case TARGET_ENTITY_DELETED = 'target_entity_deleted';
case BINDING_REMOVED = 'binding_removed';
case DUPLICATE_SUBMISSION = 'duplicate_submission';
case DATA_QUALITY_ISSUE = 'data_quality_issue';
case OTHER = 'other';
public function requiresNote(): bool
{
return $this === self::OTHER;
}
public function label(): string
{
return match ($this) {
self::SCHEMA_DELETED => 'Formulier verwijderd',
self::TARGET_ENTITY_DELETED => 'Doel-entiteit verwijderd',
self::BINDING_REMOVED => 'Binding verwijderd',
self::DUPLICATE_SUBMISSION => 'Dubbele inzending',
self::DATA_QUALITY_ISSUE => 'Datakwaliteit-probleem',
self::OTHER => 'Anders',
};
}
}