import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import { transferOrderLifecycle } from "../db/transferOrder.lifecycle.generated"; import type { Transaction } from "../generated/kysely-tailordb"; import { isTransferOrderInTransitClear } from "../internal/transferOrderProgress"; import { InvalidStateTransitionError, TransferOrderInTransitError, TransferOrderNotFoundError, } from "../lib/errors.generated"; export interface CloseTransferOrderInput { id: string; } export async function run(db: Transaction, input: CloseTransferOrderInput, _ctx: CommandContext) { const existing = await db .selectFrom("TransferOrder") .selectAll() .where("id", "=", input.id) .forUpdate() .executeTakeFirst(); if (!existing) { return err(new TransferOrderNotFoundError(input.id)); } const nextStatus = transferOrderLifecycle.tryTransition(existing.status, "close"); if (!nextStatus) { return err(new InvalidStateTransitionError(input.id)); } const lines = await db .selectFrom("TransferOrderLine") .selectAll() .where("transferOrderId", "=", input.id) .execute(); if (!isTransferOrderInTransitClear(lines)) { return err(new TransferOrderInTransitError(input.id)); } const stockReservations = await db .updateTable("StockReservation") .set({ status: "CLOSED" }) .where("sourceType", "=", "TRANSFER_ORDER") .where("sourceId", "=", input.id) .where("status", "=", "OPEN") .returningAll() .execute(); const supplyPlans = await db .updateTable("InventorySupplyPlan") .set({ status: "CLOSED" }) .where("sourceType", "=", "TRANSFER_ORDER") .where("sourceId", "=", input.id) .where("status", "=", "OPEN") .returningAll() .execute(); const transferOrder = await db .updateTable("TransferOrder") .set({ status: nextStatus, closedAt: new Date() }) .where("id", "=", input.id) .returningAll() .executeTakeFirstOrThrow(); return ok({ transferOrder, stockReservations, supplyPlans }); }