---
title: Payment preference selection
summary: Composite object that lets a payee choose and validate an EFT authorization or debit-card enrollment as their preferred payment method.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Business.Payment.EFT
reference_type: package
operation_id: OP-EFT-02
trigger: Caller creates or retrieves a clsPaymentPreference (or clsProviderPaymentPreference) and calls Save() after setting a preferred payment authorization and/or debit card
---

# Payment preference selection

`clsPaymentPreference` (and its provider-specific variant `clsProviderPaymentPreference`) is a composite object implementing `iPaymentPreference`. It does not own any database table of its own — every `Criteria` SQL-building property throws `ApplicationException("This object type is retrieved differently")`. Instead, it wraps and coordinates two child business objects: a `clsEFTAuthorization` (the payment authorization) and a `clsDebitCardEnrollmentRequest` (the debit card), delegating persistence to each child's own `Save()`.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-EFT-02 |
| **Trigger** | Caller obtains a `clsPaymentPreference`/`clsProviderPaymentPreference`, assigns a child `PaymentAuthorization` and/or `DebitCard` object, and calls `Save()` |
| **Inputs** | A `clsEFTAuthorization` instance and/or a `clsDebitCardEnrollmentRequest` instance; bank routing/account numbers (validated externally) |
| **Outputs** | Persisted child `PAYMENT_AUTHORIZATION` and/or `DEBIT_CARD_ENROLLMENT_REQUEST` rows (no rows are written directly by `clsPaymentPreference` itself) |
| **Primary components** | `clsPaymentPreference`, `clsProviderPaymentPreference`, `Save()`, `SaveChildObject` |
| **Entry point** | `Business\SAIF.Business.Payment.EFT\clsPaymentPreference.vb`, `Business\SAIF.Business.Payment.EFT\clsProviderPaymentPreference.vb` |

## Steps

1. **Caller assembles the preference.** The caller sets `PaymentAuthorization` to a `clsEFTAuthorization` object (see [EFT authorization / consent](eft-authorization-consent.md)) and/or `DebitCard` to a `clsDebitCardEnrollmentRequest` object (see [Debit card enrollment](debit-card-enrollment.md)). Neither assignment triggers a database call.
2. **Validate bank routing/account numbers before assigning a new bank account.** When a new routing number is supplied, `clsPaymentPreference` calls `SAIF.Business.BankValidatorServices.IsValidBankRoutingNum` and `IsVerifiedBankRoutingNum`/`RetrieveBankName` to confirm the number is well-formed and recognized, and `IsValidBankAccountNum` to confirm the account-number format is acceptable for the bank.
   > **Origin:** Delegated to `SAIF.Business.BankValidatorServices` in `SAIF.Business` — see [Address and bank validation support](../../saif-business/operations/address-and-bank-validation-support.md).
   - If validation succeeds, `NewRoutingNumVerified` is set to `True` on the associated `clsBankAccount`, satisfying the Level Two rule enforced in [Bank account management](bank-account-management.md).
   - If the bank-validator service is unavailable (`IsServiceAvailable` returns `False`), the routing-number verification is skipped and the bank account cannot be newly saved until verification succeeds on a later attempt.*
3. **Save the composite.** `Save()` calls `SaveChildObject` on `PaymentAuthorization` (if present) and on `DebitCard` (if present) — each delegates its own insert/update/validation logic to [EFT authorization / consent](eft-authorization-consent.md) and [Debit card enrollment](debit-card-enrollment.md) respectively. `clsPaymentPreference` itself performs no SQL of its own; it aggregates the success/failure of both children.
4. **Debit-card eligibility gate.** Before a debit card can be set as the preference, the caller (or upstream `SAIF.Business.Claim.Payment` caller) determines eligibility using [BR-EFT-02](../business-rules.md#br-eft-02-debit-card-payment-eligibility-governed-by-allowdebitcard) (`AllowDebitCard = True` only when the payee type is `Worker`) — this rule is enforced by the calling context, not by `clsPaymentPreference` itself.
5. **Provider variant.** `clsProviderPaymentPreference` follows the identical composite pattern for provider payees, wrapping the same two child object types with provider-specific defaults; it has no additional SQL of its own.

## Process flow

```mermaid
flowchart TD
	Start([Caller builds a payment preference]) --> Auth{Assign EFT authorization?}
	Auth -->|Yes| AuthSet[Set PaymentAuthorization]
	Auth -->|No| Card{Assign debit card?}
	AuthSet --> Card
	Card -->|Yes| CardSet[Set DebitCard]
	Card -->|No| SaveCall[Save preference]
	CardSet --> Validate{New routing number?}
	Validate -->|Yes| BankCheck[Call BankValidatorServices]
	Validate -->|No| SaveCall
	BankCheck --> Verified{Verified?}
	Verified -->|Yes| MarkVerified[Set NewRoutingNumVerified = True]
	Verified -->|No| Skip[Skip verification;<br>save deferred]
	MarkVerified --> SaveCall
	SaveCall --> SaveAuth[SaveChildObject: PaymentAuthorization]
	SaveAuth --> SaveCard[SaveChildObject: DebitCard]
	SaveCard --> Done([Aggregate result returned])
```

## Failure and edge-case behavior

- `clsPaymentPreference` has no `Criteria` SQL of its own; every retrieval attempt through this object throws `ApplicationException` — callers must retrieve the underlying `clsEFTAuthorization`/`clsDebitCardEnrollmentRequest` directly and assemble the composite themselves.*
- If the bank-validator service is unavailable, routing-number verification is silently skipped rather than failing hard, which can leave a new bank account unable to save until a subsequent verification succeeds.*
- Debit-card eligibility ([BR-EFT-02](../business-rules.md#br-eft-02-debit-card-payment-eligibility-governed-by-allowdebitcard)) is enforced by the calling context (e.g., `SAIF.Business.Claim.Payment`), not by this class — `clsPaymentPreference` will accept a debit-card assignment regardless of payee type.*

## 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.Payment.EFT\clsPaymentPreference.vb`
- `Business\SAIF.Business.Payment.EFT\clsProviderPaymentPreference.vb`
