import type { Prisma } from "@capakraken/db"; import { CommercialTermsSchema, PermissionKey, UpdateCommercialTermsSchema } from "@capakraken/shared"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; import { controllerProcedure, managerProcedure, requirePermission } from "../trpc.js"; export const estimateCommercialProcedures = { getCommercialTerms: controllerProcedure .input(z.object({ estimateId: z.string(), versionId: z.string().optional() })) .query(async ({ ctx, input }) => { const estimate = await ctx.db.estimate.findUnique({ where: { id: input.estimateId }, include: { versions: { ...(input.versionId ? { where: { id: input.versionId } } : { orderBy: { versionNumber: "desc" as const }, take: 1 }), select: { id: true, commercialTerms: true }, }, }, }); if (!estimate || estimate.versions.length === 0) { throw new TRPCError({ code: "NOT_FOUND", message: "Estimate version not found" }); } const version = estimate.versions[0]!; const raw = version.commercialTerms; const terms = raw ? CommercialTermsSchema.parse(raw) : CommercialTermsSchema.parse({}); return { versionId: version.id, terms }; }), updateCommercialTerms: managerProcedure .input(UpdateCommercialTermsSchema) .mutation(async ({ ctx, input }) => { requirePermission(ctx, PermissionKey.MANAGE_PROJECTS); const estimate = await ctx.db.estimate.findUnique({ where: { id: input.estimateId }, include: { versions: { ...(input.versionId ? { where: { id: input.versionId } } : { where: { status: "WORKING" }, take: 1 }), select: { id: true, status: true }, }, }, }); if (!estimate || estimate.versions.length === 0) { throw new TRPCError({ code: "NOT_FOUND", message: "Estimate version not found" }); } const version = estimate.versions[0]!; if (version.status !== "WORKING") { throw new TRPCError({ code: "PRECONDITION_FAILED", message: "Commercial terms can only be edited on working versions", }); } const validated = CommercialTermsSchema.parse(input.terms); await ctx.db.$transaction(async (tx) => { await tx.estimateVersion.update({ where: { id: version.id }, data: { commercialTerms: validated as unknown as Prisma.InputJsonValue }, }); await tx.auditLog.create({ data: { entityType: "Estimate", entityId: estimate.id, action: "UPDATE", ...(ctx.dbUser?.id ? { userId: ctx.dbUser.id } : {}), changes: { field: "commercialTerms", after: validated, } as Prisma.InputJsonValue, }, }); }); return { versionId: version.id, terms: validated }; }), };