Bank account management¶
A clsBankAccount represents one payee's bank-account record — routing number, account number, account type, and status — and implements the IBankAccount contract consumed by SAIF.Business.Payment. Every EFT authorization and payment preference in this library ultimately points at one clsBankAccount. A related, smaller object, clsBankAccountTransfer, links a bank account to a US Bank online-banking session (US_BANK_USER_SEQ_NUM) once the account has been transferred/enrolled at US Bank.
| Field | Value |
|---|---|
| Operation ID | OP-EFT-01 |
| Trigger | Caller calls clsBankAccount.NewBankAccount to start a new account, or GetBankAccount/GetBankAccounts to retrieve one or more existing accounts by ID or create user; edits properties and calls Save() |
| Inputs | Bank routing number, account number, account type/status/data-source codes, business/consumer code, nickname, holder/owner name; for transfer, a US_BANK_USER_SEQ_NUM |
| Outputs | Persisted/updated BANK_ACCOUNT row with encrypted routing and account numbers; soft-deleted (status = DELETED) or, if PurgeRecord is set, hard-deleted row; persisted BANK_ACCOUNT_TRANSFER link row |
| Primary components | clsBankAccount.BeforeCreate/AfterCreate, BeforeInsert/AfterInsert, BeforeRetrieve/AfterRetrieve, BeforeUpdate/AfterUpdate, BeforeDelete/AfterDelete, AddBusinessRules; clsBankAccountCollection; clsBankAccountTransfer |
| Entry point | Business\SAIF.Business.Payment.EFT\clsBankAccount.vb |
Steps¶
- Obtain the next bank-account sequence number.
NewBankAccounttriggersBeforeCreate/AfterCreate, which executesSELECT BANK_ACCOUNT_seq.NEXTVAL FROM DUALas a scalar request (SQL-001, DUAL) and stores the result asBankAccountID; the create user is stamped from the data-portal info. - Caller populates account fields. Routing number and account number setters encrypt the incoming value via
SAIF.Security.clsSecureEncrypt.EncryptStringbefore storing it, and only re-encrypt/mark dirty if the decrypted stored value differs from the new value; account type, status, data-source, business/consumer code, nickname, and owner name are set directly. - Validate before save.
IsValid/CheckRulesruns the registered business rules: - Required-field rules: non-zero
BankAccountID, non-blank account number, bank name, holder name, business/consumer code, data-source code, status code, owner name, create IP address, create user, and a required create date (BR-EFT-05 governs the write side of these fields). HasBadCharacters: rejects</>characters in the nickname or holder name.ValidRoutingNumber: decrypts the routing number and requires exactly 9 numeric digits with no separators.- On new accounts only (Level Two):
IsNewRoutingNumVerifedadditionally requiresNewRoutingNumVerified = Truebefore the account can be saved — this flag is normally set upstream by Payment preference selection after a successful bank-validator check, or automatically by EFT authorization / consent when a default routing number is applied from the authorization type.
- On new accounts only (Level Two):
ValidAccountNumber(only whenValidateBankAccountNumberForOldBankAccountapplies): decrypts the account number and requires a length of 5–17 characters, numeric unless the account is a debit card, with no separators.- Level Two code-validity rules:
ValidAccountDataSouceCode,ValidAccountStatusCode,ValidPaymentReturnReasonCode(only if not blank),ValidAccountTypeCode,ValidConsummerBusnessCode— each defers to the corresponding lookup object's ownIsValid(see Code table lookups). - On any failure: the broken-rule collection accumulates messages and
Save()proceeds to fail validation; no database call is attempted. - Insert a new account.
BeforeInsert/AfterInsertexecutesINSERT INTO BANK_ACCOUNT (...)with the encrypted routing/account numbers and all descriptive fields (SQL-009, BANK_ACCOUNT). - On failure (
RowsAffected <> 1): adds anInsertErrormessage (BR-EFT-05). - Retrieve an existing account.
BeforeRetrieve/AfterRetrieveselects the full column set byBankAccountID(SQL-030, BANK_ACCOUNT); a companion collection retrieval selects byCREATE_USER(case-insensitive) (SQL-031). - A commented-out alternate retrieval via stored procedure
PK72970_EPAY.retrieve_BankAccountexists in source but is not wired intoBeforeRetrieve— dead code.* - Update an existing account.
BeforeUpdate/AfterUpdatestampsUpdateDate/UpdateUserand executes a full-columnUPDATE BANK_ACCOUNTkeyed onBankAccountID(SQL-077, BANK_ACCOUNT);CREATE_DATE/CREATE_IP_ADDR/CREATE_USERare intentionally excluded from the SET clause so audit-creation fields never change. - On failure (
RowsAffected <> 1): adds anUpdateErrormessage (BR-EFT-05). - Delete an account.
BeforeDeletebranches on thePurgeRecordflag (BR-EFT-11): - Default (
PurgeRecord = False): issues a soft-deleteUPDATE BANK_ACCOUNT SET BANK_ACCOUNT_STATUS_CODE = 'DELETED', UPDATE_DATE = ..., UPDATE_USER = ...(SQL-088, BANK_ACCOUNT) — the row remains for historical linkage to authorizations and payment details (BR-EFT-04). - If
PurgeRecord = True: issues a physicalDELETE BANK_ACCOUNT WHERE BANK_ACCOUNT_SEQ_NUM = :BankAccountID, permanently removing the row. - On failure (
RowsAffected <> 1): adds aDeleteErrormessage. - Link the account to a US Bank session (optional).
clsBankAccountTransfer.Create()copiesBankAccountSeqNum/USBankUserSeqNumfrom the criteria (no sequence round-trip — the composite key is supplied by the caller) and inserts intoBANK_ACCOUNT_TRANSFER(SQL-010, BANK_ACCOUNT_TRANSFER); retrieval selects by the same composite key (SQL-036), and updates/deletes follow the same pattern (SQL-078, SQL-089). - Return the outcome.
Save()callsApplyEdit(), dispatches toSaveChild()or the baseSave()depending on whether the account is a child object, and callsMarkOld()on success; the boolean result reflectsErrorCount = 0.
Process flow¶
flowchart TD
Start([Caller creates or retrieves<br>a bank account]) --> New{New account?}
New -->|Yes| Seq[Fetch BANK_ACCOUNT_SEQ.NEXTVAL]
New -->|No| Retrieve[Retrieve by BankAccountID<br>or CreateUser]
Seq --> Edit[Caller sets routing/account<br>numbers, type, status]
Edit --> Validate{IsValid?}
Validate -->|No| Fail([Broken rules returned;<br>no database call])
Validate -->|Yes| Insert[INSERT BANK_ACCOUNT]
Retrieve --> EditExisting[Caller edits fields]
EditExisting --> ValidateU{IsValid?}
ValidateU -->|No| Fail
ValidateU -->|Yes| Update[UPDATE BANK_ACCOUNT]
Insert --> Rows{RowsAffected = 1?}
Update --> Rows
Rows -->|No| Contention([InsertError / UpdateError added])
Rows -->|Yes| Done([Save returns ErrorCount = 0])
Retrieve --> Delete{Delete requested?}
Delete -->|PurgeRecord = True| Purge[DELETE BANK_ACCOUNT row]
Delete -->|PurgeRecord = False| Soft[UPDATE status = DELETED]
Purge --> RowsD{RowsAffected = 1?}
Soft --> RowsD
RowsD -->|No| DeleteErr([DeleteError added])
RowsD -->|Yes| Done
Failure and edge-case behavior¶
- A
RowsAffectedvalue other than1on insert, update, or delete adds an error message but does not raise an exception; the caller must checkErrorCount/IsValidafterSave()(BR-EFT-05). - Soft-delete is the default and preserves the row (and its historical linkage to authorizations/payment details) with
BANK_ACCOUNT_STATUS_CODE = 'DELETED'; only an explicitPurgeRecord = Trueperforms a hard delete (BR-EFT-11). - New accounts cannot be saved until
NewRoutingNumVerified = True, which is normally set by an upstream bank-validator check (see Payment preference selection) or by the authorization-type cascade in EFT authorization / consent (BR-EFT-09). IsValid/IsDirtyoverrides onclsBankAccountcontain only placeholder comments for child-object validation that was never implemented — no child business objects are actually validated from this class today.*- A commented-out alternate retrieval SQL referencing stored procedure
PK72970_EPAY.retrieve_BankAccountexists in source but is not reachable from any code path — dead code.* - Several duplicate/no-op parameter-binding calls exist in the Insert and Update SQL builders (e.g.,
UpdateDate/UpdateIPAddr/UpdateUser/BankAccountIDadded twice); these are redundant but harmless.*
Related documentation¶
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.Payment.EFT\clsBankAccount.vbBusiness\SAIF.Business.Payment.EFT\clsBankAccountCollection.vbBusiness\SAIF.Business.Payment.EFT\clsBankAccountTransfer.vb