from __future__ import annotations from datetime import datetime, timezone from uuid import uuid4 from sqlalchemy import JSON, DateTime, Float, Integer, String, Text from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column def _utcnow() -> datetime: return datetime.now(timezone.utc) class WWIBase(DeclarativeBase): pass class WWIReorderRecommendation(WWIBase): """Persisted WWI stock reorder recommendation runs.""" __tablename__ = "wwi_reorder_recommendations" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4())) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_utcnow, index=True) item_count: Mapped[int] = mapped_column(Integer) trigger_source: Mapped[str] = mapped_column(String(64), index=True) trace_id: Mapped[str | None] = mapped_column(String(32), nullable=True, index=True) span_id: Mapped[str | None] = mapped_column(String(16), nullable=True) payload: Mapped[list[dict]] = mapped_column(JSON, default=list) class WWISupplierScore(WWIBase): """Persisted WWI supplier reliability scoring runs.""" __tablename__ = "wwi_supplier_scores" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4())) computed_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_utcnow, index=True) supplier_count: Mapped[int] = mapped_column(Integer) top_n: Mapped[int] = mapped_column(Integer) trigger_source: Mapped[str] = mapped_column(String(64), index=True) trace_id: Mapped[str | None] = mapped_column(String(32), nullable=True, index=True) span_id: Mapped[str | None] = mapped_column(String(16), nullable=True) payload: Mapped[list[dict]] = mapped_column(JSON, default=list) class WWIWhatIfScenario(WWIBase): """User-submitted what-if simulation results.""" __tablename__ = "wwi_whatif_scenarios" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4())) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_utcnow, index=True) stock_item_key: Mapped[int] = mapped_column(Integer, index=True) stock_item_name: Mapped[str] = mapped_column(String(200)) demand_multiplier: Mapped[float] = mapped_column(Float) current_stock: Mapped[float] = mapped_column(Float) avg_daily_demand: Mapped[float] = mapped_column(Float) projected_days_until_stockout: Mapped[float | None] = mapped_column(Float, nullable=True) recommended_order_qty: Mapped[float] = mapped_column(Float) trace_id: Mapped[str | None] = mapped_column(String(32), nullable=True, index=True) span_id: Mapped[str | None] = mapped_column(String(16), nullable=True) result: Mapped[dict] = mapped_column(JSON, default=dict) class WWIBusinessEvent(WWIBase): """Automatically generated business alert events.""" __tablename__ = "wwi_business_events" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4())) occurred_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_utcnow, index=True) event_type: Mapped[str] = mapped_column(String(50), index=True) # LOW_STOCK, ORDER_DROP, SUPPLIER_RISK severity: Mapped[str] = mapped_column(String(20), index=True) # HIGH, MEDIUM, LOW entity_key: Mapped[str] = mapped_column(String(100), index=True) entity_name: Mapped[str] = mapped_column(String(200)) message: Mapped[str] = mapped_column(Text) trace_id: Mapped[str | None] = mapped_column(String(32), nullable=True, index=True) span_id: Mapped[str | None] = mapped_column(String(16), nullable=True) details: Mapped[dict] = mapped_column(JSON, default=dict)