refactor: update deposit system with 24h no-show rule, optional forgiveness, and admin enforcement toggle

- Change no-show threshold from 12h to 24h for late cancellations
- Add optional forgive_no_show boolean to cancellation endpoint
- Add optional enforce_deposits boolean to admin booking creation
- Set deposits_required = 3 on no-show (not +=3) to prevent escalation
- Implement per-cancellation forgiveness instead of bulk forgiveness
- Remove ForgiveNoShowsForUser() function (now per-event)
- Admin can now bypass deposit checks when needed
- All changes backward compatible (nil defaults to enforce)
This commit is contained in:
2026-03-07 17:39:32 +00:00
parent faa4d89152
commit c275265794
2 changed files with 48 additions and 61 deletions
+14 -7
View File
@@ -139,6 +139,7 @@ type ServiceOverride struct {
// DeleteBookingRequest represents the request payload for deleting a booking with payment
type DeleteBookingRequest struct {
Reason string `json:"reason" validate:"required,oneof=client_cancelled we_cancelled re-schedule no_show"`
ForgiveNoShow *bool `json:"forgive_no_show,omitempty"` // Admin-only: forgive a no-show at cancellation time
}
// AdminUserSummary represents a small user summary for admin views
@@ -1842,13 +1843,19 @@ func DeleteBookingHandler(w http.ResponseWriter, r *http.Request) {
tx.QueryRow(r.Context(), "SELECT start_time FROM bookings WHERE id = $1", bookingID).Scan(&startTime)
noticeHours := startTime.Sub(time.Now()).Hours()
if noticeHours < 12 {
tx.Exec(r.Context(), "UPDATE users SET deposits_required = deposits_required + 3 WHERE id = $1", userID)
tx.Exec(r.Context(), "UPDATE bookings SET status = 'no_show' WHERE id = $1", bookingID)
} else if noticeHours < 24 {
tx.Exec(r.Context(), `
INSERT INTO admin_notifications (reason, booking_id, user_id) VALUES ($1, $2, $3)
`, "late_cancellation", bookingID, userID)
// < 24 hours notice: treat as no-show
if noticeHours < 24 {
// Check if admin is forgiving this no-show
isForgiving := req.ForgiveNoShow != nil && *req.ForgiveNoShow
if !isForgiving {
// No forgiveness: apply penalty
tx.Exec(r.Context(), "UPDATE users SET deposits_required = 3 WHERE id = $1", userID)
tx.Exec(r.Context(), "UPDATE bookings SET status = 'no_show' WHERE id = $1", bookingID)
} else {
// Forgiveness granted: treat as client_cancelled, no penalty
tx.Exec(r.Context(), "UPDATE bookings SET status = 'client_cancelled' WHERE id = $1", bookingID)
}
}
if _, err := tx.Exec(r.Context(), `