45 lines
1.9 KiB
Python
45 lines
1.9 KiB
Python
"""Select shelf-stable stock using Ocado metadata, without a product-name list."""
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Decision:
|
|
include: bool
|
|
reason: str
|
|
uncertain: bool = False
|
|
|
|
|
|
PERISHABLE_CATEGORIES = {"fresh & chilled food", "frozen food", "bakery"}
|
|
SHELF_STABLE_CATEGORIES = {
|
|
"food cupboard", "treats & snacks", "soft drinks, tea & coffee", "beer, wine & spirits",
|
|
"household & cleaning", "home care & cleaning", "health, beauty & personal care",
|
|
"beauty & toiletries", "pets", "health, medicines & wellbeing", "home & garden",
|
|
"m&s food cupboard", "m&s snacks & treats",
|
|
}
|
|
|
|
|
|
def classify(item, overrides=None):
|
|
overrides = overrides or {}
|
|
key = item.product_id or item.name
|
|
if key in overrides:
|
|
value = overrides[key]
|
|
if not isinstance(value, bool):
|
|
raise ValueError(f"pantry override {key!r} must be true or false")
|
|
return Decision(value, "explicit product override")
|
|
storage_type = item.metadata.get("storage_type")
|
|
if storage_type in {"FRIDGE", "FREEZER"}:
|
|
return Decision(False, "requires cold storage")
|
|
product = item.metadata.get("ocado", {})
|
|
storage = str(product.get("storage", "")).casefold()
|
|
if "keep refrigerated" in storage or "keep frozen" in storage:
|
|
return Decision(False, "requires cold storage")
|
|
categories = product.get("categoryPath", [])
|
|
if isinstance(categories, str):
|
|
categories = [categories]
|
|
categories = {str(category).strip().casefold() for category in categories}
|
|
if categories & PERISHABLE_CATEGORIES:
|
|
return Decision(False, "fresh, chilled, frozen or bakery category")
|
|
if categories & SHELF_STABLE_CATEGORIES:
|
|
return Decision(True, "shelf-stable product category")
|
|
# CUPBOARD alone also describes bananas, onions and potatoes.
|
|
return Decision(False, "missing or ambiguous product category", uncertain=True)
|