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, ItemNotFoundError, } from "../lib/errors.generated"; import type { ItemManagementQueries } from "../module"; export interface SubmitStockAdjustmentInput { id: string; } /** * Function: submitStockAdjustment * * Transitions a stock adjustment from DRAFT to SUBMITTED status. * No inventory changes occur at this stage; posting happens on confirm. */ export async function run( db: Transaction, input: SubmitStockAdjustmentInput, ctx: CommandContext, itemManagementQueries: Pick, ) { const adjustment = await db .selectFrom("StockAdjustment") .selectAll() .where("id", "=", input.id) .forUpdate() .executeTakeFirst(); if (!adjustment) { return err(new StockAdjustmentNotFoundError(input.id)); } const nextStatus = stockAdjustmentLifecycle.tryTransition(adjustment.status, "submit"); if (!nextStatus) { return err(new InvalidStatusError(input.id)); } const lines = await db .selectFrom("StockAdjustmentLine") .selectAll() .where("stockAdjustmentId", "=", input.id) .execute(); for (const line of lines) { const { item } = (await itemManagementQueries.getItem(db, { id: line.itemId }, ctx)).value; if (!item) { return err(new ItemNotFoundError(line.itemId)); } } const stockAdjustment = await db .updateTable("StockAdjustment") .set({ status: nextStatus }) .where("id", "=", input.id) .returningAll() .executeTakeFirstOrThrow(); return ok({ stockAdjustment }); }