Add occupancy pick-up history + bookability history popup

Schema: migrate newbook_occupancy_report_data from single-row upsert to
snapshot model (drop unique constraint, add valid_from / last_verified_at)
matching the pattern used by newbook_current_rates.

Backend: sync_occupancy now inserts a new row only when occupied/available/
maintenance figures change, otherwise bumps last_verified_at. New endpoint
GET /bookability/occupancy-history/{category_id}/{date} returns the timeline.
Rate matrix query updated to DISTINCT ON for the multi-row table.

Frontend: clicking any cell in the Bookability matrix opens a modal with
two stacked Plotly charts — rate history per tariff (step lines, green/red
markers for available/unavailable) and occupancy pick-up over time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-07-12 12:38:02 +00:00
parent aef7d755f1
commit 2743b0e877
4 changed files with 372 additions and 52 deletions

View file

@ -225,6 +225,42 @@ CREATE TABLE IF NOT EXISTS newbook_occupancy_report_data (
CREATE INDEX IF NOT EXISTS idx_occupancy_report_date ON newbook_occupancy_report_data(date);
-- Migrate occupancy table to snapshot model (drop unique constraint, add valid_from / last_verified_at)
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM pg_constraint c
JOIN pg_class t ON t.oid = c.conrelid
WHERE t.relname = 'newbook_occupancy_report_data'
AND c.contype = 'u'
AND c.conname = 'newbook_occupancy_report_data_date_category_id_key'
) THEN
ALTER TABLE newbook_occupancy_report_data
DROP CONSTRAINT newbook_occupancy_report_data_date_category_id_key;
END IF;
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'newbook_occupancy_report_data' AND column_name = 'valid_from'
) THEN
ALTER TABLE newbook_occupancy_report_data ADD COLUMN valid_from TIMESTAMPTZ;
UPDATE newbook_occupancy_report_data SET valid_from = fetched_at WHERE valid_from IS NULL;
ALTER TABLE newbook_occupancy_report_data ALTER COLUMN valid_from SET DEFAULT NOW();
END IF;
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'newbook_occupancy_report_data' AND column_name = 'last_verified_at'
) THEN
ALTER TABLE newbook_occupancy_report_data ADD COLUMN last_verified_at TIMESTAMPTZ;
UPDATE newbook_occupancy_report_data SET last_verified_at = fetched_at WHERE last_verified_at IS NULL;
ALTER TABLE newbook_occupancy_report_data ALTER COLUMN last_verified_at SET DEFAULT NOW();
END IF;
END $$;
CREATE INDEX IF NOT EXISTS idx_occupancy_report_latest
ON newbook_occupancy_report_data(date, category_id, valid_from DESC);
-- ============================================
-- DIRECT COMPETITOR HOTEL CONFIGS
-- ============================================