Phase 05: Visibility and Client Portal - 5 plans in 3 waves - 2 parallel (wave 1), 1 sequential (wave 2), 2 parallel (wave 3) - Ready for execution Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.7 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 05-visibility-and-client-portal | 01 | execute | 1 |
|
true |
|
Purpose: DASH-01, DASH-02, DASH-03, DASH-04 — the ISP owner's single-page business health overview. Output: DashboardService, API route, passing tests.
<execution_context> @C:\Users\KevinAsprec.claude/get-shit-done/workflows/execute-plan.md @C:\Users\KevinAsprec.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/05-visibility-and-client-portal/05-CONTEXT.md@src/lib/services/financial-report-service.ts @src/lib/services/outstanding-report-service.ts @src/lib/services/collection-report-service.ts @src/lib/services/expense-report-service.ts @src/lib/services/payment-service.ts @src/lib/services/collector-service.ts @src/lib/middleware/authorize.ts @prisma/schema.prisma
Task 1: DashboardService with metric aggregation src/lib/services/dashboard-service.ts Create DashboardService with these methods, all accepting a TenantPrismaClient (same pattern as all other services):-
getRevenueMetrics(db, tenantId) — Revenue collected today and this month (DASH-01):
- Query Payment table with status COMPLETED, grouped by date range
revenueToday: sum of payments where createdAt is today (midnight to now)revenueThisMonth: sum of payments where createdAt is current month- Return
{ revenueToday: Decimal, revenueThisMonth: Decimal }
-
getOverdueMetrics(db, tenantId) — Overdue subscriber count and outstanding total (DASH-02):
- Query Invoice table for OVERDUE status invoices
- Count distinct subscriberIds with overdue invoices
- Sum (totalAmount - amountPaid) for all overdue invoices
- Return
{ overdueCount: number, totalOutstanding: Decimal }
-
getSubscriberMetrics(db, tenantId) — Status breakdown (DASH-03):
- Query Subscriber table grouped by status
- Return
{ active: number, suspended: number, cancelled: number, total: number }
-
getCashFlowSummary(db, tenantId, startDate, endDate) — Money in vs money out (DASH-04):
- Money in: sum of POSTED JE lines where account is revenue-type (4xxx codes) — use debit/credit with normal balance logic, same as FinancialReportService
- Money out: sum of POSTED JE lines where account is expense-type (5xxx codes)
- Return
{ moneyIn: Decimal, moneyOut: Decimal, netCashFlow: Decimal } - Default date range: current month
-
getCollectorSummary(db, tenantId) — Today's collections and unverified remittances (from CONTEXT.md):
collectionsToday: sum of non-voided Collection amounts where createdAt is todayunverifiedRemittances: count of Remittance records with status SUBMITTED (not VERIFIED)- Return
{ collectionsToday: Decimal, unverifiedRemittances: number }
-
getDashboardSummary(db, tenantId) — Aggregator that calls all five methods above and returns a single object.
Use Prisma aggregate/groupBy for efficiency. Follow the existing TenantPrismaClient pattern (type as any). Use Decimal from Prisma for all money fields. All date comparisons use UTC.
TypeScript compiles: npx tsc --noEmit src/lib/services/dashboard-service.ts (or full project compile)
DashboardService exports all 6 methods with correct return types
Integration Tests (src/lib/tests/dashboard-service.test.ts): Create tests using vitest with live PostgreSQL (same pattern as all other test files):
Setup: Create tenant, seed COA, create subscriber, generate invoice, record payment, create collection, create remittance.
Tests (minimum 6):
getRevenueMetrics returns today's revenue— after recording a payment, revenueToday > 0getOverdueMetrics counts overdue invoices— create invoice with past due date, verify overdueCount = 1getSubscriberMetrics returns status breakdown— create active + suspended subscribers, verify countsgetCashFlowSummary computes net cash flow— after payment + expense, verify moneyIn and moneyOutgetCollectorSummary returns today's collections— after collection, verify collectionsToday > 0getDashboardSummary aggregates all metrics— verify the composite object has all fields
Cleanup order: follow the most comprehensive cleanup pattern from 04-04 (expense report tests) since dashboard touches payments, invoices, collections, remittances, expenses, and JEs.
Run tests with: npx vitest run src/lib/__tests__/dashboard-service.test.ts
npx vitest run src/lib/__tests__/dashboard-service.test.ts — all tests pass
GET /api/dashboard returns all dashboard metrics; 6+ tests pass verifying metric accuracy
<success_criteria>
- DashboardService aggregates revenue, overdue, subscriber status, cash flow, and collector metrics
- GET /api/dashboard returns the composite dashboard object
- All integration tests pass, verifying metric accuracy against seeded data
- DASH-01, DASH-02, DASH-03, DASH-04 requirements satisfied </success_criteria>