UPDATED TEST FILES:
1. backend/handlers/bookings/bookings_test.go (added 6 new tests):
- TestBookings_Create_MinimumAdvance: Renamed from 48h check, now tests 1h requirement
- TestBookings_Create_WithNotes_StatusPending: NEW - verifies notes cause 'pending' status
- TestBookings_Create_WithoutNotes_StatusConfirmed: NEW - verifies auto-approval without notes
- TestBookings_Create_Within1Hour_ShouldFail: NEW - verifies < 1h bookings are rejected
- TestBookings_Delete_NoShow24hThreshold: NEW - tests 24h no-show rule & deposit penalty
- TestBookings_Delete_NoShow_WithForgiveness: NEW - tests forgive_no_show parameter
2. backend/handlers/admin/bookings_test.go (added 2 new tests):
- TestAdminBookings_Create_EnforceDeposits_Bypass: NEW - admin can bypass deposit checks
- TestAdminBookings_Create_EnforceDeposits_Enforced: NEW - default enforcement behavior
3. backend/handlers/scheduling/time_blockers_test.go (added 1 new test):
- TestCleanupOldReservations: NEW - verifies 1h+ old reservations are cleaned up
TEST COVERAGE FOR NEW FEATURES:
✓ 1h minimum advance requirement (universal, not deposit-dependent)
✓ Notes → 'pending' status (auto-approval workflow)
✓ No notes → 'confirmed' status (auto-approved)
✓ 24h no-show threshold (< 24h = penalty, >= 24h = late cancellation)
✓ forgive_no_show parameter (admin can forgive no-shows)
✓ Deposit penalty: set to 3 (not +=3, prevents escalation)
✓ enforce_deposits parameter (admin can bypass checks)
✓ Reservation cleanup (auto-delete > 1h old reservations)
VERIFICATION:
✓ All test code compiles (go build -tags test ./handlers/bookings)
✓ All test code compiles (go build -tags test ./handlers/admin)
✓ All test code compiles (go build -tags test ./handlers/scheduling)
✓ Main build still works (go build -tags dev ./main.go)
TEST EXECUTION (to run):
go test -tags test -v ./handlers/bookings -run TestBookings_Create_WithNotes
go test -tags test -v ./handlers/bookings -run TestBookings_Delete_NoShow
go test -tags test -v ./handlers/admin -run TestAdminBookings_Create_EnforceDeposits
go test -tags test -v ./handlers/scheduling -run TestCleanupOldReservations
- Change no-show threshold from 12h to 24h for late cancellations
- Add optional forgive_no_show boolean to cancellation endpoint
- Add optional enforce_deposits boolean to admin booking creation
- Set deposits_required = 3 on no-show (not +=3) to prevent escalation
- Implement per-cancellation forgiveness instead of bulk forgiveness
- Remove ForgiveNoShowsForUser() function (now per-event)
- Admin can now bypass deposit checks when needed
- All changes backward compatible (nil defaults to enforce)
CHANGES:
Phase 1: Schema
- Change deposits_required default from 3 to 0 for new users
- Add forgiven_no_shows table to track forgiven no-show bookings
Phase 2: No-Show Logic (manage.go)
- CountUnforgivenNoShows(): Count unforgiven no-shows in 6-month period
- ApplyDepositsIfNeeded(): Auto-apply 3 deposits if 2+ no-shows detected
- ForgiveNoShowsForUser(): Clear no-shows and reset deposits on full payment
Phase 3: Slot Reservation System
- Add CleanupOldReservations() to delete 1h+ old reservation blockers
- Call cleanup in GetAvailableHours() on each availability check
- Delete existing user reservation before creating new booking
Phase 4: Minimum Advance Time
- Changed from 48h (deposit-only) to 1h (all users)
- Now universally enforced at booking creation time
Phase 5: Notes-Based Approval Workflow
- If booking has notes (not empty) → status = 'pending' (needs approval)
- If no notes → status = 'confirmed' (auto-approved)
- Uses CASE statement in INSERT for status determination
Phase 6: Late Night Lock
- After 22:00, non-admin users cannot book next morning before 11:00
- Implemented in GetAvailableHours() via artificial blocker subtraction
- Admin users see all times (no restriction)
Phase 7: Admin Notifications
- Notify admin if booking has notes OR is for same day
- All qualifying bookings trigger notification for admin review
VERIFICATION:
✓ Build passes: go build -tags dev ./main.go succeeds
✓ All 7 phases implemented as per dev-approved plan
✓ No breaking changes to existing schemas
✓ Backward compatible with existing booking flow
- Use fixed date (Thursday Feb 26, 2026) instead of dynamic tomorrow
to avoid timezone-related test flakiness
- Remove orphaned SQL fragment from init-script.sql
- Clean up duplicate color code definitions in local-dev-2.sh
- Add Rustfs data wipe and SabreDAV startup to dev script
- Add composer.lock to .gitignore
- 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
- 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
- Add TestMain to set test env vars and testdb.TruncateTables for test
isolation
- Add chi routing context to test helpers for path parameter extraction
- Fix SQL error handling to use errors.Is() instead of ==
- Add validators package with ID validation
- Fix admin test middleware chain (RequireAdmin wrapper)
- Update test user inserts to include phone and date_of_birth fields
- Update service delete test to check soft-delete (is_active=false)
- Update holiday hours test to use new schema (weekday, is_open)
- Add phone number validation tests for UK mobile numbers
Backend:
- Fix GetAllAdminBookingsHandler and SearchAdminBookingsHandler to
return totalPages in response
- Auto-record patch tests when booking status progresses to "completed"
- Add GET/POST /api/admin/users/{id}/patch-tests endpoints
Frontend:
- BookingsCard: proper pagination with 4 per page, prev/next buttons
- UsersCard, BookingCreateModal, WalkInCreateModal: per_page=4 for user
search
- Add PatchTestModal for manual patch test entry in UserModal
- Hide patch test section when user has no eligible services
Database:
- Add UNIQUE constraint on user_service_patch_tests(user_id, service_id)
- Add AcknowledgePendingBookingNotification helper for acknowledging notifications
- ConfirmBookingHandler: acknowledge pending notification when booking confirmed
- Cancel handlers: acknowledge pending notification and only create cancelled_booking notification if booking was not in pending status
- Add user_notification_preferences table with email, sms, push enabled flags
- Update cancellation logic to check original status before creating notifications
Backend:
- Enriched GetAllUserBookings response with calculated total_amount,
amount_paid, and duration_minutes.
- Refactored GetBookingHandler to return a flat booking object matching
frontend expectations.
- Added account_role to admin user list response and sorted users by
booking activity.
- Corrected function name oo to AdminCreateBookingForUserHandler.
Frontend:
- Rebuilt BookingCreateModal into a 4-step wizard supporting guest
bookings, service overrides, and real-time availability checks.
- Fixed account dashboard logic to correctly identify upcoming vs past
bookings and sort unpaid items to the top.
- Extracted booking flow into a shared BookingFlow component.
- Redirected admin users from home page to /today.