---
title: Provider bank account retrieval
summary: Retrieves the set of non-deleted bank accounts associated with a provider's payment authorizations, and decrypts/masks individual bank account fields on demand.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Business.Provider.PaymentPreference
reference_type: package
operation_id: OP-PP-06
trigger: Caller calls clsProviderBankAccountCollection.GetProviderBankAccounts for a provider, then reads properties on the returned clsProviderBankAccount items
---

# Provider bank account retrieval

`clsProviderBankAccountCollection.GetProviderBankAccounts` finds every bank account linked to a provider through that provider's locations' payment authorizations, excluding deleted accounts. Each returned `clsProviderBankAccount` is a thin wrapper that only carries a `BankAccountSeqNum`; its nickname, routing number, account number, and masked account number are resolved lazily, one property access at a time, from the shared `clsBankAccount` object. Both the collection query and the per-account field resolution are documented together because the second only exists to serve callers of the first.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-PP-06 |
| **Trigger** | `clsProviderBankAccountCollection.GetProviderBankAccounts(dpi, providerID)` |
| **Inputs** | `ProviderSeqNum` |
| **Outputs** | Populated `clsProviderBankAccountCollection` of `clsProviderBankAccount` (sequence number only); decrypted/masked field values on subsequent property access |
| **Primary components** | `clsProviderBankAccountCollection.GetProviderBankAccounts`, `clsProviderBankAccount.BankAccountNickName`, `clsProviderBankAccount.BankRoutingNumber`, `clsProviderBankAccount.BankAccountNumber`, `clsProviderBankAccount.MaskedBankAccountNumber`, `clsProviderBankAccount.BankAccount` |
| **Entry point** | `Business\SAIF.Business.Provider.PaymentPreference\clsProviderBankAccounts.vb` |

## Steps

1. **Query candidate accounts.** `GetProviderBankAccounts(dpi, providerID)` selects `BANK_ACCOUNT_SEQ_NUM` from `BANK_ACCOUNT` where the account is not status `DELET` ([BR-14](../business-rules.md#br-14-bank-account-status-delet-is-excluded-from-all-bank-account-retrievals-for-a-provider)) and its sequence number appears in `PAYMENT_AUTHORIZATION` rows whose `customer_id` matches one of the provider's location sequence numbers ([SQL-004](../sql/SQL-004-select-provider-bank-accounts-by-provider.md), [BANK_ACCOUNT](../database-tables.md#bank_account), [PAYMENT_AUTHORIZATION](../database-tables.md#payment_authorization), [PROVIDER_LOCATION](../database-tables.md#provider_location)).
   - The query does not filter on `revoke_date is null` — a commented-out line in source shows this filter was considered and removed, so bank accounts tied to a revoked payment authorization are still returned by this query.*
2. **Load and mark each row.** Each matched row is loaded into a `clsProviderBankAccount` carrying only `BankAccountSeqNum`, and the object is marked Old on load — there is no create/update/delete path on this class; it is read-only.
3. **Resolve the underlying bank account on demand.** The private `BankAccount` property calls `clsBankAccount.GetBankAccount(MyCriteria.DataPortalInfo, BankAccountSeqNum)` every time it is accessed — it is not cached on the object. Each of the four public properties below independently triggers this call:
   - `BankAccountNickName` returns `BankAccount.BankAccountNickName` unmodified.
   - `BankRoutingNumber` returns `SAIF.Security.clsSecureEncrypt.DecryptString(BankAccount.BankRoutingNumber)` — the routing number is decrypted from its stored encrypted form before being returned.
   - `BankAccountNumber` returns `SAIF.Security.clsSecureEncrypt.DecryptString(BankAccount.BankAccountNumber)` — likewise decrypted.
   - `MaskedBankAccountNumber` returns `BankAccount.MaskedBankAccountNumber` — pre-masked by the underlying object, not decrypted.

   > **Origin**: `clsBankAccount` and its `GetBankAccount`/masking logic are implemented in `SAIF.Business.Payment.EFT` and executed on behalf of this operation. That library is documented in the previous format, so no per-operation page exists; see [Bank account management](../../saif-business-payment-eft/operations/bank-account-management.md) in the `SAIF.Business.Payment.EFT` documentation set. Decryption itself is performed by `SAIF.Security.clsSecureEncrypt`, delivered via the local `SAIFEncrypt.dll` per this library's dependency documentation.

## Process flow

```mermaid
flowchart TD
	Start([Caller requests provider bank accounts]) --> Query[Select BANK_ACCOUNT_SEQ_NUM<br>where status <> DELET and linked via<br>PAYMENT_AUTHORIZATION to a provider location]
	Query --> Load[Load each row as clsProviderBankAccount,<br>MarkOld]
	Load --> Collection([Populated clsProviderBankAccountCollection])
	Collection --> Access{Caller reads a field?}
	Access -->|BankAccountNickName| Fetch1[GetBankAccount lookup] --> Nick([Return nickname])
	Access -->|BankRoutingNumber| Fetch2[GetBankAccount lookup] --> Decrypt1[DecryptString] --> Routing([Return routing number])
	Access -->|BankAccountNumber| Fetch3[GetBankAccount lookup] --> Decrypt2[DecryptString] --> AcctNum([Return account number])
	Access -->|MaskedBankAccountNumber| Fetch4[GetBankAccount lookup] --> Masked([Return masked number])
```

## Failure and edge-case behavior

- Each of the four field properties calls `clsBankAccount.GetBankAccount` independently and without caching; reading all four properties for the same object issues four separate underlying lookups rather than one, a potential N+1-style performance cost when iterating a large collection.*
- The class's `Criteria.CreateSQL`/`RetrieveSQL`/`InsertSQL`/`UpdateSQL`/`DeleteSQL` properties all throw `ApplicationException(InvalidSQLProperty)` when accessed. Since `clsProviderBankAccount` is only ever populated via `Load()` from the collection's inline SQL (never through the standard DataPortal Fetch/BeforeRetrieve/Create/Update/Delete path in normal use), `BeforeRetrieve`/`AfterRetrieve` on the individual object and all of these criteria SQL properties are effectively unreachable in the traced code paths.*
- Because the `DELET` status filter is the only exclusion applied, a bank account whose payment authorization has been revoked (see [EFT payment location assignment](eft-payment-location-assignment.md)) can still be returned by this query and have its fields resolved normally.*

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming
> conventions, or contextual evidence where direct confirmation was not available
> in source artifacts.

## Sources
- `Business\SAIF.Business.Provider.PaymentPreference\clsProviderBankAccounts.vb`
