fix: project status counts now show latest round state per project
Previously counted distinct projects per state across ALL rounds, inflating counts (e.g., 215 Passed when many were later rejected). Now picks each project's latest round state (highest sortOrder) to determine its current status. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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<string, unknown> = {}
|
||||
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<string, string>()
|
||||
for (const s of allStates) {
|
||||
if (!latestByProject.has(s.projectId)) {
|
||||
latestByProject.set(s.projectId, s.state)
|
||||
}
|
||||
}
|
||||
|
||||
// Aggregate counts
|
||||
const countMap = new Map<string, number>()
|
||||
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<string, number> = {}
|
||||
for (const g of roundStateCounts) {
|
||||
statusCounts[g.state] = g.count
|
||||
for (const [state, count] of roundStateCounts) {
|
||||
statusCounts[state] = count
|
||||
}
|
||||
|
||||
const projectsWithLogos = await attachProjectLogoUrls(projects)
|
||||
|
||||
Reference in New Issue
Block a user