148 lines
5.1 KiB
Python
148 lines
5.1 KiB
Python
"""
|
|
Business impact analyzer for alerts.
|
|
|
|
Calculates financial impact, affected orders, customer impact, and other
|
|
business metrics from event metadata.
|
|
"""
|
|
|
|
from typing import Dict, Any
|
|
import structlog
|
|
|
|
logger = structlog.get_logger()
|
|
|
|
|
|
class BusinessImpactAnalyzer:
|
|
"""Analyze business impact from event metadata"""
|
|
|
|
def analyze(self, event_type: str, metadata: Dict[str, Any]) -> dict:
|
|
"""
|
|
Analyze business impact for an event.
|
|
|
|
Returns dict with:
|
|
- financial_impact_eur: Direct financial cost
|
|
- affected_orders: Number of orders impacted
|
|
- affected_customers: List of customer names
|
|
- production_delay_hours: Hours of production delay
|
|
- estimated_revenue_loss_eur: Potential revenue loss
|
|
- customer_impact: high/medium/low
|
|
- waste_risk_kg: Potential waste in kg
|
|
"""
|
|
|
|
impact = {
|
|
"financial_impact_eur": 0,
|
|
"affected_orders": 0,
|
|
"affected_customers": [],
|
|
"production_delay_hours": 0,
|
|
"estimated_revenue_loss_eur": 0,
|
|
"customer_impact": "low",
|
|
"waste_risk_kg": 0
|
|
}
|
|
|
|
# Stock-related impacts
|
|
if "stock" in event_type or "shortage" in event_type:
|
|
impact.update(self._analyze_stock_impact(metadata))
|
|
|
|
# Production-related impacts
|
|
elif "production" in event_type or "delay" in event_type or "equipment" in event_type:
|
|
impact.update(self._analyze_production_impact(metadata))
|
|
|
|
# Procurement-related impacts
|
|
elif "po_" in event_type or "delivery" in event_type:
|
|
impact.update(self._analyze_procurement_impact(metadata))
|
|
|
|
# Quality-related impacts
|
|
elif "quality" in event_type or "expired" in event_type:
|
|
impact.update(self._analyze_quality_impact(metadata))
|
|
|
|
return impact
|
|
|
|
def _analyze_stock_impact(self, metadata: Dict[str, Any]) -> dict:
|
|
"""Analyze impact of stock-related alerts"""
|
|
impact = {}
|
|
|
|
# Calculate financial impact
|
|
shortage_amount = metadata.get("shortage_amount", 0)
|
|
unit_cost = metadata.get("unit_cost", 5) # Default €5/kg
|
|
impact["financial_impact_eur"] = float(shortage_amount) * unit_cost
|
|
|
|
# Affected orders from metadata
|
|
impact["affected_orders"] = metadata.get("affected_orders", 0)
|
|
|
|
# Customer impact based on affected orders
|
|
if impact["affected_orders"] > 5:
|
|
impact["customer_impact"] = "high"
|
|
elif impact["affected_orders"] > 2:
|
|
impact["customer_impact"] = "medium"
|
|
|
|
# Revenue loss (estimated)
|
|
avg_order_value = 50 # €50 per order
|
|
impact["estimated_revenue_loss_eur"] = impact["affected_orders"] * avg_order_value
|
|
|
|
return impact
|
|
|
|
def _analyze_production_impact(self, metadata: Dict[str, Any]) -> dict:
|
|
"""Analyze impact of production-related alerts"""
|
|
impact = {}
|
|
|
|
# Delay minutes to hours
|
|
delay_minutes = metadata.get("delay_minutes", 0)
|
|
impact["production_delay_hours"] = round(delay_minutes / 60, 1)
|
|
|
|
# Affected orders and customers
|
|
impact["affected_orders"] = metadata.get("affected_orders", 0)
|
|
|
|
customer_names = metadata.get("customer_names", [])
|
|
impact["affected_customers"] = customer_names
|
|
|
|
# Customer impact based on delay
|
|
if delay_minutes > 120: # 2+ hours
|
|
impact["customer_impact"] = "high"
|
|
elif delay_minutes > 60: # 1+ hours
|
|
impact["customer_impact"] = "medium"
|
|
|
|
# Financial impact: hourly production cost
|
|
hourly_cost = 100 # €100/hour operational cost
|
|
impact["financial_impact_eur"] = impact["production_delay_hours"] * hourly_cost
|
|
|
|
# Revenue loss
|
|
if impact["affected_orders"] > 0:
|
|
avg_order_value = 50
|
|
impact["estimated_revenue_loss_eur"] = impact["affected_orders"] * avg_order_value
|
|
|
|
return impact
|
|
|
|
def _analyze_procurement_impact(self, metadata: Dict[str, Any]) -> dict:
|
|
"""Analyze impact of procurement-related alerts"""
|
|
impact = {}
|
|
|
|
# PO amount as financial impact
|
|
po_amount = metadata.get("po_amount", metadata.get("total_amount", 0))
|
|
impact["financial_impact_eur"] = float(po_amount)
|
|
|
|
# Days overdue affects customer impact
|
|
days_overdue = metadata.get("days_overdue", 0)
|
|
if days_overdue > 3:
|
|
impact["customer_impact"] = "high"
|
|
elif days_overdue > 1:
|
|
impact["customer_impact"] = "medium"
|
|
|
|
return impact
|
|
|
|
def _analyze_quality_impact(self, metadata: Dict[str, Any]) -> dict:
|
|
"""Analyze impact of quality-related alerts"""
|
|
impact = {}
|
|
|
|
# Expired products
|
|
expired_count = metadata.get("expired_count", 0)
|
|
total_value = metadata.get("total_value", 0)
|
|
|
|
impact["financial_impact_eur"] = float(total_value)
|
|
impact["waste_risk_kg"] = metadata.get("total_quantity_kg", 0)
|
|
|
|
if expired_count > 5:
|
|
impact["customer_impact"] = "high"
|
|
elif expired_count > 2:
|
|
impact["customer_impact"] = "medium"
|
|
|
|
return impact
|