Spaces:
Sleeping
Sleeping
File size: 2,754 Bytes
8981bf6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | """Mock orders API.
Stands in for a real OMS/Shopify Orders endpoint. Reads ``orders.json`` and offers
lookup by order id (optionally verified against the customer email). In production you
would swap this class for a thin HTTP client to the real orders service; the rest of
the app depends only on its small interface.
"""
from __future__ import annotations
import json
from dataclasses import dataclass
from datetime import date
from pathlib import Path
from typing import Any
from .config import get_settings
@dataclass(frozen=True)
class Order:
order_id: str
email: str
status: str
placed_at: str
delivered_at: str | None
carrier: str | None
tracking: str | None
items: list[dict[str, Any]]
total: float
final_sale: bool
def days_since_delivery(self, today: date | None = None) -> int | None:
"""Whole days since delivery, or ``None`` if not delivered yet."""
if not self.delivered_at:
return None
today = today or date.today()
delivered = date.fromisoformat(self.delivered_at)
return (today - delivered).days
def human_status(self) -> str:
if self.status == "shipped" and self.tracking:
return f"shipped via {self.carrier} (tracking {self.tracking})"
if self.status == "delivered":
return f"delivered on {self.delivered_at}"
return self.status
class OrdersService:
"""In-memory mock orders store loaded from ``orders.json``."""
def __init__(self, orders_path: Path | None = None):
path = orders_path or (get_settings().data_dir / "orders.json")
raw = json.loads(path.read_text(encoding="utf-8"))
self._orders: dict[str, Order] = {}
for o in raw.get("orders", []):
self._orders[o["order_id"].upper()] = Order(
order_id=o["order_id"],
email=o["email"],
status=o["status"],
placed_at=o["placed_at"],
delivered_at=o.get("delivered_at"),
carrier=o.get("carrier"),
tracking=o.get("tracking"),
items=o.get("items", []),
total=float(o.get("total", 0.0)),
final_sale=bool(o.get("final_sale", False)),
)
def get(self, order_id: str, email: str | None = None) -> Order | None:
"""Look up an order. If ``email`` is given it must match (case-insensitive)."""
order = self._orders.get((order_id or "").strip().upper())
if order is None:
return None
if email and order.email.lower() != email.strip().lower():
return None
return order
def all(self) -> list[Order]:
return list(self._orders.values())
|