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[] = []; await db.$transaction(async (tx) => { for (const change of changes) { if (change.remove && change.assignmentId) { await tx.assignment.update({ where: { id: change.assignmentId }, data: { status: "CANCELLED" }, }); continue; } if (change.assignmentId) { await tx.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 tx.resource.findUnique({ where: { id: change.resourceId }, select: { lcrCents: true }, }); const dailyCostCents = Math.round((resource?.lcrCents ?? 0) * change.hoursPerDay); const newAssignment = await tx.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 }; }