Fix: exclude cancelled bookings from the no-overlap constraint
Test backoffice (smb-crm) / test (push) Successful in 1m31s
Test backoffice (smb-crm) / test (push) Successful in 1m31s
bookings_no_overlap (the GiST exclusion constraint preventing
double-booking) had no WHERE clause, so a cancelled booking's old time
range stayed "occupied" forever -- permanently blocking that
resource+slot from ever being booked again, even though the booking
itself is dead. Found live: a cancelled test booking blocked a real
reschedule attempt into the same slot ("overlaps with an existing
appointment" even though nothing active was there).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+12
-5
@@ -166,16 +166,23 @@ ALTER TABLE bookings ADD COLUMN IF NOT EXISTS resource_id text;
|
|||||||
ALTER TABLE bookings ADD COLUMN IF NOT EXISTS during tstzrange
|
ALTER TABLE bookings ADD COLUMN IF NOT EXISTS during tstzrange
|
||||||
GENERATED ALWAYS AS (tstzrange(start_time, end_time, '[)')) STORED;
|
GENERATED ALWAYS AS (tstzrange(start_time, end_time, '[)')) STORED;
|
||||||
|
|
||||||
-- ALTER TABLE ... ADD CONSTRAINT has no IF NOT EXISTS form, so guard by name
|
-- ALTER TABLE ... ADD CONSTRAINT has no IF NOT EXISTS form, so drop-then-add
|
||||||
-- to keep this file safe to re-run on every deploy like everything above it.
|
-- unconditionally to keep this file safe to re-run on every deploy like
|
||||||
|
-- everything above it. The WHERE clause is load-bearing: without it, a
|
||||||
|
-- cancelled booking's old time range stays "occupied" forever, permanently
|
||||||
|
-- blocking that resource+slot from ever being booked again even though the
|
||||||
|
-- booking itself is dead -- found 2026-09-12 when a cancelled test booking
|
||||||
|
-- blocked a real reschedule into the same slot.
|
||||||
DO $$
|
DO $$
|
||||||
BEGIN
|
BEGIN
|
||||||
IF NOT EXISTS (
|
IF EXISTS (
|
||||||
SELECT 1 FROM pg_constraint WHERE conname = 'bookings_no_overlap'
|
SELECT 1 FROM pg_constraint WHERE conname = 'bookings_no_overlap'
|
||||||
) THEN
|
) THEN
|
||||||
ALTER TABLE bookings ADD CONSTRAINT bookings_no_overlap
|
ALTER TABLE bookings DROP CONSTRAINT bookings_no_overlap;
|
||||||
EXCLUDE USING gist (resource_id WITH =, during WITH &&);
|
|
||||||
END IF;
|
END IF;
|
||||||
|
ALTER TABLE bookings ADD CONSTRAINT bookings_no_overlap
|
||||||
|
EXCLUDE USING gist (resource_id WITH =, during WITH &&)
|
||||||
|
WHERE (status <> 'cancelled');
|
||||||
END $$;
|
END $$;
|
||||||
|
|
||||||
ALTER TABLE clients ADD COLUMN IF NOT EXISTS slug text UNIQUE;
|
ALTER TABLE clients ADD COLUMN IF NOT EXISTS slug text UNIQUE;
|
||||||
|
|||||||
Reference in New Issue
Block a user