Files
zavrsni-rad-otel-app/backend/app/core/export.py
2026-05-11 10:58:46 +02:00

83 lines
2.5 KiB
Python

from __future__ import annotations
import io
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import cm
from reportlab.platypus import (
Paragraph,
SimpleDocTemplate,
Spacer,
Table,
TableStyle,
)
_PAGE_W, _ = landscape(A4)
_MARGIN = 1.5 * cm
_HEADER_BG = colors.HexColor("#1a56db")
_ROW_BG = colors.HexColor("#eef2ff")
def _pdf_table(rows: list[dict]) -> Table:
if not rows:
table_data: list[list] = [["No data available"]]
n_cols = 1
else:
headers = list(rows[0].keys())
n_cols = len(headers)
table_data = [headers] + [
[str(row.get(h, "")) for h in headers] for row in rows
]
col_w = (_PAGE_W - 2 * _MARGIN) / n_cols
t = Table(table_data, colWidths=[col_w] * n_cols, repeatRows=1)
style: list = [
("BACKGROUND", (0, 0), (-1, 0), _HEADER_BG),
("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 8),
("FONTNAME", (0, 1), (-1, -1), "Helvetica"),
("FONTSIZE", (0, 1), (-1, -1), 7),
("ALIGN", (0, 0), (-1, -1), "LEFT"),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
("GRID", (0, 0), (-1, -1), 0.25, colors.HexColor("#d1d5db")),
("TOPPADDING", (0, 0), (-1, -1), 3),
("BOTTOMPADDING", (0, 0), (-1, -1), 3),
("LEFTPADDING", (0, 0), (-1, -1), 5),
("RIGHTPADDING", (0, 0), (-1, -1), 5),
]
for i in range(1, len(table_data)):
bg = _ROW_BG if i % 2 == 1 else colors.white
style.append(("BACKGROUND", (0, i), (-1, i), bg))
t.setStyle(TableStyle(style))
return t
def to_pdf_bytes(rows: list[dict], title: str, subtitle: str = "") -> bytes:
"""Serialise *rows* to a single-sheet PDF and return the raw bytes."""
buf = io.BytesIO()
styles = getSampleStyleSheet()
story = []
story.append(Paragraph(title, styles["Title"]))
if subtitle:
story.append(Spacer(1, 0.2 * cm))
story.append(Paragraph(subtitle, styles["Normal"]))
story.append(Spacer(1, 0.5 * cm))
story.append(_pdf_table(rows))
doc = SimpleDocTemplate(
buf,
pagesize=landscape(A4),
leftMargin=_MARGIN,
rightMargin=_MARGIN,
topMargin=_MARGIN,
bottomMargin=_MARGIN,
)
doc.build(story)
return buf.getvalue()