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[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[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[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; }), };