refactor(api): extract scenario router helpers
This commit is contained in:
@@ -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 };
|
||||
}
|
||||
Reference in New Issue
Block a user