import { updateAssignment, updateDemandRequirement, } from "@capakraken/application"; import type { PrismaClient } from "@capakraken/db"; import { assertTimelineProjectShiftValid, buildTimelineProjectShiftEventPayload, buildTimelineProjectShiftValidation, type LoadedTimelineShiftContext, } from "./timeline-shift-support.js"; import { buildTimelineProjectDateRangeUpdate, buildTimelineProjectShiftAuditChanges, buildTimelineShiftedAssignmentUpdate, recalculateShiftedAssignmentDailyCost, } from "./timeline-shift-mutation-support.js"; export interface ApplyTimelineProjectShiftInput { db: PrismaClient; projectId: string; newStartDate: Date; newEndDate: Date; context: LoadedTimelineShiftContext; } export async function applyTimelineProjectShift(input: ApplyTimelineProjectShiftInput) { const validation = buildTimelineProjectShiftValidation({ context: input.context, newStartDate: input.newStartDate, newEndDate: input.newEndDate, }); assertTimelineProjectShiftValid(validation); const updatedProject = await input.db.$transaction(async (tx) => { const projectRecord = await tx.project.update({ where: { id: input.projectId }, data: buildTimelineProjectDateRangeUpdate(input), }); for (const demandRequirement of input.context.demandRequirements) { await updateDemandRequirement( tx as unknown as Parameters[0], demandRequirement.id, buildTimelineProjectDateRangeUpdate(input), ); } for (const assignment of input.context.assignments) { const dailyCostCents = await recalculateShiftedAssignmentDailyCost({ db: input.db, assignment, newStartDate: input.newStartDate, newEndDate: input.newEndDate, }); await updateAssignment( tx as unknown as Parameters[0], assignment.id, buildTimelineShiftedAssignmentUpdate({ newStartDate: input.newStartDate, newEndDate: input.newEndDate, dailyCostCents, }), ); } await tx.auditLog.create({ data: { entityType: "Project", entityId: input.projectId, action: "SHIFT", changes: buildTimelineProjectShiftAuditChanges({ project: input.context.project, newStartDate: input.newStartDate, newEndDate: input.newEndDate, validation, }), }, }); return projectRecord; }); return { project: updatedProject, validation, event: buildTimelineProjectShiftEventPayload({ projectId: input.projectId, newStartDate: input.newStartDate, newEndDate: input.newEndDate, validation, assignments: input.context.assignments, }), }; }