VirtForemanBackend / app /services /document_engine.py
Dirbol's picture
deploy: backend 2026-06-22T05:07:40Z
0c46399
Raw
History Blame Contribute Delete
1.71 kB
"""Document generation service via docxtpl (.docx + Jinja2)."""
from __future__ import annotations
import io
from datetime import datetime
from pathlib import Path
from docxtpl import DocxTemplate
from loguru import logger
from app.models.tech_stack import DocumentRequest
TEMPLATES_DIR = Path(__file__).resolve().parents[2] / "templates"
class DocumentEngine:
"""Render .docx templates with supplied context."""
SUPPORTED = {
"act_hidden_works": "act_hidden_works.docx",
"act_osmotr_responsibility": "act_osmotr_responsibility.docx",
"general_work_log": "general_work_log.docx",
"material_certificate": "material_certificate.docx",
}
def render(self, request: DocumentRequest) -> bytes:
template_file = self.SUPPORTED.get(request.template_name)
if template_file is None:
raise ValueError(
f"Unknown template: {request.template_name}. "
f"Supported: {list(self.SUPPORTED)}"
)
template_path = TEMPLATES_DIR / template_file
if not template_path.exists():
raise FileNotFoundError(
f"Template file not found: {template_path}"
)
logger.info(f"Rendering document: {request.template_name}")
tpl = DocxTemplate(str(template_path))
context = {
"generated_at": datetime.utcnow().strftime("%d.%m.%Y %H:%M"),
"project_id": request.project_id,
**request.context,
}
tpl.render(context)
buf = io.BytesIO()
tpl.save(buf)
buf.seek(0)
return buf.read()
def get_document_engine() -> DocumentEngine:
return DocumentEngine()