HH/apps/core/pdf_utils.py
2026-07-11 19:24:28 +03:00

70 lines
2.4 KiB
Python

"""
Shared PDF generation helper for any model using the hospital letterhead (artboard).
"""
import io
import base64
from django.conf import settings
from django.template.loader import render_to_string
from weasyprint import HTML
def _img_to_data_uri(path):
"""Open an image file and return it as a base64 data URI."""
try:
from PIL import Image as PILImage
img = PILImage.open(path)
buf = io.BytesIO()
img.save(buf, format="PNG", optimize=True)
return "data:image/png;base64," + base64.b64encode(buf.getvalue()).decode()
except Exception:
return None
def _get_logo_data_uri():
"""Load the HH_P_ICON as a base64 data URI for embedding in PDF."""
return _img_to_data_uri(settings.BASE_DIR / "static" / "img" / "HH_P_ICON.png")
def _get_letterhead_data_uri(obj):
"""Load the hospital letterhead (artboard) for the given object's hospital.
Priority: hospital.letterhead upload → static fallback artboard image.
"""
hospital = getattr(obj, "hospital", None)
if hospital and hospital.letterhead:
uri = _img_to_data_uri(hospital.letterhead.path)
if uri:
return uri
# Static fallback
return _img_to_data_uri(settings.BASE_DIR / "static" / "images" / "artboard" / "Artboard 1@3x.png")
def generate_letterhead_pdf(template_name, context, filename, obj=None):
"""Render a template with the hospital letterhead (artboard) and return an HttpResponse with the PDF.
Args:
template_name: Django template path.
context: Dict of template context variables.
filename: Output PDF filename.
obj: The model instance (used to resolve hospital.letterhead). If None,
falls back to the static artboard image.
"""
from django.http import HttpResponse
logo_path = _get_logo_data_uri()
letterhead_path = _img_to_data_uri(settings.BASE_DIR / "static" / "images" / "artboard" / "Artboard 1@3x.png")
if obj:
letterhead_path = _get_letterhead_data_uri(obj)
full_context = {**context, "logo_path": logo_path, "letterhead_path": letterhead_path}
html_string = render_to_string(template_name, full_context)
pdf_file = HTML(string=html_string, base_url=str(settings.BASE_DIR / "static")).write_pdf()
response = HttpResponse(pdf_file, content_type="application/pdf")
response["Content-Disposition"] = f'attachment; filename="{filename}"'
return response