Reimbursement recording¶
When DCBS pays back a batch of EAIP bills, the payment arrives as one remittance covering many claims. This operation records that remittance as a three-level structure: a reimbursement header carrying the received, posted, and reconciled dates and the total amount; one detail row per claim named on the remittance; and, at both levels, an amount breakdown by expense type. Nothing here matches the money to bills — that is the job of DCBS reimbursement balancing. This operation's responsibility is to capture what DCBS said it paid, keyed so the balancing run can find it.
| Field | Value |
|---|---|
| Operation ID | OP-EAIP-07 |
| Trigger | clsReimbursement.NewReimbursement(dpi) or one of the shared retrieval methods, followed by edits and Save() |
| Inputs | IDataPortalInfo; received date, posted date, reimbursement amount, and explanation text; per-detail DCBS claim number, DCBS WCD claim number, DCBS worker name, request received date, injury date, total amount, and disabling indicator; per-amount expense type code with disabling, non-disabling, and total amounts (header level) or reimbursed amount (detail level) |
| Outputs | An EAIP_REIMBURSEMENT row with its detail and amount children; resolved claim data on each detail; a claim-not-found rule violation for an unresolvable DCBS claim number; DB contention errors when a statement affects no rows |
| Primary components | clsReimbursement (Create, AddInsertUpdateParms, AfterInsert, AfterUpdate, GetReimbursementsByReceivedDate, GetReimbursementsByPostedDate, GetReimbursements, OverrideBusinessRules), clsReimbursementDetail (DcbsSaifClaimNum, ClaimData, BeforeUpdate, Rule_ValidClaim), clsAmount, clsDetailAmount |
| Entry point | Business\SAIF.Business.Claim.EAIP\Reimbursement\clsReimbursement.vb |
Steps¶
- Create the reimbursement header.
NewReimbursement(dpi)runsCreate(), which takes the next value ofeaip_reimb_seqas the reimbursement identifier and records the create stamp (SQL-005, EAIP_REIMB_SEQ). Existing remittances are opened by identifier throughpk82500_eaip.eaip_reimbursement_select(SQL-024, Details). - Record the remittance facts. The caller sets the received date (when SAIF got the payment), the posted date (the DCBS posting date that keys the balancing batch), the reimbursement amount, and the free-text explanation. The reconciled date, reconciled amount, and reconciled flag are left for the balancing run to fill in.
- Add a detail row per claim.
clsReimbursementDetail.NewReimbursementDetailtakes the next value ofeaip_reimb_detail_seqand links itself to the parent reimbursement (SQL-006, EAIP_REIMB_DETAIL_SEQ). Each detail carries what DCBS reported: the DCBS SAIF claim number, the DCBS WCD claim number, the DCBS worker name, the request received date, the injury date, the total amount for that claim, and the disabling indicator. - Resolve the claim behind the DCBS claim number. Setting
DcbsSaifClaimNumclears the cached claim data, so the next read ofClaimDatare-resolves it. TheSAIFClaimNum,ClaimID, andWorkerNameproperties all read through that resolved claim data rather than through the DCBS-supplied text, which is what lets the balancing run find SAIF's own billing rows for a claim DCBS identified by its own number.Origin: Claim resolution, the formatted worker name, and the validity check behind it are implemented by
clsClaimDatainSAIF.Business.View.Claimand executed on behalf of this operation. That library is documented in the previous format, so no per-operation page exists; see Operations and processes in theSAIF.Business.View.Claimdocumentation set. - Validate the claim. The detail registers exactly one rule, bound to
DcbsSaifClaimNum: the detail is valid when it is not dirty or the resolved claim data reports itself valid; otherwise the message "Error: Claim number not found." is raised. A clean (unedited) detail is never re-validated, so a claim that later becomes unresolvable does not invalidate a stored remittance. - Break the detail down by expense type. Each detail carries a collection of
clsDetailAmountkeyed by the detail identifier plus the expense type code, holding the reimbursed amount for that type and a read-only reconciled indicator. Unlike the header and detail rows, these have no sequence of their own:Create()sets only the create stamp and the criteria's create-statement property throws an invalid-statement exception, because the composite key is supplied by the caller. - Break the header down by expense type as well. The header carries a parallel collection of
clsAmountkeyed by the reimbursement identifier plus the expense type code, holding the disabling amount, the non-disabling amount, and the total. It is built the same way, with no sequence and a throwing create-statement property. - Persist the header.
AddInsertUpdateParmsbinds the reimbursement identifier, received date, posted date, reconciled date, reconciled flag, reimbursement amount, reconciled amount, explanation text, and audit stamp;BeforeUpdateadditionally bindsLastUpdateNumand increments the update information. Insert targetspk82500_eaip.eaip_reimbursement_insert(SQL-015, Details) and update targetseaip_reimbursement_update(SQL-035, Details); each checks the affected row count and adds a DB contention error when it is not one. - Cascade the children. Both
AfterInsertandAfterUpdatesave the detail collection and then the amount collection, but only after their own row-count check passed. A failed header write therefore leaves the children unsaved rather than orphaned. - Persist the details.
clsReimbursementDetail.BeforeUpdatefirst recomputesTotalAmountas the sum of its detail amounts' reimbursed amounts, so the stored total always agrees with the breakdown that produced it. The parameter binding uses the resolvedWorkerNamewhen it is non-blank and falls back to the DCBS-supplied worker name otherwise. Insert, update, and delete targetpk82500_eaip.eaip_reimb_detail_insert,_update, and_delete(SQL-016, SQL-036, SQL-046, Details). A single detail is read by identifier throughGetReimbDetailByIDand the collection for a reimbursement througheaip_reimb_detail_select(SQL-025, Details). - Persist the amount breakdowns.
clsAmountwrites throughEAIP_Reimb_Amount_insert,_update, and_delete(SQL-013, SQL-033, SQL-043, Details) and reads a single row throughGetReimbAmountbyTypeor the whole set throughEAIP_Reimb_Amount_Select(SQL-022, Details).clsDetailAmountmirrors this againstreimb_detail_amount_insert,_update,_delete,GetReimbDetailAmountbyType, andreimb_detail_amount_Select(SQL-014, SQL-034, SQL-044, SQL-023, Details). - Allow the expense type to change. Because the expense type code is part of the key,
BeforeUpdateon both amount classes binds the previous code asLastExpenseTypeCodealongsideLastUpdateNum, andAfterInsert/AfterUpdatere-synchronize the criteria's expense type code to the current value. This is what lets an operator correct a misclassified breakdown line in place rather than deleting and re-adding it. - Delete. The header's delete targets
pk82500_eaip.eaip_reimbursement_delete(SQL-045, Details); a code comment records that the child details and amounts are removed by database triggers, so this library issues no cascading child deletes. - Retrieve remittances for downstream work. Three shared readers serve the balancing run and the operator screens: by received date through
GetReimbByReceivedDate, by posted date throughGetReimbByPostedDate(Details) — the entry point for DCBS reimbursement balancing — and by reconciled flag throughGetReimbReconciledFlag(Details), which drives the outstanding-remittance worklist. - Bypass validation for batch work. Setting
OverrideBusinessRuleson the header makesIsValidreturn true unconditionally, regardless of broken rules on the object or its children. The balancing run relies on this so that a remittance naming a claim SAIF cannot resolve can still be saved with its reconciliation outcome recorded, rather than blocking the whole batch.*
Process flow¶
The following diagram visualizes this operation's control flow.
flowchart TD
Start([Remittance received from DCBS]) --> New[NewReimbursement: eaip_reimb_seq nextval,<br>create stamp]
New --> Head[Set received date, posted date,<br>amount, explanation]
Head --> Det[Add a detail per claim:<br>eaip_reimb_detail_seq nextval]
Det --> Resolve[Setting DcbsSaifClaimNum clears cache;<br>ClaimData re-resolves the SAIF claim]
Resolve --> Rule{Detail dirty and<br>claim data invalid?}
Rule -->|Yes| Broken[Rule violation:<br>Claim number not found]
Rule -->|No| Amt[Add expense-type amounts at<br>detail level and header level]
Broken --> Amt
Amt --> Save([Save])
Save --> Ovr{OverrideBusinessRules set?}
Ovr -->|Yes| Write
Ovr -->|No| Valid{IsValid?}
Valid -->|No| Reject([Save rejected])
Valid -->|Yes| Write[Insert or update the header<br>with LastUpdateNum check]
Write --> Rows{RowsAffected = 1?}
Rows -->|No| Err([DB contention error;<br>children not saved])
Rows -->|Yes| Kids[Save details: recompute TotalAmount<br>from detail amounts, then save amounts]
Kids --> Done([Remittance recorded and<br>ready for balancing])
Failure and edge-case behavior¶
OverrideBusinessRulessuppresses all validation on the header, including violations raised by its children. Anything saved through that path bypasses the claim-number check entirely.- The detail's claim rule short-circuits on
Not IsDirty, so an existing detail whose claim later becomes invalid never reports a violation. TotalAmounton a detail is recomputed only inBeforeUpdate. On an initial insert the caller-supplied total is stored as given and may disagree with the amount breakdown until the row is next updated.*- Both amount classes are keyed by a composite that includes the expense type code, and both throw an invalid-statement exception from the create-statement property. A duplicate expense type on the same parent is rejected by the database's own key constraint rather than by a business rule.*
- Child rows are deleted only by database triggers when the parent is deleted; deleting a child through this library requires deleting it individually before the parent save.
- Every statement checks its affected row count and raises a DB contention error on anything other than one, but the header, detail, and amount saves are separate statements with no surrounding transaction in this code, so a mid-cascade failure can leave a partially saved remittance.*
- The detail binds the DCBS worker name only when the resolved worker name is blank. A resolvable claim therefore overwrites what DCBS reported with SAIF's own name, which is exactly the value the balancing run later compares for name mismatches.
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.EAIP\Reimbursement\clsReimbursement.vbBusiness\SAIF.Business.Claim.EAIP\Reimbursement\clsReimbursementDetail.vbBusiness\SAIF.Business.Claim.EAIP\Reimbursement\clsAmount.vbBusiness\SAIF.Business.Claim.EAIP\Reimbursement\clsDetailAmount.vb