Skip to content

Accident injury management

Accident injury management owns the injury-facing columns of the claim row: the injury date and time, exposure and employment-injury codes, injury source, premises and inpatient flags, the free-text SAIF event description, and the injury address. Its distinguishing feature is a large set of cross-validation rules that only fire when the injury date or initial treatment date is actually modified, several of which issue live count queries against sibling claim tables. The object supports retrieve and update only; the claim row itself is never created or deleted here.

Field Value
Operation ID OP-CM-02
Trigger Caller invokes clsAccidentInjury.GetAccidentInjury(dpi, claimID) (read) or NewAccidentInjury (in-memory instance), edits properties, and calls Save()
Inputs ClaimID (Decimal criteria key); editable fields ExposureCode, EmploymentInjuryCode, InitialTreatmentDate, InjuredOnPremisesCode, InjuryDate, InjurySourceCode, InjuryTime, InPatientFlagCode, FederalInjuryLocationCode, HardwareCausedFlagCode, HighSeasFlag, MultipleWorkerFlagCode, PersonCausedFlagCode, SaifEventDescr, and the injury address; read-only supporting data (ClaimTypeCode, ClaimStatusCode, JurisdictionCode, PolicyNum, WorkerID, BirthDate, DeathDate, KnowledgeDate, Received801Date, ReceivedDate, LeaveWorkDate, DisabilityDate)
Outputs Updated claim row (address, injury, and flag columns plus audit fields); conditional deletion of three-day-wait rows; cascading save or delete of the employee work-address child; federal awards set to pending; broken-rule collection
Primary components clsAccidentInjury.GetAccidentInjury, clsAccidentInjury.Fill, clsAccidentInjury.IsValid, clsAccidentInjury.Save, clsAccidentInjury.BeforeUpdate, clsAccidentInjury.AfterUpdate, clsAccidentInjury.DetermineCountyCode, clsAccidentInjury.SetFederalAwardsToPending, clsAccidentInjury.CheckForMultipleClaimsForWorker
Entry point Business\SAIF.Business.Claim.Maintenance\clsAccidentInjury.vb

Steps

  1. Retrieve the accident/injury record. GetAccidentInjury(inDataportal, inClaimID) builds a Criteria holding the data-portal info and ClaimID and calls DataAccessLayer.RetrieveObject (SQL-026, CL_INJURY_CLAIM, CL_CLAIM_PERSON).
  2. BeforeRetrieve builds the request from MyCriteria.RetrieveSQL and binds ClaimID.
  3. AfterRetrieve reads the first row and calls Fill; if no row is read, the object remains unfilled and no explicit not-found error is raised.*
  4. Populate in-memory state (Fill).
  5. Map the claim and person columns (claim type and status, jurisdiction, dates, flags, policy number, birth and death dates) into smart-typed fields.
  6. Build the injury address through SetUpInjuryAddress() with state, zip, and zip+4 validation enabled, normalize zip padding and blank handling, and mark the address clean.
  7. Load the child work-address object for the same claim.

    • Sub-step: the work-address object issues its own retrieve keyed by ClaimID and hydrates the employer-provided work address used for validation and display.

    Origin: The employee work-address retrieve is implemented by clsClaimEmployeeWorkAddress (SAIF.Business.Claim) and 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 the SAIF.Business.Claim documentation set. - AfterRetrieve calls MarkOld() so the freshly loaded object is not dirty. 3. Alternate construction from a shared reader (Load). When a parent business object already holds an open reader, Load calls Fill, constructs a fresh criteria object, and calls MarkOld() without issuing its own query. 4. Caller edits fields. Each setter trims and compares the incoming value and calls MarkDirty() only on a real change. - Setting InjuryDate resets the cached cross-check counts to -1 so the dependent rules re-query. - Setting InjuryTime appends .00 to a non-blank value before storing. 5. Validate the object (IsValid). - MyBase.IsValid runs the registered rule set (step 6). - Compute m_InjuryDateModified, m_InitialTreatmentDateModified, and m_ExposureCodeModified from the corresponding modified flags. - Compute m_InpatientFlagCodeChangedfromNtoY, true only when the inpatient flag moved from N to Y. - Validate the child work-address object and propagate its rules onto this object; if the child is invalid, the whole object is invalid and no persistence occurs. 6. Evaluate the injury-date and initial-treatment-date rule set. All of these fire only when the relevant date's modified flag is set, so pre-existing data is not re-flagged on unrelated saves: - Requiredness and plausibility: BR-CM-040, BR-CM-041, BR-CM-056. - Duplicate-claim warning: BR-CM-042, which runs a self-join count over the claim table (SQL-021, CL_INJURY_CLAIM) and returns the duplicate claim number for the message. - Wage re-verification warning on disease claims: BR-CM-043. - In-memory date comparisons against claim and person dates: BR-CM-044, BR-CM-045, BR-CM-046, BR-CM-047, BR-CM-048, BR-CM-049, BR-CM-054, BR-CM-055. - Lazily queried cross-table comparisons, each executed only when its cached count is still -1: - BR-CM-050 (SQL-027, CL_CLAIM_WORK_RELEASE_STATUS). - BR-CM-051 (SQL-025, CL_CLAIM_REQUEST_DECISION). - BR-CM-052 (SQL-023, CL_DISABILITY_AUTH_ACTIVITY). - BR-CM-053 (SQL-024, CL_MEDICAL_CONDITION). - Delegated service checks: BR-CM-057 blocks the change outright when unposted payments or adjustments exist, and BR-CM-058 warns when no policy coverage exists at the injury date for policy numbers greater than 17. - Sub-step: ClaimServices.HasUnpostedPaymentsOrAdjustments inspects the claim's payment and adjustment queues for records that have not yet posted and returns a boolean used directly as the rule result. - Sub-step: PolicyServices.CoverageExists resolves whether the policy had coverage in force on the injury date.

    Origin: Both checks are implemented by the claim and policy service classes in SAIF.Business.Claim and 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 the SAIF.Business.Claim documentation set. - If any error-severity rule breaks: the save is blocked and the caller inspects the broken-rule collection; warnings do not block. 7. Save the object (Save). - If the work-address child is not new and reports empty, delete it through its own delete path. - Otherwise, if that child is dirty, save it through SaveChildObject. - If federal award records exist with benefit payments, SetFederalAwardsToPending() sets each award status to P and clears each benefit payment's status and approver, then saves the award collection if dirty. - Call AcceptChanges(), then MyBase.Save(), and call MarkOld() on success. 8. Build and execute the update (BeforeUpdate). - Call DetermineCountyCode() first (step 9) so the derived county code is current. - Capture the update user from the data-portal info. - Strip a single leading zero from the county code when it is longer than one character before binding it. - Bind all editable fields, the address city/state/zip/zip+4, and the ClaimID/UpdateNum concurrency key to the parameterized update (SQL-081, CL_INJURY_CLAIM). - If the inpatient flag changed from N to Y: queue a second non-query that deletes the claim's three-day-wait rows, because an inpatient stay invalidates waiting-period tracking (SQL-106, CL_CLAIM_TD_THREE_DAY_WAIT). 9. Derive the county code (DetermineCountyCode). - Reset the address county to 0. - If a non-blank state code other than OR is present, set the county to the non-Oregon constant 37. - Otherwise, if a zip code is present, look up the county code by zip and use the result when it is not null (SQL-022, ZIP_MCO_COUNTY). 10. Verify the update (AfterUpdate). - If no row was affected — a stale UpdateNum or a removed claim — add UpdateError with the DB contention message (BR-CM-001). 11. Load federal awards on demand. WorkerFederalAwards lazily retrieves the worker's active PTD, PPD, and fatal awards only when the injury date was modified and the cache is empty; the result drives the pending-award side effect in step 7. 12. Aggregate dirtiness (IsDirty). The object combines its own dirty flag with the injury address and the work-address child, so a nested address change marks the whole object dirty.

