All checks were successful
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 30s
Deploy Trade-In / build-backend (push) Successful in 41s
Deploy Trade-In / deploy (push) Successful in 36s
Co-authored-by: bot-backend <bot-backend@gendsgn.local> Co-committed-by: bot-backend <bot-backend@gendsgn.local>
70 lines
3.6 KiB
PL/PgSQL
70 lines
3.6 KiB
PL/PgSQL
-- 092_sber_price_index.sql
|
||
-- Issue #887 — city-level secondary-housing price index from СберИндекс (sberindex.ru).
|
||
--
|
||
-- Context:
|
||
-- СберИндекс publishes monthly city/region-level secondary-housing price statistics
|
||
-- across three dashboards:
|
||
-- * real_estate_deals — hedonic sold-price index (руб/м²)
|
||
-- * residential_real_estate_prices — repeat-sales / asking-adjusted hedonic
|
||
-- * dinamika-tsen-obyavlenii — asking-price benchmark (объявления, руб/м²)
|
||
--
|
||
-- The pull service (app/services/sber_index.py) fetches all three series for configured
|
||
-- cities (initially РФ-643, with EKB/MSK codes TBD — see TODO in sber_index.py) via the
|
||
-- /api/sowa POST endpoint (reverse-engineered in #794 research note) and upserts rows here.
|
||
--
|
||
-- The table feeds the estimator time-adjust coefficient (step 4, #887 out-of-scope —
|
||
-- backtest-gated, separate follow-up).
|
||
--
|
||
-- Schema notes:
|
||
-- * city — REF_AREA label as returned by the API (e.g. «Россия», «Екатеринбург»).
|
||
-- * period_month — first day of the reported month (normalised from API timestamp).
|
||
-- * segment — realty type label from API (e.g. «Вторичный»).
|
||
-- * dashboard — slug used in the route (e.g. 'real_estate_deals').
|
||
-- * PRIMARY KEY (city, period_month, dashboard) — one value per city×month×series;
|
||
-- upsert on conflict keeps the freshest fetched_at.
|
||
--
|
||
-- Idempotent: CREATE TABLE IF NOT EXISTS — safe to re-apply. ADDITIVE only, no drops.
|
||
--
|
||
-- Dependencies: none (standalone table).
|
||
--
|
||
-- Deploy order: apply before deploying app/services/sber_index.py +
|
||
-- app/tasks/sber_index_pull.py + scheduler.py changes.
|
||
|
||
BEGIN;
|
||
|
||
CREATE TABLE IF NOT EXISTS sber_price_index (
|
||
city text NOT NULL,
|
||
period_month date NOT NULL,
|
||
segment text NOT NULL DEFAULT '',
|
||
dashboard text NOT NULL,
|
||
index_value_rub_m2 double precision NOT NULL,
|
||
source text NOT NULL DEFAULT 'sberindex',
|
||
fetched_at timestamptz NOT NULL DEFAULT now(),
|
||
PRIMARY KEY (city, period_month, dashboard)
|
||
);
|
||
|
||
COMMENT ON TABLE sber_price_index IS
|
||
'Monthly city-level secondary-housing price index from СберИндекс (sberindex.ru). '
|
||
'Three series: real_estate_deals (hedonic sold), residential_real_estate_prices '
|
||
'(repeat-sales hedonic), dinamika-tsen-obyavlenii (asking benchmark). '
|
||
'Populated by app/tasks/sber_index_pull.py via in-app scheduler (#887). '
|
||
'Estimator time-adjust wire is a separate backtest-gated follow-up (step 4, #887).';
|
||
|
||
COMMENT ON COLUMN sber_price_index.city IS
|
||
'REF_AREA label from the API response (e.g. «Россия», «Екатеринбург»).';
|
||
COMMENT ON COLUMN sber_price_index.period_month IS
|
||
'First day of the reported month (normalised from API ISO timestamp).';
|
||
COMMENT ON COLUMN sber_price_index.segment IS
|
||
'Realty type label from API (e.g. «Вторичный»). Empty string when absent.';
|
||
COMMENT ON COLUMN sber_price_index.dashboard IS
|
||
'Dataset slug used in the /dataset/v1/<dashboard> route.';
|
||
COMMENT ON COLUMN sber_price_index.index_value_rub_m2 IS
|
||
'Price index in rubles per square metre.';
|
||
COMMENT ON COLUMN sber_price_index.fetched_at IS
|
||
'Wall-clock timestamp when this row was last written/updated.';
|
||
|
||
-- Index for time-series queries (latest N months per city × dashboard)
|
||
CREATE INDEX IF NOT EXISTS idx_sber_price_index_city_dashboard_period
|
||
ON sber_price_index (city, dashboard, period_month DESC);
|
||
|
||
COMMIT;
|