New alert service

This commit is contained in:
Urtzi Alfaro
2025-12-05 20:07:01 +01:00
parent 1fe3a73549
commit 667e6e0404
393 changed files with 26002 additions and 61033 deletions

View File

@@ -43,6 +43,23 @@ async def get_tenant_hierarchy(request: Request, tenant_id: str = Path(...)):
"""Get tenant hierarchy information"""
return await _proxy_to_tenant_service(request, f"/api/v1/tenants/{tenant_id}/hierarchy")
@router.api_route("/{tenant_id}/children", methods=["GET", "OPTIONS"])
async def get_tenant_children(request: Request, tenant_id: str = Path(...)):
"""Get tenant children"""
return await _proxy_to_tenant_service(request, f"/api/v1/tenants/{tenant_id}/children")
@router.api_route("/{tenant_id}/children/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"])
async def proxy_tenant_children(request: Request, tenant_id: str = Path(...), path: str = ""):
"""Proxy tenant children requests to tenant service"""
target_path = f"/api/v1/tenants/{tenant_id}/children/{path}".rstrip("/")
return await _proxy_to_tenant_service(request, target_path)
@router.api_route("/{tenant_id}/access/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"])
async def proxy_tenant_access(request: Request, tenant_id: str = Path(...), path: str = ""):
"""Proxy tenant access requests to tenant service"""
target_path = f"/api/v1/tenants/{tenant_id}/access/{path}".rstrip("/")
return await _proxy_to_tenant_service(request, target_path)
@router.get("/{tenant_id}/my-access")
async def get_tenant_my_access(request: Request, tenant_id: str = Path(...)):
"""Get current user's access level for a tenant"""
@@ -108,6 +125,70 @@ async def proxy_available_plans(request: Request):
target_path = "/api/v1/plans/available"
return await _proxy_to_tenant_service(request, target_path)
# ================================================================
# BATCH OPERATIONS ENDPOINTS
# IMPORTANT: Route order matters! Keep specific routes before wildcards:
# 1. Exact matches first (/batch/sales-summary)
# 2. Wildcard paths second (/batch{path:path})
# 3. Tenant-scoped wildcards last (/{tenant_id}/batch{path:path})
# ================================================================
@router.api_route("/batch/sales-summary", methods=["POST"])
async def proxy_batch_sales_summary(request: Request):
"""Proxy batch sales summary request to sales service"""
target_path = "/api/v1/batch/sales-summary"
return await _proxy_to_sales_service(request, target_path)
@router.api_route("/batch/production-summary", methods=["POST"])
async def proxy_batch_production_summary(request: Request):
"""Proxy batch production summary request to production service"""
target_path = "/api/v1/batch/production-summary"
return await _proxy_to_production_service(request, target_path)
@router.api_route("/batch{path:path}", methods=["POST", "GET", "PUT", "DELETE", "OPTIONS"])
async def proxy_batch_operations(request: Request, path: str = ""):
"""Proxy batch operations that span multiple tenants to appropriate services"""
# For batch operations, route based on the path after /batch/
if path.startswith("/sales-summary"):
# Route batch sales summary to sales service
# The sales service batch endpoints are at /api/v1/batch/... not /api/v1/sales/batch/...
target_path = f"/api/v1/batch{path}"
return await _proxy_to_sales_service(request, target_path)
elif path.startswith("/production-summary"):
# Route batch production summary to production service
# The production service batch endpoints are at /api/v1/batch/... not /api/v1/production/batch/...
target_path = f"/api/v1/batch{path}"
return await _proxy_to_production_service(request, target_path)
else:
# Default to sales service for other batch operations
# The service batch endpoints are at /api/v1/batch/... not /api/v1/sales/batch/...
target_path = f"/api/v1/batch{path}"
return await _proxy_to_sales_service(request, target_path)
@router.api_route("/{tenant_id}/batch{path:path}", methods=["POST", "GET", "PUT", "DELETE", "OPTIONS"])
async def proxy_tenant_batch_operations(request: Request, tenant_id: str = Path(...), path: str = ""):
"""Proxy tenant-scoped batch operations to appropriate services"""
# For tenant-scoped batch operations, route based on the path after /batch/
if path.startswith("/sales-summary"):
# Route tenant batch sales summary to sales service
# The sales service batch endpoints are at /api/v1/batch/... not /api/v1/sales/batch/...
target_path = f"/api/v1/batch{path}"
return await _proxy_to_sales_service(request, target_path)
elif path.startswith("/production-summary"):
# Route tenant batch production summary to production service
# The production service batch endpoints are at /api/v1/batch/... not /api/v1/production/batch/...
target_path = f"/api/v1/batch{path}"
return await _proxy_to_production_service(request, target_path)
else:
# Default to sales service for other tenant batch operations
# The service batch endpoints are at /api/v1/batch/... not /api/v1/sales/batch/...
target_path = f"/api/v1/batch{path}"
return await _proxy_to_sales_service(request, target_path)
# ================================================================
# TENANT-SCOPED DATA SERVICE ENDPOINTS
# ================================================================
@@ -116,7 +197,7 @@ async def proxy_available_plans(request: Request):
async def proxy_all_tenant_sales_alternative(request: Request, tenant_id: str = Path(...), path: str = ""):
"""Proxy all tenant sales requests - handles both base and sub-paths"""
base_path = f"/api/v1/tenants/{tenant_id}/sales"
# If path is empty or just "/", use base path
if not path or path == "/" or path == "":
target_path = base_path
@@ -125,9 +206,17 @@ async def proxy_all_tenant_sales_alternative(request: Request, tenant_id: str =
if not path.startswith("/"):
path = "/" + path
target_path = base_path + path
return await _proxy_to_sales_service(request, target_path)
@router.api_route("/{tenant_id}/enterprise/batch{path:path}", methods=["POST", "GET", "PUT", "DELETE", "OPTIONS"])
async def proxy_tenant_enterprise_batch(request: Request, tenant_id: str = Path(...), path: str = ""):
"""Proxy enterprise batch requests (spanning multiple tenants within an enterprise) to appropriate services"""
# Forward to orchestrator service for enterprise-level operations
target_path = f"/api/v1/tenants/{tenant_id}/enterprise/batch{path}".rstrip("/")
return await _proxy_to_orchestrator_service(request, target_path, tenant_id=tenant_id)
@router.api_route("/{tenant_id}/weather/{path:path}", methods=["GET", "POST", "OPTIONS"])
async def proxy_tenant_weather(request: Request, tenant_id: str = Path(...), path: str = ""):
"""Proxy tenant weather requests to external service"""
@@ -226,6 +315,12 @@ async def proxy_tenant_forecasting(request: Request, tenant_id: str = Path(...),
target_path = f"/api/v1/tenants/{tenant_id}/forecasting/{path}".rstrip("/")
return await _proxy_to_forecasting_service(request, target_path, tenant_id=tenant_id)
@router.api_route("/{tenant_id}/forecasting/enterprise/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"])
async def proxy_tenant_forecasting_enterprise(request: Request, tenant_id: str = Path(...), path: str = ""):
"""Proxy tenant forecasting enterprise requests to forecasting service"""
target_path = f"/api/v1/tenants/{tenant_id}/forecasting/enterprise/{path}".rstrip("/")
return await _proxy_to_forecasting_service(request, target_path, tenant_id=tenant_id)
@router.api_route("/{tenant_id}/forecasts/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"])
async def proxy_tenant_forecasts(request: Request, tenant_id: str = Path(...), path: str = ""):
"""Proxy tenant forecast requests to forecasting service"""