Process flow

The following diagram visualizes this operation's control flow.

flowchart TD
    Start([GetAccidentInjury claimID]) --> Read[BeforeRetrieve issues<br>injury select]
    Read --> Fill[Fill maps columns,<br>builds injury address,<br>loads work address child]
    Fill --> Clean[MarkOld]
    Clean --> Edit[Caller edits injury fields]
    Edit --> Valid[IsValid runs]
    Valid --> Child{Work address child valid?}
    Child -->|No| Blocked([Object invalid;<br>no persistence])
    Child -->|Yes| Rules{Injury date or treatment<br>date modified?}
    Rules -->|Yes| Cross[Evaluate date rules;<br>lazily run cross-table counts<br>and service checks]
    Rules -->|No| SaveStart[Save begins]
    Cross --> Errors{Any error-severity<br>rule broken?}
    Errors -->|Yes| Blocked
    Errors -->|No| SaveStart
    SaveStart --> WorkAddr[Delete or save<br>work address child]
    WorkAddr --> Awards{Federal awards<br>with payments?}
    Awards -->|Yes| Pending[Set awards to pending<br>and save collection]
    Awards -->|No| County[DetermineCountyCode]
    Pending --> County
    County --> Update[BeforeUpdate issues<br>claim update]
    Update --> Inpatient{Inpatient flag N to Y?}
    Inpatient -->|Yes| DeleteWait[Delete three-day-wait rows]
    Inpatient -->|No| Rows{RowsAffected > 0?}
    DeleteWait --> Rows
    Rows -->|Yes| Ok([MarkOld; save succeeded])
    Rows -->|No| Contention([DB contention error added;<br>changes retained in memory])

Failure and edge-case behavior

  • If the retrieve finds no row for the given ClaimID, the object is returned unfilled with default values rather than raising a not-found error.*
  • Optimistic concurrency failure — a stale UpdateNum or a concurrently deleted row — surfaces as a DB contention error rather than a database exception (BR-CM-001); the caller must inspect the broken-rule collection.
  • An injury-date change is blocked outright, not merely warned, when unposted payments or adjustments exist, preventing a mismatch between the injury date and already-posted financials (BR-CM-057).
  • The "injury date after X" checks fire only when the comparison date is populated and only when the injury date was actually modified, so unchanged legacy data is not re-flagged on unrelated saves.
  • The lazy count fields are cached at -1 as a "not yet queried" sentinel and are reset only by an injury-date change, so repeated validation passes without a date change reuse the cached counts.
  • Changing the inpatient flag from N to Y deletes the claim's three-day-wait rows as an update side effect, with no user confirmation modeled in this class.
  • The policy-coverage check only runs when the policy number is greater than 17 — a legacy threshold that appears to separate migrated from current policy numbering* — and is a warning rather than a blocking error.
  • Zip normalization treats a stored zip of 0 as blank and left-pads shorter non-zero zips with zeros.
  • Commented-out legacy code (body parts, DB2 awards, non-federal award pending logic, jurisdiction lookup) is present but inactive and is not part of current behavior.

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\clsAccidentInjury.vb