general fixes and ordering display overhaul
This commit is contained in:
@@ -47,9 +47,57 @@ def _raw_text(p: Network, text: str):
|
||||
p._raw(_gr(text))
|
||||
|
||||
|
||||
def _divider(p: Network):
|
||||
_DIVIDER_CHARS = {
|
||||
"dash": "-",
|
||||
"equals": "=",
|
||||
"star": "*",
|
||||
"empty": "",
|
||||
}
|
||||
|
||||
_PRINT_FONT_DEFAULTS = {
|
||||
"print.font_item_name": "16:0",
|
||||
"print.font_options": "0:0",
|
||||
"print.font_table": "16:0",
|
||||
"print.font_order_number": "48:1",
|
||||
"print.font_header": "48:1",
|
||||
"print.divider_style": "dash",
|
||||
}
|
||||
|
||||
# SIZE byte values (ESC ! base, no bold bit):
|
||||
# 0 = normal
|
||||
# 16 = double-height (bit4)
|
||||
# 32 = double-width (bit5)
|
||||
# 48 = double-height + double-width (bits 4+5)
|
||||
# Bold is applied separately via ESC E.
|
||||
|
||||
def _decode_font(value: str) -> tuple[int, bool]:
|
||||
"""Parse 'SIZE:BOLD' string → (esc_bang_byte, bold_flag)."""
|
||||
try:
|
||||
parts = str(value).split(":")
|
||||
size = int(parts[0])
|
||||
bold = len(parts) > 1 and parts[1] == "1"
|
||||
return size, bold
|
||||
except (ValueError, AttributeError):
|
||||
return 0, False
|
||||
|
||||
|
||||
def _load_print_fonts(db: Session) -> dict:
|
||||
rows = db.query(PosSettings).filter(
|
||||
PosSettings.key.in_(_PRINT_FONT_DEFAULTS.keys())
|
||||
).all()
|
||||
fonts = dict(_PRINT_FONT_DEFAULTS)
|
||||
for row in rows:
|
||||
fonts[row.key] = row.value
|
||||
return fonts
|
||||
|
||||
|
||||
def _divider(p: Network, style: str = "dash"):
|
||||
char = _DIVIDER_CHARS.get(style, "-")
|
||||
p._raw(b'\x1b\x61\x00')
|
||||
p._raw(_gr("-" * LINE_WIDTH + "\n"))
|
||||
if char:
|
||||
p._raw(_gr(char * LINE_WIDTH + "\n"))
|
||||
else:
|
||||
p._raw(b'\n')
|
||||
|
||||
|
||||
def _item_line(name: str, qty: int) -> str:
|
||||
@@ -106,34 +154,50 @@ def send_test_print(ip: str, port: int, name: str) -> Tuple[bool, str]:
|
||||
|
||||
# ── Receipt formatting ───────────────────────────────────────────────────────
|
||||
|
||||
def _font(p: Network, byte_val: int, bold: bool = False):
|
||||
p._raw(bytes([0x1b, 0x21, byte_val]))
|
||||
p._raw(b'\x1b\x45\x01' if bold else b'\x1b\x45\x00')
|
||||
|
||||
|
||||
def _print_kitchen_ticket(p: Network, order: Order, items: List[OrderItem], db: Session):
|
||||
# Header
|
||||
fonts = _load_print_fonts(db)
|
||||
div = fonts["print.divider_style"]
|
||||
|
||||
sz_order, bold_order = _decode_font(fonts["print.font_order_number"])
|
||||
sz_table, bold_table = _decode_font(fonts["print.font_table"])
|
||||
sz_item, bold_item = _decode_font(fonts["print.font_item_name"])
|
||||
sz_opt, bold_opt = _decode_font(fonts["print.font_options"])
|
||||
|
||||
# Header — order number
|
||||
p._raw(b'\x1b\x61\x01')
|
||||
p._raw(b'\x1b\x21\x38') # bold + double height + double width
|
||||
_font(p, sz_order, bold_order)
|
||||
_raw_text(p, f"Παραγγελια #{order.id}\n")
|
||||
p._raw(b'\x1b\x21\x00')
|
||||
_divider(p)
|
||||
p._raw(b'\x1b\x45\x00')
|
||||
_divider(p, div)
|
||||
|
||||
# Meta
|
||||
# Meta — table / waiter / time
|
||||
p._raw(b'\x1b\x61\x00')
|
||||
p._raw(b'\x1b\x21\x10') # double height only — keeps 48-char width
|
||||
_font(p, sz_table, bold_table)
|
||||
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
|
||||
_raw_text(p, f"Date: {now}\n")
|
||||
_raw_text(p, f"Table: {order.table_id}\n")
|
||||
_raw_text(p, f"Waiter: {order.opened_by}\n")
|
||||
p._raw(b'\x1b\x21\x00')
|
||||
_divider(p)
|
||||
p._raw(b'\x1b\x45\x00')
|
||||
_divider(p, div)
|
||||
|
||||
# Items
|
||||
for item in items:
|
||||
product = db.query(Product).filter(Product.id == item.product_id).first()
|
||||
name = product.name if product else f"Product #{item.product_id}"
|
||||
|
||||
p._raw(b'\x1b\x21\x10')
|
||||
p._raw(b'\x1b\x45\x01') # bold on
|
||||
_font(p, sz_item, bold_item)
|
||||
_raw_text(p, _item_line(name, item.quantity) + "\n")
|
||||
p._raw(b'\x1b\x45\x00') # bold off
|
||||
p._raw(b'\x1b\x21\x00')
|
||||
p._raw(b'\x1b\x45\x00')
|
||||
|
||||
_font(p, sz_opt, bold_opt)
|
||||
if item.removed_ingredients:
|
||||
try:
|
||||
removed_ids = json.loads(item.removed_ingredients)
|
||||
@@ -154,8 +218,9 @@ def _print_kitchen_ticket(p: Network, order: Order, items: List[OrderItem], db:
|
||||
_raw_text(p, f" (i) {item.notes}\n")
|
||||
|
||||
p._raw(b'\x1b\x21\x00')
|
||||
p._raw(b'\x1b\x45\x00')
|
||||
|
||||
_divider(p)
|
||||
_divider(p, div)
|
||||
|
||||
if order.notes:
|
||||
p._raw(b'\x1b\x21\x30')
|
||||
|
||||
Reference in New Issue
Block a user