docs(forms): SCHEMA crosswalk, foundation concept page, getting-started + migration playbook, copy catalogue init
SCHEMA.md - New §3.5.12 "Form Builder" with the legacy-tables-retained note placed prominently directly under the section header (per S1 wrap-up Path 3 decision: Phase 8 deferred to S2). - Crosswalk: every legacy volunteer_profiles column → its new home (user_profiles columns vs form_fields vs person_tags). - Summary table for the 13 new tables with one-line purpose + ARCH § pointer each. - Activity log strategy and multi-tenancy discipline noted. - §3.5.4 marked SUPERSEDED with a pointer to the new section. /dev-docs/form-builder-migration-playbook.md (new) - Operator runbook for forms:migrate-legacy-data on real legacy data. - Pre-flight audit, dry-run, migrate, verify, spot-check, rollback paths spelled out. Same legacy-tables-retained note prominently. /dev-docs/form-builder-getting-started.md (new) - Developer onboarding. Mental model, code samples for creating a schema/field/submission/value, adding a new subject type, registering a custom field type, suppressing activity log via App\Support\ActivityLog::suppressed. /dev-docs/COPY_CATALOGUE.md (new) - Seeded verbatim from ARCH §30 (naming conventions, tooltip catalogue, warning catalogue) with a header explaining purpose, growth strategy, and the per-PR update workflow. /docs/organizer/forms/concepts/wat-is-een-formulier.md (new VitePress) - Dutch, informal je/jij. Follows /docs/.templates/concept-page.md. - Three example use-cases: vrijwilligersregistratie, artist advance, incidentrapportage. Light foundation; depth arrives in S2-S5. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -669,6 +669,13 @@ $effectiveDate = $shift->end_date ?? $shift->timeSlot->date;
|
||||
|
||||
## 3.5.4 Volunteer Profile & History
|
||||
|
||||
> **SUPERSEDED by S1 of the form-builder refactor.** The old
|
||||
> `volunteer_profiles` table was a planning placeholder that was never
|
||||
> physically created. It has been split: user-universal columns moved
|
||||
> to the new `user_profiles` table (§3.5.12), and event-variable / skill
|
||||
> columns moved to `form_fields` and `person_tags`. See §3.5.12 for the
|
||||
> new structure and the column-by-column crosswalk.
|
||||
|
||||
### `volunteer_profiles`
|
||||
|
||||
| Column | Type | Notes |
|
||||
@@ -1924,3 +1931,59 @@ Immutable audit record of every email sent. No soft deletes.
|
||||
**Indexes:** `(organisation_id, created_at)`, `(recipient_email, created_at)`, `(template_type, status)`, `(event_id)`, `(person_id)`
|
||||
**Relations:** `belongsTo` organisation (nullable), event (nullable), person (nullable), user (nullable), triggeredBy → user
|
||||
**Soft delete:** no — immutable audit table
|
||||
|
||||
---
|
||||
|
||||
## 3.5.12 Form Builder
|
||||
|
||||
> See `/dev-docs/ARCH-FORM-BUILDER.md` v1.2 for the authoritative
|
||||
> specification. This SCHEMA.md section is a summary only and will be
|
||||
> fully rewritten at the end of S6.
|
||||
>
|
||||
> **Legacy tables retained intentionally.** The tables
|
||||
> `registration_form_fields`, `person_field_values`, and
|
||||
> `registration_field_templates` remain in the schema through end of S1.
|
||||
> They are dropped atomically in the first S2 commit together with the
|
||||
> removal of legacy controllers, services, requests, resources, policies,
|
||||
> and routes. DevSeeder and FormBuilderDevSeeder no longer write to them;
|
||||
> they hold zero rows in dev but the schema is preserved for environments
|
||||
> with real legacy data that will be migrated via
|
||||
> `forms:migrate-legacy-data`.
|
||||
|
||||
**Crosswalk: legacy `volunteer_profiles` → new locations**
|
||||
|
||||
| Legacy column | New location |
|
||||
| ------------------------------ | ----------------------------------------------- |
|
||||
| `bio` | `user_profiles.bio` |
|
||||
| `photo_url` | `user_profiles.photo_url` |
|
||||
| `tshirt_size` | `form_fields` (Pattern B, per event) |
|
||||
| `first_aid` | `person_tags` (system-seeded, S3) |
|
||||
| `driving_licence` | `person_tags` (system-seeded, S3) |
|
||||
| `allergies` | `form_fields` (Pattern B, per event) |
|
||||
| `access_requirements` | `form_fields` (Pattern B, per event) |
|
||||
| `emergency_contact_name` | `user_profiles.emergency_contact_name` |
|
||||
| `emergency_contact_phone` | `user_profiles.emergency_contact_phone` |
|
||||
| `reliability_score` | `user_profiles.reliability_score` |
|
||||
| `is_ambassador` | `user_profiles.is_ambassador` |
|
||||
|
||||
### New tables (S1)
|
||||
|
||||
| Table | Purpose |
|
||||
| --- | --- |
|
||||
| `user_profiles` | User-universal profile (bio, photo, emergency contact, reliability_score, is_ambassador, opaque settings JSON). 1:1 with `users`, auto-created by `UserObserver`. ARCH §4.13. |
|
||||
| `form_schemas` | Form definition. Polymorphic owner (event / user_profile / artist / company / null). Carries purpose, submission_mode, is_published, public_token, schema_snapshot policy, freeze_on_submit, retention/consent. ARCH §4.1. |
|
||||
| `form_schema_sections` | Optional sections within a schema (used when `section_level_submit=true`). ARCH §4.8. |
|
||||
| `form_field_library` | Reusable cross-schema field definitions. ARCH §4.7. |
|
||||
| `form_fields` | Field within a schema. `field_type` stored as string (custom types via `CustomFieldTypeRegistry`). Carries binding (Pattern A/B/C), is_filterable, is_pii, conditional_logic, value_storage_hint. ARCH §4.2. |
|
||||
| `form_submissions` | One submission per `(schema, subject)`. Polymorphic subject. Carries status, review_status, schema_snapshot copy, submission lifecycle timestamps, search_index. ARCH §4.3. |
|
||||
| `form_submission_section_statuses` | Per-section status when `section_level_submit=true`. ARCH §4.9. |
|
||||
| `form_submission_delegations` | "X fills in this submission on behalf of Y". ARCH §4.10. |
|
||||
| `form_values` | EAV row per `(submission, field)`. Integer AI PK for fast joins. Typed columns (value_indexed/number/date/bool) populated by `FormValueObserver`. ARCH §4.4. |
|
||||
| `form_value_options` | Filter pivot for multi-value fields (MULTISELECT/CHECKBOX_LIST/TAG_PICKER). Rebuilt by observer. ARCH §4.5. |
|
||||
| `form_templates` | Org-scoped reusable schema snapshots. `is_system` for shipped templates. ARCH §4.6. |
|
||||
| `form_schema_webhooks` | Webhook subscriptions per schema. URL/secret encrypted via Eloquent cast. ARCH §4.11. |
|
||||
| `form_webhook_deliveries` | Webhook delivery audit + retry queue. ARCH §4.12. |
|
||||
|
||||
**Activity log strategy:** explicit calls via `FormSchema::logSchemaChange()` and `FormField::logFieldChange()` — no `LogsActivity` trait (would produce noise). Only impactful events logged (publish toggle, purpose change, binding change, is_pii toggle, etc.). Bulk-fixture suppression via `App\Support\ActivityLog::suppressed(fn() => …)` which flips `config('activitylog.enabled')` for the callback.
|
||||
|
||||
**Multi-tenancy:** `OrganisationScope` applied on `FormSchema`, `FormTemplate`, `FormFieldLibrary`. Other form-builder tables inherit isolation through their parent schema; `FormSchemaWebhook` documents this discipline explicitly via a docblock warning to never query directly without an eager constraint.
|
||||
|
||||
Reference in New Issue
Block a user