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