feat(exporters): серверный статик-рендер карт для PDF-отчёта (#2259 PR-C Maps) #2286

Merged
bot-backend merged 1 commit from feat/report-maps into main 2026-07-03 10:29:24 +00:00
Collaborator

Что

PR-C Maps эпика #2259. Новый report_maps.py — PNG-карты для PDF без браузера (headless matplotlib Agg + geopandas + contextily):

  • render_parcel_map_png: участок + риск-зоны/красные линии/opportunity (WKT) + ЗОУИТ (GeoJSON) + конкуренты (ловушка: долгота в ключе lng) на OSM-подложке; bounded-таймаут 10с (ThreadPoolExecutor) и graceful fallback на белый фон — PDF никогда не падает из-за тайлов; битая геометрия одной зоны не роняет карту (per-geometry try/except + warning).
  • render_concept_footprint_png: контур участка + пятна корпусов с подписью этажности (для §7).
  • embed_map_png: data-URI <img> вместо плейсхолдера; None → плашка «карта недоступна».
  • Фигуры matplotlib закрываются контекст-менеджером _managed_figure (finally) на любом пути, включая неожиданный raise — иначе в долгоживущем Celery-worker'е каждый упавший рендер копил бы RSS. 2 no-leak регресс-теста, мутационно проверены (со сломанным finally падают).
  • CRS: 4326 → 3857 под OSM-тайлы. PURE-гарантия full_report_html не нарушена (report_maps из него не импортируется).

Deps

+contextily>=1.7.0, +matplotlib>=3.11.0 (uv.lock согласован, uv lock --check чист). Заметка devops: транзитивный rasterio (GDAL) — следить за весом образа при ребилде. mypy ignore-imports для трёх py.typed-less библиотек.

Тесты

15 passed (basemap no-op/exception/timeout, битые геометрии, обе ветки embed, PIL-verify PNG, max_px, 2 no-leak). Каталог exporters целиком: 125 passed. ruff+UP038 (pre-commit) clean, mypy clean.

Ревью

code-reviewer: ⚠️ MINOR → утечка фигур исправлена в этом же PR (остальное — approve).

Refs #2259

## Что PR-C Maps эпика #2259. Новый `report_maps.py` — PNG-карты для PDF без браузера (headless matplotlib Agg + geopandas + contextily): - `render_parcel_map_png`: участок + риск-зоны/красные линии/opportunity (WKT) + ЗОУИТ (GeoJSON) + конкуренты (ловушка: долгота в ключе `lng`) на OSM-подложке; bounded-таймаут 10с (ThreadPoolExecutor) и graceful fallback на белый фон — PDF никогда не падает из-за тайлов; битая геометрия одной зоны не роняет карту (per-geometry try/except + warning). - `render_concept_footprint_png`: контур участка + пятна корпусов с подписью этажности (для §7). - `embed_map_png`: data-URI `<img>` вместо плейсхолдера; None → плашка «карта недоступна». - **Фигуры matplotlib закрываются контекст-менеджером `_managed_figure` (finally) на любом пути**, включая неожиданный raise — иначе в долгоживущем Celery-worker'е каждый упавший рендер копил бы RSS. 2 no-leak регресс-теста, мутационно проверены (со сломанным finally падают). - CRS: 4326 → 3857 под OSM-тайлы. PURE-гарантия full_report_html не нарушена (report_maps из него не импортируется). ## Deps +`contextily>=1.7.0`, +`matplotlib>=3.11.0` (uv.lock согласован, `uv lock --check` чист). Заметка devops: транзитивный `rasterio` (GDAL) — следить за весом образа при ребилде. mypy ignore-imports для трёх py.typed-less библиотек. ## Тесты 15 passed (basemap no-op/exception/timeout, битые геометрии, обе ветки embed, PIL-verify PNG, max_px, 2 no-leak). Каталог exporters целиком: 125 passed. ruff+UP038 (pre-commit) clean, mypy clean. ## Ревью code-reviewer: ⚠️ MINOR → утечка фигур исправлена в этом же PR (остальное — approve). Refs #2259
bot-backend added 1 commit 2026-07-03 10:13:18 +00:00
feat(exporters): серверный статик-рендер карт для PDF-отчёта (#2259 PR-C Maps)
All checks were successful
CI / changes (pull_request) Successful in 12s
CI Trade-In / changes (pull_request) Successful in 13s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m47s
CI / backend-tests (pull_request) Successful in 15m1s
e796379074
report_maps.py: headless matplotlib(Agg)+geopandas+contextily рендер PNG
без браузера. Участок + риск-зоны/красные линии/ЗОУИТ/opportunity +
конкуренты на OSM-подложке с bounded-таймаутом (10с) и graceful fallback
на белый фон. render_concept_footprint_png — контур + пятна корпусов с
этажностью. embed_map_png — data-URI img / плашка «карта недоступна».
Фигуры закрываются _managed_figure (finally) на любом пути; 2 no-leak
регресс-теста, мутационно проверены. Ловушка: долгота конкурентов = lng.

+contextily/matplotlib deps (uv.lock; rasterio-транзитивка GDAL — вес
образа отметить при ребилде) + mypy ignore-imports.

Refs #2259
bot-backend merged commit 0b3ec7f91b into main 2026-07-03 10:29:24 +00:00
bot-backend deleted branch feat/report-maps 2026-07-03 10:29:25 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2286
No description provided.