Refund adjustment processing¶
A refund reverses money already paid on a claim. clsRefundAdjustment is a thin, shared base (total-refund-amount rule, remark-length rule) that seven concrete refund classes extend — one class per refund mode, selected by the caller at construction rather than by a runtime type switch (BR-CP-022). Most refund types build negative financial transactions directly; two (non-disabling and third-party) instead post recovery/activity requests to the external claim-data API.
| Field | Value |
|---|---|
| Operation ID | OP-CP-05 |
| Trigger | Caller constructs the concrete refund class (clsMedicalRefund, clsHwrRefund, clsOtherRefund, clsSaifCheckRefund, clsWorkerTravelRefund, clsThirdPartyRefund, clsNdRefund) with claim data, populates candidate refund amounts, and calls Save() |
| Inputs | IDataPortalInfo, clsClaimData, issue date, remark text, per-payment/per-service-line refund amounts, optional issue-date filters |
| Outputs | Negative-amount CL_FINANCIAL_TRANS/CL_FINANCIAL_TRANS_DTL rows and CL_FINANCIAL_TRANS_BILL_ADJUST rows (most types); external recovery/activity API requests (ND and third-party refunds); boolean save result |
| Primary components | clsAdjustmentBase, clsRefundAdjustment, clsMedicalRefund, clsHwrRefund, clsOtherRefund, clsSaifCheckRefund, clsWorkerTravelRefund, clsThirdPartyRefund, clsNdRefund |
| Entry point | Business\SAIF.Business.Claim.Payment\Adjustments\Refunds\clsRefundAdjustment.vb |
Steps¶
- Select the concrete refund type (BR-CP-022). The caller instantiates the class matching the refund mode; only that type's logic and rule set run for the request.
- Establish the default issue date.
clsAdjustmentBase's constructor seedsIssueDatefromclsPaymentBase.GetNextIssueDate(dpi, Adjustment);MaxIssueDateis capped 28 calendar days ahead, rolled to a work day. - Load candidate payments to refund.
SetMedicalPayments(representative of the pattern shared by the other refund types) reads posted financial transactions for the claim, optionally filtered by issue-date range, and builds one read-only line item per prior payment; medical refunds further break a payment into its individual service lines viaclsBillPaymentAdjustments.GetBillPaymentAdjustments. - Attach a per-line amount rule. Each candidate line gets a
Rule_ValidPaymentRefundAmountrule so a caller cannot request a refund amount exceeding what was actually paid on that line. - Validate the aggregate request.
Rule_RefundAmountNotZero(base) requires a non-zero total;Rule_ValidRemarkLengthrequires the remark to be 200 characters or fewer;Rule_CheckPaidCostsis a warning, surfaced when posting the adjustment would drive a cost category negative — the user may override it and proceed (BR-CP-023). - Build the reversing financial transaction. For a full-payment refund,
GetRefundTransactionclones the original transaction's claim/policy/payee snapshot fields, negatesTotalTransactionAmtand every detail line'sTransactionAmt, and copies the original detail's category/reimbursement/cost codes; a line refund instead builds fresh detail rows sized to only the refunded services, re-deriving cost category and reimbursement program throughclsMedicalBillPayment.GetClaimCostInfo. - This delegates persistence to Financial transaction and remark management — the refund transaction is created and saved exactly like any other financial transaction (
clsFinancialTrans.NewFinancialTransthenSave()), withIgnoreBusinessRules = Trueset on the new transaction before its own fields are populated. - Record a bill payment adjustment per refunded service line, if applicable.
GetBillAdjustmentbuilds aclsBillPaymentAdjustmentreferencing the refund transaction, the original bill ID, and the audited service sequence number (BR-CP-026); full-payment refunds intentionally skip this per a code comment ("don't create adjustments for full refunds"). - Save the refund.
Save()re-checksIsValid, then saves every built refund transaction in turn, stopping immediately (Return False) if any transaction fails to save; only after all transactions succeed does it save the accompanying bill payment adjustments. - Route non-disabling refunds to the external API instead (BR-CP-024).
clsNdRefunddoes not writeCL_FINANCIAL_TRANSdirectly; it builds aRecoveryRequestand posts it throughApiRoute(..., ApiRouteType.RetrieveSingleWithBody, ..., "{claimId}/recovery")against the claim-financial API client, and separately callsGetNDROverMax(see Payment list queries and NDR claim data retrieval) to flag claims already at their statutory reimbursement maximum (BR-CP-073). - Route third-party refunds to the activity API as well (BR-CP-024).
clsThirdPartyRefundbuilds anActivityRequestposted through the activity API client in addition to any recovery request, and reads negative-paid-cost information viaGetNegativePaidCostInfos, which itself calls the claim-financials API (GetApiRouteClaimFinancials) to compare proposed refund amounts against previously paid costs per cost category.
Process flow¶
flowchart TD
Start([Adjuster selects a refund type<br>and reviews candidate payments]) --> Which{Refund type?}
Which -->|Medical/HWR/Other/<br>SAIF check/Worker travel| Load[Load posted transactions;<br>build refund line items]
Load --> Rule1{Amount, remark,<br>paid-cost rules pass?}
Rule1 -->|Error| Blocked([Broken rule; save blocked])
Rule1 -->|Warning only| Confirm{User confirms<br>override?}
Confirm -->|No| Blocked
Rule1 -->|Pass| BuildTx[Build negated<br>financial transaction]
Confirm -->|Yes| BuildTx
BuildTx --> SaveTx[Save financial transaction<br>via Financial transaction management]
SaveTx --> TxOk{Save succeeded?}
TxOk -->|No| Fail([Save returns False])
TxOk -->|Yes| Adj[Save bill payment adjustments]
Adj --> Done([Refund complete])
Which -->|Non-disabling| NdrCall[Build RecoveryRequest;<br>call claim-financial API]
NdrCall --> NdrCap{Over statutory<br>reimbursement cap?}
NdrCap -->|Yes| Flagged([Claim flagged for review])
NdrCap -->|No| NdrDone([Recovery request submitted])
Which -->|Third-party| TpCall[Build ActivityRequest;<br>check negative paid costs via API]
TpCall --> TpDone([Activity/recovery requests submitted])
Failure and edge-case behavior¶
clsRefundAdjustment.Savestops at the first failed transaction save and returnsFalsewithout rolling back transactions already committed earlier in the loop — a multi-line refund can partially post.- The paid-costs and own-motion warnings can be overridden by the user; only the zero-amount and remark-length rules are hard errors (BR-CP-023).
- Non-disabling and third-party refunds never create a
CL_FINANCIAL_TRANSrow; a report or query that only looks at that table will miss these two refund types entirely. GetPostedTransactionson the base class caches its last claim ID/issue date result inStaticlocals, so refund construction against a different claim or issue date in the same process correctly triggers a re-fetch, but the cache is process-wide, not per-instance.- The
NDand third-party refund API integrations depend on external claim-data/financial/activity services outside this repository; response-failure handling for those calls was not traced in this pass and should be treated as unconfirmed.*
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\Adjustments\clsAdjustmentBase.vbBusiness\SAIF.Business.Claim.Payment\Adjustments\Refunds\clsRefundAdjustment.vbBusiness\SAIF.Business.Claim.Payment\Adjustments\Refunds\clsMedicalRefund.vbBusiness\SAIF.Business.Claim.Payment\Adjustments\Refunds\clsHwrRefund.vbBusiness\SAIF.Business.Claim.Payment\Adjustments\Refunds\clsOtherRefund.vbBusiness\SAIF.Business.Claim.Payment\Adjustments\Refunds\clsSaifCheckRefund.vbBusiness\SAIF.Business.Claim.Payment\Adjustments\Refunds\clsWorkerTravelRefund.vbBusiness\SAIF.Business.Claim.Payment\Adjustments\Refunds\clsThirdPartyRefund.vbBusiness\SAIF.Business.Claim.Payment\Adjustments\Refunds\clsNdRefund.vb