Parent
#237
What to build
Implement cancellation with deadline validation and automatic waitlist promotion (FIFO) when a confirmed participant cancels.
Action: CancelEnrollmentAction
- Validates: enrollment status must be
confirmed, waitlisted, or pending
- Validates deadline:
now() < event.starts_at - policy.cancellation_deadline_hours
- Transitions enrollment to
cancelled, sets cancelled_at timestamp
- Records transition in audit trail (triggered_by=user, reason optional)
- If the cancelled enrollment was
confirmed AND there are waitlisted enrollments: trigger promotion
Action: PromoteFromWaitlistAction
- Finds the oldest
waitlisted enrollment (ordered by enrolled_at ASC, LIMIT 1)
- Transitions it to
confirmed, sets confirmed_at, clears waitlist_position
- Records transition (triggered_by=system, reason="slot opened from cancellation")
- Dispatches
EnrollmentConfirmed domain event for the promoted enrollment
- Recalculates
waitlist_position for remaining waitlisted enrollments (optional optimization: just leave gaps)
App panel:
- "Cancel" button visible on enrollment when:
- Status is
confirmed, waitlisted, or pending
- Deadline has not passed
- Shows "Cancellation deadline passed" message when deadline expired
- Confirmation dialog before cancelling
Admin panel:
- "Cancel Enrollment" action available on enrollment records (bypasses deadline — admin override)
- Shows cancellation reason in transitions log
Edge cases:
- Cancellation after deadline: rejected with 422 and message showing deadline
- Cancellation of
waitlisted: does NOT trigger promotion (no slot was freed)
- Multiple cancellations in quick succession: each promotes the next in line
Acceptance criteria
Blocked by
Parent
#237
What to build
Implement cancellation with deadline validation and automatic waitlist promotion (FIFO) when a confirmed participant cancels.
Action:
CancelEnrollmentActionconfirmed,waitlisted, orpendingnow() < event.starts_at - policy.cancellation_deadline_hourscancelled, setscancelled_attimestampconfirmedAND there are waitlisted enrollments: trigger promotionAction:
PromoteFromWaitlistActionwaitlistedenrollment (ordered byenrolled_at ASC, LIMIT 1)confirmed, setsconfirmed_at, clearswaitlist_positionEnrollmentConfirmeddomain event for the promoted enrollmentwaitlist_positionfor remaining waitlisted enrollments (optional optimization: just leave gaps)App panel:
confirmed,waitlisted, orpendingAdmin panel:
Edge cases:
waitlisted: does NOT trigger promotion (no slot was freed)Acceptance criteria
cancelledconfirmedenrollment promotes next waitlisted participant (FIFO)confirmedstatus with proper transition recordEnrollmentConfirmedis dispatched for promoted enrollmentwaitlistedenrollment does not trigger promotionBlocked by