Skip to content

Disability activity tracking

Disability activity tracking covers two parallel entity families for a claim: disability status activity, which records the dates on which disability status changed, and disability authorization activity, which records time-loss authorization dates and reason codes. Both collections load newest-first, stamp the claim's injury context onto every item for cross-validation, enforce a non-decreasing date sequence, and persist through the usual insert, update, and delete lifecycle with row-count concurrency checks.

Field Value
Operation ID OP-CM-07
Trigger Caller invokes clsClaimDisabilityActivityCollection.GetClaimDisabilityActivityCollection or clsDisabilityAuthActivityCollection.GetDisabilityAuthActivityCollection, edits or adds items, and calls Save() on the collection*
Inputs ClaimID (Decimal, key for both families); DisabilityDate; DisabilityAuthReasonCode and DisabAuthActivityDate; the sequence keys DisabilityActivitySubNum and DisabAuthActivitySubNum; UpdateNum as the concurrency token on updates; the acting user from the data-portal info
Outputs Inserted, updated, and deleted rows in the claim disability activity and disability authorization activity tables; in-memory latest item and current authorization, the history collection, the maximum disability date, and broken-rule messages
Primary components clsClaimDisabilityActivity, clsClaimDisabilityActivityCollection (GetLatestRecord, GetInjuryDate, GetMaxDisabilityDate, UpdateHistoryCollections), clsDisabilityAuthActivity, clsDisabilityAuthActivityCollection (NewDisabilityAuthActivity, CurrentDisabAuth)
Entry point Business\SAIF.Business.Claim.Maintenance\clsClaimDisabilityActivityCollection.vb

Steps

  1. Retrieve the disability status history. GetClaimDisabilityActivityCollection(dataPortal, claimID) builds a criteria and calls the portal's retrieve; BeforeRetrieve binds the claim identifier and the statement selects every row for the claim ordered by activity sub-number descending (SQL-043, CL_CLAIM_DISABILITY_ACTIVITY).
  2. Materialize the status rows. AfterRetrieve loops the reader, creates one activity object per row, calls Load and Fill to populate claim identifier, disability date, sub-number, and audit fields, re-attaches a criteria, and adds each item to the collection.
  3. Fetch the injury context. When the cached injury date is still the minimum date, GetInjuryDate() issues a separate request that reads the injury date and occupational-disease code for the claim into collection-level fields (SQL-042, CL_INJURY_CLAIM).
  4. Stamp the injury context onto each item. Every loaded item receives the collection's injury date and occupational-disease code so it can self-validate.
  5. Determine the working "latest" row (GetLatestRecord).
  6. If the collection is empty, create a brand-new activity item whose claim identifier is set, whose sub-number and update number are zero, and whose disability date is the minimum date; mark it clean and add it as the latest item.
  7. Otherwise, sort descending by sub-number and take the first non-deleted item as the latest; if that item has already been saved, append a copy with the sub-number incremented by one so the caller gets a pre-seeded "add next status" row.
  8. Edit and validate a status item. Setting the disability date marks the item dirty; the item rules then require the date not to be in the future (checked only when the smart-date value was modified), require a date whenever the object is dirty, and forbid a date earlier than the injury date unless the claim is an occupational-disease claim.
  9. Enforce status chronology at the collection level. The collection rule sorts items descending by sub-number and rejects the set if any earlier-sequence item's date is less than a later one, so disability dates must be non-decreasing across the sequence; only items that are new and dirty or already saved take part.
  10. Save the disability status collection. Save() applies the pending edit and the base save dispatches per item:
  11. Insert: bind the disability date, acting user, claim identifier, and sub-number, then execute the insert; a rows-affected value other than one adds an insert error (SQL-003, CL_CLAIM_DISABILITY_ACTIVITY).
  12. Update: bind the disability date, update number, acting user, claim identifier, and sub-number and match on all three keys for optimistic concurrency; zero rows affected adds an update error carrying the DB contention message (SQL-088, CL_CLAIM_DISABILITY_ACTIVITY) (BR-CM-001).
  13. Delete: bind the claim identifier and sub-number; zero rows affected adds a delete error carrying the DB contention message (SQL-107, CL_CLAIM_DISABILITY_ACTIVITY) (BR-CM-001).
  14. Housekeeping after removal. Removing an item rebuilds the history collection from all list items except clean-new placeholders and re-sorts it descending by sub-number for grid display; the maximum-disability-date helper re-sorts and returns the first non-placeholder item's date, which is used to keep the claim's disability date in step.*
  15. Retrieve the disability authorization history. GetDisabilityAuthActivityCollection(dataPortal, claimID) runs a statement that joins the authorization table to the claim on claim identifier and returns every authorization row plus the injury date, ordered by authorization sub-number descending (SQL-065, CL_DISABILITY_AUTH_ACTIVITY, CL_INJURY_CLAIM).
  16. Materialize the authorization rows. AfterRetrieve loads each row into an authorization object — claim identifier, reason code, activity date, sub-number, audit fields, and the joined injury date — tracks the highest sub-number seen, and sorts the collection descending.
  17. Fall back to a separate injury-date read. If the injury date is still the minimum date after the join-based load, a scalar query supplies it, guarded by a date check before assignment (SQL-064, CL_INJURY_CLAIM).
  18. Add a new authorization activity. NewDisabilityAuthActivity(claimID) increments the maximum-sequence counter, creates an empty item (claim identifier and acting user set, reason code defaulted to 0, activity date empty, sub-number zero, marked new then clean), assigns the collection's injury date and the new sub-number, adds it, and re-sorts descending.
  19. Edit and validate an authorization item. Setting the reason code or activity date marks the item dirty; the item rules forbid a date more than seven days in the future, require the date when the object is dirty, require a non-zero reason code when dirty, and forbid a date earlier than the injury date.
  20. Enforce authorization chronology at the collection level. The collection rule sorts descending by sub-number and rejects the set if any earlier-sequence date is less than a later one; unlike the status collection, it compares all rows rather than only dirty or saved ones.
  21. Save the authorization collection. Save() applies the pending edit and the base save dispatches per item:
    • Insert: bind the activity date, acting user, claim identifier, reason code, and sub-number; zero rows affected adds an insert error (SQL-013, CL_DISABILITY_AUTH_ACTIVITY).
    • Update: bind the reason code, activity date, update number, acting user, claim identifier, and sub-number, matching on claim, sub-number, and update number; zero rows affected adds an update error carrying the DB contention message (SQL-095, CL_DISABILITY_AUTH_ACTIVITY) (BR-CM-001).
    • Delete: bind the claim identifier and sub-number; a rows-affected value other than one adds a delete error carrying the DB contention message (SQL-114, CL_DISABILITY_AUTH_ACTIVITY) (BR-CM-001).
  22. Expose the current authorization. CurrentDisabAuth scans the list for the highest sub-number and, when the collection is empty, returns a transient empty authorization that is never added to the list, so bound consumers always receive a non-null object.

