import { createContext, DomainError } from "@tailor-platform/erp-kit/app"; import { createResolver, t } from "@tailor-platform/sdk"; import { getDB } from "@/generated/kysely-tailordb"; import { arModulesExport } from "@/modules"; /** * cancelAccountReceivableDocument — cancel a DRAFT or REGISTERED customer * invoice. * * Cancellation discards an invoice that has not yet been posted and moves it * DRAFT/REGISTERED -> CANCELLED. It never touches the general ledger — a POSTED * invoice must be corrected (correctAccountReceivableDocument), not cancelled. * When a REGISTERED invoice is cancelled the linked sales order's billing status * is recalculated in the same transaction. `id` is the AccountReceivableDocument * id. */ export default createResolver({ name: "cancelAccountReceivableDocument", operation: "mutation", input: { id: t.string().description("Account receivable document ID"), }, body: async (context) => { const ctx = createContext(context); const db = getDB("main-db"); return db .transaction() .execute(async (trx) => { const result = await arModulesExport.commands.cancelAccountReceivableDocument( trx, { id: context.input.id }, ctx, ); if (!result.ok) { switch (result.error.code) { case "ACCOUNT_RECEIVABLE_DOCUMENT_NOT_FOUND": throw new DomainError(`Account receivable document not found: ${context.input.id}`); case "ACCOUNT_RECEIVABLE_INVALID_DOCUMENT_STATUS": throw new DomainError( `Only DRAFT or REGISTERED invoices can be cancelled: ${context.input.id}`, ); case "ACCOUNT_RECEIVABLE_SALES_ORDER_BILLING_SYNC_FAILED": throw new DomainError( `Failed to sync sales order billing status: ${result.error.message}`, ); case "UNAUTHENTICATED": throw new DomainError("Authentication is required"); case "INSUFFICIENT_PERMISSION": throw new DomainError("You do not have permission to perform this action"); default: throw result.error satisfies never; } } return { id: result.value.accountReceivableDocument.id, status: result.value.accountReceivableDocument.status, }; }) .catch((err: unknown) => { if (err instanceof DomainError) throw err; throw new Error("Failed to cancel the account receivable document", { cause: err }); }); }, output: t .object({ id: t.string().description("Account receivable document ID"), status: t.string().description("New document status (CANCELLED)"), }) .description("CancelAccountReceivableDocument response"), });