Payment detail, events, and allocation¶
clsPaymentDetail implements IOnlinePayment and is the central record of a single electronic payment. Rather than a simple status column update, each state change is performed by a dedicated method (PostPending, RefundVendorRemitted, ReturnVendorRemitted, CancelVendorPending/DeclineVendorPending/ReplaceVendorPending via UpdateVendorPending, DeletePending, RemitPosted, CancelPayment) that updates the payment row and appends an immutable clsPaymentEvent audit record. Related bridge objects (clsPaymentAllocation, clsSessionTransfer, clsPaymentAuthorizationSessionTransfer) connect a payment to the accounting session(s) it was allocated from, and IAT/domestic payments trigger addenda creation (see Payment addenda).
| Field | Value |
|---|---|
| Operation ID | OP-EFT-05 |
| Trigger | Caller calls NewPaymentDetail, or invokes a lifecycle method on a retrieved clsPaymentDetail |
| Inputs | Bank account, payee, amount, ACH standard entry class code, IAT indicator, warehoused/non-warehoused indicator, allocation/session-transfer references |
| Outputs | Persisted/updated PAYMENT_DETAIL row; one or more PAYMENT_EVENT audit rows per transition; PAYMENT_ALLOCATION/SESSION_TRANSFER/PAYMENT_AUTH_SESSION_TRANSFER rows; triggered addenda creation for IAT/standard payments |
| Primary components | clsPaymentDetail (lifecycle methods, CreateIATAddenda, CreateStandardAddenda), clsPaymentDetailCollection (5 retrieval builders), clsPaymentAllocation/Collection, clsSessionTransfer, clsPaymentAuthorizationSessionTransfer, clsPaymentEvent/Collection/Code |
| Entry point | Business\SAIF.Business.Payment.EFT\clsPaymentDetail.vb |
Steps¶
- Create a new payment.
NewPaymentDetailfetches the next sequence value (SQL-006, DUAL) and initializes bank account, amount, and status fields. - Validate the ACH standard entry class code.
ValidAchStdEntryClassCoderequires a standard entry class code only when the linked bank account's banking network is ACH; non-ACH accounts (e.g., debit card) are exempt (BR-EFT-10). - Insert.
BeforeInsert/AfterInsertexecutesINSERT INTO PAYMENT_DETAIL (...)(SQL-018, PAYMENT_DETAIL). - On failure (
RowsAffected <> 1): adds anInsertErrormessage (BR-EFT-05). - Retrieve via one of five retrieval builders, dispatched by
Criteria.RetrieveType:BuildSqlNormal(standard retrieval byPaymentDetailSeqNum),BuildSqlSeqNum(retrieval by an explicit sequence-number list),BuildSqlPend(payments still in a pending state, used by downstream batch processing),BuildPreNoteSql(prenote-only payments), andBuildPostedSql(already-posted/remitted payments). The SQL catalog documents these collectively under a single retrieval entry that joinsPAYMENT_AUTHORIZATIONandAUTHORIZATION_TYPE_CODE(SQL-059, PAYMENT_DETAIL); it does not enumerate each of the five builder variants as a separate SQL ID.* - PostPending, RefundVendorRemitted, ReturnVendorRemitted, and UpdateVendorPending (Cancel/Decline/Replace). Each of these state-transition methods updates the payment row with its resulting status (SQL-085, PAYMENT_DETAIL) and appends a matching
clsPaymentEventrow of the corresponding event code (SQL-019, PAYMENT_EVENT).ReturnVendorRemittedis distinct from the fuller Payment return handling flow, which additionally creates aPAYMENT_RETURNrecord for ACH-network returns. - DeletePending. Removes a payment still in pending status; performs a physical delete on
PAYMENT_DETAIL(SQL-096) and logs aDeletePendingevent (SQL-019, PAYMENT_EVENT). - RemitPosted. Marks a posted payment as remitted (funds actually sent); updates the row (SQL-085) and logs a
RemitPostedevent (SQL-019). - CancelPayment. Branches on payment source:
- If
IsUSBankPayment, delegates the cancellation call toUSBankAPIs.CancelPayment. > Origin: Delegated toSAIF.Business.EPay.USBank— see Recurring ACH authorization lifecycle. - Otherwise, cancels the payment locally by updating the row (SQL-085) and logging a
CancelPaymentevent directly (SQL-019). - Trigger addenda creation. After certain state transitions (typically at insert/post time), IAT payments call
CreateIATAddenda(), which creates 7 addenda records (type codes 10–16, using country codes rather than country names per the 2014 NACHA IAT format change) (SQL-005, SQL-015, PAYMENT_ADDENDA); non-IAT payments with addendum text callCreateStandardAddenda()to create a single addenda record. See Payment addenda for the full addenda lifecycle. - Allocate a payment against a session.
clsPaymentAllocationlinks a payment to aclsSessionTransferviaSessionTransferSeqNum; insert (SQL-016, PAYMENT_ALLOCATION), collection retrieval (SQL-057), update (SQL-084), and delete (SQL-095) follow the standard CRUD pattern. Aggregation properties on the collection compute both dynamically-calculated and GW/WCIS non-dynamic balance amounts across allocations. - Session transfer bridge.
clsSessionTransferbridgesclsPaymentDetailandclsPaymentAllocation; insert (SQL-021, SESSION_TRANSFER), retrieve (SQL-076), and update (SQL-087) follow the standard pattern.BeforeDeleteenforces that the transfer is still inTransactionPendingstate and cascades aSave()of its childPaymentAllocationscollection before allowing the delete to proceed (SQL-097). - Auto-pay session scheduling.
clsPaymentAuthorizationSessionTransferis an insert (SQL-017) / retrieve (SQL-058) -only junction table (no update/delete) keyed byDueDate, used to schedule which session an auto-pay authorization's next payment will be drawn from (PAYMENT_AUTH_SESSION_TRANSFER). - Immutable event log.
clsPaymentEventrecords are append-only:DeleteSQLis intentionally disabled and throws "This object never deletes events" if invoked (PAYMENT_EVENT); a single event can be retrieved by sequence number, joined withPAYMENT_EVENT_CODEandPAYMENT_RETURN_REASON_CODEdescriptions (SQL-060), or all events for a payment detail can be retrieved as a collection (SQL-063);clsPaymentEventCodeis a static, read-only lookup of the valid event-code values (see Code table lookups).
Process flow¶
flowchart TD
Start([Caller creates a payment]) --> Insert[INSERT PAYMENT_DETAIL]
Insert --> IAT{IAT payment?}
IAT -->|Yes| IATAddenda[CreateIATAddenda: 7 records]
IAT -->|No addendum text| StdAddenda[CreateStandardAddenda: 1 record]
IAT -->|No| Pending[Payment pending]
IATAddenda --> Pending
StdAddenda --> Pending
Pending --> Transition{State transition}
Transition -->|PostPending| Post[Update row; log event]
Transition -->|CancelPayment| USBank{IsUSBankPayment?}
Transition -->|DeletePending| DelPend[Physical delete; log event]
Transition -->|RemitPosted| Remit[Update row; log event]
USBank -->|Yes| Delegate[Delegate to USBankAPIs.CancelPayment]
USBank -->|No| LocalCancel[Update row locally; log event]
Post --> Return{Return/refund event?}
Return -->|ReturnVendorRemitted| RVR[Update row; log event]
Return -->|RefundVendorRemitted| RfVR[Update row; log event]
Post --> Allocate[Allocate to session via<br>clsPaymentAllocation/clsSessionTransfer]
Allocate --> Done([Lifecycle event logged])
Failure and edge-case behavior¶
- Every state-transition method logs an immutable
PAYMENT_EVENTrow; events can never be deleted once created —clsPaymentEvent.DeleteSQLalways throws. ValidAchStdEntryClassCodeonly requires the entry class code for ACH-network bank accounts; debit-card and other non-ACH accounts are exempt, so a blank entry class code is valid in those cases (BR-EFT-10).clsSessionTransfer.BeforeDeleterefuses to delete unless the transfer is stillTransactionPending, and always attempts to save its childPaymentAllocationsfirst — a failure in the child save can block the parent delete.CancelPaymentbehavior differs materially by payment source: US Bank payments are cancelled through an external API call (which may fail independently of local database state), while non-US-Bank payments are cancelled purely locally.clsPaymentAuthorizationSessionTransfersupports insert and retrieve only — there is no update or delete path, so a scheduling mistake must be corrected by inserting a new row rather than modifying the existing one.*- The five
clsPaymentDetailCollectionretrieval builders are selected by an enum and are not interchangeable; calling the wrongRetrieveTypefor a given scenario (e.g., usingBuildSqlPendto find posted payments) will return an empty or incorrect result set rather than raising an error.*
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\clsPaymentDetail.vbBusiness\SAIF.Business.Payment.EFT\clsPaymentDetailCollection.vbBusiness\SAIF.Business.Payment.EFT\clsPaymentAllocation.vbBusiness\SAIF.Business.Payment.EFT\clsPaymentAllocationCollection.vbBusiness\SAIF.Business.Payment.EFT\clsSessionTransfer.vbBusiness\SAIF.Business.Payment.EFT\clsPaymentAuthorizationSessionTransfer.vbBusiness\SAIF.Business.Payment.EFT\clsPaymentEvent.vbBusiness\SAIF.Business.Payment.EFT\clsPaymentEventCollection.vbBusiness\SAIF.Business.Payment.EFT\clsPaymentEventCode.vb