diff --git a/src/server/routers/project.ts b/src/server/routers/project.ts index c092deb..d6c8c40 100644 --- a/src/server/routers/project.ts +++ b/src/server/routers/project.ts @@ -165,28 +165,40 @@ export const projectRouter = router({ }, }), ctx.prisma.project.count({ where }), - // Count distinct projects per state (avoids double-counting projects that passed multiple rounds) + // Count projects by their LATEST round state (highest sortOrder round). + // This avoids inflated counts where a project that passed round 1 + // but was rejected in round 2 shows up in both PASSED and REJECTED. (async () => { - const stateFilter = where.programId ? { project: { programId: where.programId as string } } : {} - const states = ['PENDING', 'IN_PROGRESS', 'PASSED', 'REJECTED', 'COMPLETED', 'WITHDRAWN'] as const - const counts = await Promise.all( - states.map(async (state) => ({ - state, - count: await ctx.prisma.projectRoundState.findMany({ - where: { ...stateFilter, state }, - select: { projectId: true }, - distinct: ['projectId'], - }).then((rows) => rows.length), - })) - ) - return counts + const stateFilter: Record = {} + if (where.programId) stateFilter.project = { programId: where.programId as string } + + const allStates = await ctx.prisma.projectRoundState.findMany({ + where: stateFilter, + select: { projectId: true, state: true, round: { select: { sortOrder: true } } }, + orderBy: { round: { sortOrder: 'desc' } }, + }) + + // Pick the latest round state per project + const latestByProject = new Map() + for (const s of allStates) { + if (!latestByProject.has(s.projectId)) { + latestByProject.set(s.projectId, s.state) + } + } + + // Aggregate counts + const countMap = new Map() + for (const state of latestByProject.values()) { + countMap.set(state, (countMap.get(state) ?? 0) + 1) + } + return countMap })(), ]) - // Build round-state counts (distinct projects per state) + // Build round-state counts from the latest-state map const statusCounts: Record = {} - for (const g of roundStateCounts) { - statusCounts[g.state] = g.count + for (const [state, count] of roundStateCounts) { + statusCounts[state] = count } const projectsWithLogos = await attachProjectLogoUrls(projects)