fix text centering, add automatic second copy

This commit is contained in:
Catering PC 2026-04-12 13:37:13 +02:00
parent 9b054652d7
commit 062e6b482f
2 changed files with 69 additions and 37 deletions

105
main.py
View File

@ -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...")

View File

@ -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