package bookings import ( "context" "errors" "sort" "time" "github.com/jackc/pgx/v5" "bookra/apps/backend/internal/db" ) // PromoteWaitlist confirms the earliest waitlisted bookings on a class session // while free capacity remains. It returns the promoted records so callers can // notify customers. A missing session is treated as nothing to promote. func PromoteWaitlist(ctx context.Context, repo db.Repository, tenantID, sessionID string) ([]db.BookingRecord, error) { session, err := repo.GetClassSessionByID(ctx, sessionID) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil, nil } return nil, err } bookings, err := repo.ListBookingsByTenantBetween(ctx, tenantID, session.StartsAt.Add(-time.Second), session.EndsAt.Add(time.Second)) if err != nil { return nil, err } confirmed := 0 var waitlisted []db.BookingRecord for _, booking := range bookings { if booking.ClassSessionID == nil || *booking.ClassSessionID != sessionID { continue } switch booking.Status { case "confirmed": confirmed++ case "waitlisted": waitlisted = append(waitlisted, booking) } } if len(waitlisted) == 0 { return nil, nil } sort.SliceStable(waitlisted, func(i, j int) bool { return waitlisted[i].CreatedAt.Before(waitlisted[j].CreatedAt) }) var promoted []db.BookingRecord for _, booking := range waitlisted { if session.Capacity > 0 && confirmed >= int(session.Capacity) { break } if err := repo.UpdateBookingStatus(ctx, booking.ID, "confirmed"); err != nil { return promoted, err } _ = repo.ResolveWaitlistEntry(ctx, tenantID, sessionID, booking.CustomerEmail) confirmed++ promoted = append(promoted, booking) } return promoted, nil }