import { createContext, DomainError } from "@tailor-platform/erp-kit/app"; import { createResolver, t } from "@tailor-platform/sdk"; import { getDB } from "@/generated/kysely-tailordb"; import { finModulesExport } from "@/modules"; /** * reverseJournalEntry — reverse a POSTED journal entry. * * Thin wrapper over the native `reverseJournalEntry`. Creates a new POSTED entry * whose debits/credits mirror the original (the only correction mechanism for a * posted entry). The original stays POSTED for traceability. The reversal posts * to the original period unless `reversalPeriodId` is given, and that target * period must be OPEN. */ export default createResolver({ name: "reverseJournalEntry", operation: "mutation", input: { id: t.string().description("Original (POSTED) journal entry ID"), reversalPeriodId: t .string({ optional: true }) .description("Accounting period for the reversal; defaults to the original entry's period"), }, body: async (context) => { const ctx = createContext(context); const db = getDB("main-db"); return db .transaction() .execute(async (trx) => { const result = await finModulesExport.commands.reverseJournalEntry( trx, { id: context.input.id, reversalPeriodId: context.input.reversalPeriodId ?? undefined, }, ctx, ); if (!result.ok) { switch (result.error.code) { case "FINANCIAL_ACCOUNTING_JOURNAL_ENTRY_NOT_FOUND": throw new DomainError(`Journal entry not found: ${context.input.id}`); case "FINANCIAL_ACCOUNTING_INVALID_STATUS_FOR_REVERSAL": throw new DomainError("Only a POSTED journal entry can be reversed."); case "FINANCIAL_ACCOUNTING_ALREADY_REVERSED": throw new DomainError("This journal entry has already been reversed."); case "FINANCIAL_ACCOUNTING_INVALID_PERIOD_STATUS": throw new DomainError("The reversal's accounting period is not OPEN."); 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.reversalEntry.id, status: result.value.reversalEntry.status, originalId: result.value.originalEntry.id, }; }) .catch((err: unknown) => { if (err instanceof DomainError) throw err; throw new Error("Failed to reverse the journal entry", { cause: err }); }); }, output: t .object({ id: t.string().description("Reversal journal entry ID"), status: t.string().description("Reversal document status (POSTED)"), originalId: t.string().description("The original (reversed) journal entry ID"), }) .description("ReverseJournalEntry response"), });