Plan: Reporting & Data Quality Dashboard
On this page
Status
| Step | Description | Status |
|---|---|---|
1 |
Plan file and nav entry |
Done (2026-03-21) — MR !50 |
2 |
Reporting route module + view models |
Done (2026-03-21) — MR !50 |
3 |
Quality dashboard page |
Done (2026-03-21) — MR !50 |
4 |
Quality issues list page |
Done (2026-03-21) — MR !50 |
5 |
AFCARS submission workflow page |
Done (2026-03-21) — MR !50 |
6 |
NCANDS submission workflow page |
Done (2026-03-21) — MR !50 |
7 |
Nav link + RBAC (supervisor+) |
Done (2026-03-21) — MR !50 |
8 |
E2E tests |
Done (2026-03-21) — MR !50 |
9 |
Documentation, commit, push, MR |
Done (2026-03-21) — MR !50 |
Issues: TBD
Branch: feature/reporting-dashboard
Context
The craig-reporting API (port 8006) is fully built with 14 endpoints covering data quality issues, AFCARS submissions, and NCANDS submissions. The web UI has zero reporting pages — no routes, no templates, no view models. This plan wires the existing API into the web UI.
Scope
In scope:
-
Quality dashboard page (metrics, severity breakdown, readiness percentages)
-
Quality issues list page (paginated, filterable, resolve action)
-
AFCARS submission list + detail + workflow actions (generate, review, approve, transmit)
-
NCANDS submission list + detail + workflow actions
-
Navigation link (supervisor+ visibility)
-
E2E tests for page rendering
Out of scope:
-
New API endpoints (all exist on craig-reporting)
-
Trend charts or graphs (future enhancement — tables and badges only)
Design
Route Module
File: services/craig-web/src/routes/reporting.rs — new module
View models:
#[allow(dead_code)]
#[derive(Deserialize, Default, Clone)]
pub struct QualityDashboardView {
pub total_unresolved_issues: i64,
pub severity_breakdown: Vec<SeverityCount>,
pub afcars_readiness: Option<f64>,
pub ncands_readiness: Option<f64>,
pub field_completeness: Option<f64>,
}
#[allow(dead_code)]
#[derive(Deserialize, Default, Clone)]
pub struct SeverityCount {
pub severity: String,
pub count: i64,
}
#[allow(dead_code)]
#[derive(Deserialize, Default, Clone)]
pub struct QualityIssueView {
pub id: Uuid,
pub source_service: String,
pub source_record_id: Option<Uuid>,
pub issue_type: String,
pub field_name: Option<String>,
pub description: String,
pub severity: String,
pub resolved: bool,
pub resolved_by: Option<String>,
pub resolved_by_name: Option<String>,
pub resolved_at: Option<String>,
pub detected_at: String,
}
#[allow(dead_code)]
#[derive(Deserialize, Default, Clone)]
pub struct AfcarsSubmissionView {
pub id: Uuid,
pub reporting_period: String,
pub record_count: i32,
pub validation_errors: i32,
pub status: String,
pub reviewed_by: Option<String>,
pub reviewed_by_name: Option<String>,
pub approved_by: Option<String>,
pub approved_by_name: Option<String>,
pub created_at: String,
}
Handlers
-
GET /reporting/— quality dashboard (fetch/v1/reporting/quality/dashboardfrom API) -
GET /reporting/issues— issues list (paginated, fetch/v1/reporting/quality/issues) -
POST /reporting/issues/{id}/resolve— resolve issue (POST to API, redirect) -
GET /reporting/afcars— AFCARS list (fetch/v1/reporting/afcars) -
GET /reporting/afcars/{id}— AFCARS detail -
POST /reporting/afcars/generate— generate submission -
POST /reporting/afcars/{id}/review— review -
POST /reporting/afcars/{id}/approve— approve -
POST /reporting/afcars/{id}/transmit— transmit -
GET /reporting/ncands— NCANDS list -
Similar NCANDS workflow handlers
Templates
-
templates/reporting/dashboard.html— stat tiles for readiness, severity breakdown table, unresolved count -
templates/reporting/issues.html— data table with severity badges, source service, description, resolve button -
templates/reporting/afcars.html— submission list with status badges + workflow actions -
templates/reporting/afcars_detail.html— detail with review/approve/transmit buttons -
templates/reporting/ncands.html— similar
Navigation
Add "Reporting" link to authenticated nav bar between "Financial" and "Rules" (or after Financial for caseworker, after Rules for admin). Visible to supervisor+ only.
File: services/craig-web/templates/base.html — add nav link with role check
Route Registration
File: services/craig-web/src/main.rs — add reporting routes:
.route("/reporting/", get(routes::reporting::dashboard))
.route("/reporting/issues", get(routes::reporting::issues_list))
.route("/reporting/issues/{id}/resolve", post(routes::reporting::resolve_issue))
.route("/reporting/afcars", get(routes::reporting::afcars_list))
.route("/reporting/afcars/generate", post(routes::reporting::generate_afcars))
.route("/reporting/afcars/{id}", get(routes::reporting::afcars_detail))
// ... similar for ncands
Verification
-
cargo xtask dev reload+ navigate to/reporting/ -
Dashboard shows quality metrics from API
-
Issues list renders with pagination and severity badges
-
AFCARS workflow actions work (generate → review → approve → transmit)
-
E2E tests verify page rendering
-
All 121+ existing E2E tests pass
Files Touched
| File | Change |
|---|---|
|
New: ~15 handlers + view models |
|
Register reporting module |
|
Add ~15 routes |
|
5 new templates |
|
Add Reporting nav link |
|
Add |
|
New E2E tests |
Documentation Updates
-
.claude/docs/services.md— note web UI reporting pages -
CHANGELOG.adoc -
docs/modules/ROOT/pages/roadmap.adoc— tick reporting dashboard item -
docs/modules/ROOT/pages/guide/supervisor.adoc— reporting workflow