Commit Graph

8 Commits

Author SHA1 Message Date
889441cb39 fix(timetable): config-flag observer + cleaner idempotency_key
OrganisationObserver was gated on app()->runningUnitTests() — replaced
with config('artist_advance.bootstrap_on_org_create') (default true,
phpunit.xml overrides to false). Behaviour identical, but the seam is
explicit and removable. Tracked for full convergence by new BACKLOG
entry TECH-OBSERVER-TEST-CONVERGENCE — productiegedrag = testgedrag,
geen branching, na test-cleanup.

idempotency_key for the engagement-scoped draft simplified from
'aa-' + sha1(engagement_id)[0:27] to 'aa:' + engagement_id (29 chars,
fits varchar(30)). Same uniqueness guarantee, recognisable shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 23:18:15 +02:00
96eb7e91e7 test(timetable): Phase C — observer, resolver, seeder, portal controller tests
22 new tests across four files:
  - AdvanceSectionObserverTest (7) — counter recompute on create / status
    transition / delete / is_open toggle no-op / orphaned-section guard /
    no activity-log noise on counter writes
  - ArtistResolverTest (4) — happy path / invalid token / soft-deleted
    artist / SHA-256 digest verification
  - ArtistAdvanceDefaultTest (6) — five-section + slug shape / idempotency
    / per-section field shape / observer-invocation outside tests /
    artisan one-org + all-orgs paths
  - EngagementPortalControllerTest (6) — show 200/404/410 / show-section
    schema + draft values / submit happy-path with submission persistence
    + counter recompute / cross-engagement section returns 404

Implementation tweaks driven by test feedback:
  - OrganisationObserver gated by `app()->runningUnitTests()` — auto-seed
    runs in production but is silent in CI so existing FormSchema-counting
    tests are unperturbed. Tests that need the seeded schema invoke
    `ArtistAdvanceDefault::seedFor()` explicitly.
  - EngagementPortalController idempotency_key uses `aa-` + sha1 prefix
    (28 chars) so it fits the form_submissions.idempotency_key
    varchar(30) column.

Test count: 1709 (Session 2 close) → 1731 (+22).
Larastan: 0 new errors over baseline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 22:39:04 +02:00
e26da4fb42 docs(timetable): close ART-OBSERVER-ADVANCE-AGGREGATE; wire event_id through createDraft
§17.3 footnote already accurately describes ArtistResolver::fromPortalToken
(checked at commit cc48011). Wired event_id end-to-end on the cleaner
path: FormSubmissionService::createDraft now accepts event_id via the
\$context bag, and the EngagementPortalController passes it from
\$resolved->eventId. Replaces the prior post-save fallback. Per WS-4
denormalisation requirement.

ART-OBSERVER-ADVANCE-AGGREGATE moved from open to closed — landed in
Session 3 as the AdvanceSectionObserver (commit 1716e09).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 22:23:43 +02:00
eba162f255 feat(timetable): EngagementPortalController + /p/artist/{token}/* routes
Three backend endpoints under public throttle:30,1:
  GET  /p/artist/{token}                       — engagement summary + sections
  GET  /p/artist/{token}/sections/{section}    — form schema + draft values
  POST /p/artist/{token}/sections/{section}    — section submit

Token resolution via ArtistResolver::fromPortalToken (Step 2). The
master Artist becomes the FormSubmission subject; engagement.event_id
populates form_submissions.event_id per WS-4 denormalisation. Token
mismatches map to 404 (InvalidPortalTokenException), soft-deleted
master artists to 410 Gone (ArtistDeletedException).

Section submit reuses the existing FormBindingApplicator pipeline
(RFC-WS-6 v1.3.1) by dispatching FormSubmissionSectionSubmitted —
no parallel apply path. Drafts are idempotent on
'artist_advance:{engagement_id}', so repeated POSTs find the same
submission. AdvanceSection (engagement-scoped) ↔ FormSchemaSection
bridge: case-sensitive name match against the org's artist_advance
schema; the default seeder names them in lockstep.

Frontend in Session 5 — backend complete here.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 22:22:02 +02:00
53100d4f6d feat: portal cross-event my-shifts endpoint and dashboard page
GET /portal/my-shifts aggregates shift assignments across all events
the logged-in user is linked to via Person records. Groups by event
then date, showing only active assignments (approved/pending_approval)
for approved/pending persons.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:07:08 +02:00
090d2b7d89 security: round 2 — multi-tenancy isolation (OrganisationScope, scoped validation, boundary checks)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 06:38:19 +02:00
59ad09fad2 feat(portal): auth persistence, shift visibility, profile page, and UI polish
- Fix session persistence: add loading state to App.vue, hydrate portal store
  in router guards so page refresh preserves auth + event context
- Fix shift visibility for festivals: query child event time slots so shifts
  on sub-events appear in the portal
- Add profile page with editable personal info and password change
- Add backend endpoints: PUT /portal/profile and PUT /portal/password
- Fix registration form: make first_name/last_name editable for logged-in users
- Restyle login page: remove Vuexy illustration, center form with Crewli branding
- Improve dashboard StatusCard with action cards, icons, and upcoming shift count
- Enhance shift cards with status border colors and availability progress bars

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 10:19:14 +02:00
5173f7297f feat(portal): shift claiming and my-shifts for volunteer portal
Backend: PortalShiftController with 4 endpoints (available-shifts,
my-shifts, claim, cancel) delegating to ShiftAssignmentService.
24 PHPUnit tests covering happy paths, auth, conflicts, and edge cases.

Frontend: claim-shifts and my-shifts pages with TanStack Query
composable, conflict detection, confirmation dialogs, and cancel flow.
Navigation and dashboard cards wired up for approved volunteers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 08:47:12 +02:00