refactor: migrate patch test schema from service-level to dedicated tables
- Remove patch_test_duration_hours from services table - Add new patch_tests table with service_ids array, notice_duration_hours, expiry_months - Add new user_patch_tests table linking users to patch_tests with tested_at - Update services handler to check patch_tests.service_ids for eligibility - Update booking creation to validate patch test requirements (24h notice, 6mo expiry) - Update booking completion to extend patch test validity (reset tested_at) - Update admin handlers for new patch test CRUD operations - Update test fixtures and test cases for new schema - Update seeding script to create patch_tests and link to gel services
This commit is contained in:
@@ -429,6 +429,67 @@ func AdminCreateBookingForUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Check patch test requirements for all services
|
||||
for _, serviceID := range req.ServiceIDs {
|
||||
// Find patch test for this service
|
||||
var patchTestID string
|
||||
var noticeHours int
|
||||
err := db.DB.QueryRow(r.Context(), `
|
||||
SELECT id, notice_duration_hours
|
||||
FROM patch_tests
|
||||
WHERE $1 = ANY(service_ids)
|
||||
`, serviceID).Scan(&patchTestID, ¬iceHours)
|
||||
|
||||
if err == nil {
|
||||
// Service requires a patch test - check if user has valid record
|
||||
var testedAt time.Time
|
||||
err = db.DB.QueryRow(r.Context(), `
|
||||
SELECT tested_at
|
||||
FROM user_patch_tests
|
||||
WHERE user_id = $1 AND patch_test_id = $2
|
||||
`, req.UserID, patchTestID).Scan(&testedAt)
|
||||
|
||||
if err != nil {
|
||||
// No valid patch test record
|
||||
http.Error(w, "Patch test required for this service. Please complete a patch test first.", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Check if notice period has passed
|
||||
eligibleFrom := testedAt.Add(time.Duration(noticeHours) * time.Hour)
|
||||
if req.StartTime.Before(eligibleFrom) {
|
||||
hoursNeeded := time.Until(eligibleFrom).Hours()
|
||||
http.Error(w, fmt.Sprintf("Booking time is before the %.0f hour notice period after patch test. Earliest booking: %s", hoursNeeded, eligibleFrom.Format("2006-01-02 15:04")), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Check if patch test has expired
|
||||
var expiryMonths int
|
||||
err = db.DB.QueryRow(r.Context(), `SELECT expiry_months FROM patch_tests WHERE id = $1`, patchTestID).Scan(&expiryMonths)
|
||||
if err == nil {
|
||||
expiresAt := testedAt.AddDate(0, expiryMonths, 0)
|
||||
if req.StartTime.After(expiresAt) {
|
||||
http.Error(w, "Your patch test has expired. Please complete a new patch test.", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate overrides
|
||||
if req.UserID == "" {
|
||||
http.Error(w, "User ID is required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.StartTime.IsZero() {
|
||||
http.Error(w, "Start time is required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if len(req.ServiceIDs) == 0 {
|
||||
http.Error(w, "At least one service is required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Validate overrides
|
||||
for _, override := range req.ServiceOverrides {
|
||||
if override.ServiceID == "" {
|
||||
|
||||
Reference in New Issue
Block a user