Files
conai/backend/app/services/pdf_service.py
T
sinmb79 0156d8ca4f feat: Phase 1 잔여 기능 구현 완료
- 품질시험 API: schemas/quality.py + api/quality.py (CRUD, 합격률 요약, 자동 합불 판정)
- PDF 생성: WeasyPrint + Jinja2 (작업일보/검측요청서/보고서 템플릿 + /pdf 다운로드 엔드포인트)
- RAG 시드 스크립트: scripts/seed_rag.py (PDF/TXT 청킹, 배치 임베딩, CLI)
- APScheduler: 날씨 3시간 주기 자동 수집 + 경보 평가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 21:39:05 +09:00

79 lines
2.4 KiB
Python

"""
PDF 생성 서비스 — WeasyPrint + Jinja2
"""
from datetime import datetime
from pathlib import Path
from jinja2 import Environment, FileSystemLoader
TEMPLATES_DIR = Path(__file__).parent.parent / "templates"
_jinja_env = Environment(loader=FileSystemLoader(str(TEMPLATES_DIR)), autoescape=True)
INSPECTION_TYPE_LABELS = {
"rebar": "철근 배근 검측",
"formwork": "거푸집 검측",
"concrete": "콘크리트 타설 검측",
"pipe_burial": "관 매설 검측",
"compaction": "다짐 검측",
"waterproofing": "방수 검측",
"finishing": "마감 검측",
}
REPORT_TYPE_LABELS = {
"weekly": "주간",
"monthly": "월간",
}
REPORT_STATUS_LABELS = {
"draft": "초안",
"reviewed": "검토완료",
"submitted": "제출완료",
}
def _render_html(template_name: str, **context) -> str:
template = _jinja_env.get_template(template_name)
return template.render(now=datetime.now().strftime("%Y-%m-%d %H:%M"), **context)
def _html_to_pdf(html: str) -> bytes:
try:
from weasyprint import HTML
return HTML(string=html).write_pdf()
except ImportError:
raise RuntimeError(
"WeasyPrint가 설치되지 않았습니다. `pip install weasyprint` 실행 후 재시도하세요."
)
def generate_daily_report_pdf(report, project) -> bytes:
html = _render_html("daily_report.html", report=report, project=project)
return _html_to_pdf(html)
def generate_inspection_pdf(inspection, project) -> bytes:
type_label = INSPECTION_TYPE_LABELS.get(inspection.inspection_type, inspection.inspection_type)
html = _render_html(
"inspection.html",
inspection=inspection,
project=project,
inspection_type_label=type_label,
)
return _html_to_pdf(html)
def generate_report_pdf(report, project) -> bytes:
type_label = REPORT_TYPE_LABELS.get(report.report_type.value, report.report_type.value)
status_label = REPORT_STATUS_LABELS.get(report.status.value, report.status.value)
period_label = f"{report.period_start} ~ {report.period_end} ({type_label})"
html = _render_html(
"report.html",
report=report,
project=project,
report_type_label=type_label,
status_label=status_label,
period_label=period_label,
content_json=report.content_json,
ai_draft_text=report.ai_draft_text,
)
return _html_to_pdf(html)