import { CreateUtilizationCategorySchema, UpdateUtilizationCategorySchema, } from "@capakraken/shared"; import { z } from "zod"; import { findUniqueOrThrow } from "../db/helpers.js"; import { createAuditEntry } from "../lib/audit.js"; import type { TRPCContext } from "../trpc.js"; import { assertUtilizationCategoryCodeAvailable, buildUtilizationCategoryCreateData, buildUtilizationCategoryListWhere, buildUtilizationCategoryUpdateData, unsetDefaultUtilizationCategory, } from "./utilization-category-support.js"; export const UtilizationCategoryListInputSchema = z .object({ isActive: z.boolean().optional(), }) .optional(); export const UtilizationCategoryByIdInputSchema = z.object({ id: z.string(), }); export const CreateUtilizationCategoryInputSchema = CreateUtilizationCategorySchema; export const UpdateUtilizationCategoryInputSchema = z.object({ id: z.string(), data: UpdateUtilizationCategorySchema, }); type UtilizationCategoryContext = Pick; export async function listUtilizationCategories( ctx: Pick, input: z.infer, ) { return ctx.db.utilizationCategory.findMany({ where: buildUtilizationCategoryListWhere(input ?? {}), orderBy: { sortOrder: "asc" }, include: { _count: { select: { projects: true } } }, }); } export async function getUtilizationCategoryById( ctx: Pick, input: z.infer, ) { return findUniqueOrThrow( ctx.db.utilizationCategory.findUnique({ where: { id: input.id }, include: { _count: { select: { projects: true } } }, }), "Utilization category", ); } export async function createUtilizationCategory( ctx: UtilizationCategoryContext, input: z.infer, ) { await assertUtilizationCategoryCodeAvailable(ctx.db, input.code); if (input.isDefault) { await unsetDefaultUtilizationCategory(ctx.db); } const created = await ctx.db.utilizationCategory.create({ data: buildUtilizationCategoryCreateData(input), }); void createAuditEntry({ db: ctx.db, entityType: "UtilizationCategory", entityId: created.id, entityName: created.name, action: "CREATE", ...(ctx.dbUser?.id ? { userId: ctx.dbUser.id } : {}), after: created as unknown as Record, source: "ui", }); return created; } export async function updateUtilizationCategory( ctx: UtilizationCategoryContext, input: z.infer, ) { const existing = await findUniqueOrThrow( ctx.db.utilizationCategory.findUnique({ where: { id: input.id } }), "Utilization category", ); if (input.data.code && input.data.code !== existing.code) { await assertUtilizationCategoryCodeAvailable(ctx.db, input.data.code, existing.id); } if (input.data.isDefault) { await unsetDefaultUtilizationCategory(ctx.db, input.id); } const before = existing as unknown as Record; const updated = await ctx.db.utilizationCategory.update({ where: { id: input.id }, data: buildUtilizationCategoryUpdateData(input.data), }); void createAuditEntry({ db: ctx.db, entityType: "UtilizationCategory", entityId: updated.id, entityName: updated.name, action: "UPDATE", ...(ctx.dbUser?.id ? { userId: ctx.dbUser.id } : {}), before, after: updated as unknown as Record, source: "ui", }); return updated; }