diff --git a/packages/api/src/router/resource-mutations.ts b/packages/api/src/router/resource-mutations.ts index 952173d..dbfd9e7 100644 --- a/packages/api/src/router/resource-mutations.ts +++ b/packages/api/src/router/resource-mutations.ts @@ -1,4 +1,11 @@ -import { BlueprintTarget, CreateResourceSchema, PermissionKey, ResourceRoleSchema, UpdateResourceSchema, inferStateFromPostalCode } from "@capakraken/shared"; +import { + BlueprintTarget, + CreateResourceSchema, + PermissionKey, + ResourceRoleSchema, + UpdateResourceSchema, + inferStateFromPostalCode, +} from "@capakraken/shared"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; import { findUniqueOrThrow } from "../db/helpers.js"; @@ -31,7 +38,10 @@ export const resourceMutationProcedures = { const primaryCount = (input.roles ?? []).filter((role) => role.isPrimary).length; if (primaryCount > 1) { - throw new TRPCError({ code: "BAD_REQUEST", message: "A resource can have at most one primary role" }); + throw new TRPCError({ + code: "BAD_REQUEST", + message: "A resource can have at most one primary role", + }); } const resource = await ctx.db.$transaction(async (tx) => { @@ -47,7 +57,8 @@ export const resourceMutationProcedures = { chargeabilityTarget: input.chargeabilityTarget, availability: input.availability, skills: input.skills as unknown as import("@capakraken/db").Prisma.InputJsonValue, - dynamicFields: input.dynamicFields as unknown as import("@capakraken/db").Prisma.InputJsonValue, + dynamicFields: + input.dynamicFields as unknown as import("@capakraken/db").Prisma.InputJsonValue, blueprintId: input.blueprintId, portfolioUrl: input.portfolioUrl || undefined, roleId: input.roleId || undefined, @@ -60,14 +71,24 @@ export const resourceMutationProcedures = { ...(input.countryId !== undefined ? { countryId: input.countryId || null } : {}), ...(input.metroCityId !== undefined ? { metroCityId: input.metroCityId || null } : {}), ...(input.orgUnitId !== undefined ? { orgUnitId: input.orgUnitId || null } : {}), - ...(input.managementLevelGroupId !== undefined ? { managementLevelGroupId: input.managementLevelGroupId || null } : {}), - ...(input.managementLevelId !== undefined ? { managementLevelId: input.managementLevelId || null } : {}), + ...(input.managementLevelGroupId !== undefined + ? { managementLevelGroupId: input.managementLevelGroupId || null } + : {}), + ...(input.managementLevelId !== undefined + ? { managementLevelId: input.managementLevelId || null } + : {}), ...(input.resourceType !== undefined ? { resourceType: input.resourceType } : {}), - ...(input.chgResponsibility !== undefined ? { chgResponsibility: input.chgResponsibility } : {}), + ...(input.chgResponsibility !== undefined + ? { chgResponsibility: input.chgResponsibility } + : {}), ...(input.rolledOff !== undefined ? { rolledOff: input.rolledOff } : {}), ...(input.departed !== undefined ? { departed: input.departed } : {}), - ...(input.enterpriseId !== undefined ? { enterpriseId: input.enterpriseId || null } : {}), - ...(input.clientUnitId !== undefined ? { clientUnitId: input.clientUnitId || null } : {}), + ...(input.enterpriseId !== undefined + ? { enterpriseId: input.enterpriseId || null } + : {}), + ...(input.clientUnitId !== undefined + ? { clientUnitId: input.clientUnitId || null } + : {}), ...(input.fte !== undefined ? { fte: input.fte } : {}), resourceRoles: input.roles?.length ? { @@ -100,7 +121,12 @@ export const resourceMutationProcedures = { }), update: managerProcedure - .input(z.object({ id: z.string(), data: UpdateResourceSchema.extend({ roles: z.array(ResourceRoleSchema).optional() }) })) + .input( + z.object({ + id: z.string(), + data: UpdateResourceSchema.extend({ roles: z.array(ResourceRoleSchema).optional() }), + }), + ) .mutation(async ({ ctx, input }) => { requirePermission(ctx, PermissionKey.MANAGE_RESOURCES); const existing = await findUniqueOrThrow( @@ -109,7 +135,9 @@ export const resourceMutationProcedures = { ); const nextBlueprintId = input.data.blueprintId ?? existing.blueprintId ?? undefined; - const nextDynamicFields = (input.data.dynamicFields ?? existing.dynamicFields ?? {}) as Record; + const nextDynamicFields = (input.data.dynamicFields ?? + existing.dynamicFields ?? + {}) as Record; await assertBlueprintDynamicFields({ db: ctx.db, @@ -121,7 +149,10 @@ export const resourceMutationProcedures = { if (input.data.roles !== undefined) { const primaryCount = input.data.roles.filter((role) => role.isPrimary).length; if (primaryCount > 1) { - throw new TRPCError({ code: "BAD_REQUEST", message: "A resource can have at most one primary role" }); + throw new TRPCError({ + code: "BAD_REQUEST", + message: "A resource can have at most one primary role", + }); } } @@ -129,19 +160,42 @@ export const resourceMutationProcedures = { const result = await tx.resource.update({ where: { id: input.id }, data: { - ...(input.data.displayName !== undefined ? { displayName: input.data.displayName } : {}), + ...(input.data.displayName !== undefined + ? { displayName: input.data.displayName } + : {}), ...(input.data.email !== undefined ? { email: input.data.email } : {}), ...(input.data.chapter !== undefined ? { chapter: input.data.chapter } : {}), ...(input.data.lcrCents !== undefined ? { lcrCents: input.data.lcrCents } : {}), ...(input.data.ucrCents !== undefined ? { ucrCents: input.data.ucrCents } : {}), ...(input.data.currency !== undefined ? { currency: input.data.currency } : {}), - ...(input.data.chargeabilityTarget !== undefined ? { chargeabilityTarget: input.data.chargeabilityTarget } : {}), - ...(input.data.availability !== undefined ? { availability: input.data.availability as unknown as import("@capakraken/db").Prisma.InputJsonValue } : {}), - ...(input.data.skills !== undefined ? { skills: input.data.skills as unknown as import("@capakraken/db").Prisma.InputJsonValue } : {}), - ...(input.data.dynamicFields !== undefined ? { dynamicFields: input.data.dynamicFields as unknown as import("@capakraken/db").Prisma.InputJsonValue } : {}), - ...(input.data.blueprintId !== undefined ? { blueprintId: input.data.blueprintId } : {}), + ...(input.data.chargeabilityTarget !== undefined + ? { chargeabilityTarget: input.data.chargeabilityTarget } + : {}), + ...(input.data.availability !== undefined + ? { + availability: input.data + .availability as unknown as import("@capakraken/db").Prisma.InputJsonValue, + } + : {}), + ...(input.data.skills !== undefined + ? { + skills: input.data + .skills as unknown as import("@capakraken/db").Prisma.InputJsonValue, + } + : {}), + ...(input.data.dynamicFields !== undefined + ? { + dynamicFields: input.data + .dynamicFields as unknown as import("@capakraken/db").Prisma.InputJsonValue, + } + : {}), + ...(input.data.blueprintId !== undefined + ? { blueprintId: input.data.blueprintId } + : {}), ...(input.data.isActive !== undefined ? { isActive: input.data.isActive } : {}), - ...(input.data.portfolioUrl !== undefined ? { portfolioUrl: input.data.portfolioUrl || null } : {}), + ...(input.data.portfolioUrl !== undefined + ? { portfolioUrl: input.data.portfolioUrl || null } + : {}), ...(input.data.roleId !== undefined ? { roleId: input.data.roleId || null } : {}), ...(input.data.postalCode !== undefined ? { postalCode: input.data.postalCode } : {}), ...(input.data.postalCode && !input.data.federalState @@ -149,17 +203,35 @@ export const resourceMutationProcedures = { : input.data.federalState !== undefined ? { federalState: input.data.federalState } : {}), - ...(input.data.countryId !== undefined ? { countryId: input.data.countryId || null } : {}), - ...(input.data.metroCityId !== undefined ? { metroCityId: input.data.metroCityId || null } : {}), - ...(input.data.orgUnitId !== undefined ? { orgUnitId: input.data.orgUnitId || null } : {}), - ...(input.data.managementLevelGroupId !== undefined ? { managementLevelGroupId: input.data.managementLevelGroupId || null } : {}), - ...(input.data.managementLevelId !== undefined ? { managementLevelId: input.data.managementLevelId || null } : {}), - ...(input.data.resourceType !== undefined ? { resourceType: input.data.resourceType } : {}), - ...(input.data.chgResponsibility !== undefined ? { chgResponsibility: input.data.chgResponsibility } : {}), + ...(input.data.countryId !== undefined + ? { countryId: input.data.countryId || null } + : {}), + ...(input.data.metroCityId !== undefined + ? { metroCityId: input.data.metroCityId || null } + : {}), + ...(input.data.orgUnitId !== undefined + ? { orgUnitId: input.data.orgUnitId || null } + : {}), + ...(input.data.managementLevelGroupId !== undefined + ? { managementLevelGroupId: input.data.managementLevelGroupId || null } + : {}), + ...(input.data.managementLevelId !== undefined + ? { managementLevelId: input.data.managementLevelId || null } + : {}), + ...(input.data.resourceType !== undefined + ? { resourceType: input.data.resourceType } + : {}), + ...(input.data.chgResponsibility !== undefined + ? { chgResponsibility: input.data.chgResponsibility } + : {}), ...(input.data.rolledOff !== undefined ? { rolledOff: input.data.rolledOff } : {}), ...(input.data.departed !== undefined ? { departed: input.data.departed } : {}), - ...(input.data.enterpriseId !== undefined ? { enterpriseId: input.data.enterpriseId || null } : {}), - ...(input.data.clientUnitId !== undefined ? { clientUnitId: input.data.clientUnitId || null } : {}), + ...(input.data.enterpriseId !== undefined + ? { enterpriseId: input.data.enterpriseId || null } + : {}), + ...(input.data.clientUnitId !== undefined + ? { clientUnitId: input.data.clientUnitId || null } + : {}), ...(input.data.fte !== undefined ? { fte: input.data.fte } : {}), } as unknown as Parameters[0]["data"], include: { @@ -247,17 +319,20 @@ export const resourceMutationProcedures = { }), batchUpdateCustomFields: managerProcedure - .input(z.object({ - ids: z.array(z.string()).min(1).max(100), - fields: z.record(z.string(), z.unknown()), - })) + .input( + z.object({ + ids: z.array(z.string()).min(1).max(100), + fields: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()])), + }), + ) .mutation(async ({ ctx, input }) => { requirePermission(ctx, PermissionKey.MANAGE_RESOURCES); await ctx.db.$transaction(async (tx) => { await Promise.all( - input.ids.map((id) => - tx.$executeRaw` + input.ids.map( + (id) => + tx.$executeRaw` UPDATE "Resource" SET "dynamicFields" = "dynamicFields" || ${JSON.stringify(input.fields)}::jsonb WHERE id = ${id} @@ -270,7 +345,9 @@ export const resourceMutationProcedures = { entityType: "Resource", entityId: input.ids.join(","), action: "UPDATE", - changes: { after: { dynamicFields: input.fields, ids: input.ids } } as unknown as import("@capakraken/db").Prisma.InputJsonValue, + changes: { + after: { dynamicFields: input.fields, ids: input.ids }, + } as unknown as import("@capakraken/db").Prisma.InputJsonValue, }, }); }); @@ -300,7 +377,9 @@ export const resourceMutationProcedures = { entityId: input.id, action: "DELETE", userId: ctx.dbUser?.id, - changes: { before: resource } as unknown as import("@capakraken/db").Prisma.InputJsonValue, + changes: { + before: resource, + } as unknown as import("@capakraken/db").Prisma.InputJsonValue, }, }); });