Commit graph

198 commits

Author SHA1 Message Date
f987e819b2 fix(honesty): true competitors/neighbors totals + permits truncation disclosure (#2464 cluster B) (#2471)
All checks were successful
Deploy / changes (push) Successful in 10s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m6s
Deploy / build-worker (push) Successful in 3m13s
Deploy / deploy (push) Successful in 1m38s
2026-07-08 08:31:02 +00:00
d3f3370bed fix(site_finder): SAVEPOINT supply/market + convert 2 bare rollbacks (#2464 Wave 2) (#2469)
All checks were successful
Deploy / changes (push) Successful in 10s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m30s
Deploy / build-worker (push) Successful in 3m45s
Deploy / deploy (push) Successful in 1m54s
2026-07-08 06:46:09 +00:00
01360e9c3d fix(site_finder): SAVEPOINT-isolate gate-lookup db.execute swallows (#2464 Wave 2) (#2468)
Some checks failed
Deploy / build-backend (push) Blocked by required conditions
Deploy / build-worker (push) Blocked by required conditions
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Has been cancelled
2026-07-08 06:46:03 +00:00
22f3c44dc2 fix(site_finder): SAVEPOINT-isolate quarter-dump lookup db.execute (#2464 Wave 2) (#2467)
All checks were successful
Deploy / changes (push) Successful in 11s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m42s
Deploy / build-worker (push) Successful in 3m53s
Deploy / deploy (push) Successful in 1m54s
2026-07-08 06:30:32 +00:00
82fdabccba fix(forecasting): SAVEPOINT-isolate §22 db.execute failures + close RELEASE-trap (#2464) (#2466)
All checks were successful
Deploy / changes (push) Successful in 9s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m35s
Deploy / build-worker (push) Successful in 3m1s
Deploy / deploy (push) Successful in 1m34s
2026-07-08 05:41:35 +00:00
39dd63333e fix(site_finder): SAVEPOINT-isolate DB errors across cluster A (#2464) (#2465)
All checks were successful
Deploy / changes (push) Successful in 9s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 3m29s
Deploy / build-worker (push) Successful in 4m48s
Deploy / deploy (push) Successful in 1m43s
2026-07-07 12:50:11 +00:00
82e0b8b0a3 fix(site-finder): true-counts вместо молча-усечённых len(list) в connection-points/utility (#2445-A1/A2) (#2450)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Successful in 2m9s
Deploy / build-frontend (push) Successful in 3m27s
Deploy / build-worker (push) Successful in 4m19s
Deploy / deploy (push) Successful in 1m55s
2026-07-05 18:54:49 +00:00
b40995780b fix(site-finder): раскрыть proxy-fraction в EKB-median velocity-бенчмарке (#2445-A4) (#2448)
Some checks failed
Deploy / changes (push) Has been cancelled
Deploy / build-backend (push) Has been cancelled
Deploy / build-worker (push) Has been cancelled
Deploy / build-frontend (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
2026-07-05 18:54:42 +00:00
c8c96a87ee fix(site-finder): competitors avg-price по per-object снапшоту, не глобальному (#2445-A5) (#2447)
Some checks failed
Deploy / build-backend (push) Blocked by required conditions
Deploy / build-worker (push) Blocked by required conditions
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Has been cancelled
2026-07-05 18:54:36 +00:00
9b6aba42dc fix(site-finder): L2 hidden-supply не обнуляет неизвестный flat_count (#2445-A3) (#2446)
Some checks failed
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Has been cancelled
Deploy / build-worker (push) Has been cancelled
2026-07-05 18:54:14 +00:00
b3a59b7cf1 feat(gisogd66): permits_nearby — точный радиус-запрос РНС/РВЭ (#2367 PR-2, backend-half) (#2401)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Successful in 2m25s
Deploy / build-worker (push) Successful in 3m38s
Deploy / build-frontend (push) Successful in 4m18s
Deploy / deploy (push) Successful in 1m51s
2026-07-04 09:59:49 +00:00
9feadc8458 fix(market-metrics): offer-trend таймаут — warning вместо exception (ложные GlitchTip-события) (#2329)
Some checks failed
Deploy / build-backend (push) Has been cancelled
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Has been cancelled
2026-07-03 22:26:19 +00:00
85435fbf1b fix(site-finder): SET LOCAL литералом — bind-параметр ломал nearby_network_zones (#2283)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m57s
Deploy / build-worker (push) Successful in 3m3s
Deploy / deploy (push) Successful in 1m47s
2026-07-03 08:44:38 +00:00
7c12812f81 feat(site-finder): позитив-разрез сетевых ЗОУИТ «сеть рядом с участком» (Фаза C2/C3) (#2281)
Some checks failed
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Successful in 2m49s
Deploy / build-worker (push) Successful in 4m31s
Deploy / build-frontend (push) Successful in 5m19s
Deploy / deploy (push) Has been cancelled
2026-07-03 08:18:24 +00:00
99ee09e230 feat(site-finder): теплотрассы из OSM в слой инженерной инфраструктуры (Фаза C1) (#2280)
All checks were successful
Deploy / changes (push) Successful in 21s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m53s
Deploy / build-worker (push) Successful in 3m11s
Deploy / deploy (push) Successful in 1m34s
2026-07-03 08:05:44 +00:00
f891f8f00f feat(eias-heat): +6 тепло-организаций ЕКБ — ненулевые резервы ×10 (#2119) (#2270)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m14s
Deploy / build-worker (push) Successful in 3m19s
Deploy / deploy (push) Successful in 1m43s
2026-07-03 07:02:03 +00:00
21608eced1 fix(site-finder): три честности-фикса — B1 ГРС «выход №N» + околонуль + Росреестр-квартал (#2257)
All checks were successful
Deploy / changes (push) Successful in 9s
Deploy / build-backend (push) Successful in 3m35s
Deploy / build-worker (push) Successful in 5m31s
Deploy / build-frontend (push) Successful in 7m23s
Deploy / deploy (push) Successful in 2m17s
2026-07-03 06:27:27 +00:00
6f5bdffbe4 feat(site-finder): OSM-геокод городских ТП/РП ЕКБ (#2119 B2, финальный хвост) (#2252)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m51s
Deploy / build-worker (push) Successful in 3m0s
Deploy / deploy (push) Successful in 1m36s
2026-07-03 05:22:02 +00:00
15757685c9 feat(site-finder): Celery + §3 точки выхода газосети (#2119 B2, PR-4/4 — финал формы-6) (#2251)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Successful in 2m17s
Deploy / build-worker (push) Successful in 3m19s
Deploy / build-frontend (push) Successful in 3m54s
Deploy / deploy (push) Successful in 1m34s
2026-07-03 04:26:41 +00:00
cc9516ab3d feat(ekgas): геокод точек выхода через DaData (#2119 B2, PR-3/4) (#2249)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m6s
Deploy / build-worker (push) Successful in 3m8s
Deploy / deploy (push) Successful in 1m34s
2026-07-03 03:19:18 +00:00
c438c9a9e8 fix(ekgas): label-детект сетки формы 6 — живой файл сдвинут (#2119 B2) (#2248)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m54s
Deploy / deploy (push) Successful in 1m27s
Deploy / build-worker (push) Successful in 3m9s
2026-07-03 02:51:03 +00:00
af70d50f0d feat(site-finder): лоадер точек выхода ГРС «Екатеринбурггаз» — форма 6 (#2119 B2, PR-2/4) (#2247)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m46s
Deploy / build-worker (push) Successful in 2m51s
Deploy / deploy (push) Successful in 1m28s
2026-07-03 02:25:12 +00:00
1bba3db7eb fix(best-layouts): lots-проекты в пуле core-матчинга — supply-only реально наполняется (#2177) (#2241)
All checks were successful
Deploy / build-backend (push) Successful in 1m40s
Deploy / changes (push) Successful in 6s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 2m42s
Deploy / deploy (push) Successful in 1m24s
2026-07-03 00:14:19 +00:00
9cfefc0ca4 feat(site-finder): supply-only fallback в §4.2 — предложение без темпа продаж (#2177 шаг 3) (#2240)
Some checks failed
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 1m48s
Deploy / build-worker (push) Failing after 1m54s
Deploy / build-frontend (push) Successful in 3m31s
Deploy / deploy (push) Has been skipped
2026-07-02 23:18:42 +00:00
fc55c2c0b7 feat(best-layouts): атрибуция velocity по ядру комплекса (#2177 шаг 2b) (#2239)
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 1m54s
Deploy / build-worker (push) Successful in 2m59s
Deploy / build-frontend (push) Successful in 3m34s
Deploy / deploy (push) Successful in 1m32s
2026-07-02 22:41:25 +00:00
4c23c222f6 fix(vodokanal): column-aligned парсинг DOCX — реальные резервы вместо № п/п (#2119/#2126) (#2238)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 2m48s
Deploy / build-backend (push) Successful in 1m33s
Deploy / deploy (push) Successful in 1m27s
2026-07-02 22:03:15 +00:00
ae483468c9 feat(site-finder): оптимизатор программ — «Как участок сходится» при отрицательном вердикте (#2181) (#2222)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Successful in 2m40s
Deploy / build-worker (push) Successful in 3m54s
Deploy / build-frontend (push) Successful in 4m55s
Deploy / deploy (push) Successful in 1m35s
2026-07-02 20:57:12 +00:00
b028377584 fix(best-layouts): покрытие §4.2 в комплексах, не в сырых obj_id (#2177, шаг 1/3) (#2198)
All checks were successful
Deploy / changes (push) Successful in 10s
Deploy / build-backend (push) Successful in 2m51s
Deploy / build-worker (push) Successful in 4m5s
Deploy / build-frontend (push) Successful in 5m8s
Deploy / deploy (push) Successful in 1m37s
2026-07-02 19:34:11 +00:00
139bf16a8a fix(eias-heat): не терять резерв при одинаковых именах систем (#2119 B2) (#2191)
All checks were successful
Deploy / build-backend (push) Successful in 2m3s
Deploy / build-worker (push) Successful in 3m25s
Deploy / deploy (push) Successful in 1m40s
Deploy / changes (push) Successful in 9s
Deploy / build-frontend (push) Has been skipped
2026-07-02 18:34:42 +00:00
a3db6e4158 feat(site-finder): §4.3 тренд из цен предложения Объектива при устаревших сделках (#2178) (#2190)
Some checks failed
Deploy / changes (push) Successful in 5s
Deploy / deploy (push) Blocked by required conditions
Deploy / build-worker (push) Has been cancelled
Deploy / build-frontend (push) Has been cancelled
Deploy / build-backend (push) Has been cancelled
2026-07-02 18:33:16 +00:00
cdc1e03b32 fix(eias-heat): column-aligned парсинг листа ТП по реальной сетке (#2119 B2) (#2176)
All checks were successful
Deploy / deploy (push) Successful in 1m45s
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m54s
Deploy / build-worker (push) Successful in 3m7s
2026-07-02 17:55:16 +00:00
15224da3b5 fix(eias-heat): ссылка TemplatePrinter из onclick + период «N кв. YYYY» (#2119 B2) (#2172)
All checks were successful
Deploy / build-backend (push) Successful in 1m48s
Deploy / build-worker (push) Successful in 2m50s
Deploy / deploy (push) Successful in 1m26s
Deploy / changes (push) Successful in 6s
Deploy / build-frontend (push) Has been skipped
2026-07-02 17:24:26 +00:00
e501dedf78 feat(site-finder): ЕЭСК-резервы городских ПС/ТП + тепло из ФГИС ФАС (#2119 B2) (#2165)
All checks were successful
Deploy / build-frontend (push) Successful in 4m38s
Deploy / deploy (push) Successful in 1m37s
Deploy / build-backend (push) Successful in 2m48s
Deploy / build-worker (push) Successful in 3m59s
Deploy / changes (push) Successful in 9s
2026-07-02 16:44:57 +00:00
0a6281b6e2 fix(site-finder): ГРС-парсер переписан под реальную структуру таблицы ГТЕ (#2145)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m45s
Deploy / build-worker (push) Successful in 3m15s
Deploy / deploy (push) Successful in 1m30s
2026-07-02 14:45:42 +00:00
da0b8f0374 fix(site-finder): ГРС-лоадер — Russian Trusted CA для домена Газпрома (#2124)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Successful in 1m42s
Deploy / build-worker (push) Successful in 3m3s
Deploy / build-frontend (push) Has been skipped
Deploy / deploy (push) Successful in 1m30s
2026-07-02 13:25:30 +00:00
5839680998 feat(site-finder): газ — свободная мощность ГРС + пометка ЕЭСК в §3 (#2119 Фаза B1) (#2123)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Successful in 2m2s
Deploy / build-worker (push) Successful in 3m17s
Deploy / build-frontend (push) Successful in 3m57s
Deploy / deploy (push) Successful in 1m31s
2026-07-02 12:54:05 +00:00
e1a75d98d4 fix(site-finder): Россети-раскрытие — URL-энкоженные href, ссылки на xlsx не находились (#2121)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m53s
Deploy / build-worker (push) Successful in 2m58s
Deploy / deploy (push) Successful in 1m33s
2026-07-02 09:36:14 +00:00
4758ea5e2b feat(site-finder): резервы мощности для ТП — электро+вода на карте §3 (#2119 Фаза A) (#2120)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Successful in 2m16s
Deploy / build-worker (push) Successful in 3m27s
Deploy / build-frontend (push) Successful in 3m47s
Deploy / deploy (push) Successful in 1m30s
2026-07-02 08:36:51 +00:00
02b5f0b5d1 feat(site-finder): max-info попапы — конкурент / §3-таблица / польз.точка / соседи (#2111) (#2113)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Successful in 2m26s
Deploy / build-worker (push) Successful in 3m41s
Deploy / deploy (push) Successful in 1m30s
Deploy / build-frontend (push) Successful in 4m2s
2026-06-30 13:45:43 +00:00
6d6e0ce0ca feat(site-finder): §3 «Сети и точки подключения» — попапы показывают характеристики (#2111) (#2112)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Successful in 2m2s
Deploy / build-worker (push) Successful in 3m29s
Deploy / build-frontend (push) Successful in 3m44s
Deploy / deploy (push) Successful in 1m30s
2026-06-30 13:16:07 +00:00
53cfd3c3b8 feat(networks): человеко-язык типов §3 + реальные имена НСПД-точек (#1953) (#2107)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Successful in 1m55s
Deploy / build-worker (push) Successful in 3m4s
Deploy / build-frontend (push) Successful in 3m35s
Deploy / deploy (push) Successful in 1m31s
2026-06-30 11:34:29 +00:00
c8e7cb1c79 perf(objective_lots): inline DISTINCT ON for 3 view-fullscan consumers + cache landing stats (#1953) (#2067)
All checks were successful
Deploy / build-frontend (push) Has been skipped
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Successful in 2m8s
Deploy / build-worker (push) Successful in 3m16s
Deploy / deploy (push) Successful in 5m41s
2026-06-28 17:25:41 +00:00
94d01ed066 perf(objective_lots): inline-pushdown competitors._SOLD_COUNT_SQL + covering physflat index (#1953) (#2054)
Some checks failed
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 10m23s
Deploy / build-worker (push) Successful in 11m34s
Deploy / deploy (push) Failing after 8m8s
2026-06-28 14:07:49 +00:00
e67cb721bf fix(objective): physflat-dedup current-state consumers + honest n_sold window (#1964)
objective_lots — current-state UPSERT (UNIQUE objective_lot_id, 5 snapshot_date),
но Объектив присваивает ОДНОМУ физлоту (project,corpus,section,floor,lot_number)
несколько lot_id за пере-листинги → таблица раздута ~2.91× (прод: 1.75M квартир-
строк vs 603k физлотов). История — в отдельной objective_lots_history (не трогаем).

STEP 1: миграция 175 — VIEW v_objective_lots_latest (DISTINCT ON physflat-ключ,
последний снапшот). ol.* стабилен (51==51 колонок). DRY-RUN на проде: 603 049
квартир vs 1 753 283 raw.

STEP 2: репойнт current-state консьюмеров objective_lots → v_objective_lots_latest:
- supply_layers._L1_OPEN_SQL (L1 открытое предложение → дефицит-форсайт; прод:
  Юго-Западный комфорт 58 606 → 12 620)
- competitors._SOLD_COUNT_SQL (+ комментарий: COUNT(DISTINCT lot_id) СОХРАНЁН для
  fan-out-защиты маппинга, не COUNT(*) — view гарантирует physflat-дедуп, DISTINCT
  гарантирует mapping-fan-out-safety)
- parcels.py obj_pricing CTE (карточка конкурента units_sold/available)
- special_indices._ARTIFICIAL_DEMAND_SQL
- parcels.py district price block + geo-radius median (sample_size/n)
- concepts._OBJECTIVE_MEDIAN_SQL (гейт n≥10)
- landing KPI3 (% квартир с ценой)
- admin_scrape coverage: `lots` оставлен сырым (ETL-fidelity vs SQLite), добавлен
  `lots_physflat`
#1959 inline-дедуп в market_metrics НЕ рефакторим — добавлен комментарий об общем
physflat-ключе с view.

STEP 3: report_assembler._deal_count теперь = unit_velocity × window_months
(оконные продажи), НЕ кумулятивный n_sold. confidence_engine помечает фактор
«за 6 мес» и гейтит порогами окна (high≥50) — кумулятив (прод EKB ~380 921) делал
гейт бессмысленным и подпись лживой; оконное (~24 876 за 6 мес) честно.

Тесты: +guard'ы (L1/sold-count читают view, deal_count оконный). 963 passed.
2026-06-28 04:27:43 +05:00
0acd72a325 fix(best-layouts): per-object latest snapshot for supply (#1956)
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m53s
CI / backend-tests (pull_request) Successful in 13m45s
_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 больше не вызывается).
2026-06-27 23:24:28 +05:00
3cafe22c15 docs(forecast): исправить устаревшие комментарии #1959 (deep-review follow-up)
All checks were successful
CI / changes (pull_request) Successful in 8s
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m59s
CI / backend-tests (pull_request) Successful in 14m2s
Doc-only, без изменений логики (deep-code-reviewer APPROVE):
- market_metrics _STOCK_SQL/_SALES_WINDOW_SQL + docstring: убрать ложную
  отсылку «зеркало … из 100_*.sql» (индекс создаётся ТОЛЬКО в миграции 173).
- _SALES_WINDOW_SQL комментарий + compute_market_metrics docstring: room_bucket
  это Source-B room_area-вокабуляр («Студии 15-30»/«2-к 45-60»/«80+ м²», зеркало
  room_area_bucket_of), НЕ Source-A «студия/1/2/3» — приводим к фактическому CASE.
- market_metrics: добавить комментарий, что DISTINCT-ON дедуп БЕЗУСЛОВНЫЙ (все
  вызовы compute_market_metrics, не только форсайт-путь); deep-review подтвердил
  безопасность для ratio/saturated-velocity консьюмеров; дедуп сырой таблицы
  objective_lots для platform-wide остаётся #1964.
- recommendation.map_class docstring: Economy → «стандарт» (код уже маппит так).
2026-06-27 23:02:09 +05:00
41804ed70e fix(forecast): посегментный+дедуплицированный индекс дефицита (#1959)
Корень «−1.00 везде» (эпик #1953): compute_demand_supply_forecast брал
district-wide unit_velocity (847.5/мес, ВСЕ классы/комнаты) как спрос и
весь district-сток (~63k доступных) как предложение для КАЖДОЙ ячейки
what_to_build → один и тот же ratio во всех ячейках → все deficit_index
прижаты к −1.0. Плюс objective_lots — append-per-snapshot (~2.9× инфляция
строк), что симметрично раздувало обе базы → даже сегментация без дедупа
осталась бы вырожденной.

Фикс (blast radius — ТОЛЬКО forecast/deficit calc; platform-wide dedup = #1964):
- market_metrics.compute_market_metrics: +obj_class/+room_bucket (+cache key).
  _STOCK_SQL и _SALES_WINDOW_SQL дедуплят до ПОСЛЕДНЕГО снапшота на физлот
  (DISTINCT ON project_name,corpus_name,section,floor,lot_number ORDER BY …
  snapshot_date DESC,id DESC), затем агрегируют. Class-фильтр (LOWER=LOWER,
  class lowercase) + room-bucket (Source-B room_area-вокабуляр, зеркало
  sales_series.room_area_bucket_of → what_to_build фильтрует без перевода).
  ROLLUP/GROUPING сохранён; confidence считается на дедуплицированных counts.
- demand_supply_forecast: base_pace и open-сток теперь ПОСЕГМЕНТНЫЕ
  (market_metrics(obj_class,room_bucket)). При заданном сегменте L2/L3
  (hidden/future) ИСКЛЮЧЕНЫ из баланса — они класс/формат-агностичны, иначе
  двоились бы по всем ячейкам. +_market_room_bucket VOCAB-мост (валидирующий
  pass-through Source-B меток; неизвестное → None = без фильтра, не тихий 0-rows).
- what_to_build/_DEFAULT_CLASSES и recommendation Economy-маппинг: «эконом»→
  «стандарт» (в objective_lots эконома НЕТ, стандарт=483k → раньше ячейка
  матчила 0 строк и молча выпадала).
- report_assembler honesty-guard: если ВСЯ сетка прижата к ±1.0
  (degenerate-fallback) — не эмитим «строить»/«избегать», показываем
  «недостаточно гранулярных данных для посегментного вывода».
- data/sql/173_objective_lots_physflat_idx.sql: partial index под DISTINCT ON
  (Index Only Scan + Unique, без Sort на 1.75M строк; idempotent, BEGIN/COMMIT).

Prod-verify (parcel 66:41:0205010:287, Железнодорожный, h=24): ячейки
ДИФФЕРЕНЦИРУЮТ (12 measured, 7 distinct) вместо all −1.0; MOI комфорт/студия
38.5 vs стандарт/студия 244.3 (точное совпадение с ожидаемым).

Тесты: регрессия «ячейки различаются (не all −1.0)» + vocab-translation +
honesty-guard + посегментное предложение. ruff clean; no :name::type.
2026-06-27 22:50:58 +05:00
bd1ed4861c docs(zouit): уточнить DISTINCT ON-комментарий + убрать stale cad_zouit из FE-типа (#1957)
All checks were successful
CI / changes (pull_request) Successful in 6s
CI / frontend-tests (pull_request) Successful in 1m0s
CI / openapi-codegen-check (pull_request) Successful in 1m51s
CI / backend-tests (pull_request) Successful in 12m4s
Code-review nits (без изменения поведения):
- quarter_dump_lookup.py: комментарий про дедуп ошибочно утверждал, что зоны без
  рег-номера не схлопываются. На деле reg_numb_border — TEXT NOT NULL (0 NULL на
  проде), а DISTINCT ON в PG считает NULL равными. Переформулировано на точное.
- frontend/types/nspd.ts: убран устаревший 'cad_zouit' из списка возможных
  group_key (бэкенд теперь эмитит только protected/engineering/okn/natural/other).
2026-06-27 14:21:01 +05:00
76647bb4cf fix(report): площадь/обновлено EGRN, forecast-confidence dedup, ЗОУИТ типизация (#1953)
#1954 — площадь «—»: COALESCE(land_record_area, specified_area, declared_area)
в EGRN-блоке analyze (land_record_area NULL у 12809/42233 участков, но
specified_area заполнена). area_m2 для 66:41:0205010:287 теперь 106378 (был NULL).

#1954 — «Обновлено» сломано: cost_registration_date — мёртвая колонка (0/42233);
репойнт на updated_at (42233/42233 заполнено). Ключ ответа last_egrn_update_date
не меняется (additive value fix).

#1958 — confidence-фактор «Прогноз спрос/предложение» дублировался ×4
(по фактору на горизонт). Сворачиваем в один weakest-link'ом (MIN ранга
по горизонтам) в _component_confidences до confidence-движка (#990).

#1957 — ЗОУИТ backend:
- _get_cad_zouit_overlaps: DISTINCT ON (reg_numb_border) — дедуп дубль-строк
  (одна физ. зона 2× с разным category_name). group_key cad_zouit→protected.
- _get_zouit_overlaps (dump path): subcategory→RU-тип карта (26→СЗЗ и др.,
  коды сверены кросс-джойном dump↔cad_zouit на проде); type_zone из карты,
  reg из props.options.reg_numb_border. Раньше отдавал blank-строки.
- унификация group_key (protected/engineering/okn/natural/other) + top-level
  reg_numb_border в обоих путях.

UP038-модернизация isinstance в report_assembler (pre-commit ruff 0.7.4).

Frontend note (#1957): nspd_zouit_overlaps теперь всегда group_key из набора
{protected,engineering,okn,natural,other} — сырой 'cad_zouit' больше не отдаётся;
оба пути несут type_zone + reg_numb_border.

Tests: +4 _component_confidences collapse, +6 ЗОУИТ (subcategory map, dump
typing, DISTINCT ON), schema-test обновлён на protected. 451 passed targeted.
2026-06-27 14:14:40 +05:00
7533bc333b fix(site_finder): correct best-layouts supply fan-out + objects-first perf
All checks were successful
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m55s
CI / changes (pull_request) Successful in 7s
CI / backend-tests (pull_request) Successful in 12m10s
domrf_kn_objects is a snapshot dimension (UNIQUE (obj_id, snapshot_date), ~8
snapshots/obj_id). _SUPPLY_BATCH_SQL joined flats to ALL object-snapshot rows
(no o.snapshot_date filter), counting each flat ~8.5x → supply_units_in_radius
inflated ~8.5x, sold_pct_of_supply deflated ~8.5x, is_oversold under-fired
(all user-facing, best_layouts.py:571-611; sold_pct=deals/supply is a raw
ratio so no canceling).

Fix: dedup objects to one row per obj_id (latest-snapshot coords) via
DISTINCT ON in an objects-first MATERIALIZED CTE, then join domrf_kn_flats via
idx_kn_flats_obj. units now = one count per flat (prod cross-check at radius
1.5km: units == count(*) == count(DISTINCT f.id) == 9612 for 65 objects;
correction factor 8.56x at 1.5km, 9.13x at 1.0km). This also aligns the supply
denominator with the deals numerator (_COMPETITORS_IN_RADIUS_SQL already uses
DISTINCT ON latest snapshot).

Perf bonus: objects-first avoids the parallel seq scan of the ~376k-row flats
snapshot. radius 1.5km / snapshot 2026-05-17: 240ms/~28k buffers/6712 disk
reads -> 49ms/1554 buffers/0 disk reads (~5x).

Tests: add SQL-text fan-out guard (DISTINCT ON + MATERIALIZED, no bare
flats->objects join); update stale EXPLAIN mirror in test_phantom_columns.

USER-FACING: best-layouts supply/sold_pct/is_oversold/sell-out-months shift
~8.5x toward correct (frontend BestLayoutsBlock only; ТЗ recommendation + PDF
unchanged — they derive from sum_deals, not supply). Deep-reviewed (APPROVE).
2026-06-27 10:45:19 +05:00