New alert service

This commit is contained in:
Urtzi Alfaro
2025-12-05 20:07:01 +01:00
parent 1fe3a73549
commit 667e6e0404
393 changed files with 26002 additions and 61033 deletions

View File

@@ -165,7 +165,7 @@ class EnrichedAlert(BaseModel):
trend_context: Optional[TrendContext] = Field(None, description="Trend analysis (if trend warning)")
# AI Reasoning
ai_reasoning_summary: Optional[str] = Field(None, description="Plain language AI reasoning")
ai_reasoning_i18n: Optional[Dict[str, Any]] = Field(None, description="i18n-ready AI reasoning with key and params")
reasoning_data: Optional[Dict[str, Any]] = Field(None, description="Structured reasoning from orchestrator")
confidence_score: Optional[float] = Field(None, description="AI confidence 0-1")

146
shared/schemas/events.py Normal file
View File

@@ -0,0 +1,146 @@
"""
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