Files
bakery-ia/shared/schemas/events.py
2025-12-05 20:07:01 +01:00

147 lines
5.4 KiB
Python

"""
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.
"""
from pydantic import BaseModel, Field
from typing import Dict, Any, Literal, Optional
from datetime import datetime
from uuid import UUID
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