import { TRPCError } from "@trpc/server"; import { calculateScenarioEntryHours, getScenarioAvailability, loadScenarioAvailabilityContexts, scenarioBaselineAssignmentInclude, scenarioBaselineProjectSelect, scenarioDemandInclude, type ScenarioDb, } from "./scenario-shared.js"; export async function readProjectScenarioBaseline( db: ScenarioDb, projectId: string, ) { const project = await db.project.findUnique({ where: { id: projectId }, select: scenarioBaselineProjectSelect, }); if (!project) { throw new TRPCError({ code: "NOT_FOUND", message: "Project not found" }); } const assignments = await db.assignment.findMany({ where: { projectId, status: { not: "CANCELLED" }, }, include: scenarioBaselineAssignmentInclude, }); const demands = await db.demandRequirement.findMany({ where: { projectId, status: { not: "CANCELLED" }, }, include: scenarioDemandInclude, }); const assignmentRangeStart = assignments.length > 0 ? new Date(Math.min(...assignments.map((assignment) => assignment.startDate.getTime()))) : project.startDate; const assignmentRangeEnd = assignments.length > 0 ? new Date(Math.max(...assignments.map((assignment) => assignment.endDate.getTime()))) : project.endDate; const contexts = await loadScenarioAvailabilityContexts( db, assignments .flatMap((assignment) => (assignment.resource ? [assignment.resource] : [])), assignmentRangeStart, assignmentRangeEnd, ); const baselineAllocations = assignments.map((assignment) => { const availability = getScenarioAvailability(assignment.resource?.availability); const lcrCents = assignment.resource?.lcrCents ?? 0; const totalHours = calculateScenarioEntryHours({ resourceId: assignment.resourceId, lcrCents, hoursPerDay: assignment.hoursPerDay, startDate: assignment.startDate, endDate: assignment.endDate, availability, }, { periodStart: assignmentRangeStart, periodEnd: assignmentRangeEnd, contexts, }); const costCents = Math.round(totalHours * lcrCents); const workingDays = assignment.hoursPerDay > 0 ? Math.round((totalHours / assignment.hoursPerDay) * 100) / 100 : 0; return { id: assignment.id, resourceId: assignment.resourceId, resourceName: assignment.resource?.displayName ?? "Unknown", resourceEid: assignment.resource?.eid ?? "", lcrCents, roleId: assignment.roleId, roleName: assignment.roleEntity?.name ?? assignment.role ?? "", roleColor: assignment.roleEntity?.color ?? null, startDate: assignment.startDate.toISOString(), endDate: assignment.endDate.toISOString(), hoursPerDay: assignment.hoursPerDay, status: assignment.status, costCents, totalHours, workingDays, }; }); const baselineDemands = demands.map((demand) => ({ id: demand.id, roleId: demand.roleId, roleName: demand.roleEntity?.name ?? demand.role ?? "", roleColor: demand.roleEntity?.color ?? null, startDate: demand.startDate.toISOString(), endDate: demand.endDate.toISOString(), hoursPerDay: demand.hoursPerDay, headcount: demand.headcount, status: demand.status, })); return { project, assignments: baselineAllocations, demands: baselineDemands, totalCostCents: baselineAllocations.reduce((sum, allocation) => sum + allocation.costCents, 0), totalHours: baselineAllocations.reduce((sum, allocation) => sum + allocation.totalHours, 0), budgetCents: project.budgetCents, }; }