Refactor patch test system and add booking edit requests

- Replace patch_test_duration_hours on services with separate
  patch_tests table
- Add user_patch_tests table to track user patch test records
- Add booking edit request system: users can request time changes
- Add admin handlers to list, approve, and reject edit requests
- Add validation to prevent editing completed/cancelled bookings
- Add overlap and closed-day checks for booking edits
This commit is contained in:
2026-02-24 17:23:28 +00:00
parent 89d848ee72
commit f59595eeec
11 changed files with 906 additions and 255 deletions
+20 -22
View File
@@ -30,12 +30,11 @@ func TestAdminServices_Create(t *testing.T) {
handler := http.HandlerFunc(services.CreateServiceHandler)
createReq := services.CreateServiceRequest{
Name: "Test Manicure",
Description: stringPtr("A test manicure service"),
Price: 35.00,
DurationMinutes: 45,
PatchTestDurationHours: 0,
MinimumAgeRequired: 16,
Name: "Test Manicure",
Description: stringPtr("A test manicure service"),
Price: 35.00,
DurationMinutes: 45,
MinimumAgeRequired: 16,
}
w := makeAdminRequest(handler, "POST", "/api/admin/services", createReq)
@@ -66,11 +65,11 @@ func TestAdminServices_List(t *testing.T) {
// Insert test services
_, err := db.DB.Exec(context.Background(), `
INSERT INTO services (name, description, price, duration_minutes, is_active, patch_test_duration_hours, minimum_age_required)
INSERT INTO services (name, description, price, duration_minutes, is_active, minimum_age_required)
VALUES
('Manicure', 'Basic manicure', 25.00, 30, true, 0, 0),
('Pedicure', 'Basic pedicure', 30.00, 45, false, 0, 0),
('Gel Polish', 'Gel polish service', 40.00, 60, true, 48, 16)
('Manicure', 'Basic manicure', 25.00, 30, true, 0),
('Pedicure', 'Basic pedicure', 30.00, 45, false, 0),
('Gel Polish', 'Gel polish service', 40.00, 60, true, 16)
`)
if err != nil {
t.Fatalf("failed to create services: %v", err)
@@ -116,8 +115,8 @@ func TestAdminServices_Toggle(t *testing.T) {
// Create a service
var serviceID string
err := db.DB.QueryRow(context.Background(), `
INSERT INTO services (name, description, price, duration_minutes, is_active, patch_test_duration_hours, minimum_age_required)
VALUES ('Test Service', 'A test service', 50.00, 60, true, 0, 16)
INSERT INTO services (name, description, price, duration_minutes, is_active, minimum_age_required)
VALUES ('Test Service', 'A test service', 50.00, 60, true, 16)
RETURNING id
`).Scan(&serviceID)
if err != nil {
@@ -164,8 +163,8 @@ func TestAdminServices_Delete(t *testing.T) {
// Create a service
var serviceID string
err := db.DB.QueryRow(context.Background(), `
INSERT INTO services (name, description, price, duration_minutes, is_active, patch_test_duration_hours, minimum_age_required)
VALUES ('Test Service', 'A test service', 50.00, 60, true, 0, 16)
INSERT INTO services (name, description, price, duration_minutes, is_active, minimum_age_required)
VALUES ('Test Service', 'A test service', 50.00, 60, true, 16)
RETURNING id
`).Scan(&serviceID)
if err != nil {
@@ -206,12 +205,11 @@ func TestAdminServices_NonAdmin(t *testing.T) {
// Test CREATE - should get 403 when using middleware
createHandler := mw.RequireAdmin(http.HandlerFunc(services.CreateServiceHandler))
createReq := services.CreateServiceRequest{
Name: "Test Service",
Description: stringPtr("Test"),
Price: 50.00,
DurationMinutes: 60,
PatchTestDurationHours: 0,
MinimumAgeRequired: 16,
Name: "Test Service",
Description: stringPtr("Test"),
Price: 50.00,
DurationMinutes: 60,
MinimumAgeRequired: 16,
}
w := makeUserRequest(createHandler, "POST", "/api/admin/services", createReq)
if w.Code != http.StatusForbidden {
@@ -228,8 +226,8 @@ func TestAdminServices_NonAdmin(t *testing.T) {
// Test TOGGLE - should get 403 when using middleware
var serviceID string
err = db.DB.QueryRow(context.Background(), `
INSERT INTO services (name, description, price, duration_minutes, is_active, patch_test_duration_hours, minimum_age_required)
VALUES ('Test Service', 'A test service', 50.00, 60, true, 0, 16)
INSERT INTO services (name, description, price, duration_minutes, is_active, minimum_age_required)
VALUES ('Test Service', 'A test service', 50.00, 60, true, 16)
RETURNING id
`).Scan(&serviceID)
if err != nil {