main
py 138 lines 6.4 KB
Raw
1 from typing import List
2 from typing import Optional
3
4 from fastapi import APIRouter
5 from fastapi import Depends
6 from fastapi import Query
7 from loguru import logger
8 from sqlalchemy import func
9 from sqlalchemy import select
10 from sqlalchemy.ext.asyncio import AsyncSession
11
12 from app.auth.models.users import User
13 from app.auth.utils import AuthHandler
14 from app.customer_portal.schema.dashboard import CustomerDashboardAlertStatsResponse
15 from app.customer_portal.schema.dashboard import CustomerDashboardCaseStatsResponse
16 from app.customer_portal.schema.dashboard import CustomerDashboardStatsResponse
17 from app.db.db_session import get_db
18 from app.db.universal_models import Agents
19 from app.incidents.models import Alert
20 from app.incidents.models import Case
21 from app.middleware.customer_access import customer_access_handler
22
23 customer_portal_dashboard_router = APIRouter()
24
25
26 @customer_portal_dashboard_router.get(
27 "/dashboard/stats",
28 response_model=CustomerDashboardStatsResponse,
29 )
30 async def get_customer_dashboard_stats(
31 customer_codes: Optional[List[str]] = Query(None, description="Optional subset of customer codes to scope the stats to"),
32 current_user: User = Depends(AuthHandler().get_current_user),
33 db: AsyncSession = Depends(get_db),
34 ):
35 """Get total alerts, cases, and agents for the logged-in customer."""
36 accessible_customers = await customer_access_handler.resolve_effective_customers(current_user, customer_codes, db)
37 logger.info(f"Fetching dashboard stats for user {current_user.username}, customers: {accessible_customers}")
38
39 if "*" in accessible_customers:
40 alert_count_q = select(func.count(Alert.id))
41 case_count_q = select(func.count(Case.id))
42 agent_count_q = select(func.count(Agents.id))
43 else:
44 alert_count_q = select(func.count(Alert.id)).where(Alert.customer_code.in_(accessible_customers))
45 case_count_q = select(func.count(Case.id)).where(Case.customer_code.in_(accessible_customers))
46 agent_count_q = select(func.count(Agents.id)).where(Agents.customer_code.in_(accessible_customers))
47
48 total_alerts = (await db.execute(alert_count_q)).scalar_one()
49 total_cases = (await db.execute(case_count_q)).scalar_one()
50 total_agents = (await db.execute(agent_count_q)).scalar_one()
51
52 return CustomerDashboardStatsResponse(
53 total_alerts=total_alerts,
54 total_cases=total_cases,
55 total_agents=total_agents,
56 success=True,
57 message="Dashboard stats retrieved successfully",
58 )
59
60
61 @customer_portal_dashboard_router.get(
62 "/dashboard/alert-stats",
63 response_model=CustomerDashboardAlertStatsResponse,
64 )
65 async def get_customer_dashboard_alert_stats(
66 customer_codes: Optional[List[str]] = Query(None, description="Optional subset of customer codes to scope the stats to"),
67 current_user: User = Depends(AuthHandler().get_current_user),
68 db: AsyncSession = Depends(get_db),
69 ):
70 """Get alert counts (total, open, in-progress, closed) for the logged-in customer."""
71 accessible_customers = await customer_access_handler.resolve_effective_customers(current_user, customer_codes, db)
72 logger.info(f"Fetching dashboard alert stats for user {current_user.username}, customers: {accessible_customers}")
73
74 if "*" in accessible_customers:
75 total_q = select(func.count(Alert.id))
76 open_q = select(func.count(Alert.id)).where(Alert.status == "OPEN")
77 in_progress_q = select(func.count(Alert.id)).where(Alert.status == "IN_PROGRESS")
78 closed_q = select(func.count(Alert.id)).where(Alert.status == "CLOSED")
79 else:
80 customer_filter = Alert.customer_code.in_(accessible_customers)
81 total_q = select(func.count(Alert.id)).where(customer_filter)
82 open_q = select(func.count(Alert.id)).where(customer_filter, Alert.status == "OPEN")
83 in_progress_q = select(func.count(Alert.id)).where(customer_filter, Alert.status == "IN_PROGRESS")
84 closed_q = select(func.count(Alert.id)).where(customer_filter, Alert.status == "CLOSED")
85
86 total = (await db.execute(total_q)).scalar_one()
87 open_count = (await db.execute(open_q)).scalar_one()
88 in_progress_count = (await db.execute(in_progress_q)).scalar_one()
89 closed_count = (await db.execute(closed_q)).scalar_one()
90
91 return CustomerDashboardAlertStatsResponse(
92 total=total,
93 open=open_count,
94 in_progress=in_progress_count,
95 closed=closed_count,
96 success=True,
97 message="Dashboard alert stats retrieved successfully",
98 )
99
100
101 @customer_portal_dashboard_router.get(
102 "/dashboard/case-stats",
103 response_model=CustomerDashboardCaseStatsResponse,
104 )
105 async def get_customer_dashboard_case_stats(
106 customer_codes: Optional[List[str]] = Query(None, description="Optional subset of customer codes to scope the stats to"),
107 current_user: User = Depends(AuthHandler().get_current_user),
108 db: AsyncSession = Depends(get_db),
109 ):
110 """Get case counts (total, open, in-progress, closed) for the logged-in customer."""
111 accessible_customers = await customer_access_handler.resolve_effective_customers(current_user, customer_codes, db)
112 logger.info(f"Fetching dashboard case stats for user {current_user.username}, customers: {accessible_customers}")
113
114 if "*" in accessible_customers:
115 total_q = select(func.count(Case.id))
116 open_q = select(func.count(Case.id)).where(Case.case_status == "OPEN")
117 in_progress_q = select(func.count(Case.id)).where(Case.case_status == "IN_PROGRESS")
118 closed_q = select(func.count(Case.id)).where(Case.case_status == "CLOSED")
119 else:
120 customer_filter = Case.customer_code.in_(accessible_customers)
121 total_q = select(func.count(Case.id)).where(customer_filter)
122 open_q = select(func.count(Case.id)).where(customer_filter, Case.case_status == "OPEN")
123 in_progress_q = select(func.count(Case.id)).where(customer_filter, Case.case_status == "IN_PROGRESS")
124 closed_q = select(func.count(Case.id)).where(customer_filter, Case.case_status == "CLOSED")
125
126 total = (await db.execute(total_q)).scalar_one()
127 open_count = (await db.execute(open_q)).scalar_one()
128 in_progress_count = (await db.execute(in_progress_q)).scalar_one()
129 closed_count = (await db.execute(closed_q)).scalar_one()
130
131 return CustomerDashboardCaseStatsResponse(
132 total=total,
133 open=open_count,
134 in_progress=in_progress_count,
135 closed=closed_count,
136 success=True,
137 message="Dashboard case stats retrieved successfully",
138 )