2025-11-30 09:12:40 +01:00
|
|
|
"""
|
|
|
|
|
Enterprise Dashboard API Endpoints for Orchestrator Service
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
|
|
|
from typing import List, Optional, Dict, Any
|
|
|
|
|
from datetime import date
|
|
|
|
|
import structlog
|
|
|
|
|
|
|
|
|
|
from app.services.enterprise_dashboard_service import EnterpriseDashboardService
|
|
|
|
|
from shared.auth.tenant_access import verify_tenant_access_dep
|
|
|
|
|
from shared.clients.tenant_client import TenantServiceClient
|
|
|
|
|
from shared.clients.forecast_client import ForecastServiceClient
|
|
|
|
|
from shared.clients.production_client import ProductionServiceClient
|
|
|
|
|
from shared.clients.sales_client import SalesServiceClient
|
|
|
|
|
from shared.clients.inventory_client import InventoryServiceClient
|
|
|
|
|
from shared.clients.distribution_client import DistributionServiceClient
|
|
|
|
|
|
|
|
|
|
logger = structlog.get_logger()
|
|
|
|
|
router = APIRouter(prefix="/api/v1/tenants/{tenant_id}/enterprise", tags=["enterprise"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add dependency injection function
|
|
|
|
|
from app.services.enterprise_dashboard_service import EnterpriseDashboardService
|
|
|
|
|
from shared.clients import (
|
|
|
|
|
get_tenant_client,
|
|
|
|
|
get_forecast_client,
|
|
|
|
|
get_production_client,
|
|
|
|
|
get_sales_client,
|
|
|
|
|
get_inventory_client,
|
2025-11-30 16:29:38 +01:00
|
|
|
get_procurement_client,
|
|
|
|
|
get_distribution_client
|
2025-11-30 09:12:40 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def get_enterprise_dashboard_service() -> EnterpriseDashboardService:
|
|
|
|
|
from app.core.config import settings
|
|
|
|
|
tenant_client = get_tenant_client(settings)
|
|
|
|
|
forecast_client = get_forecast_client(settings)
|
|
|
|
|
production_client = get_production_client(settings)
|
|
|
|
|
sales_client = get_sales_client(settings)
|
|
|
|
|
inventory_client = get_inventory_client(settings)
|
2025-11-30 16:29:38 +01:00
|
|
|
distribution_client = get_distribution_client(settings)
|
2025-11-30 09:12:40 +01:00
|
|
|
procurement_client = get_procurement_client(settings)
|
|
|
|
|
|
|
|
|
|
return EnterpriseDashboardService(
|
|
|
|
|
tenant_client=tenant_client,
|
|
|
|
|
forecast_client=forecast_client,
|
|
|
|
|
production_client=production_client,
|
|
|
|
|
sales_client=sales_client,
|
|
|
|
|
inventory_client=inventory_client,
|
|
|
|
|
distribution_client=distribution_client,
|
|
|
|
|
procurement_client=procurement_client
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@router.get("/network-summary")
|
|
|
|
|
async def get_network_summary(
|
|
|
|
|
tenant_id: str,
|
|
|
|
|
enterprise_service: EnterpriseDashboardService = Depends(get_enterprise_dashboard_service),
|
|
|
|
|
verified_tenant: str = Depends(verify_tenant_access_dep)
|
|
|
|
|
):
|
|
|
|
|
"""
|
|
|
|
|
Get network summary metrics for enterprise dashboard
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
# Verify user has network access
|
|
|
|
|
tenant_info = await enterprise_service.tenant_client.get_tenant(tenant_id)
|
|
|
|
|
if not tenant_info:
|
|
|
|
|
raise HTTPException(status_code=404, detail="Tenant not found")
|
|
|
|
|
if tenant_info.get('tenant_type') != 'parent':
|
|
|
|
|
raise HTTPException(status_code=403, detail="Only parent tenants can access enterprise dashboard")
|
|
|
|
|
|
|
|
|
|
result = await enterprise_service.get_network_summary(parent_tenant_id=tenant_id)
|
|
|
|
|
return result
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"Error getting network summary: {e}", exc_info=True)
|
|
|
|
|
raise HTTPException(status_code=500, detail="Failed to get network summary")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/children-performance")
|
|
|
|
|
async def get_children_performance(
|
|
|
|
|
tenant_id: str,
|
|
|
|
|
metric: str = "sales",
|
|
|
|
|
period_days: int = 30,
|
|
|
|
|
enterprise_service: EnterpriseDashboardService = Depends(get_enterprise_dashboard_service),
|
|
|
|
|
verified_tenant: str = Depends(verify_tenant_access_dep)
|
|
|
|
|
):
|
|
|
|
|
"""
|
|
|
|
|
Get anonymized performance ranking of child tenants
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
# Verify user has network access
|
|
|
|
|
tenant_info = await enterprise_service.tenant_client.get_tenant(tenant_id)
|
|
|
|
|
if not tenant_info:
|
|
|
|
|
raise HTTPException(status_code=404, detail="Tenant not found")
|
|
|
|
|
if tenant_info.get('tenant_type') != 'parent':
|
|
|
|
|
raise HTTPException(status_code=403, detail="Only parent tenants can access enterprise dashboard")
|
|
|
|
|
|
|
|
|
|
result = await enterprise_service.get_children_performance(
|
|
|
|
|
parent_tenant_id=tenant_id,
|
|
|
|
|
metric=metric,
|
|
|
|
|
period_days=period_days
|
|
|
|
|
)
|
|
|
|
|
return result
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"Error getting children performance: {e}", exc_info=True)
|
|
|
|
|
raise HTTPException(status_code=500, detail="Failed to get children performance")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/distribution-overview")
|
|
|
|
|
async def get_distribution_overview(
|
|
|
|
|
tenant_id: str,
|
|
|
|
|
target_date: Optional[date] = None,
|
|
|
|
|
enterprise_service: EnterpriseDashboardService = Depends(get_enterprise_dashboard_service),
|
|
|
|
|
verified_tenant: str = Depends(verify_tenant_access_dep)
|
|
|
|
|
):
|
|
|
|
|
"""
|
|
|
|
|
Get distribution overview for enterprise dashboard
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
# Verify user has network access
|
|
|
|
|
tenant_info = await enterprise_service.tenant_client.get_tenant(tenant_id)
|
|
|
|
|
if not tenant_info:
|
|
|
|
|
raise HTTPException(status_code=404, detail="Tenant not found")
|
|
|
|
|
if tenant_info.get('tenant_type') != 'parent':
|
|
|
|
|
raise HTTPException(status_code=403, detail="Only parent tenants can access enterprise dashboard")
|
|
|
|
|
|
|
|
|
|
if target_date is None:
|
|
|
|
|
target_date = date.today()
|
|
|
|
|
|
|
|
|
|
result = await enterprise_service.get_distribution_overview(
|
|
|
|
|
parent_tenant_id=tenant_id,
|
|
|
|
|
target_date=target_date
|
|
|
|
|
)
|
|
|
|
|
return result
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"Error getting distribution overview: {e}", exc_info=True)
|
|
|
|
|
raise HTTPException(status_code=500, detail="Failed to get distribution overview")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/forecast-summary")
|
|
|
|
|
async def get_enterprise_forecast_summary(
|
|
|
|
|
tenant_id: str,
|
|
|
|
|
days_ahead: int = 7,
|
|
|
|
|
enterprise_service: EnterpriseDashboardService = Depends(get_enterprise_dashboard_service),
|
|
|
|
|
verified_tenant: str = Depends(verify_tenant_access_dep)
|
|
|
|
|
):
|
|
|
|
|
"""
|
|
|
|
|
Get aggregated forecast summary for the enterprise network
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
# Verify user has network access
|
|
|
|
|
tenant_info = await enterprise_service.tenant_client.get_tenant(tenant_id)
|
|
|
|
|
if not tenant_info:
|
|
|
|
|
raise HTTPException(status_code=404, detail="Tenant not found")
|
|
|
|
|
if tenant_info.get('tenant_type') != 'parent':
|
|
|
|
|
raise HTTPException(status_code=403, detail="Only parent tenants can access enterprise dashboard")
|
|
|
|
|
|
|
|
|
|
result = await enterprise_service.get_enterprise_forecast_summary(
|
|
|
|
|
parent_tenant_id=tenant_id,
|
|
|
|
|
days_ahead=days_ahead
|
|
|
|
|
)
|
|
|
|
|
return result
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"Error getting enterprise forecast summary: {e}", exc_info=True)
|
|
|
|
|
raise HTTPException(status_code=500, detail="Failed to get enterprise forecast summary")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/network-performance")
|
|
|
|
|
async def get_network_performance_metrics(
|
|
|
|
|
tenant_id: str,
|
|
|
|
|
start_date: Optional[date] = None,
|
|
|
|
|
end_date: Optional[date] = None,
|
|
|
|
|
enterprise_service: EnterpriseDashboardService = Depends(get_enterprise_dashboard_service),
|
|
|
|
|
verified_tenant: str = Depends(verify_tenant_access_dep)
|
|
|
|
|
):
|
|
|
|
|
"""
|
|
|
|
|
Get aggregated performance metrics across the tenant network
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
# Verify user has network access
|
|
|
|
|
tenant_info = await enterprise_service.tenant_client.get_tenant(tenant_id)
|
|
|
|
|
if not tenant_info:
|
|
|
|
|
raise HTTPException(status_code=404, detail="Tenant not found")
|
|
|
|
|
if tenant_info.get('tenant_type') != 'parent':
|
|
|
|
|
raise HTTPException(status_code=403, detail="Only parent tenants can access enterprise dashboard")
|
|
|
|
|
|
|
|
|
|
if not start_date:
|
|
|
|
|
start_date = date.today()
|
|
|
|
|
if not end_date:
|
|
|
|
|
end_date = date.today()
|
|
|
|
|
|
|
|
|
|
result = await enterprise_service.get_network_performance_metrics(
|
|
|
|
|
parent_tenant_id=tenant_id,
|
|
|
|
|
start_date=start_date,
|
|
|
|
|
end_date=end_date
|
|
|
|
|
)
|
|
|
|
|
return result
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"Error getting network performance metrics: {e}", exc_info=True)
|
|
|
|
|
raise HTTPException(status_code=500, detail="Failed to get network performance metrics")
|