update tests
This commit is contained in:
@@ -1240,8 +1240,35 @@ func CreateBookingHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
if req.StartTime.Before(time.Now()) {
|
if req.StartTime.Before(time.Now()) {
|
||||||
http.Error(w, "Start time cannot be in the past", http.StatusBadRequest)
|
http.Error(w, "Start time cannot be in the past", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate booking fits within operating hours for regular users
|
||||||
|
var svcDuration int
|
||||||
|
if err := db.DB.QueryRow(r.Context(), `
|
||||||
|
SELECT COALESCE(SUM(duration_minutes), 0) FROM services WHERE id = ANY($1)
|
||||||
|
`, req.ServiceIDs).Scan(&svcDuration); err != nil {
|
||||||
|
log.Printf("Failed to calc duration: %v", err)
|
||||||
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
weekday := int(req.StartTime.Weekday())
|
||||||
|
var closeStr string
|
||||||
|
if err := db.DB.QueryRow(r.Context(), `SELECT end_time::text FROM working_hours WHERE weekday = $1`, weekday).Scan(&closeStr); err != nil {
|
||||||
|
log.Printf("Failed to get hours: %v", err)
|
||||||
|
http.Error(w, "Could not verify hours", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
endTime := req.StartTime.Add(time.Duration(svcDuration) * time.Minute)
|
||||||
|
closeTime, _ := time.Parse("15:04:05", closeStr)
|
||||||
|
if endTime.Hour() > closeTime.Hour() || (endTime.Hour() == closeTime.Hour() && endTime.Minute() > closeTime.Minute()) {
|
||||||
|
http.Error(w, "Cannot book this time - services would extend beyond closing hours", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get created by from context (if available)
|
// Get created by from context (if available)
|
||||||
var createdBy *string
|
var createdBy *string
|
||||||
if creatorID, ok := r.Context().Value(mw.UserIDKey).(string); ok {
|
if creatorID, ok := r.Context().Value(mw.UserIDKey).(string); ok {
|
||||||
@@ -1698,6 +1725,31 @@ func ConfirmBookingHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for overlapping confirmed/in_progress/completed bookings before confirming
|
||||||
|
var bkStart time.Time
|
||||||
|
if err := db.DB.QueryRow(r.Context(), "SELECT start_time FROM bookings WHERE id = $1", bookingID).Scan(&bkStart); err != nil {
|
||||||
|
log.Printf("Failed to get start time: %v", err)
|
||||||
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var dur int
|
||||||
|
db.DB.QueryRow(r.Context(), `
|
||||||
|
SELECT COALESCE(SUM(COALESCE(bs.override_duration_minutes, s.duration_minutes)), 60)
|
||||||
|
FROM booking_services bs JOIN services s ON bs.service_id = s.id WHERE bs.booking_id = $1
|
||||||
|
`, bookingID).Scan(&dur)
|
||||||
|
newEnd := bkStart.Add(time.Duration(dur) * time.Minute)
|
||||||
|
|
||||||
|
var cnt int
|
||||||
|
db.DB.QueryRow(r.Context(), `
|
||||||
|
SELECT COUNT(*) FROM bookings WHERE id != $1 AND status IN ('confirmed','in_progress','completed') AND start_time < $3 AND start_time + (INTERVAL '1 minute' * (SELECT COALESCE(SUM(COALESCE(bs.override_duration_minutes,s.duration_minutes)),60) FROM booking_services bs JOIN services s ON bs.service_id=s.id WHERE bs.booking_id=bookings.id)) > $2
|
||||||
|
`, bookingID, bkStart, newEnd).Scan(&cnt)
|
||||||
|
if cnt > 0 {
|
||||||
|
http.Error(w, "Cannot confirm - time slot overlaps with existing booking", http.StatusConflict)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
tx, err := db.DB.Begin(r.Context())
|
tx, err := db.DB.Begin(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to start transaction: %v", err)
|
log.Printf("Failed to start transaction: %v", err)
|
||||||
|
|||||||
@@ -537,8 +537,25 @@ func AdminCreateBookingForUserHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
if isClosed {
|
if isClosed {
|
||||||
http.Error(w, "Cannot book during holiday hours when the salon is closed", http.StatusConflict)
|
http.Error(w, "Cannot book during holiday hours when the salon is closed", http.StatusConflict)
|
||||||
return
|
return
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for overlapping confirmed/in_progress/completed bookings
|
||||||
|
var dur int
|
||||||
|
db.DB.QueryRow(r.Context(), `
|
||||||
|
SELECT COALESCE(SUM(duration_minutes), 0) FROM services WHERE id = ANY($1)
|
||||||
|
`, req.ServiceIDs).Scan(&dur)
|
||||||
|
newEnd := req.StartTime.Add(time.Duration(dur) * time.Minute)
|
||||||
|
var cnt int
|
||||||
|
db.DB.QueryRow(r.Context(), `
|
||||||
|
SELECT COUNT(*) FROM bookings WHERE status IN ('confirmed','in_progress','completed') AND start_time < $2 AND start_time + (INTERVAL '1 minute' * (SELECT COALESCE(SUM(COALESCE(bs.override_duration_minutes,s.duration_minutes)),60) FROM booking_services bs JOIN services s ON bs.service_id=s.id WHERE bs.booking_id=bookings.id)) > $1
|
||||||
|
`, req.StartTime, newEnd).Scan(&cnt)
|
||||||
|
if cnt > 0 {
|
||||||
|
http.Error(w, "Cannot create booking - time slot overlaps with existing booking", http.StatusConflict)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
tx, err := db.DB.Begin(r.Context())
|
tx, err := db.DB.Begin(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to start transaction: %v", err)
|
log.Printf("Failed to start transaction: %v", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user