gendesign/backend/app/services/generative
bot-backend f227768a53
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m17s
CI / backend-tests (pull_request) Successful in 17m20s
fix(ptica): три места, где код делал не то, что говорил (#2464)
1. `load_water_reserves_from_docx` собирал `result` с ключом `period`,
   печатал ПОЛНЫЙ словарь в лог, а возвращал
   `{k: v for … if isinstance(v, int)}` — период это строка или None,
   поэтому выбрасывался всегда. По логам казалось, что период отдаётся;
   вызывающий не получал его ни разу.

   Фильтр стоял ради аннотации `dict[str, int]` и ничего не защищал:
   соседняя ветка `load_water_reserves` кладёт в тот же словарь
   `{"error": str(...)}`, а единственный потребитель — задача
   `sync_water_reserves` — результат логирует и возвращает как есть.
   Период полезен: без него «загружено 42 записи» не отличить от
   прошлогодних. Аннотация исправлена, иначе следующий проход mypy вернул
   бы фильтр обратно — на это поставлен отдельный тест.

2. `get_sqlite_info` — TOCTOU: `p.exists()`, затем незащищённый
   `p.stat()`. try/except покрывал только `sqlite3.connect` ниже, поэтому
   OSError из stat улетал наружу и превращал диагностическую функцию в
   источник отказа. Файл между проверками реально исчезает — его
   переписывает выгрузка Объектива. Теперь отдаём то, что успели узнать,
   с ключом `stat_error`.

3. `place_program` — предупреждение «участок мал» печатало КАТАЛОЖНЫЕ
   `house.footprint_*`, хотя ставили по `fp_w`/`fp_d`. При
   переопределённом в программе габарите сообщение называло размер,
   которым никто не пытался ставить, и уводило от причины.

Двусторонне: против origin/main четыре теста красные с конкретными
значениями («период выброшен из ответа: {'records': 1, 'inserted': 1,
'updated': 0}», «аннотация всё ещё требует только int: dict[str, int]»).

Контроли зелёные с обеих сторон: отсутствующий файл по-прежнему даёт
exists=False без ошибки; `fp_w`/`fp_d` — действительно те размеры,
которыми ставят (иначе первый тест сверял бы имена, а не смысл).

pytest backend/tests/services/ — 3207 passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 23:59:02 +05:00
..
exporters fix(ptica): сноска концепт-PDF печатает фактический срок распродажи, а не «30 мес» (#2464) (#2945) 2026-08-19 17:39:37 +00:00
__init__.py feat(generative): движок концепций Stage 1a/1b/1c (#54 #55 #56) 2026-06-13 21:32:32 +05:00
catalog.py feat(concept): house-type catalog + program-driven placement (#1965 Stage 3a) 2026-06-28 01:29:04 +05:00
financial.py feat(financial/dcf): dormant separate-index inflation capability (default OFF) 2026-06-25 12:12:02 +00:00
geometry.py fix(generative): отклонять спроецированные координаты до pyproj CRSError → 422 (#2445-B1) (#2453) 2026-07-05 19:20:19 +00:00
placement.py fix(ptica): три места, где код делал не то, что говорил (#2464) 2026-08-20 23:59:02 +05:00
teap.py feat(generative): LIVE financial recompute from massing program (#1965 Stage 2a) 2026-06-28 00:27:25 +05:00