Add forecasting demand insights trigger + fix RabbitMQ cleanup

Issue 1: Forecasting demand insights not triggered in demo workflow
- Created internal ML endpoint: /forecasting/internal/ml/generate-demand-insights
- Added trigger_demand_insights_internal() to ForecastServiceClient
- Integrated forecasting insights into demo session post-clone workflow
- Now triggers 4 AI insight types: price, safety stock, yield, + demand

Issue 2: RabbitMQ client cleanup error in procurement service
- Fixed: rabbitmq_client.close() → rabbitmq_client.disconnect()
- Added proper cleanup in exception handler
- Error: "'RabbitMQClient' object has no attribute 'close'"

Files modified:
- services/forecasting/app/api/ml_insights.py (new internal_router)
- services/forecasting/app/main.py (register internal router)
- shared/clients/forecast_client.py (new trigger method)
- services/demo_session/app/services/clone_orchestrator.py (+ demand insights)
- services/procurement/app/api/internal_demo.py (fix disconnect)

Expected impact:
- Demo sessions will now generate demand forecasting insights
- No more RabbitMQ cleanup errors in logs
- AI insights count should increase from 1 to 2-3 per session

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Urtzi Alfaro
2025-12-16 11:28:04 +01:00
parent b461d620ab
commit 4418ff0876
5 changed files with 244 additions and 2 deletions

View File

@@ -341,6 +341,53 @@ class ForecastServiceClient(BaseServiceClient):
}
return await self.post("forecasting/ml/insights/generate-rules", data=data, tenant_id=tenant_id)
async def trigger_demand_insights_internal(
self,
tenant_id: str
) -> Optional[Dict[str, Any]]:
"""
Trigger demand forecasting insights for a tenant (internal service use only).
This method calls the internal endpoint which is protected by X-Internal-Service header.
Used by demo-session service after cloning to generate AI insights from seeded data.
Args:
tenant_id: Tenant ID to trigger insights for
Returns:
Dict with trigger results or None if failed
"""
try:
result = await self._make_request(
method="POST",
endpoint=f"forecasting/internal/ml/generate-demand-insights",
tenant_id=tenant_id,
data={"tenant_id": tenant_id},
headers={"X-Internal-Service": "demo-session"}
)
if result:
self.logger.info(
"Demand insights triggered successfully via internal endpoint",
tenant_id=tenant_id,
insights_posted=result.get("insights_posted", 0)
)
else:
self.logger.warning(
"Demand insights internal endpoint returned no result",
tenant_id=tenant_id
)
return result
except Exception as e:
self.logger.error(
"Error triggering demand insights via internal endpoint",
tenant_id=tenant_id,
error=str(e)
)
return None
# ================================================================
# Legacy/Compatibility Methods (deprecated)
# ================================================================