home-kitchen-admin / generators.py
Nguyen Minh Nhat
After-Shift Admin Assistant
11b9749
Raw
History Blame Contribute Delete
4.28 kB
"""Output generators for custom food orders: receipt, customer message, pickup
reminder, ingredient shopping list.
Pure string formatting from a normalized order dict β€” no model calls, no I/O.
Storage keys are generic; their meaning here: services=items, next_appointment=pickup,
supplies=ingredients, amount_paid=deposit/payment.
"""
from __future__ import annotations
from datetime import datetime
from config import BUSINESS_NAME, CURRENCY
def money(x) -> str:
try:
return f"{CURRENCY}{float(x or 0):,.2f}"
except (TypeError, ValueError):
return f"{CURRENCY}0.00"
def _balance(order: dict) -> float:
return round(float(order.get("amount_charged") or 0) - float(order.get("amount_paid") or 0), 2)
def _item_lines(order: dict) -> str:
items = order.get("services") or []
if not items:
return " β€’ Order"
return "\n".join(f" β€’ {s}" for s in items)
def invoice(order: dict) -> str:
"""Order receipt for the customer."""
customer = order.get("customer") or "Customer"
date = (order.get("created_at") or datetime.now().isoformat())[:10]
balance = _balance(order)
paid = float(order.get("amount_paid") or 0)
header = BUSINESS_NAME or "ORDER RECEIPT"
lines = [
header,
"=" * max(len(header), 28),
f"Date: {date}",
f"Customer: {customer}",
"",
"Order:",
_item_lines(order),
]
if order.get("next_appointment"):
lines.append(f"\nPickup/Delivery: {order['next_appointment']}")
lines += [
"",
f"Order total: {money(order.get('amount_charged'))}",
f"Paid: {money(paid)}"
+ (f" ({order['payment_method']})" if order.get("payment_method") else ""),
f"Balance: {money(balance)}",
]
if balance <= 0:
lines.append("\nStatus: PAID IN FULL β€” thank you!")
elif paid > 0:
lines.append(f"\nStatus: DEPOSIT PAID β€” {money(balance)} due on collection")
else:
lines.append(f"\nStatus: UNPAID β€” {money(balance)} due on collection")
return "\n".join(lines)
_HONORIFICS = {"mr", "mrs", "ms", "miss", "madam", "mdm", "auntie", "aunty", "uncle", "dr"}
def followup(order: dict) -> str:
"""Ready-to-send WhatsApp/SMS order confirmation, tone depends on payment."""
name = (order.get("customer") or "").strip()
first = name.split()[0] if name else "there"
# "Mrs Tan" must not become "Hi Mrs," β€” keep the full name after an honorific.
customer = name if first.lower().rstrip(".") in _HONORIFICS else first
balance = _balance(order)
paid = float(order.get("amount_paid") or 0)
items = order.get("services") or []
item_txt = " and ".join(items).lower() if items else "your order"
if balance <= 0:
msg = f"Hi {customer}, thanks so much for your order of {item_txt} β€” all paid, "
msg += "and it'll be ready for you."
elif paid > 0:
msg = (f"Hi {customer}, thanks for your order of {item_txt}! "
f"Total {money(order.get('amount_charged'))}, deposit of {money(paid)} received β€” "
f"just {money(balance)} to settle on collection.")
else:
msg = (f"Hi {customer}, confirming your order of {item_txt}. "
f"That's {money(order.get('amount_charged'))}, payable on collection.")
if order.get("next_appointment"):
msg += f" Ready for {order['next_appointment']}. See you then!"
return msg
def reminder(order: dict) -> str:
customer = order.get("customer") or "Customer"
when = order.get("next_appointment")
items = ", ".join(order.get("services") or []) or "order"
if not when:
return "No pickup/delivery time set."
return f"🧁 {when}: {customer} β€” {items}"
def supplies_list(order: dict) -> str:
items = order.get("supplies") or []
if not items:
return "No ingredients to buy."
return "πŸ›’ Ingredients to buy:\n" + "\n".join(f" ☐ {i}" for i in items)
def generate_all(order: dict) -> dict:
"""Convenience: all four outputs in one dict, for the UI."""
return {
"invoice": invoice(order),
"followup": followup(order),
"reminder": reminder(order),
"supplies": supplies_list(order),
}