import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/core"; import { workOrderLifecycle } from "../db/workOrder.lifecycle.generated"; import type { Transaction } from "../generated/kysely-tailordb"; import { WorkOrderNotFoundError, WorkOrderNotResumableError, ParentOrderNotExecutableError, } from "../lib/errors.generated"; const EXECUTABLE_ORDER_STATUSES = ["RELEASED", "IN_PROGRESS"] as const; export interface ResumeWorkOrderInput { id: string; } /** * Function: resumeWorkOrder * * Restarts a paused work order without losing the accumulated execution * history recorded before the interruption. Clears the pause reason. */ export async function run(db: Transaction, input: ResumeWorkOrderInput, _ctx: CommandContext) { const { id } = input; // 1. Fetch work order with lock const workOrder = await db .selectFrom("WorkOrder") .selectAll() .where("id", "=", id) .forUpdate() .executeTakeFirst(); if (!workOrder) { return err(new WorkOrderNotFoundError(id)); } // 2. Validate status is PAUSED const nextStatus = workOrderLifecycle.tryTransition(workOrder.status, "resume"); if (!nextStatus) { return err(new WorkOrderNotResumableError(id)); } // 3. Check parent production order is still execution-capable const parentOrder = await db .selectFrom("ProductionOrder") .selectAll() .where("id", "=", workOrder.productionOrderId) .forUpdate() .executeTakeFirst(); if ( !parentOrder || !EXECUTABLE_ORDER_STATUSES.includes( parentOrder.status as (typeof EXECUTABLE_ORDER_STATUSES)[number], ) ) { return err(new ParentOrderNotExecutableError(id)); } // 4. Record resume event and set IN_PROGRESS, clear pause reason const now = new Date(); const updatedWorkOrder = await db .updateTable("WorkOrder") .set({ status: nextStatus, pauseReason: null, }) .where("id", "=", id) .returningAll() .executeTakeFirstOrThrow(); // 5. Create RESUMED execution event await db .insertInto("WorkOrderExecutionEvent") .values({ workOrderId: id, eventType: "RESUMED", timestamp: now, quantity: null, timeValue: null, scrapValue: null, notes: null, }) .execute(); return ok({ workOrder: updatedWorkOrder }); }