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 datetime import datetime
from typing import List
import uvicorn import uvicorn
from fastapi import FastAPI, HTTPException from fastapi import FastAPI, HTTPException, Header
from fastapi.params import Header
from pydantic import BaseModel from pydantic import BaseModel
from escpos.printer import Usb from escpos.printer import Usb
from escpos.capabilities import get_profile
from PIL import Image
MAX_LINE_LEN = 30 PRINTER = Usb(0x28e9, 0x0289, profile="simple")
PRINTER = Usb(0x28e9, 0x0289)
MAX_LINE_LEN = 32
SECRET_PASSWORD = "Alkohol1" SECRET_PASSWORD = "Alkohol1"
class OrderItem(BaseModel): class OrderItem(BaseModel):
menu_item_name: str menu_item_name: str
amount: int amount: int
class Order(BaseModel): class Order(BaseModel):
order_id: str order_id: str
order_date: datetime order_date: datetime
customer_name: str customer_name: str
seat_id: 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]: def sanitize_text(text: str) -> str:
formatted_order = [] return (text.replace("ä", "ae")
for item in order: .replace("ö", "oe")
formatted_text = f"{item.amount}x {item.menu_item_name}" .replace("ü", "ue")
formatted_text = formatted_text.replace("ä", "ae") .replace("ß", "ss"))
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]
formatted_order.append(formatted_text + "\n")
return formatted_order
def print_order(order: Order, printer_: Usb) -> None: def build_header(order: Order, copy_num: int) -> str:
header = build_header(order.order_id, order.order_date, order.customer_name, order.seat_id) return (
items = format_order(order.items) "EZ GG e.V. - EZGG LAN 1.0\n"
printer_.image("logo.png") "--------------------------------\n"
printer_.text(header) 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: 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() printer_.cut()
api = FastAPI() api = FastAPI()
@ -67,11 +95,16 @@ async def print_order_api_endpoint(order: Order, x_password: str = Header(None))
for item in order.items: for item in order.items:
if item.amount < 1: 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__": if __name__ == "__main__":
print("Starting receipt printing server...") print("Starting receipt printing server...")

View File

@ -7,7 +7,6 @@ fastapi==0.115.12
h11==0.14.0 h11==0.14.0
idna==3.10 idna==3.10
importlib_resources==6.5.2 importlib_resources==6.5.2
pillow==11.2.0
pydantic==2.11.1 pydantic==2.11.1
pydantic_core==2.33.0 pydantic_core==2.33.0
python-barcode==0.15.1 python-barcode==0.15.1