Deposit tracking
This commit is contained in:
@@ -1488,3 +1488,153 @@ func TestAdminBookings_ApproveEditRequest(t *testing.T) {
|
|||||||
t.Errorf("expected notification to be acknowledged after approve, but acknowledged_at is still NULL")
|
t.Errorf("expected notification to be acknowledged after approve, but acknowledged_at is still NULL")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Deposit System Tests
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
// TestAdminBookings_Get_DepositFields verifies that admin booking endpoints return
|
||||||
|
// deposit-related fields (deposit_required, deposit_amount, deposit_paid, deposit_deadline)
|
||||||
|
// for bookings that have deposit_required=true.
|
||||||
|
func TestAdminBookings_Get_DepositFields(t *testing.T) {
|
||||||
|
cleanup := setupTestDB(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
adminID, err := fixtures.CreateTestAdminUser(db.DB)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create admin user: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteUser(db.DB, adminID)
|
||||||
|
|
||||||
|
userID, err := fixtures.CreateTestUser(db.DB)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create test user: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteUser(db.DB, userID)
|
||||||
|
|
||||||
|
serviceID, err := fixtures.CreateTestService(db.DB)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create test service: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteService(db.DB, serviceID)
|
||||||
|
|
||||||
|
// Create booking via SQL with deposit_required=true (simulating user-created booking)
|
||||||
|
futureTime := time.Now().Add(72 * time.Hour).Truncate(time.Second)
|
||||||
|
var bookingID string
|
||||||
|
err = db.DB.QueryRow(context.Background(), `
|
||||||
|
INSERT INTO bookings (user_id, start_time, status, deposit_required)
|
||||||
|
VALUES ($1, $2, 'confirmed', true)
|
||||||
|
RETURNING id
|
||||||
|
`, userID, futureTime).Scan(&bookingID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create booking: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteBooking(db.DB, bookingID)
|
||||||
|
|
||||||
|
// Link service to booking
|
||||||
|
_, err = db.DB.Exec(context.Background(), `
|
||||||
|
INSERT INTO booking_services (booking_id, service_id)
|
||||||
|
VALUES ($1, $2)
|
||||||
|
`, bookingID, serviceID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to link service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET single booking via admin endpoint
|
||||||
|
w := makeAdminRequest(http.HandlerFunc(bookings.GetAdminBookingHandler), "GET", "/api/admin/bookings/"+bookingID, nil)
|
||||||
|
|
||||||
|
if w.Code != http.StatusOK {
|
||||||
|
t.Fatalf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
var fetchedBooking bookings.Booking
|
||||||
|
if err := parseResponseBody(w, &fetchedBooking); err != nil {
|
||||||
|
t.Fatalf("failed to parse response: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify deposit fields are populated
|
||||||
|
if !fetchedBooking.DepositRequired {
|
||||||
|
t.Error("expected DepositRequired to be true")
|
||||||
|
}
|
||||||
|
if fetchedBooking.DepositAmount <= 0 {
|
||||||
|
t.Error("expected DepositAmount to be positive")
|
||||||
|
}
|
||||||
|
// DepositPaid is a bool, just verify it exists
|
||||||
|
_ = fetchedBooking.DepositPaid
|
||||||
|
if fetchedBooking.DepositDeadline == nil {
|
||||||
|
t.Error("expected DepositDeadline to be set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestAdminBookings_List_DepositFields verifies that admin booking list returns
|
||||||
|
// deposit-related fields for each booking.
|
||||||
|
func TestAdminBookings_List_DepositFields(t *testing.T) {
|
||||||
|
cleanup := setupTestDB(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
adminID, err := fixtures.CreateTestAdminUser(db.DB)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create admin user: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteUser(db.DB, adminID)
|
||||||
|
|
||||||
|
userID, err := fixtures.CreateTestUser(db.DB)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create test user: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteUser(db.DB, userID)
|
||||||
|
|
||||||
|
serviceID, err := fixtures.CreateTestService(db.DB)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create test service: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteService(db.DB, serviceID)
|
||||||
|
|
||||||
|
// Create booking via SQL with deposit_required=true
|
||||||
|
futureTime := time.Now().Add(72 * time.Hour).Truncate(time.Second)
|
||||||
|
var bookingID string
|
||||||
|
err = db.DB.QueryRow(context.Background(), `
|
||||||
|
INSERT INTO bookings (user_id, start_time, status, deposit_required)
|
||||||
|
VALUES ($1, $2, 'pending', true)
|
||||||
|
RETURNING id
|
||||||
|
`, userID, futureTime).Scan(&bookingID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create booking: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteBooking(db.DB, bookingID)
|
||||||
|
|
||||||
|
// Link service to booking
|
||||||
|
_, err = db.DB.Exec(context.Background(), `
|
||||||
|
INSERT INTO booking_services (booking_id, service_id)
|
||||||
|
VALUES ($1, $2)
|
||||||
|
`, bookingID, serviceID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to link service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET all bookings via admin endpoint
|
||||||
|
w := makeAdminRequest(http.HandlerFunc(bookings.GetAllAdminBookingsHandler), "GET", "/api/admin/bookings", nil)
|
||||||
|
|
||||||
|
if w.Code != http.StatusOK {
|
||||||
|
t.Fatalf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp bookings.BookingListResponse
|
||||||
|
if err := parseResponseBody(w, &resp); err != nil {
|
||||||
|
t.Fatalf("failed to parse response: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(resp.Bookings) != 1 {
|
||||||
|
t.Fatalf("expected 1 booking, got %d", len(resp.Bookings))
|
||||||
|
}
|
||||||
|
|
||||||
|
booking := resp.Bookings[0]
|
||||||
|
|
||||||
|
// Verify deposit fields are populated in list
|
||||||
|
if !booking.DepositRequired {
|
||||||
|
t.Error("expected DepositRequired to be true in list")
|
||||||
|
}
|
||||||
|
if booking.DepositAmount <= 0 {
|
||||||
|
t.Error("expected DepositAmount to be positive in list")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2629,10 +2629,220 @@ func TestBookings_Create_NoDepositRequired_Within48Hours(t *testing.T) {
|
|||||||
t.Errorf("expected status 201 for booking within 48h with no deposit required, got %d. body: %s", w.Code, w.Body.String())
|
t.Errorf("expected status 201 for booking within 48h with no deposit required, got %d. body: %s", w.Code, w.Body.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// =============================================================================
|
||||||
|
// Deposit Snapshot and Field Tests
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
// TestBookings_Create_DepositSnapshot verifies that deposit_required is snapshotted
|
||||||
|
// at booking creation time from user's current deposits_required value.
|
||||||
|
func TestBookings_Create_DepositSnapshot(t *testing.T) {
|
||||||
|
cleanup := setupTestDB(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
seedDefaultWorkingHours(t)
|
||||||
|
|
||||||
|
userID, err := fixtures.CreateTestUser(db.DB)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create test user: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteUser(db.DB, userID)
|
||||||
|
|
||||||
|
// Set deposits_required=3 BEFORE creating booking
|
||||||
|
_, err = db.DB.Exec(context.Background(), "UPDATE users SET deposits_required = 3 WHERE id = $1", userID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to set deposits_required: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceID, err := fixtures.CreateTestService(db.DB)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create test service: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteService(db.DB, serviceID)
|
||||||
|
|
||||||
|
token := jwt.GenerateUserToken(userID)
|
||||||
|
|
||||||
|
// Create booking after deposits_required is set
|
||||||
|
after48h := time.Now().Add(72 * time.Hour).Truncate(time.Second)
|
||||||
|
after48h = time.Date(after48h.Year(), after48h.Month(), after48h.Day(), 10, 0, 0, 0, after48h.Location())
|
||||||
|
req := CreateBookingRequest{
|
||||||
|
StartTime: after48h,
|
||||||
|
ServiceIDs: []string{serviceID},
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := http.HandlerFunc(CreateBookingHandler)
|
||||||
|
w := makeRequest(handler, "POST", "/api/bookings", req, token)
|
||||||
|
|
||||||
|
if w.Code != http.StatusCreated {
|
||||||
|
t.Fatalf("expected status 201, got %d. body: %s", w.Code, w.Body.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify deposit_required was snapshotted on the booking
|
||||||
|
var depositRequired bool
|
||||||
|
err = db.DB.QueryRow(context.Background(),
|
||||||
|
"SELECT deposit_required FROM bookings WHERE user_id = $1", userID).Scan(&depositRequired)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to query booking: %v", err)
|
||||||
|
}
|
||||||
|
if !depositRequired {
|
||||||
|
t.Error("expected deposit_required=true to be snapshotted on booking")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now change user's deposits_required to 0
|
||||||
|
_, err = db.DB.Exec(context.Background(), "UPDATE users SET deposits_required = 0 WHERE id = $1", userID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to update deposits_required: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the booking's deposit_required is still true (snapshot is not updated)
|
||||||
|
err = db.DB.QueryRow(context.Background(),
|
||||||
|
"SELECT deposit_required FROM bookings WHERE user_id = $1", userID).Scan(&depositRequired)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to query booking: %v", err)
|
||||||
|
}
|
||||||
|
if !depositRequired {
|
||||||
|
t.Error("expected deposit_required to remain true after user's deposits_required changed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestBookings_Create_DepositRequired_OneActiveBookingLimit verifies that a user
|
||||||
|
// with deposits_required > 0 can only have ONE active booking at a time.
|
||||||
|
func TestBookings_Create_DepositRequired_OneActiveBookingLimit(t *testing.T) {
|
||||||
|
cleanup := setupTestDB(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
seedDefaultWorkingHours(t)
|
||||||
|
|
||||||
|
userID, err := fixtures.CreateTestUser(db.DB)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create test user: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteUser(db.DB, userID)
|
||||||
|
|
||||||
|
// Set deposits_required=3 (triggers one-active-booking limit)
|
||||||
|
_, err = db.DB.Exec(context.Background(), "UPDATE users SET deposits_required = 3 WHERE id = $1", userID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to set deposits_required: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceID, err := fixtures.CreateTestService(db.DB)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create test service: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteService(db.DB, serviceID)
|
||||||
|
|
||||||
|
token := jwt.GenerateUserToken(userID)
|
||||||
|
|
||||||
|
// Create first booking (should succeed)
|
||||||
|
after48h := time.Now().Add(72 * time.Hour).Truncate(time.Second)
|
||||||
|
after48h = time.Date(after48h.Year(), after48h.Month(), after48h.Day(), 10, 0, 0, 0, after48h.Location())
|
||||||
|
req1 := CreateBookingRequest{
|
||||||
|
StartTime: after48h,
|
||||||
|
ServiceIDs: []string{serviceID},
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := http.HandlerFunc(CreateBookingHandler)
|
||||||
|
w := makeRequest(handler, "POST", "/api/bookings", req1, token)
|
||||||
|
|
||||||
|
if w.Code != http.StatusCreated {
|
||||||
|
t.Fatalf("expected first booking to succeed, got %d. body: %s", w.Code, w.Body.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to create second booking (should fail - one active booking limit)
|
||||||
|
after72h := time.Now().Add(96 * time.Hour).Truncate(time.Second)
|
||||||
|
after72h = time.Date(after72h.Year(), after72h.Month(), after72h.Day(), 10, 0, 0, 0, after72h.Location())
|
||||||
|
req2 := CreateBookingRequest{
|
||||||
|
StartTime: after72h,
|
||||||
|
ServiceIDs: []string{serviceID},
|
||||||
|
}
|
||||||
|
|
||||||
|
w = makeRequest(handler, "POST", "/api/bookings", req2, token)
|
||||||
|
|
||||||
|
if w.Code != http.StatusConflict {
|
||||||
|
t.Errorf("expected status 409 for second booking attempt, got %d. body: %s", w.Code, w.Body.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Contains(w.Body.Bytes(), []byte("active booking")) {
|
||||||
|
t.Errorf("expected error about active booking, got: %s", w.Body.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestBookings_Get_DepositFieldsReturned verifies that GET /api/bookings returns
|
||||||
|
// the deposit-related fields (deposit_required, deposit_amount, deposit_paid, deposit_deadline).
|
||||||
|
func TestBookings_Get_DepositFieldsReturned(t *testing.T) {
|
||||||
|
cleanup := setupTestDB(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
seedDefaultWorkingHours(t)
|
||||||
|
|
||||||
|
userID, err := fixtures.CreateTestUser(db.DB)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create test user: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteUser(db.DB, userID)
|
||||||
|
|
||||||
|
// Set deposits_required=3 and create booking
|
||||||
|
_, err = db.DB.Exec(context.Background(), "UPDATE users SET deposits_required = 3 WHERE id = $1", userID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to set deposits_required: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceID, err := fixtures.CreateTestService(db.DB)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create test service: %v", err)
|
||||||
|
}
|
||||||
|
defer fixtures.DeleteService(db.DB, serviceID)
|
||||||
|
|
||||||
|
token := jwt.GenerateUserToken(userID)
|
||||||
|
|
||||||
|
// Create booking with deposit requirement
|
||||||
|
after48h := time.Now().Add(72 * time.Hour).Truncate(time.Second)
|
||||||
|
after48h = time.Date(after48h.Year(), after48h.Month(), after48h.Day(), 10, 0, 0, 0, after48h.Location())
|
||||||
|
req := CreateBookingRequest{
|
||||||
|
StartTime: after48h,
|
||||||
|
ServiceIDs: []string{serviceID},
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := http.HandlerFunc(CreateBookingHandler)
|
||||||
|
w := makeRequest(handler, "POST", "/api/bookings", req, token)
|
||||||
|
|
||||||
|
if w.Code != http.StatusCreated {
|
||||||
|
t.Fatalf("expected status 201, got %d. body: %s", w.Code, w.Body.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET the booking and verify deposit fields
|
||||||
|
w = makeRequest(http.HandlerFunc(GetAllUserBookingsHandler), "GET", "/api/bookings", nil, token)
|
||||||
|
|
||||||
|
if w.Code != http.StatusOK {
|
||||||
|
t.Fatalf("expected status 200, got %d. body: %s", w.Code, w.Body.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp BookingListResponse
|
||||||
|
if err := parseResponseBody(w, &resp); err != nil {
|
||||||
|
t.Fatalf("failed to parse response: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(resp.Bookings) != 1 {
|
||||||
|
t.Fatalf("expected 1 booking, got %d", len(resp.Bookings))
|
||||||
|
}
|
||||||
|
|
||||||
|
booking := resp.Bookings[0]
|
||||||
|
|
||||||
|
// Verify deposit fields exist
|
||||||
|
// Verify deposit fields exist
|
||||||
|
if !booking.DepositRequired {
|
||||||
|
t.Error("expected DepositRequired to be true")
|
||||||
|
}
|
||||||
|
if booking.DepositAmount <= 0 {
|
||||||
|
t.Error("expected DepositAmount to be positive")
|
||||||
|
}
|
||||||
|
// DepositPaid is a bool, check it's set (should be false for new booking)
|
||||||
|
// Just verify the field exists by accessing it
|
||||||
|
_ = booking.DepositPaid
|
||||||
|
if booking.DepositDeadline == nil {
|
||||||
|
t.Error("expected DepositDeadline to be set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// Holiday/Closed Day Booking Tests
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
// TestBookings_Edit_ClosedDay_UserBlocked verifies that a regular user cannot edit a booking
|
// TestBookings_Edit_ClosedDay_UserBlocked verifies that a regular user cannot edit a booking
|
||||||
// to fall on a closed day (exceptional hours marked as is_open=false).
|
// to fall on a closed day (exceptional hours marked as is_open=false).
|
||||||
|
|||||||
@@ -208,6 +208,7 @@ CREATE TABLE bookings (
|
|||||||
start_time TIMESTAMPTZ NOT NULL,
|
start_time TIMESTAMPTZ NOT NULL,
|
||||||
status booking_status NOT NULL DEFAULT 'pending',
|
status booking_status NOT NULL DEFAULT 'pending',
|
||||||
notes TEXT,
|
notes TEXT,
|
||||||
|
deposit_required BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
created_by CHAR(12)
|
created_by CHAR(12)
|
||||||
|
|||||||
+23
-2
@@ -264,8 +264,10 @@ if api_post "$BASE_URL/register" "{\"firstName\":\"Oscar\",\"lastName\":\"Hughes
|
|||||||
# Promote Admin
|
# Promote Admin
|
||||||
docker exec postgres psql -U myuser -d mydb -c "UPDATE users SET account_role = 'admin' WHERE email = '$ADMIN_EMAIL'" > /dev/null 2>&1
|
docker exec postgres psql -U myuser -d mydb -c "UPDATE users SET account_role = 'admin' WHERE email = '$ADMIN_EMAIL'" > /dev/null 2>&1
|
||||||
|
|
||||||
# Set deposits_required=0 for all users (so they can confirm bookings without deposit issues)
|
# Set deposits_required=0 for main test user (so bookings can be created without 48h restriction)
|
||||||
docker exec postgres psql -U myuser -d mydb -c "UPDATE users SET deposits_required = 0" > /dev/null 2>&1
|
# Set deposits_required=3 for some users to demonstrate deposit snapshot behavior
|
||||||
|
docker exec postgres psql -U myuser -d mydb -c "UPDATE users SET deposits_required = 0 WHERE email = '$USER_EMAIL'" > /dev/null 2>&1
|
||||||
|
docker exec postgres psql -U myuser -d mydb -c "UPDATE users SET deposits_required = 3 WHERE email IN ('poppy.thompson@example.com', 'mia.white@example.com')" > /dev/null 2>&1
|
||||||
echo "${C_GREEN}✅ Registered $success/$total Users${C_RESET}"
|
echo "${C_GREEN}✅ Registered $success/$total Users${C_RESET}"
|
||||||
|
|
||||||
# 2. Login
|
# 2. Login
|
||||||
@@ -454,6 +456,25 @@ echo "${C_GREEN}✅ Created $count_future/30 Bookings (Future)${C_RESET}"
|
|||||||
echo "${C_GREEN}✅ Created $count_past/8 Bookings (Past)${C_RESET}"
|
echo "${C_GREEN}✅ Created $count_past/8 Bookings (Past)${C_RESET}"
|
||||||
echo "${C_GREEN}✅ Created $TOTAL/45 Bookings (Total)${C_RESET}"
|
echo "${C_GREEN}✅ Created $TOTAL/45 Bookings (Total)${C_RESET}"
|
||||||
|
|
||||||
|
# 4b. Create Booking for Deposit-Required User
|
||||||
|
echo -e "\n${C_BLUE}💰 Creating Booking for Deposit-Required User...${C_RESET}"
|
||||||
|
|
||||||
|
# Login as Poppy (deposits_required=3)
|
||||||
|
POPPY_LOGIN_RESP=$(curl -s -X POST -H 'Content-Type: application/json' -d '{"email":"poppy.thompson@example.com","password":"password"}' "$BASE_URL/login")
|
||||||
|
POPPY_TOKEN=$(echo "$POPPY_LOGIN_RESP" | tr -d '\r\n\t ' | sed -n 's/.*"token":"\([^"]*\).*/\1/p')
|
||||||
|
|
||||||
|
if [[ -n "$POPPY_TOKEN" ]]; then
|
||||||
|
# Book 3 days ahead (50h+ to satisfy 48h requirement for deposit-required users)
|
||||||
|
DEPOSIT_TIME=$(TZ=Europe/London date -d "3 days 10:00" +"%Y-%m-%dT%H:%M:%S%:z")
|
||||||
|
if create_booking "$POPPY_TOKEN" "$DEPOSIT_TIME" "[\"$(get_svc 0)\"]" "" "Poppy (deposit required)"; then
|
||||||
|
echo "${C_GREEN}✅ Created deposit-required booking (deposit_required=true snapshotted)${C_RESET}"
|
||||||
|
else
|
||||||
|
echo "${C_YELLOW}⚠️ Could not create deposit-required booking${C_RESET}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "${C_YELLOW}⚠️ Could not login as Poppy to create deposit-required booking${C_RESET}"
|
||||||
|
fi
|
||||||
|
|
||||||
# 5. Confirm Random Half of Upcoming Bookings
|
# 5. Confirm Random Half of Upcoming Bookings
|
||||||
echo -e "\n${C_BLUE}🔒 Confirming Random Upcoming Bookings...${C_RESET}"
|
echo -e "\n${C_BLUE}🔒 Confirming Random Upcoming Bookings...${C_RESET}"
|
||||||
confirmed_count=0
|
confirmed_count=0
|
||||||
|
|||||||
Reference in New Issue
Block a user