refactor(api): extract project computation graph snapshot loading

This commit is contained in:
2026-03-31 11:28:18 +02:00
parent be597dc1c5
commit 7dde6a7461
2 changed files with 109 additions and 85 deletions
@@ -0,0 +1,100 @@
import type { TRPCContext } from "../trpc.js";
export type ProjectGraphInput = {
projectId: string;
};
export async function loadProjectGraphSnapshot(
ctx: { db: TRPCContext["db"] },
input: ProjectGraphInput,
) {
const project = await ctx.db.project.findUniqueOrThrow({
where: { id: input.projectId },
select: {
id: true,
name: true,
shortCode: true,
budgetCents: true,
winProbability: true,
startDate: true,
endDate: true,
},
});
const estimate = await ctx.db.estimate.findFirst({
where: { projectId: input.projectId },
select: {
id: true,
versions: {
orderBy: { versionNumber: "desc" },
take: 1,
select: {
id: true,
commercialTerms: true,
demandLines: {
select: {
id: true,
hours: true,
costRateCents: true,
billRateCents: true,
costTotalCents: true,
priceTotalCents: true,
chapter: true,
monthlySpread: true,
scopeItemId: true,
resourceId: true,
},
},
scopeItems: {
select: {
id: true,
name: true,
scopeType: true,
frameCount: true,
itemCount: true,
unitMode: true,
},
},
resourceSnapshots: {
select: {
id: true,
resourceId: true,
displayName: true,
chapter: true,
lcrCents: true,
ucrCents: true,
location: true,
level: true,
},
},
},
},
},
orderBy: { updatedAt: "desc" },
});
const latestVersion = estimate?.versions[0];
let effortRuleCount = 0;
let experienceRuleCount = 0;
try {
effortRuleCount = await ctx.db.effortRule.count();
experienceRuleCount = await ctx.db.experienceMultiplierRule.count();
} catch {
// tables may not exist yet
}
const projectAllocations = await ctx.db.assignment.findMany({
where: { projectId: input.projectId },
select: { status: true, dailyCostCents: true, startDate: true, endDate: true, hoursPerDay: true },
});
return {
project,
latestVersion,
effortRuleCount,
experienceRuleCount,
projectAllocations,
};
}
export type ProjectGraphSnapshot = Awaited<ReturnType<typeof loadProjectGraphSnapshot>>;