Commit graph

432 commits

Author SHA1 Message Date
c129515ab8 feat(exporters): DOCX-вариант полного отчёта ПТИЦА (#2259 R2) (#2301)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Successful in 3m34s
Deploy / build-worker (push) Successful in 4m25s
Deploy / build-frontend (push) Successful in 5m25s
Deploy / deploy (push) Successful in 1m33s
2026-07-03 20:21:19 +00:00
b902edd44c fix(full-report): generic-маркеры областных админ-единиц в ЕКБ-фильтре тепла (#2297)
All checks were successful
Deploy / build-worker (push) Successful in 3m41s
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m25s
Deploy / deploy (push) Successful in 1m40s
2026-07-03 19:59:58 +00:00
e9e3cc7dcf fix(full-report): §7 на MultiPolygon + чистка печатного шума §3/§4 (вычитка живого отчёта) (#2296)
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 3m7s
Deploy / deploy (push) Successful in 1m41s
2026-07-03 19:33:11 +00:00
034d9f9bca feat(reports): Celery-джоба полного PDF-отчёта + кэш + 3 endpoint'а (#2259 PR-D) (#2287)
Some checks failed
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Successful in 3m12s
Deploy / build-worker (push) Successful in 4m8s
Deploy / build-frontend (push) Successful in 4m46s
Deploy / deploy (push) Has been cancelled
2026-07-03 11:13:06 +00:00
0b3ec7f91b feat(exporters): серверный статик-рендер карт для PDF-отчёта (#2259 PR-C Maps) (#2286)
All checks were successful
Deploy / deploy (push) Successful in 1m59s
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 3m47s
Deploy / build-worker (push) Successful in 4m45s
2026-07-03 10:29:23 +00:00
e7881cf45c feat(exporters): PURE HTML §4–§7 полного PDF-отчёта (#2259 PR-B Sections) (#2285)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m5s
Deploy / build-worker (push) Successful in 3m50s
Deploy / deploy (push) Successful in 1m55s
2026-07-03 10:10:43 +00:00
c0c18f4ecc feat(exporters): PURE HTML-агрегатор §1–§3 + альтернативы (#2259 PR-A Foundation) (#2284)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m56s
Deploy / build-worker (push) Successful in 3m56s
Deploy / deploy (push) Successful in 1m49s
2026-07-03 09:52:32 +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
dfc1ee8be0 feat: ревью-инструмент авто-маппингов Объектив↔ДОМ.РФ (/admin/mapping-review) (#2278)
Some checks failed
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Successful in 2m47s
Deploy / build-worker (push) Successful in 5m42s
Deploy / build-frontend (push) Successful in 5m55s
Deploy / deploy (push) Has been cancelled
2026-07-03 07:59:13 +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
fc6542416d feat(exporters): §4.2 supply-only блок в ТЗ-PDF (#2177) (#2260)
All checks were successful
Deploy / changes (push) Successful in 9s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m50s
Deploy / build-worker (push) Successful in 5m25s
Deploy / deploy (push) Successful in 2m27s
2026-07-03 06:38:23 +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
55b13e2b13 fix(dadata): фолбэк на suggest/address при отключённой фиче CLEAN (#2250)
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m54s
Deploy / build-worker (push) Successful in 2m56s
Deploy / deploy (push) Successful in 1m33s
2026-07-03 03:42:40 +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
830d9f429a fix(etl): гео-проход — префикс «г Екатеринбург» адресам без города (#2177 остаток) (#2245)
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 3m0s
Deploy / deploy (push) Successful in 1m37s
2026-07-03 01:41:19 +00:00
031bafde86 feat(etl): гео-проход auto_core_geo_v6 для tier_b/ambiguous mapping (#2177 остаток) (#2244)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m43s
Deploy / build-worker (push) Successful in 2m47s
Deploy / deploy (push) Successful in 1m27s
2026-07-03 01:19:59 +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
e9c8d05e1d feat(etl): auto_core_dev_v5 — core-name+dev backfill mapping'а (#2177 шаг 2) (#2237)
Some checks failed
Deploy / changes (push) Successful in 7s
Deploy / deploy (push) Blocked by required conditions
Deploy / build-backend (push) Successful in 2m8s
Deploy / build-frontend (push) Has been cancelled
Deploy / build-worker (push) Has been cancelled
2026-07-02 21:59:16 +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
1c184959a8 feat(etl): read tradein data via market.v_* contract views (#2138 step 2/3)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m15s
Deploy / build-worker (push) Successful in 3m12s
Deploy / deploy (push) Successful in 1m34s
2026-07-02 15:00:38 +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
975c400536 feat(section7): editable section footprint + корпус plural/program hint (#1953) (#2102)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Successful in 1m57s
Deploy / build-frontend (push) Successful in 3m34s
Deploy / build-worker (push) Successful in 3m41s
Deploy / deploy (push) Successful in 1m32s
2026-06-30 09:48:11 +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
3421b21632 fix(scrapers): разблокировать domrf_kn flats — изоляция flats от poison-extras + throttle (#1945) (#2050)
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 9m31s
Deploy / build-worker (push) Successful in 11m57s
Deploy / deploy (push) Successful in 3m51s
2026-06-28 13:03:43 +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
94cf1f6217 feat(concept): house-type catalog + program-driven placement (#1965 Stage 3a)
Extend the concept generator so ConceptInput can carry an optional
building_program (list of typed houses from a catalog). When present,
placement lays out EXACTLY that program — for each item, place `count`
sections of the catalog footprint at the item's floors — instead of the
greedy max-FAR coverage-cap sweep. When absent, the existing greedy
behavior is unchanged (byte-for-byte backward-compatible).

- catalog.py: hardcoded HOUSE_TYPES (panel_econom, monolith_comfort,
  tower_business, lowrise_comfort, townhouse) — sane-default catalog,
  promote to DB later; get_house_type / available_section_types lookups.
- schema: additive BuildingProgramItem {section_type, floors, count} and
  ConceptInput.building_program (default None -> greedy). ConceptVariant
  gains optional placed_count / requested_count (partial-fit signal).
- placement: shared _Placer (collision/STRtree/setback machine extracted
  from greedy sweep, reused — no duplication); place_program +
  place_program_variant; branch in place_all_strategies on
  building_program. Mixed-floor TEAP via exact per-floor-group aggregation
  (GFA = sum(area_i * floors_i), no rounding drift).
- partial fit: when the parcel can't fit all sections, place as many as
  fit and report placed_count < requested_count (no hard-422); zero-fit
  still raises ParcelGeometryError (-> 422).
- API: validate program section_type keys against the catalog (unknown ->
  422) before placement.
- tests: catalog integrity, greedy backward-compat, exact 2-item program +
  TEAP reflection, over-packed partial placement, API program path.
- regenerate frontend api-types.ts (OpenAPI codegen gate stays green).
2026-06-28 01:29:04 +05:00
d38d5d43c5 feat(generative): LIVE financial recompute from massing program (#1965 Stage 2a)
Stage 2a of epic #1953: backend service + endpoint for live economic recompute
driven by the interactive 3D massing (Stage 2b debounced sliders).

- teap.py: add pure synthesize_teap_from_program(total_footprint_sqm, floors,
  site_area_sqm, housing_class, sections) — builds a TEAP from the SCALAR
  aggregate footprint × floors, mirroring synthesize_teap_from_buildability and
  reusing the same shared norm constants (_OFFICE_SHARE_OF_GFA / _EFFICIENCY_BY_CLASS
  / _AVG_APARTMENT_SQM / _PARKING_PER_APARTMENT) — single source of truth.
- schemas/concept.py: add MassingProgram (program contract, optional pre-resolved
  market_price_per_sqm + parcel_centroid_wkt) and MassingRecomputeOutput (teap + financial).
- api/v1/concepts.py: add POST /api/v1/concepts/recompute — synthesize TEAP → run
  the existing pure compute_financial. FAST path uses body market_price_per_sqm
  (no DB); else _lookup_market_price by centroid via run_in_threadpool; else class norm.
- tests: synthesize_teap_from_program (gfa math, parity with compute_teap, class
  efficiency, sections no-op) + endpoint (200, coherent output, price passthrough
  skips DB, DB fallback, class-norm default, floors validation).
2026-06-28 00:27:25 +05:00