Skip to main content

Bank Account Service API

Manages bank accounts, balances, and cash transactions for funds. The service still throws Error instances for validation and existence checks; it will migrate to Result-based responses alongside the accounting portfolio work (see NEVERTHROW_MIGRATION_PLAN.md).

Migration Tip: During legacy fund transitions, coordinate changes through the Fund Migration Coordinator to revalidate routing numbers and balances before reactivation.

Location: worker/services/bank-account/service.ts

Dependencies

  • BankAccountRepository – persistence for accounts and transactions
  • Optional FundService – validates fund ownership (returns Result downstream)
  • Optional IAccountingService – mirrors ledger accounts on create

Bank Account Management

createBankAccount(data: CreateBankAccountRequest): Promise<BankAccountEntity> : Performs extensive validation (required fields, currency, interest range, per-fund uniqueness). Uses FundService.getFundById to ensure the fund exists and throws when the Result is an error.

getBankAccountById(id: string): Promise<BankAccountEntity | null> getBankAccountByAccountNumber(accountNumber: string, fundId: string): Promise<BankAccountEntity | null> getBankAccountsByFund(fundId: string): Promise<BankAccountEntity[]> getActiveBankAccounts(fundId: string): Promise<BankAccountEntity[]> : Query helpers that return nullable or array results directly from the repository.

upsertBankAccountForMigration(command: BankAccountMigrationUpsertCommand): Promise<BankAccountEntity> : Validates migration payloads, enforces fund ownership, and throws when invariants fail.

updateBankAccount(id: string, data: UpdateBankAccountRequest): Promise<BankAccountEntity> deactivateBankAccount(id: string): Promise<void> deleteBankAccount(id: string): Promise<void> : Ensure the account exists before mutating; throw descriptive errors otherwise.

Balances

updateBankAccountBalance(id: string, data: UpdateBankAccountBalanceRequest): Promise<void> getBankAccountBalance(id: string): Promise<{ amount: number }> calculateInterest(accountId: string): Promise<{ amount: number }> : Fetch the account first, throw when missing, and return/update balance information.

Transactions

createBankTransaction(data: CreateBankTransactionRequest): Promise<BankTransactionEntity> getBankTransactionById(id: string): Promise<BankTransactionEntity | null> getBankTransactions(accountId: string): Promise<BankTransactionEntity[]> markTransactionAsCleared(id: string): Promise<void> : Perform existence checks and throw meaningful errors when the account or transaction cannot be found.

Migration Notes

  • Callers should continue wrapping the service in try/catch blocks and convert thrown errors into domain errors at the boundary (for example, inside tRPC routers).
  • Once the neverthrow migration reaches the banking vertical, these methods will return Result objects and the validation logic will use shared error helpers.

Last Validated: 2025-11-10 against commit 0342a62e