feat(reports): Celery-джоба полного PDF-отчёта + кэш + 3 endpoint'а (#2259 PR-D) #2287

Merged
bot-backend merged 1 commit from feat/full-report-integration into main 2026-07-03 11:13:07 +00:00
Collaborator

Что

PR-D Integration эпика #2259 — сшивает A+B+C в работающий сервис:

  • Оркестратор full_report_pdf.py: analyze-ран + форсайт-ран (реальная schema "1.0") + best-effort server-side концепция (поток POST /concepts, comfort) + best-effort connection-capacity (§3-резервы + «Сети рядом») + карты report_maps (max_px 1400) → WeasyPrint → файл на volume + метадата-ран report-pdf-1.0.
  • Кэш по (analyze_run_id, forecast_run_id) с проверкой существования файла (сирота-ран → чистый ре-рендер); новый /analyze автоматически инвалидирует.
  • Запись атомарная (tmp с PID + os.replace), имя файла — whitelist-санитизация кад.номера (только [0-9:]_).
  • Celery task on-demand (time_limit=600, дефолтная очередь, паттерн forecast-таска, SessionLocal+try/finally).
  • 3 endpoint'а (2+-сегментные, без конфликта с однодольными): POST /{cad}/report (202 building / 200 ready при кэше), GET /{cad}/report/status, GET /{cad}/report/download (FileResponse, дата в имени — из generated_at метадаты).
  • Deploy: bind-mount ./reports:/app/reports (backend+worker) + mkdir -p reports && chown 1000:1000 в deploy.yml — иначе docker создаёт bind-source root:root и первый прод-билд молча зависает в «building» (PermissionError под uid 1000). reports/ в .gitignore.
  • WeasyPrint — только локальный import в render-функции: web-процесс native-библиотеки не тянет (проверено импортом app.main).
  • В full_report_html.py — блок connection-capacity в §3 (единственная разрешённая правка; _fmt_pct_raw — проценты 0–100 без домножения).
  • api-types.ts регенерён (+219, ReportBuildResponse/ReportStatusResponse + 3 пути).

Тесты

161 passed / 6 skipped (19 новых: кэш hit/miss/сирота, no-analyze → ValueError, best-effort деградации, 404/202/200-ready/503, download 200/404 + дата из generated_at, cad_safe whitelist). weasyprint/карты замоканы — CI без native. ruff+UP clean, CAST-grep пуст.

Ревью

code-reviewer: ⚠️ MINOR → все 5 пунктов применены (chown в deploy, атомарная запись, дата из generated_at, whitelist cad_safe, .gitignore). «Failed-состояние в status» — осознанное упрощение: фронт получит cap на поллинг в PR-E.

Post-merge

Деплой пересоберёт образ с contextily/matplotlib/rasterio (GDAL) — проверить вес. qa: права /opt/gendesign/reports, полный цикл POST→status→download на реальном cad.

Refs #2259

## Что PR-D Integration эпика #2259 — сшивает A+B+C в работающий сервис: - **Оркестратор `full_report_pdf.py`**: analyze-ран + форсайт-ран (реальная schema `"1.0"`) + best-effort server-side концепция (поток POST /concepts, comfort) + best-effort connection-capacity (§3-резервы + «Сети рядом») + карты report_maps (max_px 1400) → WeasyPrint → файл на volume + метадата-ран `report-pdf-1.0`. - **Кэш** по `(analyze_run_id, forecast_run_id)` с проверкой существования файла (сирота-ран → чистый ре-рендер); новый /analyze автоматически инвалидирует. - **Запись атомарная** (tmp с PID + `os.replace`), имя файла — whitelist-санитизация кад.номера (только `[0-9:]`→`_`). - **Celery task** on-demand (`time_limit=600`, дефолтная очередь, паттерн forecast-таска, SessionLocal+try/finally). - **3 endpoint'а** (2+-сегментные, без конфликта с однодольными): `POST /{cad}/report` (202 building / 200 ready при кэше), `GET /{cad}/report/status`, `GET /{cad}/report/download` (FileResponse, дата в имени — из `generated_at` метадаты). - **Deploy**: bind-mount `./reports:/app/reports` (backend+worker) + `mkdir -p reports && chown 1000:1000` в deploy.yml — иначе docker создаёт bind-source root:root и первый прод-билд молча зависает в «building» (PermissionError под uid 1000). `reports/` в .gitignore. - WeasyPrint — только локальный import в render-функции: web-процесс native-библиотеки не тянет (проверено импортом app.main). - В `full_report_html.py` — блок connection-capacity в §3 (единственная разрешённая правка; `_fmt_pct_raw` — проценты 0–100 без домножения). - `api-types.ts` регенерён (+219, ReportBuildResponse/ReportStatusResponse + 3 пути). ## Тесты 161 passed / 6 skipped (19 новых: кэш hit/miss/сирота, no-analyze → ValueError, best-effort деградации, 404/202/200-ready/503, download 200/404 + дата из generated_at, cad_safe whitelist). weasyprint/карты замоканы — CI без native. ruff+UP clean, CAST-grep пуст. ## Ревью code-reviewer: ⚠️ MINOR → все 5 пунктов применены (chown в deploy, атомарная запись, дата из generated_at, whitelist cad_safe, .gitignore). «Failed-состояние в status» — осознанное упрощение: фронт получит cap на поллинг в PR-E. ## Post-merge Деплой пересоберёт образ с contextily/matplotlib/rasterio (GDAL) — проверить вес. qa: права /opt/gendesign/reports, полный цикл POST→status→download на реальном cad. Refs #2259
bot-backend added 1 commit 2026-07-03 10:57:35 +00:00
feat(reports): Celery-джоба полного PDF-отчёта + кэш + 3 endpoint'а (#2259 PR-D)
All checks were successful
CI / changes (pull_request) Successful in 8s
CI Trade-In / changes (pull_request) Successful in 8s
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) Successful in 1m15s
CI / openapi-codegen-check (pull_request) Successful in 2m7s
CI / backend-tests (pull_request) Successful in 14m57s
880bac7738
Оркестратор build_full_report собирает §1-§7 + карты из analyze/forecast
ранов (реальная schema форсайта = "1.0"), best-effort дотягивает
connection-capacity (§3-резервы + сети рядом) и server-side концепцию
(поток POST /concepts: ConceptInput comfort → generate), рендерит
WeasyPrint'ом (локальный import — web-процесс native не тянет) на volume
/app/reports с метадата-раном report-pdf-1.0. Кэш по (analyze_run_id,
forecast_run_id) с проверкой существования файла (сирота → ре-рендер).
Запись атомарная (tmp+os.replace), имя файла из whitelist-санитизации
кад.номера. Celery task on-demand (time_limit 600), endpoint'ы POST
/{cad}/report (202/200) + status + download (дата из generated_at).

Deploy: bind-mount ./reports:/app/reports (backend+worker) + mkdir/chown
uid1000 в deploy.yml (docker создал бы root:root → PermissionError →
вечный building). reports/ в .gitignore. api-types регенерён (+219).

Refs #2259
bot-backend merged commit 034d9f9bca into main 2026-07-03 11:13:07 +00:00
bot-backend deleted branch feat/full-report-integration 2026-07-03 11:13:07 +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#2287
No description provided.