import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/core"; import { stockAdjustmentLifecycle } from "../db/stockAdjustment.lifecycle.generated"; import type { Transaction } from "../generated/kysely-tailordb"; import { StockAdjustmentNotFoundError, InvalidStatusError } from "../lib/errors.generated"; export interface RejectStockAdjustmentInput { id: string; rejectionReason?: string; } /** * Function: rejectStockAdjustment * * Transitions a stock adjustment from SUBMITTED to REJECTED status. * An optional rejection reason can be provided. * No inventory or ledger changes occur. */ export async function run( db: Transaction, input: RejectStockAdjustmentInput, _ctx: CommandContext, ) { const { id, rejectionReason } = input; // 1. Fetch adjustment const adjustment = await db .selectFrom("StockAdjustment") .selectAll() .where("id", "=", id) .forUpdate() .executeTakeFirst(); if (!adjustment) { return err(new StockAdjustmentNotFoundError(id)); } // 2. Validate transition is allowed const nextStatus = stockAdjustmentLifecycle.tryTransition(adjustment.status, "reject"); if (!nextStatus) { return err(new InvalidStatusError(id)); } // 3. Transition to REJECTED const stockAdjustment = await db .updateTable("StockAdjustment") .set({ status: nextStatus, rejectionReason: rejectionReason ?? null, }) .where("id", "=", id) .returningAll() .executeTakeFirstOrThrow(); return ok({ stockAdjustment }); }