Skip to content

Commit 280c1e3

Browse files
Merge pull request #365 from bg-playground/copilot/quality-kpi-dashboard-v1
Add project-wide Quality KPI Dashboard at /quality-dashboard
2 parents f9655c8 + 151b502 commit 280c1e3

21 files changed

Lines changed: 2361 additions & 15 deletions

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ docker compose logs -f # view logs (or: docker-compose logs -f)
127127
4. **Implement**: Apply the framework to your testing processes
128128
5. **Build (Optional)**: Use as foundation for custom testing tools
129129
6. **Release Readiness**: Use the [Release Readiness Dashboard](docs/features/release-readiness-dashboard.md) for Go/Caution/No-Go checks
130+
7. **Quality Trends**: Use the [Quality KPI Dashboard](docs/features/quality-kpi-dashboard.md) for defect, pass-rate, module, and automation trend visuals
130131

131132
## 🛠️ Manual Setup
132133

@@ -259,6 +260,7 @@ docker compose -f docker-compose.test.yml down -v
259260
| `rbac.spec.ts` | Role-based access: viewer, reviewer, admin |
260261
| `notifications.spec.ts` | Notification bell, mark-as-read, lifecycle |
261262
| `release-readiness.spec.ts` | Release readiness status banner, sign-off, and markdown export |
263+
| `quality-dashboard.spec.ts` | Quality KPI charts, window toggle, and release-readiness cross-link |
262264

263265
**Useful commands:**
264266

backend/app/api/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
"""API routers for BGSTM AI Traceability"""
22

3-
from . import links, release_readiness, requirements, test_cases
3+
from . import links, quality_metrics, release_readiness, requirements, test_cases
44

55
__all__ = [
66
"requirements",
77
"test_cases",
88
"links",
9+
"quality_metrics",
910
"release_readiness",
1011
]

backend/app/api/quality_metrics.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from typing import Literal
2+
3+
from fastapi import APIRouter, Depends, Query
4+
from sqlalchemy.ext.asyncio import AsyncSession
5+
6+
from app.auth.dependencies import get_current_user
7+
from app.crud import quality_metrics as crud
8+
from app.db.session import get_db
9+
from app.models.user import User
10+
from app.schemas.quality_metrics import (
11+
AutomationCoverageResponse,
12+
DefectsByModuleResponse,
13+
DefectTrendResponse,
14+
PassRateTrendResponse,
15+
QualityDashboardSnapshot,
16+
SummaryStatsResponse,
17+
)
18+
19+
router = APIRouter(prefix="/quality-metrics")
20+
21+
WindowParam = Literal[7, 30, 90]
22+
23+
24+
@router.get("/", response_model=QualityDashboardSnapshot)
25+
async def get_quality_dashboard(
26+
db: AsyncSession = Depends(get_db),
27+
current_user: User = Depends(get_current_user),
28+
) -> QualityDashboardSnapshot:
29+
_ = current_user
30+
return await crud.get_quality_dashboard_snapshot(db, 30)
31+
32+
33+
@router.get("/defect-trend", response_model=DefectTrendResponse)
34+
async def get_defect_trend(
35+
window: WindowParam = Query(30),
36+
db: AsyncSession = Depends(get_db),
37+
current_user: User = Depends(get_current_user),
38+
) -> DefectTrendResponse:
39+
_ = current_user
40+
return await crud.get_defect_trend(db, window)
41+
42+
43+
@router.get("/pass-rate-trend", response_model=PassRateTrendResponse)
44+
async def get_pass_rate_trend(
45+
window: WindowParam = Query(30),
46+
db: AsyncSession = Depends(get_db),
47+
current_user: User = Depends(get_current_user),
48+
) -> PassRateTrendResponse:
49+
_ = current_user
50+
return await crud.get_pass_rate_trend(db, window)
51+
52+
53+
@router.get("/defects-by-module", response_model=DefectsByModuleResponse)
54+
async def get_defects_by_module(
55+
window: WindowParam = Query(30),
56+
top_n: int = Query(10, ge=1, le=50),
57+
db: AsyncSession = Depends(get_db),
58+
current_user: User = Depends(get_current_user),
59+
) -> DefectsByModuleResponse:
60+
_ = current_user
61+
return await crud.get_defects_by_module(db, window, top_n)
62+
63+
64+
@router.get("/automation-coverage", response_model=AutomationCoverageResponse)
65+
async def get_automation_coverage(
66+
db: AsyncSession = Depends(get_db),
67+
current_user: User = Depends(get_current_user),
68+
) -> AutomationCoverageResponse:
69+
_ = current_user
70+
return await crud.get_automation_coverage(db)
71+
72+
73+
@router.get("/summary-stats", response_model=SummaryStatsResponse)
74+
async def get_summary_stats(
75+
db: AsyncSession = Depends(get_db),
76+
current_user: User = Depends(get_current_user),
77+
) -> SummaryStatsResponse:
78+
_ = current_user
79+
return await crud.get_summary_stats(db)

backend/app/crud/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
"""CRUD operations for BGSTM AI Traceability"""
22

3-
from . import link, release_readiness, requirement, test_case
3+
from . import link, quality_metrics, release_readiness, requirement, test_case
44

55
__all__ = [
66
"requirement",
77
"test_case",
88
"link",
9+
"quality_metrics",
910
"release_readiness",
1011
]

0 commit comments

Comments
 (0)