refactor(api): extract scenario router helpers

This commit is contained in:
2026-03-31 11:03:50 +02:00
parent e013d1af9f
commit 3e0d9d9af7
5 changed files with 705 additions and 632 deletions
+89
View File
@@ -0,0 +1,89 @@
import { TRPCError } from "@trpc/server";
import { createAuditEntry } from "../lib/audit.js";
import type { ScenarioChangeInput, ScenarioDb } from "./scenario-shared.js";
export async function applyProjectScenario(
db: ScenarioDb,
input: {
projectId: string;
changes: ScenarioChangeInput[];
userId?: string;
},
) {
const { projectId, changes, userId } = input;
const project = await db.project.findUnique({
where: { id: projectId },
select: { id: true, name: true },
});
if (!project) {
throw new TRPCError({ code: "NOT_FOUND", message: "Project not found" });
}
const created: string[] = [];
for (const change of changes) {
if (change.remove && change.assignmentId) {
await db.assignment.update({
where: { id: change.assignmentId },
data: { status: "CANCELLED" },
});
continue;
}
if (change.assignmentId) {
await db.assignment.update({
where: { id: change.assignmentId },
data: {
startDate: change.startDate,
endDate: change.endDate,
hoursPerDay: change.hoursPerDay,
...(change.resourceId ? { resourceId: change.resourceId } : {}),
...(change.roleId ? { roleId: change.roleId } : {}),
},
});
created.push(change.assignmentId);
continue;
}
if (!change.resourceId) {
continue;
}
const resource = await db.resource.findUnique({
where: { id: change.resourceId },
select: { lcrCents: true },
});
const dailyCostCents = Math.round((resource?.lcrCents ?? 0) * change.hoursPerDay);
const newAssignment = await db.assignment.create({
data: {
projectId,
resourceId: change.resourceId,
...(change.roleId ? { roleId: change.roleId } : {}),
startDate: change.startDate,
endDate: change.endDate,
hoursPerDay: change.hoursPerDay,
percentage: 100,
dailyCostCents,
status: "PROPOSED",
metadata: {},
},
});
created.push(newAssignment.id);
}
void createAuditEntry({
db,
entityType: "ScenarioApplication",
entityId: projectId,
entityName: project.name,
action: "CREATE",
...(userId ? { userId } : {}),
summary: `Applied scenario to project "${project.name}" (${created.length} allocations created/modified)`,
metadata: { appliedCount: created.length, assignmentIds: created },
source: "ui",
});
return { appliedCount: created.length };
}