refactor(api): extract dispo router support modules
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
import {
|
||||
DispoStagedRecordType,
|
||||
ImportBatchStatus,
|
||||
StagedRecordStatus,
|
||||
} from "@capakraken/db";
|
||||
import { commitDispoImportBatch } from "@capakraken/application";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { createAuditEntry } from "../lib/audit.js";
|
||||
|
||||
type AuditDb = Parameters<typeof createAuditEntry>[0]["db"];
|
||||
type CommitDb = Parameters<typeof commitDispoImportBatch>[0];
|
||||
|
||||
export async function cancelImportBatch(
|
||||
db: AuditDb & {
|
||||
importBatch: { findUnique: Function; update: Function };
|
||||
},
|
||||
input: { id: string; userId?: string | undefined },
|
||||
) {
|
||||
const batch = await db.importBatch.findUnique({
|
||||
where: { id: input.id },
|
||||
select: { id: true, status: true },
|
||||
});
|
||||
|
||||
if (!batch) {
|
||||
throw new TRPCError({ code: "NOT_FOUND", message: `Import batch "${input.id}" not found` });
|
||||
}
|
||||
|
||||
const terminalStatuses: ImportBatchStatus[] = [
|
||||
ImportBatchStatus.COMMITTED,
|
||||
ImportBatchStatus.CANCELLED,
|
||||
];
|
||||
if (terminalStatuses.includes(batch.status)) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: `Cannot cancel batch in status "${batch.status}"`,
|
||||
});
|
||||
}
|
||||
|
||||
const cancelled = await db.importBatch.update({
|
||||
where: { id: input.id },
|
||||
data: { status: ImportBatchStatus.CANCELLED },
|
||||
});
|
||||
|
||||
void createAuditEntry({
|
||||
db,
|
||||
entityType: "ImportBatch",
|
||||
entityId: input.id,
|
||||
action: "UPDATE",
|
||||
summary: "Cancelled import batch",
|
||||
after: cancelled as Record<string, unknown>,
|
||||
source: "ui",
|
||||
...(input.userId !== undefined ? { userId: input.userId } : {}),
|
||||
});
|
||||
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
export async function resolveStagedRecord(
|
||||
db: {
|
||||
stagedResource: { update: Function };
|
||||
stagedClient: { update: Function };
|
||||
stagedProject: { update: Function };
|
||||
stagedAssignment: { update: Function };
|
||||
stagedVacation: { update: Function };
|
||||
stagedAvailabilityRule: { update: Function };
|
||||
stagedUnresolvedRecord: { update: Function };
|
||||
},
|
||||
input: { action: "APPROVE" | "REJECT" | "SKIP"; id: string; recordType: DispoStagedRecordType },
|
||||
) {
|
||||
const statusMap: Record<string, StagedRecordStatus> = {
|
||||
APPROVE: StagedRecordStatus.APPROVED,
|
||||
REJECT: StagedRecordStatus.REJECTED,
|
||||
SKIP: StagedRecordStatus.REJECTED,
|
||||
};
|
||||
const nextStatus = statusMap[input.action]!;
|
||||
|
||||
switch (input.recordType) {
|
||||
case DispoStagedRecordType.RESOURCE:
|
||||
return db.stagedResource.update({
|
||||
where: { id: input.id },
|
||||
data: { status: nextStatus },
|
||||
});
|
||||
case DispoStagedRecordType.CLIENT:
|
||||
return db.stagedClient.update({
|
||||
where: { id: input.id },
|
||||
data: { status: nextStatus },
|
||||
});
|
||||
case DispoStagedRecordType.PROJECT:
|
||||
return db.stagedProject.update({
|
||||
where: { id: input.id },
|
||||
data: { status: nextStatus },
|
||||
});
|
||||
case DispoStagedRecordType.ASSIGNMENT:
|
||||
return db.stagedAssignment.update({
|
||||
where: { id: input.id },
|
||||
data: { status: nextStatus },
|
||||
});
|
||||
case DispoStagedRecordType.VACATION:
|
||||
return db.stagedVacation.update({
|
||||
where: { id: input.id },
|
||||
data: { status: nextStatus },
|
||||
});
|
||||
case DispoStagedRecordType.AVAILABILITY_RULE:
|
||||
return db.stagedAvailabilityRule.update({
|
||||
where: { id: input.id },
|
||||
data: { status: nextStatus },
|
||||
});
|
||||
case DispoStagedRecordType.UNRESOLVED:
|
||||
return db.stagedUnresolvedRecord.update({
|
||||
where: { id: input.id },
|
||||
data: { status: nextStatus },
|
||||
});
|
||||
default:
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: `Unknown record type: ${input.recordType as string}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function commitImportBatch(
|
||||
db: CommitDb,
|
||||
input: {
|
||||
importBatchId: string;
|
||||
allowTbdUnresolved?: boolean | undefined;
|
||||
importTbdProjects?: boolean | undefined;
|
||||
userId?: string | undefined;
|
||||
},
|
||||
) {
|
||||
const result = await commitDispoImportBatch(db, {
|
||||
importBatchId: input.importBatchId,
|
||||
...(input.allowTbdUnresolved !== undefined ? { allowTbdUnresolved: input.allowTbdUnresolved } : {}),
|
||||
...(input.importTbdProjects !== undefined ? { importTbdProjects: input.importTbdProjects } : {}),
|
||||
});
|
||||
|
||||
const counts = result as unknown as Record<string, unknown>;
|
||||
void createAuditEntry({
|
||||
db: db as AuditDb,
|
||||
entityType: "ImportBatch",
|
||||
entityId: input.importBatchId,
|
||||
entityName: input.importBatchId,
|
||||
action: "IMPORT",
|
||||
summary: `Committed import batch (${JSON.stringify(counts)})`,
|
||||
after: counts,
|
||||
source: "ui",
|
||||
...(input.userId !== undefined ? { userId: input.userId } : {}),
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user