52 lines
2.5 KiB
SQL
52 lines
2.5 KiB
SQL
-- Forecasting Pipeline Tables
|
|
-- Run once to create the schema. Safe to re-run (IF NOT EXISTS).
|
|
|
|
-- Precomputed reference decay curves per brand (or brand x category at any hierarchy level)
|
|
CREATE TABLE IF NOT EXISTS brand_lifecycle_curves (
|
|
id SERIAL PRIMARY KEY,
|
|
brand TEXT NOT NULL,
|
|
root_category TEXT, -- NULL = brand-level fallback curve, else category name
|
|
cat_id BIGINT, -- NULL = brand-only; else category_hierarchy.cat_id for precise matching
|
|
category_level SMALLINT, -- NULL = brand-only; 0-3 = hierarchy depth
|
|
amplitude NUMERIC(10,4), -- A in: sales(t) = A * exp(-λt) + C
|
|
decay_rate NUMERIC(10,6), -- λ (higher = faster decay)
|
|
baseline NUMERIC(10,4), -- C (long-tail steady-state daily sales)
|
|
r_squared NUMERIC(6,4), -- goodness of fit
|
|
sample_size INT, -- number of products that informed this curve
|
|
median_first_week_sales NUMERIC(10,2), -- for scaling new launches
|
|
median_preorder_sales NUMERIC(10,2), -- for scaling pre-order products
|
|
median_preorder_days NUMERIC(10,2), -- median pre-order accumulation window (days)
|
|
computed_at TIMESTAMP DEFAULT NOW(),
|
|
UNIQUE(brand, cat_id)
|
|
);
|
|
|
|
-- Per-product daily forecasts (next 90 days, regenerated each run)
|
|
CREATE TABLE IF NOT EXISTS product_forecasts (
|
|
pid BIGINT NOT NULL,
|
|
forecast_date DATE NOT NULL,
|
|
forecast_units NUMERIC(10,2),
|
|
forecast_revenue NUMERIC(14,4),
|
|
lifecycle_phase TEXT, -- preorder, launch, decay, mature, slow_mover, dormant
|
|
forecast_method TEXT, -- lifecycle_curve, exp_smoothing, velocity, zero
|
|
confidence_lower NUMERIC(10,2),
|
|
confidence_upper NUMERIC(10,2),
|
|
generated_at TIMESTAMP DEFAULT NOW(),
|
|
PRIMARY KEY (pid, forecast_date)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_pf_date ON product_forecasts(forecast_date);
|
|
CREATE INDEX IF NOT EXISTS idx_pf_phase ON product_forecasts(lifecycle_phase);
|
|
|
|
-- Forecast run history (for monitoring)
|
|
CREATE TABLE IF NOT EXISTS forecast_runs (
|
|
id SERIAL PRIMARY KEY,
|
|
started_at TIMESTAMP NOT NULL,
|
|
finished_at TIMESTAMP,
|
|
status TEXT DEFAULT 'running', -- running, completed, failed
|
|
products_forecast INT,
|
|
phase_counts JSONB, -- {"launch": 50, "decay": 200, ...}
|
|
curve_count INT, -- brand curves computed
|
|
error_message TEXT,
|
|
duration_seconds NUMERIC(10,2)
|
|
);
|