From 6a5006822b878309cd5de26f8f2c0b1c759171c0 Mon Sep 17 00:00:00 2001 From: lorentz Date: Fri, 17 Jul 2026 03:19:40 +0000 Subject: [PATCH] fix(setup-queue): surface dead-policy clients hidden behind badge count The Manager nav badge, dashboard tile, and metrics gauge counted Shape/ Shape 2 clients missing an advocate/setup with ANY policy, while the Setup Queue page itself required an ACTIVE (non-dead-status) policy. Clients with only Cancelled/Expired/etc policies inflated the badge but never appeared anywhere except a bare "(N skipped)" note with no names. - setup/page.tsx: replace the bare skipped count with a full "No Active Policies" card listing each client (linked), policy count, what's missing, and a Mark N/A action - Align the active-policy filter across setup-queue API, manager dashboard count, and the Prometheus setup-queue gauge so all four surfaces agree on what's actually actionable --- ondeck/src/app/(dashboard)/manager/page.tsx | 2 +- .../app/(dashboard)/manager/setup/page.tsx | 57 ++++++++++++++++--- .../src/app/api/clients/setup-queue/route.ts | 4 +- ondeck/src/app/api/metrics/route.ts | 1 + 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/ondeck/src/app/(dashboard)/manager/page.tsx b/ondeck/src/app/(dashboard)/manager/page.tsx index 3c04097..c4a10dd 100644 --- a/ondeck/src/app/(dashboard)/manager/page.tsx +++ b/ondeck/src/app/(dashboard)/manager/page.tsx @@ -26,7 +26,7 @@ export default async function ManagerPage() { prisma.client.count({ where: { designation: { name: { in: ['Shape', 'Shape 2'] } }, - policies: { some: {} }, + policies: { some: { status: { notIn: ['Cancelled', 'Expired', 'Non-Renewed', 'Rewritten', 'Not taken'] } } }, setupNaAt: null, OR: [ { claimsAdvocateId: null }, diff --git a/ondeck/src/app/(dashboard)/manager/setup/page.tsx b/ondeck/src/app/(dashboard)/manager/setup/page.tsx index 2607835..2995007 100644 --- a/ondeck/src/app/(dashboard)/manager/setup/page.tsx +++ b/ondeck/src/app/(dashboard)/manager/setup/page.tsx @@ -34,7 +34,7 @@ export default async function SetupQueuePage() { const DEAD_STATUSES = ['Cancelled', 'Expired', 'Non-Renewed', 'Rewritten', 'Not taken'] - const [clients, skippedCount, naClients] = await Promise.all([ + const [clients, skippedClients, naClients] = await Promise.all([ prisma.client.findMany({ where: { designation: { name: { in: ['Shape', 'Shape 2'] } }, @@ -59,13 +59,15 @@ export default async function SetupQueuePage() { }, orderBy: { createdAt: 'asc' }, }), - prisma.client.count({ + prisma.client.findMany({ where: { designation: { name: { in: ['Shape', 'Shape 2'] } }, setupNaAt: null, OR: [{ claimsAdvocateId: null }, { setupCompletedAt: null }], NOT: { policies: { some: { status: { notIn: DEAD_STATUSES } } } }, }, + select: { id: true, name: true, claimsAdvocateId: true, setupCompletedAt: true, _count: { select: { policies: true } } }, + orderBy: { name: 'asc' }, }), prisma.client.findMany({ where: { @@ -110,11 +112,6 @@ export default async function SetupQueuePage() {

New Client Setup

Clients that need a claims advocate or renewal group configuration. - {skippedCount > 0 && ( - - ({skippedCount} skipped — no active policies) - - )}

@@ -216,6 +213,52 @@ export default async function SetupQueuePage() { )} + {skippedClients.length > 0 && ( + + + No Active Policies ({skippedClients.length}) + + Shape/Shape 2 clients missing an advocate or setup completion, but with no + active (non-dead) policies — likely lost business or a data cleanup issue. + Not shown in the queue above since there's nothing to configure yet. + Mark N/A once confirmed, or assign an advocate if the client is still active. + + + +
+ + + + + + + + + + {skippedClients.map((c) => ( + + + + + + + ))} + +
ClientTotal PoliciesMissing +
+ + {c.name} + + {c._count.policies} + {[!c.claimsAdvocateId && 'Advocate', !c.setupCompletedAt && 'Setup'].filter(Boolean).join(', ')} + + +
+
+
+
+ )} + {naClients.length > 0 && ( diff --git a/ondeck/src/app/api/clients/setup-queue/route.ts b/ondeck/src/app/api/clients/setup-queue/route.ts index cdd279b..ab665fe 100644 --- a/ondeck/src/app/api/clients/setup-queue/route.ts +++ b/ondeck/src/app/api/clients/setup-queue/route.ts @@ -18,9 +18,11 @@ export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url) const countOnly = searchParams.get('count') === 'true' + const DEAD_STATUSES = ['Cancelled', 'Expired', 'Non-Renewed', 'Rewritten', 'Not taken'] + const where = { designation: { name: { in: ['Shape', 'Shape 2'] } }, - policies: { some: {} }, + policies: { some: { status: { notIn: DEAD_STATUSES } } }, setupNaAt: null, OR: [ { claimsAdvocateId: null }, diff --git a/ondeck/src/app/api/metrics/route.ts b/ondeck/src/app/api/metrics/route.ts index cbbccdb..d1e36f8 100644 --- a/ondeck/src/app/api/metrics/route.ts +++ b/ondeck/src/app/api/metrics/route.ts @@ -74,6 +74,7 @@ export async function GET(request: NextRequest) { prisma.client.count({ where: { designation: { name: { in: ['Shape', 'Shape 2'] } }, + policies: { some: { status: { notIn: ['Cancelled', 'Expired', 'Non-Renewed', 'Rewritten', 'Not taken'] } } }, setupNaAt: null, OR: [{ claimsAdvocateId: null }, { setupCompletedAt: null }], },