From c82b17f9c1d9f1f9fbe07adb6528bd7a69d8a05f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Markovi=C4=87?= Date: Thu, 2 Jul 2026 20:19:17 +0200 Subject: [PATCH] =?UTF-8?q?Mock=20server:=20dnevni=20izve=C5=A1taj=20sad?= =?UTF-8?q?=20generi=C5=A1e=20pravi=20PDF=20(reportlab=20+=20DejaVu=20Sans?= =?UTF-8?q?=20Mono)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Fisk/receipt.py | 42 ++++++++++++++++++++++++++++++++++++++++++ Fisk/requirements.txt | 1 + Fisk/server.py | 5 +++-- 3 files changed, 46 insertions(+), 2 deletions(-) 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}