import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { CashAccountInvalidError, CashAccountNotFoundError, CashCompanyNotFoundError, CashCurrencyNotFoundError, } from "../lib/errors.generated"; import type { CoaManagementQueries, OrganizationQueries, PrimitivesQueries } from "../module"; export interface CreateBankAccountInput { companyId: string; currencyId: string; cashAccountId: string; incomingClearingAccountId?: string; outgoingClearingAccountId?: string; bankName: string; accountNumberMasked: string; } export async function run = Record>( db: Transaction, input: CreateBankAccountInput & CF, ctx: CommandContext, organizationQueries: Pick, primitivesQueries: Pick, coaManagementQueries: Pick, ) { const { companyId, currencyId, cashAccountId, incomingClearingAccountId, outgoingClearingAccountId, bankName, accountNumberMasked, ...customFields } = input; const { company } = (await organizationQueries.getCompany(db, { id: companyId }, ctx)).value; if (!company) return err(new CashCompanyNotFoundError(companyId)); const { currency } = (await primitivesQueries.getCurrency(db, { id: currencyId }, ctx)).value; if (!currency) return err(new CashCurrencyNotFoundError(currencyId)); const accountIds = [cashAccountId, incomingClearingAccountId, outgoingClearingAccountId].filter( (id): id is string => id != null, ); for (const accountId of new Set(accountIds)) { const { account } = (await coaManagementQueries.getAccount(db, { id: accountId }, ctx)).value; if (!account) return err(new CashAccountNotFoundError(accountId)); if (account.companyId !== companyId || account.status !== "ACTIVE") { return err(new CashAccountInvalidError(accountId)); } } const bankAccount = await db .insertInto("BankAccount") .values({ ...(customFields as Record), companyId, currencyId, cashAccountId, incomingClearingAccountId: incomingClearingAccountId ?? null, outgoingClearingAccountId: outgoingClearingAccountId ?? null, bankName, accountNumberMasked, status: "ACTIVE", }) .returningAll() .executeTakeFirstOrThrow(); return ok({ bankAccount }); }