Financial transaction and remark management¶
A financial transaction is the permanent, append-only ledger entry every payment, refund, and transfer in this library ultimately writes: a header row plus one or more detail lines and an optional remark. Almost every other operation in SAIF.Business.Claim.Payment ends by building one of these through clsPaymentBase, so this operation documents the shared object that all payee/payment flows delegate to for persistence.
| Field | Value |
|---|---|
| Operation ID | OP-CP-01 |
| Trigger | clsFinancialTrans.NewFinancialTrans(dpi, claimData [, tranType]) (create), clsFinancialTrans.GetTransaction(dpi, tranID, tranType) or one of nine clsFinancialTransCollection factories (retrieve) |
| Inputs | IDataPortalInfo, claim data or claim ID, transaction type code (Payment/Refund/Transfer), status, issue date, benefit sequence number, payment ID, payee/address data, detail amounts/dates/flags, remark code |
| Outputs | Persisted CL_FINANCIAL_TRANS / CL_FINANCIAL_TRANS_DTL / remark rows; populated object graph; boolean save result; broken-rule/error messages |
| Primary components | clsFinancialTrans.Create/SetHistory/ApplyValueChecks/ValidAddress, clsFinancialTransDtl, clsFinancialTransDtlCollection, clsFinancialTransCollection, clsFinancialTranRemark |
| Entry point | Business\SAIF.Business.Claim.Payment\FinancialTransaction\clsFinancialTrans.vb |
Steps¶
- Create a new transaction.
NewFinancialTransassignsClaimFinancialTransSeqNumfrom a sequence,ClaimIDfrom the criteria's claim data, and eagerly loads an (initially empty) detail collection and the child remark placeholder. TwoClaimID-only overloads are marked obsolete and internally resolve full claim data viaclsClaimData(SAIF.Business.View.Claim, not yet migrated — see Payee management for the related note). - Apply create defaults (BR-CP-007): status Released, medical/indemnity display code
I, issue/entry date today, initiator the logged-on user.SetHistory()snapshots the claim's jurisdiction, status, type, coverage, injury date, policy, tail-coverage, preferred-worker, federal-benefit, NCE, HWR, and own-motion values onto the transaction row. - Add a detail line.
InsertTranDetailcreates aclsFinancialTransDtl, assigns the transaction type code, and numbers itTranDetail.Count + 1— a 1-based sub-number with no gap or uniqueness re-check. - Apply value checks before insert (BR-CP-005, BR-CP-006).
ApplyValueCheckssets each detail's reimbursement program (SD, then Retro Reserve, then NCE, in that precedence) and clears or sets the claim cost category based on chargeability, payee type, and reimbursable-program membership; an uncategorized detail is forced non-chargeable. - Validate the payee address (BR-CP-004).
ValidAddressruns as a level-one rule onAddressLine1unlessIgnoreBusinessRulesis set or the object is an existing record whose address was already valid. - Worker/Beneficiary payees require a previously validated address (delegated to
clsPayeeBase/clsProviderAddress,SAIF.Business.View.Provider— not yet migrated). - Attorney/Other/Medical Provider payees require address line 1, plus city and state unless the address is foreign.
- On failure: broken rule naming the payee ("Error: Worker/Beneficiary/Provider address is invalid \<PayeeFullName>").
- Insert the header.
BeforeInsertnormalizes blank special-handling codes and zero zip/provider-location values to NULL, and prefers the parent provider location when the payee's address is a parent location. The header insert itself has no catalogued SQL entry in this library's SQL index; it is described here from the traced stored-procedure call rather than linked. - On a rows-affected value other than 1:
"Insert Failed"error added; child detail and remark are not saved. - Insert the detail line (SQL-020, CL_FINANCIAL_TRANS_DTL). Only runs after the header insert succeeds.
- On a rows-affected value other than 1:
"Insert Failed"error added. - Insert the remark, if any. When
PayRemarkCodeis blank the remark object is marked clean and no request is sent; otherwise it is inserted (SQL-054 covers the matching retrieve path; the remark insert/update/delete procedures were traced by name but have no distinct catalog entry beyond the retrieve). - Update an existing transaction. Only
PaymentMethodCode,PaymentID, andFinancialTransactionStatusCodemay be changed after creation — every other field is insert-only, append-style history. - On a rows-affected value other than 1:
DBContentionErroradded (BR-CP-001). - Update or delete the remark. Clearing
PayRemarkCodeto empty on an existing remark routes the save through the delete path instead of update (SQL-101 update, SQL-124 delete).- On a rows-affected value other than 1:
DBContentionErroradded.
- On a rows-affected value other than 1:
- Retrieve a transaction or transaction history.
GetTransactionretrieves by sequence number and type;clsFinancialTransCollectionexposes nine retrieval factories keyed by claim, issue date, benefit sequence, recovery eligibility, status, payment ID, or payment category, each backed by its own stored procedure (SQL-055, SQL-056, SQL-057, SQL-058, SQL-059, SQL-060, SQL-061, SQL-062, SQL-063, SQL-065, CL_FINANCIAL_TRANS).- If no row matches (single retrieve): the returned object is populated as a placeholder and a runtime-added rule reports "No valid transaction found for Id and Type supplied."
- For
ByStatus,ByStatusAndIssueDate, andByClaimretrievals, detail lines for the whole result set are eagerly batch-loaded and grouped by transaction; other retrieval types load details lazily per transaction (N+1 pattern).
- Bulk status transition.
updateFinancialTranStatusmoves every matching transaction from one status to another for a claim/issue-date/payment-type in a single stored-procedure call (SQL-102) and returns the raw rows-affected count with no<> 1check and no legal-transition validation of its own. - Ad hoc aggregate queries.
HasOverLapAmtsums detail amounts for a claim/category whose date range overlaps a proposed period;PreviousPaidAmt/PreviousPaidDayssum prior positive payments or refunds for an exact from/thru match (note:PreviousPaidDaysmust be read only afterPreviousPaidAmt— an ordering dependency, not a rule);LatestPaymentDatefinds the latest posted, non-8F, non-penalty transaction thru-date;GetLastPaymentThruDatebuilds its category list by string formatting rather than binding (low risk — values are enum-derived, not user input). - First-payment determination (BR-CP-008).
FirstPaymentreturns true only while none of the claim's transactions has reached Posted status.
Process flow¶
flowchart TD
Start([Payment workflow or caller<br>requests a transaction]) --> Which{Create or retrieve?}
Which -->|Create| New[NewFinancialTrans:<br>seed header, snapshot claim data]
New --> Detail[Add detail line]
Detail --> Checks[Apply value checks:<br>reimbursement program,<br>cost category]
Checks --> AddrRule{Payee address valid?}
AddrRule -->|No| Blocked([Broken rule added;<br>save blocked])
AddrRule -->|Yes| InsHeader[Insert header]
InsHeader --> Rows1{RowsAffected = 1?}
Rows1 -->|No| Fail1([Insert Failed;<br>children not saved])
Rows1 -->|Yes| InsDetail[Insert detail line]
InsDetail --> InsRemark{Remark code blank?}
InsRemark -->|Yes| SkipRemark[No remark row created]
InsRemark -->|No| InsRemarkRow[Insert remark row]
Which -->|Retrieve| Retr[Select factory by<br>claim / status / issue date / etc.]
Retr --> Found{Row(s) found?}
Found -->|No| Placeholder([Placeholder object;<br>not-found rule added])
Found -->|Yes| Loaded([Populated transaction<br>or collection returned])
SkipRemark --> Done([Save complete])
InsRemarkRow --> Done
Failure and edge-case behavior¶
- Detail-line update always throws
ApplicationException(InvalidSQLProperty)becauseclsFinancialTransDtl.Criteria.UpdateSQLis not implemented — detail lines are effectively insert-only in practice. - Detail-line delete uses an inline statement with unbound literal placeholders and a mismatched column name (
claim_financial_trans_idinstead ofclaim_financial_trans_seq_num); it is very likely a dead/non-functional path. clsFinancialTransDtlCollection.RemoveandclsFinancialTransCollection.Removeare self-recursive — calling either with a matching item causes a stack overflow rather than removing it.- A missing remark on retrieve is not an error; a clean, empty placeholder remark object is returned instead.
- Static code-map caches (
RecoveryTypeCodes,FinancialTransTypeCodes) are process-wide and only refresh when explicitly requested. GetTransactionsetsIgnoreBusinessRules = Trueon the returned object, which suppresses the address-validity rule but not the runtime-added not-found rule.- The header insert/update/retrieve stored procedures were traced from source but have no distinct entry in this library's SQL catalog separate from the collection-level entries cited above; they are described in prose rather than linked to avoid citing a non-existent SQL ID.
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.Claim.Payment\FinancialTransaction\clsFinancialTrans.vbBusiness\SAIF.Business.Claim.Payment\FinancialTransaction\clsFinancialTransCollection.vbBusiness\SAIF.Business.Claim.Payment\FinancialTransaction\clsFinancialTransDtl.vbBusiness\SAIF.Business.Claim.Payment\FinancialTransaction\clsFinancialTransDtlCollection.vbBusiness\SAIF.Business.Claim.Payment\FinancialTransaction\clsFinancialTranRemark.vb