Files
bakery-ia/services/procurement/app/api/internal_delivery_tracking.py

103 lines
3.4 KiB
Python
Raw Normal View History

2025-12-05 20:07:01 +01:00
"""
Internal API for triggering delivery tracking alerts.
Used by demo session cloning to generate realistic late delivery alerts.
Moved from orchestrator service to procurement service (domain ownership).
2025-12-13 23:57:54 +01:00
URL Pattern: /api/v1/tenants/{tenant_id}/procurement/internal/delivery-tracking/trigger
This follows the tenant-scoped pattern so gateway can proxy correctly.
2025-12-05 20:07:01 +01:00
"""
from fastapi import APIRouter, HTTPException, Request, Path
from uuid import UUID
import structlog
logger = structlog.get_logger()
router = APIRouter()
2025-12-13 23:57:54 +01:00
# New URL pattern: tenant-scoped so gateway proxies to procurement service correctly
@router.post("/api/v1/tenants/{tenant_id}/procurement/internal/delivery-tracking/trigger")
2025-12-05 20:07:01 +01:00
async def trigger_delivery_tracking(
tenant_id: UUID = Path(..., description="Tenant ID to check deliveries for"),
request: Request = None
) -> dict:
"""
Trigger delivery tracking for a specific tenant (internal use only).
This endpoint is called by the demo session cloning process after POs are seeded
to generate realistic delivery alerts (arriving soon, overdue, etc.).
2026-01-12 22:15:11 +01:00
Security: Protected by x-internal-service header check.
2025-12-05 20:07:01 +01:00
Args:
tenant_id: Tenant UUID to check deliveries for
request: FastAPI request object
Returns:
{
"success": true,
"tenant_id": "uuid",
"alerts_generated": 3,
"breakdown": {
"arriving_soon": 1,
"overdue": 1,
"receipt_incomplete": 1
}
}
"""
try:
# Verify internal service header
2026-01-12 22:15:11 +01:00
if not request or request.headers.get("x-internal-service") not in ["demo-session", "internal"]:
2025-12-05 20:07:01 +01:00
logger.warning("Unauthorized internal API call", tenant_id=str(tenant_id))
raise HTTPException(
status_code=403,
detail="This endpoint is for internal service use only"
)
# Get delivery tracking service from app state
delivery_tracking_service = getattr(request.app.state, 'delivery_tracking_service', None)
if not delivery_tracking_service:
logger.error("Delivery tracking service not initialized")
raise HTTPException(
status_code=500,
detail="Delivery tracking service not available"
)
# Trigger delivery tracking for this tenant
logger.info("Triggering delivery tracking", tenant_id=str(tenant_id))
result = await delivery_tracking_service.check_expected_deliveries(tenant_id)
logger.info(
"Delivery tracking completed",
tenant_id=str(tenant_id),
alerts_generated=result.get("total_alerts", 0)
)
return {
"success": True,
"tenant_id": str(tenant_id),
"alerts_generated": result.get("total_alerts", 0),
"breakdown": {
"arriving_soon": result.get("arriving_soon", 0),
"overdue": result.get("overdue", 0),
"receipt_incomplete": result.get("receipt_incomplete", 0)
}
}
except HTTPException:
raise
except Exception as e:
logger.error(
"Error triggering delivery tracking",
tenant_id=str(tenant_id),
error=str(e),
exc_info=True
)
raise HTTPException(
status_code=500,
detail=f"Failed to trigger delivery tracking: {str(e)}"
)