feat: smart re-assignment with cancellation source tracking

Add cancelled_by, cancellation_source (organiser|volunteer|system), and
cancelled_at columns to shift_assignments. Cancel flow now records who
cancelled and why. Assign flow reactivates existing cancelled/rejected
records instead of creating duplicates, preventing UNIQUE constraint
violations. Assignable-persons endpoint returns previous_assignment data
for contextual UI indicators. Frontend shows cancellation source labels,
previous assignment history in assign dialog, and "Opnieuw toewijzen"
buttons with volunteer-cancelled confirmation dialogs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-10 21:50:24 +02:00
parent dfe7a63ad3
commit 3e292567c3
11 changed files with 554 additions and 7 deletions

View File

@@ -438,6 +438,9 @@ $effectiveDate = $shift->end_date ?? $shift->timeSlot->date;
| `approved_by` | ULID FK nullable | → users |
| `approved_at` | timestamp nullable | |
| `rejection_reason` | text nullable | |
| `cancelled_by` | ULID FK nullable | → users (who performed the cancellation) |
| `cancellation_source` | enum nullable | `organiser\|volunteer\|system` |
| `cancelled_at` | timestamp nullable | |
| `hours_expected` | decimal(4,2) nullable | Planned hours for this assignment |
| `hours_completed` | decimal(4,2) nullable | Actual hours worked — set after shift completion |
| `checked_in_at` | timestamp nullable | Shift-level check-in (when reported at section) |