diff --git a/Fisk/receipt.py b/Fisk/receipt.py index e53ed86..794dd3f 100644 --- a/Fisk/receipt.py +++ b/Fisk/receipt.py @@ -6,9 +6,24 @@ Prati izgled definisan u LPFR VM template-u i locale fajlovima. from pathlib import Path from datetime import datetime +import io + +from reportlab.lib.pagesizes import A4 +from reportlab.pdfgen import canvas +from reportlab.pdfbase import pdfmetrics +from reportlab.pdfbase.ttfonts import TTFont DATA_DIR = Path(__file__).parent / "data" +_FONT_NAME = "Courier" +_FONT_PATH = Path("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf") +if _FONT_PATH.exists(): + try: + pdfmetrics.registerFont(TTFont("DejaVuSansMono", str(_FONT_PATH))) + _FONT_NAME = "DejaVuSansMono" + except Exception: + pass + def load_locale(lang="latin"): """Učitava lokalizacioni fajl u dict.""" filename = f"locale_{lang}.properties" @@ -646,3 +661,30 @@ def generate_report(report_data, lang="latin"): lines.append(separator("=", W)) return "\n".join(lines) + + +def render_report_pdf(report_text): + """Renderuje monospace tekst izveštaja (48 kolona) u pravi PDF (A4, Courier). + Vraća bajtove gotovog PDF fajla.""" + buf = io.BytesIO() + c = canvas.Canvas(buf, pagesize=A4) + width, height = A4 + + font_name = _FONT_NAME + font_size = 10 + line_height = font_size * 1.15 + margin_left = 20 * (72 / 25.4) # 20mm u tačkama + margin_top = 15 * (72 / 25.4) # 15mm u tačkama + + c.setFont(font_name, font_size) + y = height - margin_top + for line in report_text.split("\n"): + if y < margin_top: + c.showPage() + c.setFont(font_name, font_size) + y = height - margin_top + c.drawString(margin_left, y, line) + y -= line_height + c.showPage() + c.save() + return buf.getvalue() diff --git a/Fisk/requirements.txt b/Fisk/requirements.txt index 4f87d98..d3d0b94 100644 --- a/Fisk/requirements.txt +++ b/Fisk/requirements.txt @@ -1,2 +1,3 @@ qrcode pillow +reportlab diff --git a/Fisk/server.py b/Fisk/server.py index 613a78e..64fcced 100755 --- a/Fisk/server.py +++ b/Fisk/server.py @@ -21,7 +21,7 @@ import socket import urllib.parse import qrcode -from receipt import generate_receipt, generate_receipt_html, generate_report, load_locale +from receipt import generate_receipt, generate_receipt_html, generate_report, render_report_pdf, load_locale # ── Konfiguracija ────────────────────────────────────────── PORT = 4566 # Teron standard port @@ -665,7 +665,8 @@ def resp_financial_report_summary(request_body=None): "perTransactionType": [], } tekst = generate_report(report_data, lang) - pdf_b64 = base64.b64encode(tekst.encode("utf-8")).decode("ascii") + pdf_bytes = render_report_pdf(tekst) + pdf_b64 = base64.b64encode(pdf_bytes).decode("ascii") filename = f"{title} - {report_data['startDate']} - {report_data['endDate']}.pdf" log(f" 📄 Dnevni izveštaj #{report_data['number']} generisan ({summary['invoiceCount']} računa)") return {"reportPdfBase64": pdf_b64, "reportName": title, "filename": filename}