_SUPPLY_BATCH_SQL джойнил domrf_kn_flats по ОДНОЙ глобальной дате (f.snapshot_date = MAX(snapshot_date) по всей таблице). Но domrf_kn_flats — ПО-ОБЪЕКТНЫЙ time-series: каждый ЖК скрейпится в свой день. На единственной глобал-max дате присутствует обычно 1 объект → у остальных 0 квартир → supply_units_in_radius=0 для всех строк 4.2 Планировки → frontend показывал «Срок продажи 0 мес» и «% продано —». Регрессия от #1944 (objects-first дедуп snapshot'ов объектов, который сам по себе корректен). Фикс: flats_latest CTE (DISTINCT ON (obj_id) ... ORDER BY obj_id, snapshot_date DESC, id DESC) берёт для КАЖДОГО obj_id его собственный последний снимок и джойнится к nearby. objects-first MATERIALIZED дедуп (#1944) сохранён → fan-out по снимкам не возвращается. Глобальный db.scalar(MAX(snapshot_date)) + :latest_snap bind удалены. Прод (66:41:0205010:287, r=1км, 9 объектов): supply 0 (global-max) → 2675 (per-object, 4 объекта имеют flats на разных датах 2026-05-17/05-05; ни один не на глобал-max 2026-06-22). Данные flats частично сломаны (#1945, отдельно), но фикс корректно двигает supply с 0 к реальным per-object числам. Тесты: новый guard test_supply_joins_flats_per_object_latest_snapshot; обновлены mock-фабрики (db.scalar больше не вызывается). |
||
|---|---|---|
| .. | ||
| analysis_runs | ||
| analytics | ||
| cadastre | ||
| chat | ||
| etl | ||
| exporters | ||
| forecasting | ||
| generative | ||
| llm | ||
| photos | ||
| scrapers | ||
| site_finder | ||
| __init__.py | ||
| analytics_queries.py | ||
| analytics_refresh.py | ||
| forecast_request_cache.py | ||
| insights.py | ||
| job_settings.py | ||
| objective_etl.py | ||
| objective_sync_config.py | ||
| own_projects.py | ||
| weather_cache.py | ||