demo seed change 7

This commit is contained in:
Urtzi Alfaro
2025-12-15 13:39:33 +01:00
parent 46bd4f77b6
commit 5642b5a0c0
14 changed files with 5653 additions and 780 deletions

View File

@@ -1858,6 +1858,124 @@ class ProductionService:
)
raise
async def get_ai_waste_impact(
self,
tenant_id: UUID,
start_date: datetime,
end_date: datetime
) -> Dict[str, Any]:
"""
Get AI impact on waste reduction
Compares waste rates between AI-assisted and manual batches
to demonstrate ROI of AI features for sustainability.
"""
try:
async with self.database_manager.get_session() as session:
from app.repositories.production_batch_repository import ProductionBatchRepository
from sqlalchemy import text
batch_repo = ProductionBatchRepository(session)
# Query for AI vs manual batch comparison
query = text("""
SELECT
-- AI-assisted batches
COUNT(CASE WHEN is_ai_assisted = true THEN 1 END) as ai_batches,
COALESCE(SUM(CASE WHEN is_ai_assisted = true THEN planned_quantity ELSE 0 END), 0) as ai_planned,
COALESCE(SUM(CASE WHEN is_ai_assisted = true THEN actual_quantity ELSE 0 END), 0) as ai_actual,
COALESCE(SUM(CASE WHEN is_ai_assisted = true THEN waste_quantity ELSE 0 END), 0) as ai_waste,
COALESCE(SUM(CASE WHEN is_ai_assisted = true THEN defect_quantity ELSE 0 END), 0) as ai_defects,
-- Manual batches
COUNT(CASE WHEN is_ai_assisted = false THEN 1 END) as manual_batches,
COALESCE(SUM(CASE WHEN is_ai_assisted = false THEN planned_quantity ELSE 0 END), 0) as manual_planned,
COALESCE(SUM(CASE WHEN is_ai_assisted = false THEN actual_quantity ELSE 0 END), 0) as manual_actual,
COALESCE(SUM(CASE WHEN is_ai_assisted = false THEN waste_quantity ELSE 0 END), 0) as manual_waste,
COALESCE(SUM(CASE WHEN is_ai_assisted = false THEN defect_quantity ELSE 0 END), 0) as manual_defects
FROM production_batches
WHERE tenant_id = :tenant_id
AND created_at BETWEEN :start_date AND :end_date
AND status IN ('COMPLETED', 'QUALITY_CHECK')
""")
result = await session.execute(
query,
{
'tenant_id': tenant_id,
'start_date': start_date,
'end_date': end_date
}
)
row = result.fetchone()
# Calculate waste percentages
ai_total_waste = float(row.ai_waste or 0) + float(row.ai_defects or 0)
manual_total_waste = float(row.manual_waste or 0) + float(row.manual_defects or 0)
ai_waste_pct = (ai_total_waste / float(row.ai_planned)) * 100 if row.ai_planned > 0 else 0
manual_waste_pct = (manual_total_waste / float(row.manual_planned)) * 100 if row.manual_planned > 0 else 0
# Calculate reduction
waste_reduction_pct = 0
if manual_waste_pct > 0:
waste_reduction_pct = ((manual_waste_pct - ai_waste_pct) / manual_waste_pct) * 100
# Calculate waste avoided
if manual_waste_pct > 0 and row.ai_planned > 0:
waste_avoided_kg = (float(row.ai_planned) * (manual_waste_pct / 100)) - ai_total_waste
else:
waste_avoided_kg = 0
# Financial impact (€3.50/kg average waste cost)
waste_cost_avoided = waste_avoided_kg * 3.50
ai_impact_data = {
'ai_batches': {
'count': int(row.ai_batches or 0),
'production_kg': float(row.ai_planned or 0),
'waste_kg': ai_total_waste,
'waste_percentage': round(ai_waste_pct, 2)
},
'manual_batches': {
'count': int(row.manual_batches or 0),
'production_kg': float(row.manual_planned or 0),
'waste_kg': manual_total_waste,
'waste_percentage': round(manual_waste_pct, 2)
},
'impact': {
'waste_reduction_percentage': round(waste_reduction_pct, 1),
'waste_avoided_kg': round(waste_avoided_kg, 2),
'cost_savings_eur': round(waste_cost_avoided, 2),
'annual_projection_eur': round(waste_cost_avoided * 12, 2)
},
'adoption': {
'ai_adoption_rate': round((int(row.ai_batches or 0) / (int(row.ai_batches or 0) + int(row.manual_batches or 1))) * 100, 1),
'recommendation': 'increase_ai_usage' if waste_reduction_pct > 10 else 'monitor'
},
'period': {
'start_date': start_date.isoformat(),
'end_date': end_date.isoformat()
}
}
logger.info(
"AI waste impact calculated",
tenant_id=str(tenant_id),
waste_reduction_pct=waste_reduction_pct,
waste_avoided_kg=waste_avoided_kg
)
return ai_impact_data
except Exception as e:
logger.error(
"Error calculating AI waste impact",
tenant_id=str(tenant_id),
error=str(e)
)
raise
# ================================================================
# NEW: ORCHESTRATOR INTEGRATION
# ================================================================