refactor(api): extract timeline shift procedure support
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
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<typeof updateDemandRequirement>[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<typeof updateAssignment>[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,
|
||||
}),
|
||||
};
|
||||
}
|
||||
@@ -1,20 +1,11 @@
|
||||
import {
|
||||
updateAssignment,
|
||||
updateDemandRequirement,
|
||||
type SplitAssignmentRecord,
|
||||
type SplitDemandRequirementRecord,
|
||||
import type {
|
||||
SplitAssignmentRecord,
|
||||
SplitDemandRequirementRecord,
|
||||
} from "@capakraken/application";
|
||||
import type { PrismaClient } from "@capakraken/db";
|
||||
import { validateShift } from "@capakraken/engine";
|
||||
import type { ShiftValidationResult } from "@capakraken/shared";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import type { TimelineShiftPlan } from "./timeline-shift-planning.js";
|
||||
import {
|
||||
buildTimelineProjectDateRangeUpdate,
|
||||
buildTimelineProjectShiftAuditChanges,
|
||||
buildTimelineShiftedAssignmentUpdate,
|
||||
recalculateShiftedAssignmentDailyCost,
|
||||
} from "./timeline-shift-mutation-support.js";
|
||||
|
||||
export interface TimelineShiftProjectRecord {
|
||||
id: string;
|
||||
@@ -31,14 +22,6 @@ export interface LoadedTimelineShiftContext {
|
||||
shiftPlan: TimelineShiftPlan;
|
||||
}
|
||||
|
||||
export interface ApplyTimelineProjectShiftInput {
|
||||
db: PrismaClient;
|
||||
projectId: string;
|
||||
newStartDate: Date;
|
||||
newEndDate: Date;
|
||||
context: LoadedTimelineShiftContext;
|
||||
}
|
||||
|
||||
export interface TimelineProjectShiftEventPayload extends Record<string, unknown> {
|
||||
projectId: string;
|
||||
newStartDate: string;
|
||||
@@ -96,74 +79,3 @@ export function buildTimelineProjectShiftEventPayload(input: {
|
||||
resourceIds: input.assignments.map((assignment) => assignment.resourceId),
|
||||
};
|
||||
}
|
||||
|
||||
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<typeof updateDemandRequirement>[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<typeof updateAssignment>[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,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { createTRPCRouter, managerProcedure, requirePermission } from "../trpc.j
|
||||
import { timelineAllocationMutationProcedures } from "./timeline-allocation-mutations.js";
|
||||
import { timelineReadProcedures } from "./timeline-read.js";
|
||||
import { loadProjectShiftContext } from "./timeline-project-load-support.js";
|
||||
import { applyTimelineProjectShift } from "./timeline-shift-support.js";
|
||||
import { applyTimelineProjectShift } from "./timeline-shift-procedure-support.js";
|
||||
|
||||
export const timelineRouter = createTRPCRouter({
|
||||
...timelineReadProcedures,
|
||||
|
||||
Reference in New Issue
Block a user