import { createContext, DomainError } from "@tailor-platform/erp-kit/app"; import { createResolver, t } from "@tailor-platform/sdk"; import { getDB } from "@/generated/kysely-tailordb"; import { coaModulesExport } from "@/modules"; /** * deactivateAccount — mark an ACTIVE GL account INACTIVE so it can no longer be * posted to (it stays on the chart of accounts for historical entries). The * native command rejects an account that is already inactive and one that still * carries open balances. `id` is the Account id. */ export default createResolver({ name: "deactivateAccount", operation: "mutation", input: { id: t.string().description("Account ID"), }, body: async (context) => { const ctx = createContext(context); const db = getDB("main-db"); return db .transaction() .execute(async (trx) => { const result = await coaModulesExport.commands.deactivateAccount( trx, { id: context.input.id }, ctx, ); if (!result.ok) { switch (result.error.code) { case "COA_MANAGEMENT_ACCOUNT_NOT_FOUND": throw new DomainError(`Account not found: ${context.input.id}`); case "COA_MANAGEMENT_INVALID_STATE_TRANSITION": throw new DomainError( `Only an ACTIVE account can be deactivated: ${context.input.id}`, ); case "COA_MANAGEMENT_OPEN_BALANCES_EXIST": throw new DomainError( `The account still has open balances and cannot be deactivated.`, ); 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.account.id, status: result.value.account.status }; }) .catch((err: unknown) => { if (err instanceof DomainError) throw err; throw new Error("Failed to deactivate the account", { cause: err }); }); }, output: t .object({ id: t.string().description("Account ID"), status: t.string().description("Account status (INACTIVE after deactivation)"), }) .description("Deactivated GL account"), });