From 062e6b482faa4d1d7f2ec89f8da2f7c2da05478f Mon Sep 17 00:00:00 2001 From: Catering PC Date: Sun, 12 Apr 2026 13:37:13 +0200 Subject: [PATCH] fix text centering, add automatic second copy --- main.py | 105 +++++++++++++++++++++++++++++++---------------- requirements.txt | 1 - 2 files changed, 69 insertions(+), 37 deletions(-) diff --git a/main.py b/main.py index a4e6b3b..2d80a0d 100644 --- a/main.py +++ b/main.py @@ -1,62 +1,90 @@ from datetime import datetime +from typing import List import uvicorn -from fastapi import FastAPI, HTTPException -from fastapi.params import Header +from fastapi import FastAPI, HTTPException, Header from pydantic import BaseModel from escpos.printer import Usb +from escpos.capabilities import get_profile +from PIL import Image -MAX_LINE_LEN = 30 - -PRINTER = Usb(0x28e9, 0x0289) +PRINTER = Usb(0x28e9, 0x0289, profile="simple") +MAX_LINE_LEN = 32 SECRET_PASSWORD = "Alkohol1" + class OrderItem(BaseModel): menu_item_name: str amount: int + class Order(BaseModel): order_id: str order_date: datetime customer_name: str seat_id: str - items: list[OrderItem] + items: List[OrderItem] -def build_header(order_id: str, order_date: datetime, customer_name: str, seat_id: str) -> str: - return (f"EZ GG e.V. - EZ LAN 1.0\n\n" - f"Bestellungs-ID: {order_id}\n" - f"Bestellt: {order_date.strftime('%d.%m. - %H:%M')}\n" - f"Gast: {customer_name}\n" - f"Sitzplatz: {seat_id}\n\n") -def format_order(order: list[OrderItem]) -> list[str]: - formatted_order = [] - for item in order: - formatted_text = f"{item.amount}x {item.menu_item_name}" - formatted_text = formatted_text.replace("ä", "ae") - formatted_text = formatted_text.replace("ö", "oe") - formatted_text = formatted_text.replace("ü", "ue") - formatted_text = formatted_text.replace("ß", "ss") - if len(formatted_text) < MAX_LINE_LEN: - while len(formatted_text) < MAX_LINE_LEN: - formatted_text = formatted_text.replace(" ", " ", 1) - else: - formatted_text = formatted_text[:MAX_LINE_LEN] +def sanitize_text(text: str) -> str: + return (text.replace("ä", "ae") + .replace("ö", "oe") + .replace("ü", "ue") + .replace("ß", "ss")) - formatted_order.append(formatted_text + "\n") - return formatted_order -def print_order(order: Order, printer_: Usb) -> None: - header = build_header(order.order_id, order.order_date, order.customer_name, order.seat_id) - items = format_order(order.items) - printer_.image("logo.png") - printer_.text(header) +def build_header(order: Order, copy_num: int) -> str: + return ( + "EZ GG e.V. - EZGG LAN 1.0\n" + "--------------------------------\n" + f"ID: {order.order_id}\n" + f"{order.order_date.strftime('%d.%m. %H:%M')}\n" + f"Gast: {sanitize_text(order.customer_name)}\n" + f"Sitz: {sanitize_text(order.seat_id)}\n" + f"Kopie: {copy_num}\n" + "--------------------------------\n" + ) + + +def format_order(items: List[OrderItem]) -> List[str]: + lines = [] for item in items: - printer_.text(item) + name = sanitize_text(item.menu_item_name) + line = f"{item.amount}x {name}" + if len(line) > MAX_LINE_LEN: + line = line[:MAX_LINE_LEN] + lines.append(line + "\n") + return lines + + +def print_logo(printer_: Usb, path: str = "logo.png"): + try: + img = Image.open(path) + max_width = 384 + if img.width > max_width: + ratio = max_width / img.width + new_height = int(img.height * ratio) + img = img.resize((max_width, new_height)) + printer_.set(align="center") + printer_.image(img) + printer_.text("\n") + except Exception: + printer_.text("[Logo error]\n") + + +def print_order(order: Order, printer_: Usb, copy_num: int) -> None: + printer_.set(align="center") + print_logo(printer_) + printer_.text(build_header(order, copy_num)) + printer_.set(align="left") + for line in format_order(order.items): + printer_.text(line) + printer_.text("--------------------------------\n\n") printer_.cut() + api = FastAPI() @@ -67,11 +95,16 @@ async def print_order_api_endpoint(order: Order, x_password: str = Header(None)) for item in order.items: if item.amount < 1: - return 422 + raise HTTPException(status_code=422, detail="Invalid item amount") - print_order(order, PRINTER) + for copy_num in range(1, 3): + try: + print_order(order, PRINTER, copy_num) + except Exception as e: + raise HTTPException(status_code=500, detail=f"Printing failed: {str(e)}") + + return {"status": "done"} - return "done" if __name__ == "__main__": print("Starting receipt printing server...") diff --git a/requirements.txt b/requirements.txt index 682a064..cb66a50 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,6 @@ fastapi==0.115.12 h11==0.14.0 idna==3.10 importlib_resources==6.5.2 -pillow==11.2.0 pydantic==2.11.1 pydantic_core==2.33.0 python-barcode==0.15.1