Skip to content

Manage expenses

Recovery expenses (clsThrdpartyExpense) are individual cost entries tied to a case, and the expense-approval record (clsThrdpartyExpenseApproval) tracks the approval status for the case's expense total. As the running total of a case's expenses crosses fixed dollar thresholds, the approval object automatically resets the approval code to require the next level of sign-off.

Field Value
Operation ID OP-TP-03
Trigger clsThrdpartyExpense.NewThrdpartyExpense / GetThrdpartyExpense followed by property edits and Save(); clsThrdpartyExpenseApproval.GetThrdpartyExpenseApproval followed by an approval-code edit and Save()
Inputs ThrdpartyCaseSeqNum, expense text/type, expense date, expense amount, recovery amount, budget code, expense-approval code
Outputs Persisted THRDPARTY_EXPENSE rows; persisted expense-approval code on the case; approver user/date stamped when an expense is approved
Primary components clsThrdpartyExpense.AddBusinessRules, clsThrdpartyExpense.Save (inherited), clsThrdpartyExpenseApproval.SetExpenseApproval, clsThrdpartyExpenseApproval.AddBusinessRules
Entry point Business\SAIF.Business.Claim.ThirdParty\clsThrdpartyExpense.vb

Steps

  1. Create or retrieve an expense. Create() seeds a new expense row against a ThrdpartyCaseSeqNum; retrieval reads existing rows by case (SQL-053/SQL-054, THRDPARTY_EXPENSE).
  2. Validate the expense (IsValid), skipped entirely for a deleted expense:
  3. Expense text (type) is required (BR-018).
  4. Expense amount is required (non-zero) and must not be negative (BR-018).
  5. Expense date, if entered, must fall between the claim's date of injury and today; the date-of-injury bound is obtained by retrieving the owning case. > Origin: The date-of-injury bound is read from clsThirdPartyCase.GetThirdPartyCase, documented in Maintain recovery case (SAIF.Business.Claim.ThirdParty).
  6. Budget code is required whenever a non-zero recovery amount is entered (BR-019).
  7. Recovery amount must not be negative and must not exceed the expense amount (BR-019).
  8. A confidential-claim security check exists as a rule stub but always returns True; it has no enforced effect today.*
  9. Persist the expense through the inherited BOF save lifecycle: insert (SQL-024), update (SQL-079), or delete (SQL-092) against THRDPARTY_EXPENSE.
  10. On a rows-affected value other than 1: an InsertError/UpdateError/DeleteError message is added.
  11. Retrieve the expense-approval record (clsThrdpartyExpenseApproval) for the case (SQL-052, THRDPARTY_EXPENSE); if no code is stored, it defaults to NOTR (not required).
  12. Recompute the approval code (SetExpenseApproval) based on the case's running ExpenseCollection.ExpenseTotal against two fixed limits:
  13. Below the lower limit: the approval code is forced to NOTR regardless of its prior value.
  14. At or above the lower limit but below the upper limit, and the collection needs approval: transitioning into APPR (approved) stamps ApproverUser/ApprovalDate on any not-yet-approved expenses; transitioning out of DISA back toward approved re-checks whether any expense is still unapproved.
  15. Validate the approval code (IsValid), evaluated only while the approval object is dirty:
  16. If the total is at or above the lower limit and below the upper limit and the collection needs approval, an approval code of NOTR or blank produces a warning that supervisor approval is required (BR-020).
  17. If the total is at or above the upper limit and the collection needs approval, the same condition produces a warning that director approval is required (BR-020).
  18. Both checks are warnings, not hard errors, so the expense can still be saved with an unresolved approval code.
  19. Persist the approval code on the case-scoped approval row (SQL-078, THRDPARTY_EXPENSE).

Process flow

The following diagram visualizes expense validation and the escalating approval-tier logic.

flowchart TD
    Start([Caller creates or edits expense]) --> ERules[Validate type, amount,<br>expense date, budget code,<br>recovery amount]
    ERules --> EOk{Valid?}
    EOk -->|No| Fail([Broken rules returned])
    EOk -->|Yes| ESave[Insert, update, or delete<br>THRDPARTY_EXPENSE]
    ESave --> Rows{RowsAffected = 1?}
    Rows -->|No| Contention([Insert/Update/Delete error added])
    Rows -->|Yes| Recompute[Recompute expense total<br>for the case]
    Recompute --> Tier{Total vs. thresholds}
    Tier -->|"< $5,000"| NotReq[Approval code forced to NOTR]
    Tier -->|"$5,000-$24,999"| Lower{Approval code<br>NOTR or blank?}
    Tier -->|">= $25,000"| Upper{Approval code<br>NOTR or blank?}
    Lower -->|Yes| WarnLower([Warning: supervisor<br>approval required])
    Lower -->|No| ApprSave[Persist approval code]
    Upper -->|Yes| WarnUpper([Warning: director<br>approval required])
    Upper -->|No| ApprSave
    NotReq --> ApprSave
    WarnLower --> ApprSave
    WarnUpper --> ApprSave
    ApprSave --> Done([Approval record saved])

Failure and edge-case behavior

  • The $5,000/$25,000 approval-tier checks are warnings, so an expense total can cross a threshold and still be saved without a resolved approval code; enforcement relies on UI-level review of the warning.*
  • The confidential-claim security rule for expenses is present in code as a permanently-True stub; it does not currently block access to expenses on confidential claims.*
  • The budget-code requirement only applies when a recovery amount is entered — an expense with no recovery amount can be saved without a budget code.
  • ValidExpenseDate retrieves the owning case on every validation pass to obtain the date-of-injury bound, adding a database round trip per validation cycle.*

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.ThirdParty\clsThrdpartyExpense.vb
  • Business\SAIF.Business.Claim.ThirdParty\clsThrdpartyExpenseApproval.vb
  • Business\SAIF.Business.Claim.ThirdParty\clsThrdpartyExpenseCollection.vb
  • Business\SAIF.Business.Claim.ThirdParty\clsThirdPartyConstants.vb