import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { WorkerAlreadyExistsError, WorkerCodeTakenError } from "../lib/errors.generated"; export interface CreateWorkerInput { userId: string; workerCode: string; } export async function run>( db: Transaction, input: CreateWorkerInput & CF, _ctx: CommandContext, ) { const { userId, workerCode, ...customFields } = input; // NOTE: user-management (vendored erp-kit) exposes no `getUser` query, so there is no // injected query available to validate that `userId` refers to an existing User. Following // the vendored `approval` module's precedent (node_modules/@tailor-platform/erp-kit/src/modules/approval), // we do not invent a fictitious cross-module existence check here — referential integrity for // userId is enforced by the DB-level FK constraint set up via DB type injection in module.ts. const existingWorkerForUser = await db .selectFrom("Worker") .selectAll() .where("userId", "=", userId) .forUpdate() .executeTakeFirst(); if (existingWorkerForUser) { return err(new WorkerAlreadyExistsError(userId)); } const existingWorkerCode = await db .selectFrom("Worker") .selectAll() .where("workerCode", "=", workerCode) .forUpdate() .executeTakeFirst(); if (existingWorkerCode) { return err(new WorkerCodeTakenError(workerCode)); } const worker = await db .insertInto("Worker") .values({ // Host-defined custom fields first; the builtin columns always win. ...(customFields as Record), userId, workerCode, }) .returningAll() .executeTakeFirstOrThrow(); return ok({ worker }); }