Context
The 2026-07-17 booking-lifecycle audit found that cancelling a whole webinar or class refunds nobody and notifies nobody. The cancel route only assembles notification recipients for exclusive (1:1) types, its refund block is exclusive-types-only (app/api/appointments/[appointmentId]/cancel/route.ts:167-187, 306-315, 372-376), and the participant-removal endpoints contain no payment handling at all (app/api/participants/webinar/[webinarId]/route.ts:188-211). Deletion of a paid group event is blocked with "Cancel or refund first", which is circular because no in-app path can refund the attendees. Attendee ConsultantEarnings are also never reversed, so a consultant who cancels a webinar keeps the per-attendee earnings.
Proposed approach
Once the refund-gateway wiring PR lands, iterate the group event's paid attendee appointments on wrapper cancellation: create a gateway refund per attendee payment under the existing policy snapshot, reverse the matching earnings rows through the standard cascade, and fan out cancellation notifications to every enrolled attendee. The attendee-removal endpoint should reuse the same per-attendee unit.
Blocked by the refund-gateway PR (audit M1). Audit ids C3/M2; found alongside #998.
Context
The 2026-07-17 booking-lifecycle audit found that cancelling a whole webinar or class refunds nobody and notifies nobody. The cancel route only assembles notification recipients for exclusive (1:1) types, its refund block is exclusive-types-only (
app/api/appointments/[appointmentId]/cancel/route.ts:167-187, 306-315, 372-376), and the participant-removal endpoints contain no payment handling at all (app/api/participants/webinar/[webinarId]/route.ts:188-211). Deletion of a paid group event is blocked with "Cancel or refund first", which is circular because no in-app path can refund the attendees. AttendeeConsultantEarningsare also never reversed, so a consultant who cancels a webinar keeps the per-attendee earnings.Proposed approach
Once the refund-gateway wiring PR lands, iterate the group event's paid attendee appointments on wrapper cancellation: create a gateway refund per attendee payment under the existing policy snapshot, reverse the matching earnings rows through the standard cascade, and fan out cancellation notifications to every enrolled attendee. The attendee-removal endpoint should reuse the same per-attendee unit.
Blocked by the refund-gateway PR (audit M1). Audit ids C3/M2; found alongside #998.