""" Minimal event schemas for services to emit events. Services send minimal event data with only event_type and metadata. All enrichment, i18n generation, and priority calculation happens in the alert_processor service. This is the unified messaging layer - the single source of truth for event schemas used in the messaging system. """ from pydantic import BaseModel, Field from typing import Dict, Any, Literal, Optional from datetime import datetime class MinimalEvent(BaseModel): """ Minimal event structure sent by services. Services only need to provide: - tenant_id: Who this event belongs to - event_class: alert, notification, or recommendation - event_domain: Business domain (inventory, production, supply_chain, etc.) - event_type: Specific event identifier (critical_stock_shortage, production_delay, etc.) - service: Source service name - metadata: Dictionary with event-specific data The alert_processor service enriches this with: - i18n keys and parameters - Priority score and level - Orchestrator context (AI actions) - Business impact analysis - Urgency assessment - User agency determination - Smart actions """ tenant_id: str = Field(..., description="Tenant UUID as string") event_class: Literal["alert", "notification", "recommendation"] = Field( ..., description="Event classification - alert requires action, notification is FYI, recommendation is suggestion" ) event_domain: str = Field( ..., description="Business domain: inventory, production, supply_chain, demand, operations, distribution" ) event_type: str = Field( ..., description="Specific event type identifier, e.g., critical_stock_shortage, production_delay, po_approval_needed" ) service: str = Field(..., description="Source service name, e.g., inventory, production, procurement") metadata: Dict[str, Any] = Field( default_factory=dict, description="Event-specific data - structure varies by event_type" ) timestamp: Optional[datetime] = Field( default=None, description="Event timestamp, set automatically if not provided" ) class Config: from_attributes = True json_schema_extra = { "examples": [ { "tenant_id": "550e8400-e29b-41d4-a716-446655440000", "event_class": "alert", "event_domain": "inventory", "event_type": "critical_stock_shortage", "service": "inventory", "metadata": { "ingredient_id": "123e4567-e89b-12d3-a456-426614174000", "ingredient_name": "Flour", "current_stock": 5.2, "required_stock": 10.0, "shortage_amount": 4.8, "supplier_name": "Flour Supplier Co.", "lead_time_days": 3, "po_id": "PO-12345", "po_amount": 2500.00, "po_status": "pending_approval", "delivery_date": "2025-12-10" } }, { "tenant_id": "550e8400-e29b-41d4-a716-446655440000", "event_class": "alert", "event_domain": "production", "event_type": "production_delay", "service": "production", "metadata": { "batch_id": "987fbc97-4bed-5078-9f07-9141ba07c9f3", "product_name": "Croissant", "batch_number": "B-2025-001", "delay_minutes": 45, "affected_orders": 3, "customer_names": ["Customer A", "Customer B"] } }, { "tenant_id": "550e8400-e29b-41d4-a716-446655440000", "event_class": "notification", "event_domain": "supply_chain", "event_type": "po_approved", "service": "procurement", "metadata": { "po_id": "PO-12345", "po_number": "PO-2025-001", "supplier_name": "Flour Supplier Co.", "total_amount": 2500.00, "currency": "EUR", "approved_at": "2025-12-05T10:30:00Z", "approved_by": "user@example.com" } } ] } # ============================================================ # Event Domain Constants # ============================================================ class EventDomain: """Standard event domains""" INVENTORY = "inventory" PRODUCTION = "production" SUPPLY_CHAIN = "supply_chain" DEMAND = "demand" OPERATIONS = "operations" DISTRIBUTION = "distribution" FINANCE = "finance" # ============================================================ # Event Class Constants # ============================================================ class EventClass: """Event classifications""" ALERT = "alert" # Requires user decision/action NOTIFICATION = "notification" # Informational, no action needed RECOMMENDATION = "recommendation" # Optimization suggestion # ============================================================ # Severity Levels (for routing) # ============================================================ class Severity: """Alert severity levels for routing""" URGENT = "urgent" # Immediate attention required HIGH = "high" # Important, address soon MEDIUM = "medium" # Standard priority LOW = "low" # Minor, can wait INFO = "info" # Informational only # ============================================================ # Alert Type Constants (for demo/testing purposes) # ============================================================ class AlertTypeConstants: """Standard alert type string constants""" # Inventory alerts LOW_STOCK_WARNING = "low_stock_warning" CRITICAL_STOCK_SHORTAGE = "critical_stock_shortage" EXPIRING_SOON = "expiring_soon" EXPIRED_STOCK = "expired_stock" # Production alerts PRODUCTION_DELAY = "production_delay" PRODUCTION_STALLED = "production_stalled" BATCH_AT_RISK = "batch_at_risk" PRODUCTION_BATCH_START = "production_batch_start" # Purchase Order alerts PO_APPROVAL_NEEDED = "po_approval_needed" PO_APPROVAL_ESCALATION = "po_approval_escalation" # Delivery lifecycle alerts DELIVERY_SCHEDULED = "delivery_scheduled" DELIVERY_ARRIVING_SOON = "delivery_arriving_soon" DELIVERY_OVERDUE = "delivery_overdue" STOCK_RECEIPT_INCOMPLETE = "stock_receipt_incomplete" # Forecasting alerts DEMAND_SURGE_PREDICTED = "demand_surge_predicted" DEMAND_DROP_PREDICTED = "demand_drop_predicted"