Files

157 lines
5.6 KiB
Python
Raw Permalink Normal View History

2025-12-05 20:07:01 +01:00
"""
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 = {}
2025-12-09 10:21:41 +01:00
# Extract potential_loss_eur from reasoning_data.parameters
reasoning_data = metadata.get("reasoning_data", {})
parameters = reasoning_data.get("parameters", {})
potential_loss_eur = parameters.get("potential_loss_eur")
# Use potential loss from reasoning as financial impact (what's at risk)
# Fallback to PO amount only if reasoning data is not available
if potential_loss_eur is not None:
impact["financial_impact_eur"] = float(potential_loss_eur)
else:
po_amount = metadata.get("po_amount", metadata.get("total_amount", 0))
impact["financial_impact_eur"] = float(po_amount)
2025-12-05 20:07:01 +01:00
# 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