feat(bookings): add out_of_hours field to Booking struct and admin queries

Include out_of_hours in GetAllAdminBookings, GetAdminBooking, and SearchAdminBookings queries. Add tests verifying out_of_hours appears in single and list booking responses.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-06-22 12:54:44 +01:00
co-authored by Sisyphus
parent b4c1e98176
commit 260c760971
2 changed files with 386 additions and 3 deletions
+10 -3
View File
@@ -43,6 +43,7 @@ type Booking struct {
UpdatedAt time.Time `json:"updated_at"`
CreatedBy *string `json:"created_by,omitempty"`
CreatedByName *string `json:"created_by_name,omitempty"`
OutOfHours bool `json:"out_of_hours"`
// Deposit fields.
// DepositRequired is snapshotted at creation from users.deposits_required > 0
@@ -652,7 +653,7 @@ func GetAllAdminBookingsHandler(w http.ResponseWriter, r *http.Request) {
WHERE status = 'completed'
GROUP BY booking_id
)
SELECT
SELECT
b.id,
b.created_at,
b.user_id,
@@ -665,7 +666,8 @@ func GetAllAdminBookingsHandler(w http.ResponseWriter, r *http.Request) {
COALESCE(bt.total_amount, 0) - COALESCE(pt.total_paid, 0) AS amount_due,
b.deposit_required,
COALESCE(bt.service_count, 0) AS service_count,
COALESCE(pre_pay.pre_start_amount_paid, 0) AS pre_start_amount_paid
COALESCE(pre_pay.pre_start_amount_paid, 0) AS pre_start_amount_paid,
b.out_of_hours
FROM bookings b
LEFT JOIN users u ON b.user_id = u.id
LEFT JOIN booking_totals bt ON b.id = bt.booking_id
@@ -796,6 +798,7 @@ func GetAllAdminBookingsHandler(w http.ResponseWriter, r *http.Request) {
&b.ID, &createdAt, &bookingUserID, &b.StartTime, &b.Status, &userFullName,
&b.DurationMinutes, &totalAmount, &amountPaid, &amountDue,
&depositRequired, new(int), &preStartAmountPaid,
&b.OutOfHours,
); err != nil {
log.Printf("Failed to scan booking row: %v", err)
http.Error(w, "Internal server error", http.StatusInternalServerError)
@@ -1138,6 +1141,7 @@ func GetAdminBookingHandler(w http.ResponseWriter, r *http.Request) {
SELECT
b.id, b.user_id, b.start_time, b.status, b.notes,
b.created_at, b.updated_at, b.created_by,
b.out_of_hours,
u.fn, u.email, u.phone, u.profile_pic_url, u.date_of_birth, u.loyalty_stamps,
u.referral_code, u.notes,
creator.fn,
@@ -1149,6 +1153,7 @@ func GetAdminBookingHandler(w http.ResponseWriter, r *http.Request) {
`, bookingID).Scan(
&booking.ID, &booking.User.ID, &booking.StartTime, &booking.Status, &booking.Notes,
&booking.CreatedAt, &booking.UpdatedAt, &booking.CreatedBy,
&booking.OutOfHours,
&booking.User.FullName, &booking.User.Email, &booking.User.Phone,
&booking.User.ProfilePicURL, &dateOfBirth, &booking.User.LoyaltyStamps,
&booking.User.ReferralCode, &booking.User.Notes,
@@ -1740,7 +1745,8 @@ func SearchAdminBookingsHandler(w http.ResponseWriter, r *http.Request) {
COALESCE(pt.total_paid, 0) AS amount_paid,
COALESCE(bt.total_amount, 0) - COALESCE(pt.total_paid, 0) AS amount_due,
b.deposit_required,
COALESCE(pre_pay.pre_start_amount_paid, 0) AS pre_start_amount_paid
COALESCE(pre_pay.pre_start_amount_paid, 0) AS pre_start_amount_paid,
b.out_of_hours
FROM bookings b
LEFT JOIN users u ON b.user_id = u.id
LEFT JOIN booking_totals bt ON b.id = bt.booking_id
@@ -1813,6 +1819,7 @@ func SearchAdminBookingsHandler(w http.ResponseWriter, r *http.Request) {
&b.ID, &b.StartTime, &b.Status, &userFullName,
&b.DurationMinutes, &totalAmount, &amountPaid, &amountDue,
&depositRequired, &preStartAmountPaid,
&b.OutOfHours,
); err != nil {
log.Printf("Failed to scan booking row: %v", err)
http.Error(w, "Internal server error", http.StatusInternalServerError)