b41c1d2501
CI / Architecture Guardrails (push) Successful in 2m38s
CI / Assistant Split Regression (push) Successful in 3m33s
CI / Typecheck (push) Successful in 3m51s
CI / Lint (push) Successful in 5m2s
CI / E2E Tests (push) Has been cancelled
CI / Fresh-Linux Docker Deploy (push) Has been cancelled
CI / Release Images (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
rename(phase 1): CapaKraken → Nexus across code, UI, docs, CI (#61) Co-authored-by: Hartmut Nörenberg <hn@hartmut-noerenberg.com> Co-committed-by: Hartmut Nörenberg <hn@hartmut-noerenberg.com>
172 lines
5.1 KiB
TypeScript
172 lines
5.1 KiB
TypeScript
import {
|
|
approveEstimateVersion,
|
|
createEstimateRevision,
|
|
submitEstimateVersion,
|
|
} from "@nexus/application";
|
|
import type { Prisma } from "@nexus/db";
|
|
import {
|
|
ApproveEstimateVersionSchema,
|
|
CreateEstimateRevisionSchema,
|
|
PermissionKey,
|
|
SubmitEstimateVersionSchema,
|
|
} from "@nexus/shared";
|
|
import { managerProcedure, requirePermission } from "../trpc.js";
|
|
import { rethrowEstimateRouterError } from "./estimate-procedure-support.js";
|
|
|
|
export const estimateVersionWorkflowProcedures = {
|
|
submitVersion: managerProcedure
|
|
.input(SubmitEstimateVersionSchema)
|
|
.mutation(async ({ ctx, input }) => {
|
|
requirePermission(ctx, PermissionKey.MANAGE_PROJECTS);
|
|
|
|
let estimate;
|
|
try {
|
|
estimate = await ctx.db.$transaction(async (tx) => {
|
|
const submitted = await submitEstimateVersion(
|
|
tx as unknown as Parameters<typeof submitEstimateVersion>[0],
|
|
input,
|
|
);
|
|
|
|
await tx.auditLog.create({
|
|
data: {
|
|
entityType: "Estimate",
|
|
entityId: submitted.id,
|
|
action: "UPDATE",
|
|
...(ctx.dbUser?.id ? { userId: ctx.dbUser.id } : {}),
|
|
changes: {
|
|
after: {
|
|
id: submitted.id,
|
|
status: submitted.status,
|
|
submittedVersionId: submitted.versions.find(
|
|
(version) => version.status === "SUBMITTED",
|
|
)?.id,
|
|
},
|
|
} as Prisma.InputJsonValue,
|
|
},
|
|
});
|
|
|
|
return submitted;
|
|
});
|
|
} catch (error) {
|
|
rethrowEstimateRouterError(error, [
|
|
{
|
|
code: "NOT_FOUND",
|
|
messages: ["Estimate not found", "Estimate version not found"],
|
|
},
|
|
{
|
|
code: "PRECONDITION_FAILED",
|
|
messages: ["Estimate has no working version", "Only working versions can be submitted"],
|
|
},
|
|
]);
|
|
}
|
|
|
|
return estimate;
|
|
}),
|
|
|
|
approveVersion: managerProcedure
|
|
.input(ApproveEstimateVersionSchema)
|
|
.mutation(async ({ ctx, input }) => {
|
|
requirePermission(ctx, PermissionKey.MANAGE_PROJECTS);
|
|
|
|
let estimate;
|
|
try {
|
|
estimate = await ctx.db.$transaction(async (tx) => {
|
|
const approved = await approveEstimateVersion(
|
|
tx as unknown as Parameters<typeof approveEstimateVersion>[0],
|
|
input,
|
|
);
|
|
|
|
await tx.auditLog.create({
|
|
data: {
|
|
entityType: "Estimate",
|
|
entityId: approved.id,
|
|
action: "UPDATE",
|
|
...(ctx.dbUser?.id ? { userId: ctx.dbUser.id } : {}),
|
|
changes: {
|
|
after: {
|
|
id: approved.id,
|
|
status: approved.status,
|
|
approvedVersionId: approved.versions.find(
|
|
(version) => version.status === "APPROVED",
|
|
)?.id,
|
|
},
|
|
} as Prisma.InputJsonValue,
|
|
},
|
|
});
|
|
|
|
return approved;
|
|
});
|
|
} catch (error) {
|
|
rethrowEstimateRouterError(error, [
|
|
{
|
|
code: "NOT_FOUND",
|
|
messages: ["Estimate not found", "Estimate version not found"],
|
|
},
|
|
{
|
|
code: "PRECONDITION_FAILED",
|
|
messages: [
|
|
"Estimate has no submitted version",
|
|
"Only submitted versions can be approved",
|
|
],
|
|
},
|
|
]);
|
|
}
|
|
|
|
return estimate;
|
|
}),
|
|
|
|
createRevision: managerProcedure
|
|
.input(CreateEstimateRevisionSchema)
|
|
.mutation(async ({ ctx, input }) => {
|
|
requirePermission(ctx, PermissionKey.MANAGE_PROJECTS);
|
|
|
|
let estimate;
|
|
try {
|
|
estimate = await ctx.db.$transaction(async (tx) => {
|
|
const revision = await createEstimateRevision(
|
|
tx as unknown as Parameters<typeof createEstimateRevision>[0],
|
|
input,
|
|
);
|
|
|
|
await tx.auditLog.create({
|
|
data: {
|
|
entityType: "Estimate",
|
|
entityId: revision.id,
|
|
action: "UPDATE",
|
|
...(ctx.dbUser?.id ? { userId: ctx.dbUser.id } : {}),
|
|
changes: {
|
|
after: {
|
|
id: revision.id,
|
|
status: revision.status,
|
|
latestVersionNumber: revision.latestVersionNumber,
|
|
workingVersionId: revision.versions.find(
|
|
(version) => version.status === "WORKING",
|
|
)?.id,
|
|
},
|
|
} as Prisma.InputJsonValue,
|
|
},
|
|
});
|
|
|
|
return revision;
|
|
});
|
|
} catch (error) {
|
|
rethrowEstimateRouterError(error, [
|
|
{
|
|
code: "NOT_FOUND",
|
|
messages: ["Estimate not found", "Estimate version not found"],
|
|
},
|
|
{
|
|
code: "PRECONDITION_FAILED",
|
|
messages: [
|
|
"Estimate already has a working version",
|
|
"Estimate has no locked version to revise",
|
|
"Source version must be locked before creating a revision",
|
|
],
|
|
},
|
|
]);
|
|
}
|
|
|
|
return estimate;
|
|
}),
|
|
};
|