import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/core"; import type { OrganizationModule } from "../../organization"; import type { AccountAccountType } from "../generated/enums"; import type { Transaction } from "../generated/kysely-tailordb"; import { CompanyNotFoundError, CompanyInactiveError, DuplicateAccountCodeError, NameRequiredError, InvalidAccountCodeError, } from "../lib/errors.generated"; export interface CreateAccountInput { companyId: string; code: string; name: string; accountType: AccountAccountType; } type OrganizationQueries = OrganizationModule["queries"]; /** * Function: createAccount * * Establishes a new ACTIVE GL account for a company. */ export async function run>( db: Transaction, input: CreateAccountInput & CF, ctx: CommandContext, organizationQueries: Pick, ) { const { companyId, code, name, accountType, ...customFields } = input; // 1. Validate name non-empty if (!name || name.trim() === "") { return err(new NameRequiredError(String(name))); } // 2. Validate account code is numeric if (!/^\d+$/.test(code)) { return err(new InvalidAccountCodeError(code)); } // 3. Look up company - must exist. const { company } = (await organizationQueries.getCompany(db, { id: companyId }, ctx)).value; if (!company) { return err(new CompanyNotFoundError(companyId)); } if (company.status !== "ACTIVE") { return err(new CompanyInactiveError(companyId)); } // 4. Check account code uniqueness within company const existingAccount = await db .selectFrom("Account") .selectAll() .where("companyId", "=", companyId) .where("code", "=", code) .forUpdate() .executeTakeFirst(); if (existingAccount) { return err(new DuplicateAccountCodeError(code)); } // 5. Insert account in ACTIVE status const account = await db .insertInto("Account") .values({ ...(customFields as Record), companyId, code, name, accountType, status: "ACTIVE", }) .returningAll() .executeTakeFirstOrThrow(); return ok({ account }); }