Process flow

The following diagram visualizes this operation's control flow across both entity families.

flowchart TD
    Start([Caller requests disability data<br>for a claim]) --> Family{Which family?}
    Family -->|Disability status| SRead[Select activity rows<br>ordered by sub-number desc]
    SRead --> SLoad[Load one item per row]
    SLoad --> SInj[Read injury date and<br>occupational disease code]
    SInj --> SStamp[Stamp injury context<br>onto every item]
    SStamp --> SLatest{Collection empty?}
    SLatest -->|Yes| SNew[Create blank latest item]
    SLatest -->|No| SCopy[Take newest item;<br>append incremented copy<br>if it was already saved]
    SNew --> Edit
    SCopy --> Edit
    Family -->|Disability authorization| ARead[Select authorization rows<br>joined to the claim]
    ARead --> ALoad[Load items; track max sequence;<br>sort desc]
    ALoad --> AInj{Injury date resolved?}
    AInj -->|No| AFall[Scalar injury date query<br>guarded by a date check]
    AInj -->|Yes| ANew[NewDisabilityAuthActivity<br>seeds next sequence]
    AFall --> ANew
    ANew --> Edit[Caller edits item fields]
    Edit --> Rules[Item rules: required, future date,<br>not before injury date]
    Rules --> Seq[Collection rule: dates must be<br>non-decreasing by sequence]
    Seq --> Ok{Rules pass?}
    Ok -->|No| Invalid([Broken rules returned;<br>no persistence])
    Ok -->|Yes| Save[Save applies edit,<br>dispatches per item]
    Save --> Kind{Item state}
    Kind -->|New| Ins[Insert row]
    Kind -->|Modified| Upd[Update matching<br>claim, sub-number, update num]
    Kind -->|Removed| Del[Delete by claim<br>and sub-number]
    Ins --> Rows{Expected rows affected?}
    Upd --> Rows
    Del --> Rows
    Rows -->|No| Err([Insert, update, or delete error;<br>DB contention message])
    Rows -->|Yes| Done([Item marked old;<br>history collections rebuilt])

Failure and edge-case behavior

  • Concurrency violations — another user updated or deleted the row first, so the update number no longer matches — surface as zero rows affected in the update and delete hooks for both entity families and produce a DB contention broken-rule message rather than a thrown exception (BR-CM-001).
  • The two insert hooks disagree on the exact row-count test: one treats any count other than one as failure while the other treats only zero as failure. This is a source inconsistency, not a documented business distinction.*
  • The two delete hooks are inconsistent in the same way, one testing for zero and the other for a count other than one.*
  • The future-date rule on disability status runs only when the smart date's value was modified, so a loaded, unmodified date is never re-validated against today; the required and injury-date rules always evaluate when the object is dirty or a date is set.
  • The injury-date cross-check on disability status is bypassed entirely for occupational-disease claims, allowing a disability date earlier than the injury date in that case.*
  • If the latest non-deleted status item is itself new and never saved, no extra copy row is appended — the existing new item is reused, avoiding duplicate blank rows.
  • The authorization collection's fallback injury-date query guards its scalar result with a date check, silently leaving the injury date at its default when the query returns no row or a non-date value.
  • The maximum-date and history-rebuild helpers both special-case clean-new placeholder rows so the auto-generated blank entry does not pollute max-date lookups or the history grid.
  • Statement properties that a given class does not use throw an invalid-statement application exception when invoked, guarding against use of the wrong data-access path.
  • The two collections each enforce chronological ordering and injury-date cross-checks independently and do not coordinate with each other at the level shown in the source.*

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.Maintenance\clsClaimDisabilityActivity.vb
  • Business\SAIF.Business.Claim.Maintenance\clsClaimDisabilityActivityCollection.vb
  • Business\SAIF.Business.Claim.Maintenance\clsDisabilityAuthActivity.vb
  • Business\SAIF.Business.Claim.Maintenance\clsDisabilityAuthActivityCollection.vb