Skip to content

Payment return handling

clsPaymentReturn records that a previously-issued electronic payment was returned by the receiving bank, along with the NACHA return reason. It joins to PAYMENT_RETURN_REASON_GCODE for a culture-aware description of the reason and can create a backout or vendor-refund clsPaymentEvent once a returned payment has been reviewed. Returns are permanent, append-mostly records: DeleteSQL is intentionally disabled.

Field Value
Operation ID OP-EFT-08
Trigger Reconciliation process creates a clsPaymentReturn referencing the original PaymentDetailSeqNum and the bank-reported return reason code
Inputs PaymentDetailSeqNum, return type code, return reason code, return date
Outputs Persisted PAYMENT_RETURN row; culture-aware return-reason description; PAYMENT_EVENT row of type BackoutEvent or VendorRefund once reviewed
Primary components clsPaymentReturn.BeforeCreate/Insert/Retrieve, MarkReviewed, CreateBackoutPaymentEvent; clsPaymentReturnReasonCode(+Collection); clsReturnStatusCode; clsReturnTypeCode
Entry point Business\SAIF.Business.Payment.EFT\clsPaymentReturn.vb

Steps

  1. Create a new return record. NewPaymentReturn fetches the next sequence value (SQL-008, DUAL) and links it to the original PaymentDetailSeqNum from Payment detail, events, and allocation.
  2. Classify the return using NACHA reference codes. The return reason code is validated against clsPaymentReturnReasonCode/Collection (SQL-066, SQL-067) and classified per BR-EFT-03; return status and return type are validated against clsReturnStatusCode (SQL-070, SQL-071) and clsReturnTypeCode (SQL-072, SQL-073) respectively (see Code table lookups).
  3. Insert. BeforeInsert/AfterInsert executes INSERT INTO PAYMENT_RETURN (...) (SQL-020, PAYMENT_RETURN).
  4. On failure (RowsAffected <> 1): adds an InsertError message (BR-EFT-05).
  5. Retrieve with culture-aware return-reason description. The single-record retrieval query joins PAYMENT_RETURN_REASON_GCODE on the current session's culture/language so the return-reason description text is presented in the caller's language rather than a single hard-coded locale (SQL-064, PAYMENT_RETURN, BR-EFT-07).
  6. Collection retrieval. clsPaymentReturnCollection retrieves multiple returns using the same culture-aware join, for reconciliation reporting (SQL-065).
  7. Mark as reviewed. MarkReviewed updates the return row's status once an operator has reviewed and acted on it (SQL-086, PAYMENT_RETURN).
  8. Create a backout or vendor-refund event. CreateBackoutPaymentEvent creates a clsPaymentEvent of type BackoutEvent (internal accounting reversal) or VendorRefund (funds returned to the vendor), depending on the return's classification, using the same immutable event-insert mechanism documented in Payment detail, events, and allocation (SQL-019, PAYMENT_EVENT).
  9. Update. Further updates to the return record (e.g., correcting the reason code before final processing) use the same standard UPDATE PAYMENT_RETURN statement as the review step (SQL-086).
  10. No cross-reference to authorization revocation. clsPaymentReturn never reads from or writes to clsEFTAuthorization beyond the read-only culture-aware description join above — a payment return does not automatically revoke the customer's EFT authorization / consent; revocation, if warranted, is a separate, manually-initiated action.
  11. Deletion is disabled. DeleteSQL is overridden to always throw, with the source comment indicating a payment return "should not be deleted once created" — returns are a permanent audit record.

Process flow

flowchart TD
    Start([Bank reports a returned payment]) --> Create[Create PaymentReturn record]
    Create --> Classify[Classify by NACHA return reason code]
    Classify --> Insert[INSERT PAYMENT_RETURN]
    Insert --> Rows{RowsAffected = 1?}
    Rows -->|No| Err([InsertError added])
    Rows -->|Yes| Retrieve[Retrieve with culture-aware<br>reason description]
    Retrieve --> Review{Reviewed?}
    Review -->|No| Pending([Awaiting operator review])
    Review -->|Yes| Mark[MarkReviewed]
    Mark --> Event[CreateBackoutPaymentEvent:<br>BackoutEvent or VendorRefund]
    Event --> NoRevoke([Authorization NOT revoked<br>automatically])
    NoRevoke --> Done([Return processing complete])

Failure and edge-case behavior

  • Because clsPaymentReturn never revokes the related clsEFTAuthorization, a recurring pattern of returns for the same customer/bank account will not automatically stop future auto-pay attempts unless a separate process explicitly calls RevokeAuthorization in EFT authorization / consent.*
  • DeleteSQL always throws — a return record, once inserted, is permanent and can only be corrected via update, never removed.
  • The culture-aware reason-description join depends on the caller's active session culture; if no matching localized row exists in PAYMENT_RETURN_REASON_GCODE, the description may render blank or fall back to a default language row (BR-EFT-07).*

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\clsPaymentReturn.vb
  • Business\SAIF.Business.Payment.EFT\clsPaymentReturnCollection.vb
  • Business\SAIF.Business.Payment.EFT\clsPaymentReturnReasonCode.vb
  • Business\SAIF.Business.Payment.EFT\clsReturnStatusCode.vb
  • Business\SAIF.Business.Payment.EFT\clsReturnTypeCode.vb