feat(reports): Celery-джоба полного PDF-отчёта + кэш + 3 endpoint'а (#2259 PR-D) #2287
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2287
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/full-report-integration"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Что
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 автоматически инвалидирует.os.replace), имя файла — whitelist-санитизация кад.номера (только[0-9:]→_).time_limit=600, дефолтная очередь, паттерн forecast-таска, SessionLocal+try/finally).POST /{cad}/report(202 building / 200 ready при кэше),GET /{cad}/report/status,GET /{cad}/report/download(FileResponse, дата в имени — изgenerated_atметадаты)../reports:/app/reports(backend+worker) +mkdir -p reports && chown 1000:1000в deploy.yml — иначе docker создаёт bind-source root:root и первый прод-билд молча зависает в «building» (PermissionError под uid 1000).reports/в .gitignore.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
Оркестратор 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