103 lines
3.4 KiB
Python
103 lines
3.4 KiB
Python
"""
|
|
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).
|
|
|
|
URL Pattern: /api/v1/tenants/{tenant_id}/procurement/internal/delivery-tracking/trigger
|
|
This follows the tenant-scoped pattern so gateway can proxy correctly.
|
|
"""
|
|
|
|
from fastapi import APIRouter, HTTPException, Request, Path
|
|
from uuid import UUID
|
|
import structlog
|
|
|
|
logger = structlog.get_logger()
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
# New URL pattern: tenant-scoped so gateway proxies to procurement service correctly
|
|
@router.post("/api/v1/tenants/{tenant_id}/procurement/internal/delivery-tracking/trigger")
|
|
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.).
|
|
|
|
Security: Protected by X-Internal-Service header check.
|
|
|
|
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
|
|
if not request or request.headers.get("X-Internal-Service") not in ["demo-session", "internal"]:
|
|
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)}"
|
|
)
|