import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { CompanyNotFoundError, InvalidEmploymentTypeReferenceError, InvalidWorkRegimeReferenceError, WorkerNotFoundError, EffectiveDateOverlapsExistingGenerationError, } from "../lib/errors.generated"; import type { OrganizationQueries } from "../module"; export interface CreateWorkerEmploymentInput { workerId: string; companyId: string; hireDate: Date; /** EmploymentType catalog id; must be an ACTIVE entry in the employment's company. */ employmentTypeId: string; /** WorkRegime catalog id; must be an ACTIVE entry in the employment's company. */ workRegimeId: string; } /** * Function: createWorkerEmployment * Description: Opens an employment relationship for a Worker at an * organization Company, creating the initial effective-dated generation with * effectiveStart = hireDate and effectiveEnd = null. */ export async function run>( db: Transaction, input: CreateWorkerEmploymentInput & CF, ctx: CommandContext, organizationQueries: Pick, ) { const { workerId, companyId, hireDate, employmentTypeId, workRegimeId, ...customFields } = input; const worker = await db .selectFrom("Worker") .selectAll() .where("id", "=", workerId) .executeTakeFirst(); if (!worker) { return err(new WorkerNotFoundError(workerId)); } const { company } = (await organizationQueries.getCompany(db, { id: companyId }, ctx)).value; if (!company) { return err(new CompanyNotFoundError(companyId)); } // The referenced catalog entries must exist, belong to the same company, and be ACTIVE. const employmentType = await db .selectFrom("EmploymentType") .selectAll() .where("id", "=", employmentTypeId) .executeTakeFirst(); if ( !employmentType || employmentType.companyId !== companyId || employmentType.status !== "ACTIVE" ) { return err(new InvalidEmploymentTypeReferenceError(employmentTypeId)); } const workRegime = await db .selectFrom("WorkRegime") .selectAll() .where("id", "=", workRegimeId) .executeTakeFirst(); if (!workRegime || workRegime.companyId !== companyId || workRegime.status !== "ACTIVE") { return err(new InvalidWorkRegimeReferenceError(workRegimeId)); } const openGeneration = await db .selectFrom("WorkerEmployment") .select("id") .where("workerId", "=", workerId) .where("companyId", "=", companyId) .where("effectiveEnd", "is", null) .executeTakeFirst(); if (openGeneration) { return err(new EffectiveDateOverlapsExistingGenerationError(workerId)); } const id = crypto.randomUUID(); const workerEmployment = await db .insertInto("WorkerEmployment") .values({ ...(customFields as Record), id, workerId, companyId, employmentTypeId, workRegimeId, hireDate, terminationDate: null, effectiveStart: hireDate, effectiveEnd: null, versionOf: id, }) .returningAll() .executeTakeFirstOrThrow(); return ok({ workerEmployment }); }