import { ok, err } from "@tailor-platform/erp-kit/core"; import { unitLifecycle } from "../db/unit.lifecycle.generated"; import type { Transaction } from "../generated/kysely-tailordb"; import { CannotDeactivateReferenceUnitError, UnitNotFoundError } from "../lib/errors.generated"; export interface DeactivateUnitInput { unitId: string; } /** * Function: deactivateUnit * * Disables a unit of measure from being used in new product assignments * and quantity conversions while preserving all historical data. * Reference units cannot be deactivated. */ export async function run(db: Transaction, input: DeactivateUnitInput) { // 1. Find unit by ID const unit = await db .selectFrom("Unit") .selectAll() .where("id", "=", input.unitId) .forUpdate() .executeTakeFirst(); // 2. If not found, throw error if (!unit) { return err(new UnitNotFoundError(input.unitId)); } // 3. Check if unit is reference unit for its category const uoMCategory = await db .selectFrom("UoMCategory") .selectAll() .where("id", "=", unit.categoryId) .executeTakeFirst(); if (uoMCategory?.referenceUnitId === unit.id) { return err(new CannotDeactivateReferenceUnitError(input.unitId)); } // 4. If already inactive, return unit (idempotent) const nextStatus = unitLifecycle.tryTransition(unit.status, "deactivate"); if (!nextStatus) { return ok({ unit }); } // 5. Update status to INACTIVE const updatedUnit = await db .updateTable("Unit") .set({ status: nextStatus, }) .where("id", "=", input.unitId) .returningAll() .executeTakeFirstOrThrow(); // 6. Return updated unit return ok({ unit: updatedUnit }); }