Initial commit: certgen — сервис генерации сертификатов

This commit is contained in:
apuc committed 2026-10-16 17:17:47 +03:00
commit 49bac43e16
23 files changed
+3046

No files matched your search

+70
View File
@@ -0,0 +1,70 @@
"""Ядро сервиса: построение значений и создание документа."""
from __future__ import annotations
from . import config, store
from .render import render_certificate, russian_date
def base_url() -> str:
if config.BASE_URL:
return config.BASE_URL
return f"http://{config.HOST}:{config.PORT}"
def build_values(template: dict, body: dict) -> dict:
defaults = template.get("defaults") or {}
title = (body.get("title") or defaults.get("title") or template.get("title") or "").strip()
text = body.get("body")
if text is None:
text = defaults.get("body", "")
fields = body.get("fields") or {}
values = {
"title": title,
"fio": (body.get("fio") or "").strip(),
"body": text or "",
"date": (body.get("date") or "").strip() or russian_date(),
"fields": fields,
}
# произвольные поля из fields доступны как {ключ}
for k, v in fields.items():
values.setdefault(str(k), v)
return values
def cert_api(cert: dict, base: str) -> dict:
token = cert.get("public_token")
return {
**cert,
"url": f"{base}/c/{cert['seq']}",
"page": f"{base}/c/{cert['seq']}",
"png": f"{base}/c/{cert['seq']}.png",
"pdf": f"{base}/c/{cert['seq']}.pdf",
"public_url": f"{base}/s/{token}" if token else None,
"public_png": f"{base}/s/{token}.png" if token else None,
"public_pdf": f"{base}/s/{token}.pdf" if token else None,
}
def create_certificate(template: dict, body: dict, base: str | None = None,
created_by: int | None = None) -> dict:
"""Создать документ: зарезервировать номер, отрендерить, сохранить пути."""
base = base or base_url()
values = build_values(template, body)
cert = store.reserve_certificate(
template=template["slug"], values=values, prefix=body.get("prefix"),
number=body.get("number"),
recipient_email=body.get("email") or body.get("recipient_email"),
created_by=created_by,
)
seq = cert["seq"]
values["number"] = cert["number"]
out_png = config.OUTPUT_DIR / f"{seq:06d}.png"
out_pdf = config.OUTPUT_DIR / f"{seq:06d}.pdf"
try:
render_certificate(template, values, out_png, out_pdf)
except Exception:
store.delete_certificate(seq)
raise
store.update_certificate_files(seq, str(out_png), str(out_pdf))
return cert_api(store.get_certificate(seq), base)