Fix: align task visibility filters across all API routes and dashboards

- api/tasks/route.ts: fix group-expiry filter to never hide open tasks;
  replace dueDate-based age filter with completedAt-based filter so open
  tasks are always visible regardless of how old they are
- api/dashboard/workload/route.ts: add dead-policy exclusion to base
  task filter so overdue counts and per-user workload rows exclude tasks
  on cancelled/expired/non-renewed policies
- manager/page.tsx: same dead-policy exclusion on teamMembers task query
- api/metrics/route.ts: fix horizon_tasks_overdue to exclude dead-policy tasks
This commit is contained in:
lorentz 2026-06-02 00:01:01 +00:00
parent 20f7ec1188
commit b1b0dfa64d
4 changed files with 16 additions and 6 deletions

View file

@ -56,6 +56,7 @@ export default async function ManagerPage() {
task: { task: {
clientId: { in: shapeClientIds }, clientId: { in: shapeClientIds },
status: { notIn: ['COMPLETED', 'CANCELLED', 'NA'] }, status: { notIn: ['COMPLETED', 'CANCELLED', 'NA'] },
NOT: { policy: { status: { in: ['Cancelled', 'Expired', 'Non-Renewed', 'Rewritten', 'Not taken'] } } },
} }
}, },
select: { select: {

View file

@ -30,9 +30,12 @@ export async function GET(request: NextRequest) {
}) })
const shapeClientIds = shapeClients.map((c) => c.id) const shapeClientIds = shapeClients.map((c) => c.id)
// Base task filter — scoped to Shape clients only const DEAD_POLICY_STATUSES = ['Cancelled', 'Expired', 'Non-Renewed', 'Rewritten', 'Not taken']
// Base task filter — scoped to Shape clients only, excluding dead policies
const deptTaskWhere = { const deptTaskWhere = {
clientId: { in: shapeClientIds }, clientId: { in: shapeClientIds },
NOT: { policy: { status: { in: DEAD_POLICY_STATUSES } } },
...(departmentFilter ? { department: departmentFilter.toUpperCase() as DepartmentType } : {}), ...(departmentFilter ? { department: departmentFilter.toUpperCase() as DepartmentType } : {}),
} }

View file

@ -60,7 +60,7 @@ export async function GET(request: NextRequest) {
prisma.task.count(), prisma.task.count(),
prisma.task.groupBy({ by: ['status'], _count: { id: true } }), prisma.task.groupBy({ by: ['status'], _count: { id: true } }),
prisma.task.groupBy({ by: ['department'], _count: { id: true } }), prisma.task.groupBy({ by: ['department'], _count: { id: true } }),
prisma.task.count({ where: { dueDate: { lt: now }, status: { notIn: ['COMPLETED', 'NA', 'CANCELLED'] } } }), prisma.task.count({ where: { dueDate: { lt: now }, status: { notIn: ['COMPLETED', 'NA', 'CANCELLED'] }, NOT: { policy: { status: { in: ['Cancelled', 'Expired', 'Non-Renewed', 'Rewritten', 'Not taken'] } } } } }),
prisma.task.count({ where: { createdAt: { gte: todayStart } } }), prisma.task.count({ where: { createdAt: { gte: todayStart } } }),
prisma.task.count({ where: { completedAt: { gte: todayStart } } }), prisma.task.count({ where: { completedAt: { gte: todayStart } } }),
prisma.task.count({ where: { createdAt: { gte: weekAgo } } }), prisma.task.count({ where: { createdAt: { gte: weekAgo } } }),

View file

@ -36,18 +36,24 @@ export async function GET(request: NextRequest) {
policy: { status: { in: ['Cancelled', 'Expired', 'Non-Renewed', 'Rewritten', 'Not taken'] } }, policy: { status: { in: ['Cancelled', 'Expired', 'Non-Renewed', 'Rewritten', 'Not taken'] } },
}, },
}, },
// Exclude tasks on expired renewal groups // Exclude tasks on expired renewal groups — but NEVER hide open tasks
{ {
OR: [ OR: [
{ policyGroupId: null }, { policyGroupId: null },
{ policyGroup: { renewalDate: { gte: cutoff } } }, { policyGroup: { renewalDate: { gte: cutoff } } },
{ status: { notIn: ['COMPLETED', 'CANCELLED', 'NA'] } },
], ],
}, },
// Exclude old non-terminal tasks // Keep ALL open tasks regardless of age; only show terminal tasks completed/closed recently
{ {
OR: [ OR: [
{ dueDate: { gte: cutoff } }, { status: { notIn: ['COMPLETED', 'CANCELLED', 'NA'] } },
{ status: { in: ['COMPLETED', 'CANCELLED', 'NA'] } }, {
AND: [
{ status: { in: ['COMPLETED', 'CANCELLED', 'NA'] } },
{ completedAt: { gte: cutoff } },
],
},
], ],
}, },
] ]