import { ok, err } from "@tailor-platform/erp-kit/core"; import { departmentLifecycle } from "../db/department.lifecycle.generated"; import type { Transaction } from "../generated/kysely-tailordb"; import { DepartmentNotFoundError, InvalidStateError, HasActiveChildrenError, } from "../lib/errors.generated"; export interface DeactivateDepartmentInput { departmentId: string; } /** * Function: deactivateDepartment * * Deactivates a department, preventing it from being used in new assignments. * Fails if the department has active sub-departments. */ export async function run(db: Transaction, input: DeactivateDepartmentInput) { const { departmentId } = input; // 1. Find department const existing = await db .selectFrom("Department") .selectAll() .where("id", "=", departmentId) .forUpdate() .executeTakeFirst(); if (!existing) { return err(new DepartmentNotFoundError(departmentId)); } // 2. Check status is ACTIVE const nextStatus = departmentLifecycle.tryTransition(existing.status, "deactivate"); if (!nextStatus) { return err(new InvalidStateError(departmentId)); } // 3. Check for active sub-departments const activeChild = await db .selectFrom("Department") .selectAll() .where("parentDepartmentId", "=", departmentId) .where("status", "=", "ACTIVE") .executeTakeFirst(); if (activeChild) { return err(new HasActiveChildrenError(departmentId)); } // 4. Set status INACTIVE const department = await db .updateTable("Department") .set({ status: nextStatus, }) .where("id", "=", departmentId) .returningAll() .executeTakeFirstOrThrow(); return ok({ department }); }