Fix Manager tab KPIs and workload metrics
- setupQueueCount: add policies: { some: {} } filter (match setup-queue API)
- recentTasks: scope to Shape clients, order by updatedAt not createdAt
- Workload API: scope all metrics to Shape clients only
- Workload API: filter tasks by task.department not assignee department
- Workload API: exclude NA/CANCELLED from totalTasks and completion rate denominator
- Workload API: scope userAssignments filter to match department/client scope
This commit is contained in:
parent
c40dd68360
commit
5934ff7c4f
2 changed files with 29 additions and 23 deletions
|
|
@ -25,6 +25,7 @@ export default async function ManagerPage() {
|
|||
prisma.client.count({
|
||||
where: {
|
||||
designation: { name: { in: ['Shape', 'Shape 2'] } },
|
||||
policies: { some: {} },
|
||||
OR: [
|
||||
{ claimsAdvocateId: null },
|
||||
{ setupCompletedAt: null },
|
||||
|
|
@ -70,26 +71,20 @@ export default async function ManagerPage() {
|
|||
orderBy: [{ department: 'asc' }, { displayName: 'asc' }],
|
||||
})
|
||||
|
||||
// Fetch recent tasks across the team
|
||||
// Fetch recent tasks across the team — Shape clients, recently updated/completed
|
||||
const recentTasks = await prisma.task.findMany({
|
||||
take: 10,
|
||||
orderBy: { createdAt: 'desc' },
|
||||
include: {
|
||||
client: {
|
||||
select: {
|
||||
name: true,
|
||||
}
|
||||
where: {
|
||||
status: { in: ['COMPLETED', 'IN_PROGRESS', 'NOT_STARTED'] },
|
||||
client: { designation: { name: { in: ['Shape', 'Shape 2'] } } },
|
||||
},
|
||||
assignments: {
|
||||
orderBy: { updatedAt: 'desc' },
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
displayName: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
client: { select: { name: true } },
|
||||
assignments: {
|
||||
include: { user: { select: { displayName: true } } },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from 'next/server'
|
|||
import { getServerSession } from 'next-auth'
|
||||
import { authOptions } from '@/lib/auth'
|
||||
import { prisma } from '@/lib/db'
|
||||
import { DepartmentType } from '@prisma/client'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
|
|
@ -18,10 +19,18 @@ export async function GET(request: NextRequest) {
|
|||
const weekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000)
|
||||
const monthAgo = new Date(today.getTime() - 30 * 24 * 60 * 60 * 1000)
|
||||
|
||||
// Base task filter — scoped to assignees in the department when filtering
|
||||
const deptTaskWhere = departmentFilter
|
||||
? { assignments: { some: { user: { department: { equals: departmentFilter, mode: 'insensitive' as const }, isActive: true } } } }
|
||||
: {}
|
||||
// Shape client IDs for scoping
|
||||
const shapeClients = await prisma.client.findMany({
|
||||
where: { designation: { name: { in: ['Shape', 'Shape 2'] } } },
|
||||
select: { id: true },
|
||||
})
|
||||
const shapeClientIds = shapeClients.map((c) => c.id)
|
||||
|
||||
// Base task filter — scoped to Shape clients only
|
||||
const deptTaskWhere = {
|
||||
clientId: { in: shapeClientIds },
|
||||
...(departmentFilter ? { department: departmentFilter.toUpperCase() as DepartmentType } : {}),
|
||||
}
|
||||
|
||||
// Base user filter
|
||||
const deptUserWhere = departmentFilter
|
||||
|
|
@ -112,6 +121,7 @@ export async function GET(request: NextRequest) {
|
|||
email: true,
|
||||
department: true,
|
||||
taskAssignments: {
|
||||
where: { task: deptTaskWhere },
|
||||
include: {
|
||||
task: {
|
||||
select: {
|
||||
|
|
@ -149,12 +159,12 @@ export async function GET(request: NextRequest) {
|
|||
},
|
||||
}),
|
||||
// Total tasks
|
||||
prisma.task.count({ where: deptTaskWhere }),
|
||||
prisma.task.count({ where: { ...deptTaskWhere, status: { notIn: ['NA', 'CANCELLED'] } } }),
|
||||
// Active users with task assignments
|
||||
prisma.user.count({
|
||||
where: {
|
||||
...deptUserWhere,
|
||||
taskAssignments: { some: {} },
|
||||
taskAssignments: { some: { task: deptTaskWhere } },
|
||||
},
|
||||
}),
|
||||
])
|
||||
|
|
@ -192,13 +202,14 @@ export async function GET(request: NextRequest) {
|
|||
// Sort users by active tasks (highest workload first)
|
||||
userMetrics.sort((a, b) => b.activeTasks - a.activeTasks)
|
||||
|
||||
// Calculate summary metrics
|
||||
// Calculate summary metrics (exclude NA/CANCELLED from all rate calculations)
|
||||
const totalActive = tasksByStatus
|
||||
.filter((s) => !['COMPLETED', 'CANCELLED', 'NA'].includes(s.status))
|
||||
.reduce((sum, s) => sum + s._count.id, 0)
|
||||
|
||||
const totalCompleted = tasksByStatus.find((s) => s.status === 'COMPLETED')?._count.id || 0
|
||||
|
||||
// totalTasks already excludes NA/CANCELLED (see query above)
|
||||
const completionRate = totalTasks > 0 ? Math.round((totalCompleted / totalTasks) * 100) : 0
|
||||
|
||||
// Calculate workload distribution
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue