gendesign/tradein-mvp/backend/data/sql/092_sber_price_index.sql
bot-backend de92c54540
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
feat(tradein): СберИндекс monthly city-level price index pull (#887, data-layer) (#890)
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-31 12:44:56 +00:00

70 lines
3.6 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 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;