Add AQMM dashboard for assurance engagement quality monitoring
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import csv
|
||||
import io
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.responses import RedirectResponse, StreamingResponse
|
||||
|
||||
from app.core.db.common import CommonSessionLocal
|
||||
from app.core.http_responses import ui_access_denied
|
||||
from app.core.security.csrf import get_or_create_csrf_token
|
||||
from app.core.security.session_auth import get_current_user
|
||||
from app.core.templating import templates
|
||||
from app.modules.aqmm_dashboard.service import build_aqmm_dashboard_payload, can_view_aqmm_dashboard
|
||||
from app.modules.core.rbac.deps import get_user_permissions, get_user_roles
|
||||
|
||||
router = APIRouter(prefix="/aqmm", tags=["aqmm-dashboard-ui"])
|
||||
|
||||
|
||||
def _ctx(request: Request, db, user, **extra):
|
||||
base = {
|
||||
"request": request,
|
||||
"current_user": user,
|
||||
"current_user_roles": get_user_roles(db, user.id),
|
||||
"current_user_permissions": get_user_permissions(db, user.id),
|
||||
"csrf_token": get_or_create_csrf_token(request),
|
||||
"title": "AQMM Dashboard",
|
||||
}
|
||||
base.update(extra)
|
||||
return base
|
||||
|
||||
|
||||
@router.get("/dashboard")
|
||||
def dashboard(request: Request, financial_year: str = "", q: str = ""):
|
||||
db = CommonSessionLocal()
|
||||
try:
|
||||
user = get_current_user(request, db=db)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login", status_code=303)
|
||||
if not can_view_aqmm_dashboard(db, user):
|
||||
return ui_access_denied()
|
||||
payload = build_aqmm_dashboard_payload(db, request, user, financial_year=financial_year, q=q)
|
||||
return templates.TemplateResponse(
|
||||
"modules/aqmm_dashboard/templates/aqmm_dashboard/dashboard.html",
|
||||
_ctx(request, db, user, **payload),
|
||||
)
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
@router.get("/dashboard/export.csv")
|
||||
def dashboard_export_csv(request: Request, financial_year: str = "", q: str = ""):
|
||||
db = CommonSessionLocal()
|
||||
try:
|
||||
user = get_current_user(request, db=db)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login", status_code=303)
|
||||
if not can_view_aqmm_dashboard(db, user):
|
||||
return ui_access_denied()
|
||||
payload = build_aqmm_dashboard_payload(db, request, user, financial_year=financial_year, q=q)
|
||||
|
||||
buf = io.StringIO()
|
||||
writer = csv.writer(buf)
|
||||
writer.writerow([
|
||||
"Client",
|
||||
"Service",
|
||||
"FY",
|
||||
"Status",
|
||||
"AQMM Status",
|
||||
"KYC",
|
||||
"Independence",
|
||||
"Conflict",
|
||||
"Engagement Letter",
|
||||
"AQMM Tasks",
|
||||
"Evidence Pending",
|
||||
"Manager Review Pending",
|
||||
"Partner Review Pending",
|
||||
"Review Partner Pending",
|
||||
"Closure Status",
|
||||
"Blockers",
|
||||
])
|
||||
for item in payload["engagements"]:
|
||||
row = item["row"]
|
||||
closure = item.get("closure")
|
||||
counts = item["counts"]
|
||||
writer.writerow([
|
||||
row.client.client_name if row.client else "",
|
||||
row.catalogue.service_name if row.catalogue else "",
|
||||
row.financial_year or "",
|
||||
row.status or "",
|
||||
row.quality_workflow_status or "",
|
||||
row.quality_kyc_status or "",
|
||||
row.quality_independence_status or "",
|
||||
row.quality_conflict_status or "",
|
||||
row.quality_engagement_letter_status or "",
|
||||
counts.get("total", 0),
|
||||
counts.get("evidence_pending", 0),
|
||||
counts.get("manager_pending", 0),
|
||||
counts.get("partner_pending", 0),
|
||||
counts.get("review_partner_pending", 0),
|
||||
closure.closure_status if closure else "not_started",
|
||||
"; ".join(item.get("blockers") or []),
|
||||
])
|
||||
|
||||
data = buf.getvalue().encode("utf-8-sig")
|
||||
filename = f"aqmm_dashboard_{financial_year or 'all'}.csv"
|
||||
return StreamingResponse(
|
||||
iter([data]),
|
||||
media_type="text/csv",
|
||||
headers={"Content-Disposition": f'attachment; filename="{filename}"'},
|
||||
)
|
||||
finally:
|
||||
db.close()
|
||||
Reference in New Issue
Block a user