import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import { incomingPaymentLifecycle } from "../db/incomingPayment.lifecycle.generated"; import type { Transaction } from "../generated/kysely-tailordb"; import { IncomingPaymentInvalidStatusError, IncomingPaymentNotFoundError, } from "../lib/errors.generated"; export interface CancelIncomingPaymentInput { id: string; } /** Function: cancelIncomingPayment * Cancels a draft payment without deleting its settlement history. */ export async function run( db: Transaction, input: CancelIncomingPaymentInput, _ctx: CommandContext, ) { const incomingPayment = await db .selectFrom("IncomingPayment") .selectAll() .where("id", "=", input.id) .forUpdate() .executeTakeFirst(); if (!incomingPayment) return err(new IncomingPaymentNotFoundError(input.id)); const nextStatus = incomingPaymentLifecycle.tryTransition(incomingPayment.status, "cancel"); if (!nextStatus) return err(new IncomingPaymentInvalidStatusError(input.id)); const cancelledIncomingPayment = await db .updateTable("IncomingPayment") .set({ status: nextStatus, cancelledAt: new Date() }) .where("id", "=", input.id) .returningAll() .executeTakeFirstOrThrow(); return ok({ incomingPayment: cancelledIncomingPayment }); }