fix: block duration-aware slot overlaps, not just exact time matches
booked_slots previously recorded only (date, time), so availability checking excluded an exact time match but not a real overlap — a 4-hour service booked at 9:00 AM didn't block 11:00 AM or 1:00 PM. Add duration_minutes to booked_slots (populated by sync_booked_slot() from the booked service's own duration) and switch client-side computeAvailableSlots to a half-open-interval overlap check, also rejecting candidates that wouldn't finish before closing time. Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
begin;
|
||||
select plan(47);
|
||||
select plan(53);
|
||||
|
||||
-- Seed reference data as service_role (bypasses RLS)
|
||||
set local role service_role;
|
||||
@@ -350,5 +350,46 @@ select lives_ok(
|
||||
'the unique index can be created after the self-heal dedupe removes the duplicate'
|
||||
);
|
||||
|
||||
-- Duration-aware booked_slots: the mirror row now carries the booked
|
||||
-- service's duration, so client-side availability computation can detect
|
||||
-- overlap (not just an exact time match). knotless has duration_minutes = 240
|
||||
-- (seeded at the top of this file).
|
||||
set local role service_role;
|
||||
|
||||
select lives_ok(
|
||||
$$ insert into public.bookings (service_id, date, time, contact_name, contact_phone, contact_email, contact_notes)
|
||||
values ('knotless', '2026-12-01', '9:00 AM', 'Duration Client', '555-0301', 'duration@example.com', '') $$,
|
||||
'confirmed booking for the duration test succeeds'
|
||||
);
|
||||
|
||||
select results_eq(
|
||||
$$ select duration_minutes from public.booked_slots where date = '2026-12-01' and time = '9:00 AM' $$,
|
||||
$$ values (240) $$,
|
||||
'booked_slots mirror row carries the booked services duration_minutes'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ update public.bookings set status = 'completed'
|
||||
where date = '2026-12-01' and time = '9:00 AM' and status = 'confirmed' $$,
|
||||
'marking the duration-test booking completed succeeds'
|
||||
);
|
||||
|
||||
select results_eq(
|
||||
$$ select duration_minutes from public.booked_slots where date = '2026-12-01' and time = '9:00 AM' $$,
|
||||
$$ values (240) $$,
|
||||
'booked_slots keeps the correct duration_minutes after confirmed -> completed'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ update public.bookings set status = 'cancelled'
|
||||
where date = '2026-12-01' and time = '9:00 AM' and status = 'completed' $$,
|
||||
'cancelling the duration-test booking succeeds'
|
||||
);
|
||||
|
||||
select is_empty(
|
||||
$$ select * from public.booked_slots where date = '2026-12-01' and time = '9:00 AM' $$,
|
||||
'booked_slots mirror row is removed after the duration-test booking is cancelled, regardless of duration'
|
||||
);
|
||||
|
||||
select * from finish();
|
||||
rollback;
|
||||
|
||||
Reference in New Issue
Block a user