Eyob-Sol's picture
Upload 38 files
74bb5fe verified
raw
history blame
3.58 kB
# app/catalog.py
from __future__ import annotations
import json, os
from typing import Dict, Any, List, Optional
_CATALOG: Dict[str, Any] | None = None
def get_catalog_path() -> str:
here = os.path.dirname(os.path.abspath(__file__))
root = os.path.dirname(here)
return os.path.join(root, "data", "menu_catalog.json")
def load_catalog() -> Dict[str, Any]:
global _CATALOG
if _CATALOG is not None:
return _CATALOG
path = get_catalog_path()
with open(path, "r", encoding="utf-8") as f:
_CATALOG = json.load(f)
return _CATALOG
def find_item_by_name(name: str) -> Optional[Dict[str, Any]]:
c = load_catalog()
name_l = (name or "").strip().lower()
for it in c["items"]:
if it["name"].lower() == name_l:
return it
# lightweight alias match
if name_l in it["name"].lower():
return it
return None
def find_item_by_sku(sku: str) -> Optional[Dict[str, Any]]:
c = load_catalog()
for it in c["items"]:
if it["sku"] == sku:
return it
return None
def required_fields_for_category(category: str) -> List[str]:
c = load_catalog()
schema = c["schema"].get(category) or {}
return list(schema.get("required_fields") or [])
def optional_fields_for_category(category: str) -> List[str]:
c = load_catalog()
schema = c["schema"].get(category) or {}
return list(schema.get("optional_fields") or [])
def compute_missing_fields(order_item: Dict[str, Any]) -> List[str]:
"""
order_item: {"name": "...", "sku": optional, "qty": int, "<opts>": ...}
Uses catalog schema to see which fields are missing.
"""
it = None
if "sku" in order_item:
it = find_item_by_sku(order_item["sku"])
if not it and "name" in order_item:
it = find_item_by_name(order_item["name"])
if not it:
return ["name"] # we don’t even know the item yet
category = it["category"]
req = set(required_fields_for_category(category))
present = set([k for k in order_item.keys() if k in req or k == "qty" or k == "name" or k == "sku"])
# qty normalization: consider qty present if >=1
if "qty" in req and (order_item.get("qty") is None or int(order_item.get("qty", 0)) < 1):
# keep qty “missing”
pass
else:
present.add("qty")
missing = [f for f in req if f not in present]
return missing
def friendly_requirements_prompt(order_item: Dict[str, Any]) -> str:
it = None
if "sku" in order_item:
it = find_item_by_sku(order_item["sku"])
if not it and "name" in order_item:
it = find_item_by_name(order_item["name"])
if not it:
return "Which item would you like to order?"
category = it["category"]
req = required_fields_for_category(category)
opt = optional_fields_for_category(category)
parts = []
opt_txt = ""
if opt:
opt_txt = f" Optional: {', '.join(opt)}."
if req:
parts.append(f"I need {', '.join(req)} for {it['name']}.{opt_txt}")
else:
parts.append(f"Please specify quantity for {it['name']}.{opt_txt}")
# Also list choices for required options
# e.g., size choices
opts = it.get("options") or {}
choice_bits = []
for k, spec in opts.items():
if spec.get("required"):
choices = spec.get("choices") or []
if choices:
choice_bits.append(f"{k}: {', '.join(choices)}")
if choice_bits:
parts.append("Choices → " + " | ".join(choice_bits))
return " ".join(parts)