206 lines
6.7 KiB
TypeScript
206 lines
6.7 KiB
TypeScript
import type { Prisma } from "@capakraken/db";
|
|
import {
|
|
CreateRateCardLineSchema,
|
|
CreateRateCardSchema,
|
|
UpdateRateCardLineSchema,
|
|
UpdateRateCardSchema,
|
|
} from "@capakraken/shared";
|
|
import { z } from "zod";
|
|
|
|
type RateCardListInput = {
|
|
isActive?: boolean | undefined;
|
|
search?: string | undefined;
|
|
clientId?: string | undefined;
|
|
effectiveAt?: Date | undefined;
|
|
};
|
|
|
|
type CreateRateCardInput = z.infer<typeof CreateRateCardSchema>;
|
|
type CreateRateCardLineInput = z.infer<typeof CreateRateCardLineSchema>;
|
|
type UpdateRateCardInput = z.infer<typeof UpdateRateCardSchema>;
|
|
type UpdateRateCardLineInput = z.infer<typeof UpdateRateCardLineSchema>;
|
|
|
|
export const rateCardSummaryInclude = {
|
|
_count: { select: { lines: true } },
|
|
client: { select: { id: true, name: true, code: true } },
|
|
} as const;
|
|
|
|
export const rateCardLineOrderBy: Prisma.RateCardLineOrderByWithRelationInput[] = [
|
|
{ chapter: "asc" },
|
|
{ seniority: "asc" },
|
|
{ createdAt: "asc" },
|
|
];
|
|
|
|
export const rateCardDetailInclude = {
|
|
client: { select: { id: true, name: true, code: true } },
|
|
lines: {
|
|
select: {
|
|
id: true,
|
|
rateCardId: true,
|
|
roleId: true,
|
|
chapter: true,
|
|
seniority: true,
|
|
location: true,
|
|
workType: true,
|
|
serviceGroup: true,
|
|
costRateCents: true,
|
|
billRateCents: true,
|
|
machineRateCents: true,
|
|
attributes: true,
|
|
role: { select: { id: true, name: true } },
|
|
},
|
|
orderBy: rateCardLineOrderBy,
|
|
},
|
|
} as const;
|
|
|
|
export const rateCardCreateInclude = {
|
|
lines: {
|
|
select: rateCardDetailInclude.lines.select,
|
|
},
|
|
} as const;
|
|
|
|
function buildRateCardLineCoreData(
|
|
line: CreateRateCardLineInput,
|
|
) {
|
|
return {
|
|
...(line.roleId !== undefined ? { roleId: line.roleId } : {}),
|
|
...(line.chapter !== undefined ? { chapter: line.chapter } : {}),
|
|
...(line.location !== undefined ? { location: line.location } : {}),
|
|
...(line.seniority !== undefined ? { seniority: line.seniority } : {}),
|
|
...(line.workType !== undefined ? { workType: line.workType } : {}),
|
|
...(line.serviceGroup !== undefined ? { serviceGroup: line.serviceGroup } : {}),
|
|
costRateCents: line.costRateCents,
|
|
...(line.billRateCents !== undefined ? { billRateCents: line.billRateCents } : {}),
|
|
...(line.machineRateCents !== undefined ? { machineRateCents: line.machineRateCents } : {}),
|
|
attributes: line.attributes as Prisma.InputJsonValue,
|
|
};
|
|
}
|
|
|
|
export function buildRateCardListWhere(
|
|
input?: RateCardListInput,
|
|
): Prisma.RateCardWhereInput {
|
|
return {
|
|
...(input?.isActive !== undefined ? { isActive: input.isActive } : {}),
|
|
...(input?.clientId !== undefined ? { clientId: input.clientId } : {}),
|
|
...(input?.search
|
|
? { name: { contains: input.search, mode: "insensitive" } }
|
|
: {}),
|
|
...(input?.effectiveAt
|
|
? {
|
|
OR: [
|
|
{ effectiveFrom: null },
|
|
{ effectiveFrom: { lte: input.effectiveAt } },
|
|
],
|
|
AND: [
|
|
{
|
|
OR: [
|
|
{ effectiveTo: null },
|
|
{ effectiveTo: { gte: input.effectiveAt } },
|
|
],
|
|
},
|
|
],
|
|
}
|
|
: {}),
|
|
};
|
|
}
|
|
|
|
export function buildRateCardCreateData(
|
|
input: CreateRateCardInput,
|
|
): Prisma.RateCardUncheckedCreateInput {
|
|
const { lines, ...cardData } = input;
|
|
|
|
return {
|
|
name: cardData.name,
|
|
currency: cardData.currency,
|
|
...(cardData.effectiveFrom !== undefined ? { effectiveFrom: cardData.effectiveFrom } : {}),
|
|
...(cardData.effectiveTo !== undefined ? { effectiveTo: cardData.effectiveTo } : {}),
|
|
...(cardData.source !== undefined ? { source: cardData.source } : {}),
|
|
...(cardData.clientId !== undefined ? { clientId: cardData.clientId } : {}),
|
|
lines: {
|
|
create: lines.map((line) => buildRateCardNestedLineCreateData(line)),
|
|
},
|
|
} as Prisma.RateCardUncheckedCreateInput;
|
|
}
|
|
|
|
export function buildRateCardUpdateData(
|
|
input: UpdateRateCardInput,
|
|
): Prisma.RateCardUncheckedUpdateInput {
|
|
return {
|
|
...(input.name !== undefined ? { name: input.name } : {}),
|
|
...(input.currency !== undefined ? { currency: input.currency } : {}),
|
|
...(input.effectiveFrom !== undefined ? { effectiveFrom: input.effectiveFrom } : {}),
|
|
...(input.effectiveTo !== undefined ? { effectiveTo: input.effectiveTo } : {}),
|
|
...(input.source !== undefined ? { source: input.source } : {}),
|
|
...(input.clientId !== undefined ? { clientId: input.clientId } : {}),
|
|
...(input.isActive !== undefined ? { isActive: input.isActive } : {}),
|
|
};
|
|
}
|
|
|
|
export function buildRateCardNestedLineCreateData(
|
|
line: CreateRateCardLineInput,
|
|
): Prisma.RateCardLineUncheckedCreateWithoutRateCardInput {
|
|
return buildRateCardLineCoreData(line) as Prisma.RateCardLineUncheckedCreateWithoutRateCardInput;
|
|
}
|
|
|
|
export function buildRateCardLineCreateData(
|
|
rateCardId: string,
|
|
line: CreateRateCardLineInput,
|
|
): Prisma.RateCardLineUncheckedCreateInput {
|
|
return {
|
|
rateCardId,
|
|
...buildRateCardLineCoreData(line),
|
|
} as Prisma.RateCardLineUncheckedCreateInput;
|
|
}
|
|
|
|
export function buildRateCardLineUpdateData(
|
|
input: UpdateRateCardLineInput,
|
|
): Prisma.RateCardLineUpdateInput {
|
|
const updateData: Prisma.RateCardLineUpdateInput = {};
|
|
|
|
if (input.roleId !== undefined) {
|
|
updateData.role = input.roleId
|
|
? { connect: { id: input.roleId } }
|
|
: { disconnect: true };
|
|
}
|
|
if (input.chapter !== undefined) updateData.chapter = input.chapter;
|
|
if (input.location !== undefined) updateData.location = input.location;
|
|
if (input.seniority !== undefined) updateData.seniority = input.seniority;
|
|
if (input.workType !== undefined) updateData.workType = input.workType;
|
|
if (input.serviceGroup !== undefined) updateData.serviceGroup = input.serviceGroup;
|
|
if (input.costRateCents !== undefined) updateData.costRateCents = input.costRateCents;
|
|
if (input.billRateCents !== undefined) updateData.billRateCents = input.billRateCents;
|
|
if (input.machineRateCents !== undefined) updateData.machineRateCents = input.machineRateCents;
|
|
if (input.attributes !== undefined) updateData.attributes = input.attributes as Prisma.InputJsonValue;
|
|
|
|
return updateData;
|
|
}
|
|
|
|
export function buildRateCardCreateAuditAfter(
|
|
input: Pick<CreateRateCardInput, "name" | "currency" | "lines">,
|
|
) {
|
|
return {
|
|
name: input.name,
|
|
currency: input.currency,
|
|
lineCount: input.lines.length,
|
|
};
|
|
}
|
|
|
|
export function buildRateCardLineCreateAuditAfter(
|
|
input: {
|
|
rateCardId: string;
|
|
line: Pick<CreateRateCardLineInput, "costRateCents" | "billRateCents" | "chapter">;
|
|
},
|
|
) {
|
|
return {
|
|
rateCardId: input.rateCardId,
|
|
costRateCents: input.line.costRateCents,
|
|
billRateCents: input.line.billRateCents,
|
|
chapter: input.line.chapter ?? null,
|
|
};
|
|
}
|
|
|
|
export function buildRateCardReplaceLinesAuditAfter(
|
|
replacedLineCount: number,
|
|
) {
|
|
return { replacedLineCount };
|
|
}
|