Fix schema: add missing tables and correct forecast_snapshots structure
- Add booking_com_hotels and booking_com_rates (competitor rate scraper tables) - Fix forecast_snapshots: was using old pivoted schema (snapshot_date, prophet_value etc.); code expects normalised rows (perception_date, model, forecast_value, actual_value). Add DO block migration to drop+recreate if old schema is detected. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3c66e777e4
commit
effad0a4e2
1 changed files with 70 additions and 8 deletions
|
|
@ -273,6 +273,45 @@ CREATE TABLE IF NOT EXISTS booking_scrape_log (
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_booking_scrape_log_started ON booking_scrape_log(started_at DESC);
|
CREATE INDEX IF NOT EXISTS idx_booking_scrape_log_started ON booking_scrape_log(started_at DESC);
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- COMPETITOR RATE SCRAPER (booking.com hotels and rates)
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS booking_com_hotels (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
booking_com_id VARCHAR(50) UNIQUE,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
booking_com_url TEXT,
|
||||||
|
star_rating DECIMAL(2,1),
|
||||||
|
review_score DECIMAL(3,1),
|
||||||
|
review_count INTEGER DEFAULT 0,
|
||||||
|
tier VARCHAR(20) DEFAULT 'market',
|
||||||
|
display_order INTEGER DEFAULT 999,
|
||||||
|
notes TEXT,
|
||||||
|
is_active BOOLEAN DEFAULT TRUE,
|
||||||
|
first_seen_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
last_seen_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS booking_com_rates (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
hotel_id INTEGER NOT NULL REFERENCES booking_com_hotels(id) ON DELETE CASCADE,
|
||||||
|
rate_date DATE NOT NULL,
|
||||||
|
availability_status VARCHAR(30),
|
||||||
|
rate_gross DECIMAL(10,2),
|
||||||
|
currency VARCHAR(10) DEFAULT 'GBP',
|
||||||
|
room_type VARCHAR(100),
|
||||||
|
breakfast_included BOOLEAN DEFAULT FALSE,
|
||||||
|
free_cancellation BOOLEAN DEFAULT FALSE,
|
||||||
|
no_prepayment BOOLEAN DEFAULT FALSE,
|
||||||
|
rooms_left INTEGER,
|
||||||
|
scrape_batch_id UUID REFERENCES booking_scrape_log(batch_id),
|
||||||
|
scraped_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_booking_com_rates_hotel_date ON booking_com_rates(hotel_id, rate_date);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_booking_com_rates_date ON booking_com_rates(rate_date);
|
||||||
|
|
||||||
-- ============================================
|
-- ============================================
|
||||||
-- SYNC LOGGING
|
-- SYNC LOGGING
|
||||||
-- ============================================
|
-- ============================================
|
||||||
|
|
@ -663,22 +702,45 @@ CREATE TABLE IF NOT EXISTS daily_budgets (
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_daily_budgets_date ON daily_budgets(date, budget_type);
|
CREATE INDEX IF NOT EXISTS idx_daily_budgets_date ON daily_budgets(date, budget_type);
|
||||||
|
|
||||||
-- Forecast snapshots (for tracking how forecasts evolve over time)
|
-- Forecast snapshots (one row per perception_date+target_date+model+metric)
|
||||||
CREATE TABLE IF NOT EXISTS forecast_snapshots (
|
CREATE TABLE IF NOT EXISTS forecast_snapshots (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
snapshot_date DATE NOT NULL,
|
perception_date DATE NOT NULL,
|
||||||
target_date DATE NOT NULL,
|
target_date DATE NOT NULL,
|
||||||
|
model VARCHAR(50) NOT NULL,
|
||||||
metric_code VARCHAR(50) NOT NULL,
|
metric_code VARCHAR(50) NOT NULL,
|
||||||
days_out INTEGER NOT NULL,
|
days_out INTEGER,
|
||||||
prophet_value DECIMAL(12,2),
|
forecast_value DECIMAL(12,2),
|
||||||
xgboost_value DECIMAL(12,2),
|
actual_value DECIMAL(12,2),
|
||||||
pickup_value DECIMAL(12,2),
|
|
||||||
catboost_value DECIMAL(12,2),
|
|
||||||
created_at TIMESTAMP DEFAULT NOW(),
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
UNIQUE(snapshot_date, target_date, metric_code)
|
UNIQUE(perception_date, target_date, model, metric_code)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- Migration: drop old pivoted-column schema and recreate if snapshot_date column exists
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF EXISTS (
|
||||||
|
SELECT 1 FROM information_schema.columns
|
||||||
|
WHERE table_name = 'forecast_snapshots' AND column_name = 'snapshot_date'
|
||||||
|
) THEN
|
||||||
|
DROP TABLE forecast_snapshots;
|
||||||
|
CREATE TABLE forecast_snapshots (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
perception_date DATE NOT NULL,
|
||||||
|
target_date DATE NOT NULL,
|
||||||
|
model VARCHAR(50) NOT NULL,
|
||||||
|
metric_code VARCHAR(50) NOT NULL,
|
||||||
|
days_out INTEGER,
|
||||||
|
forecast_value DECIMAL(12,2),
|
||||||
|
actual_value DECIMAL(12,2),
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
UNIQUE(perception_date, target_date, model, metric_code)
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_forecast_snapshots_target ON forecast_snapshots(target_date, metric_code);
|
CREATE INDEX IF NOT EXISTS idx_forecast_snapshots_target ON forecast_snapshots(target_date, metric_code);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_forecast_snapshots_perception ON forecast_snapshots(perception_date, model, metric_code);
|
||||||
|
|
||||||
-- ============================================
|
-- ============================================
|
||||||
-- USER ROLES (migration for existing users table)
|
-- USER ROLES (migration for existing users table)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue