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 (returnsResultdownstream) - 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/catchblocks 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
Resultobjects and the validation logic will use shared error helpers.
Last Validated: 2025-11-10 against commit
0342a62e