refactor(api): extract timeline allocation inline support
This commit is contained in:
@@ -1,18 +1,13 @@
|
||||
import {
|
||||
buildSplitAllocationReadModel,
|
||||
createAssignment,
|
||||
loadAllocationEntry,
|
||||
updateAllocationEntry,
|
||||
} from "@capakraken/application";
|
||||
import type { PrismaClient } from "@capakraken/db";
|
||||
import {
|
||||
AllocationStatus,
|
||||
PermissionKey,
|
||||
UpdateAllocationHoursSchema,
|
||||
type RecurrencePattern,
|
||||
type WeekdayAvailability,
|
||||
} from "@capakraken/shared";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
emitAllocationCreated,
|
||||
@@ -21,96 +16,25 @@ import {
|
||||
import { managerProcedure, requirePermission } from "../trpc.js";
|
||||
import {
|
||||
assertTimelineDateRangeValid,
|
||||
buildTimelineAllocationEntryUpdate,
|
||||
buildTimelineAllocationMetadata,
|
||||
buildTimelineAllocationUpdateAuditChanges,
|
||||
buildTimelineQuickAssignAssignmentInput,
|
||||
validateTimelineAllocationDateRanges,
|
||||
} from "./timeline-allocation-mutation-support.js";
|
||||
import { applyTimelineInlineAllocationUpdate } from "./timeline-allocation-inline-support.js";
|
||||
import { applyTimelineBatchAllocationShift } from "./timeline-allocation-shift-support.js";
|
||||
import { calculateTimelineAllocationDailyCost } from "./timeline-cost-support.js";
|
||||
|
||||
export const timelineAllocationMutationProcedures = {
|
||||
updateAllocationInline: managerProcedure
|
||||
.input(UpdateAllocationHoursSchema)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
requirePermission(ctx, PermissionKey.MANAGE_ALLOCATIONS);
|
||||
const resolved = await loadAllocationEntry(ctx.db, input.allocationId);
|
||||
const existing = resolved.entry;
|
||||
const existingResource = resolved.resourceId
|
||||
? await ctx.db.resource.findUnique({
|
||||
where: { id: resolved.resourceId },
|
||||
select: { id: true, lcrCents: true, availability: true },
|
||||
})
|
||||
: null;
|
||||
|
||||
const newHoursPerDay = input.hoursPerDay ?? existing.hoursPerDay;
|
||||
const newStartDate = input.startDate ?? existing.startDate;
|
||||
const newEndDate = input.endDate ?? existing.endDate;
|
||||
|
||||
assertTimelineDateRangeValid(newStartDate, newEndDate);
|
||||
const { metadata: newMeta, includeSaturday } = buildTimelineAllocationMetadata({
|
||||
existingMetadata: existing.metadata as Record<string, unknown> | null | undefined,
|
||||
const updated = await applyTimelineInlineAllocationUpdate({
|
||||
db: ctx.db as PrismaClient,
|
||||
allocationId: input.allocationId,
|
||||
hoursPerDay: input.hoursPerDay,
|
||||
startDate: input.startDate,
|
||||
endDate: input.endDate,
|
||||
includeSaturday: input.includeSaturday,
|
||||
});
|
||||
|
||||
let newDailyCostCents = 0;
|
||||
if (resolved.resourceId) {
|
||||
if (!existingResource) {
|
||||
throw new TRPCError({ code: "NOT_FOUND", message: "Resource not found" });
|
||||
}
|
||||
|
||||
const availability = existingResource.availability as unknown as WeekdayAvailability;
|
||||
const recurrence = newMeta.recurrence as RecurrencePattern | undefined;
|
||||
newDailyCostCents = await calculateTimelineAllocationDailyCost({
|
||||
db: ctx.db as PrismaClient,
|
||||
resourceId: resolved.resourceId,
|
||||
lcrCents: existingResource.lcrCents,
|
||||
hoursPerDay: newHoursPerDay,
|
||||
startDate: newStartDate,
|
||||
endDate: newEndDate,
|
||||
availability,
|
||||
includeSaturday,
|
||||
...(recurrence ? { recurrence } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
const updated = await ctx.db.$transaction(async (tx) => {
|
||||
const { allocation: updatedAllocation } = await updateAllocationEntry(
|
||||
tx as unknown as Parameters<typeof updateAllocationEntry>[0],
|
||||
{
|
||||
id: input.allocationId,
|
||||
...buildTimelineAllocationEntryUpdate({
|
||||
hoursPerDay: newHoursPerDay,
|
||||
startDate: newStartDate,
|
||||
endDate: newEndDate,
|
||||
metadata: newMeta,
|
||||
dailyCostCents: newDailyCostCents,
|
||||
role: input.role,
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
await tx.auditLog.create({
|
||||
data: {
|
||||
entityType: "Allocation",
|
||||
entityId: input.allocationId,
|
||||
action: "UPDATE",
|
||||
changes: buildTimelineAllocationUpdateAuditChanges({
|
||||
allocationId: resolved.entry.id,
|
||||
previousHoursPerDay: existing.hoursPerDay,
|
||||
previousStartDate: existing.startDate,
|
||||
previousEndDate: existing.endDate,
|
||||
nextAllocationId: updatedAllocation.id,
|
||||
nextHoursPerDay: newHoursPerDay,
|
||||
nextStartDate: newStartDate,
|
||||
nextEndDate: newEndDate,
|
||||
includeSaturday,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
return updatedAllocation;
|
||||
role: input.role,
|
||||
});
|
||||
|
||||
emitAllocationUpdated({
|
||||
|
||||
Reference in New Issue
Block a user