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"; // The five GL account classes coa-management supports. const ACCOUNT_TYPES = ["ASSET", "LIABILITY", "EQUITY", "REVENUE", "EXPENSE"] as const; type AccountType = (typeof ACCOUNT_TYPES)[number]; /** * updateAccount — edit a GL account's code, name, or class. * * A partial patch: only the provided fields change. The native command * re-validates a changed code (well-formed and unique within the company) and a * non-empty name. Account status is NOT edited here — it is managed by * deactivateAccount / reactivateAccount. `id` is the Account id. */ export default createResolver({ name: "updateAccount", operation: "mutation", input: { id: t.string().description("Account ID"), code: t .string({ optional: true }) .description("New GL account code, unique within the company (e.g. 1200)"), name: t.string({ optional: true }).description("New account name"), accountType: t .string({ optional: true }) .description(`New account class: ${ACCOUNT_TYPES.join(" | ")}`), }, body: async (context) => { const ctx = createContext(context); const db = getDB("main-db"); let accountType: AccountType | undefined; if (context.input.accountType !== undefined) { if (!ACCOUNT_TYPES.includes(context.input.accountType as AccountType)) { throw new DomainError( `Invalid accountType: ${context.input.accountType}. Expected one of ${ACCOUNT_TYPES.join(", ")}.`, ); } accountType = context.input.accountType as AccountType; } return db .transaction() .execute(async (trx) => { const result = await coaModulesExport.commands.updateAccount( trx, { id: context.input.id, code: context.input.code ?? undefined, name: context.input.name ?? undefined, accountType, }, 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_NAME_REQUIRED": throw new DomainError("Account name is required."); case "COA_MANAGEMENT_INVALID_ACCOUNT_CODE": throw new DomainError(`Invalid account code: ${context.input.code}.`); case "COA_MANAGEMENT_DUPLICATE_ACCOUNT_CODE": throw new DomainError( `An account with code ${context.input.code} already exists in this company.`, ); 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, code: result.value.account.code }; }) .catch((err: unknown) => { if (err instanceof DomainError) throw err; throw new Error("Failed to update the account", { cause: err }); }); }, output: t .object({ id: t.string().description("Updated account ID"), code: t.string().description("Account code"), }) .description("Updated GL account"), });