Skip to content

Policy unit CRUD

A policy unit represents an NCCI reporting period of exposure and loss data for a policy. This operation covers the full lifecycle of clsPolicyUnit and clsPolicyUnitCollection: creation with sequence-number allocation and default flags, retrieval by three different key shapes, update with optimistic-concurrency checking, deletion, and activation/inactivation with its cascading correction-flag side effect.

Field Value
Operation ID OP-US-01
Trigger clsPolicyUnit.NewPolicyUnit / GetPolicyUnit / clsPolicyUnitCollection.GetPolicyUnits, followed by property edits and Save(), or ActivatePolicyUnit() / InactivatePolicyUnit()
Inputs Policy number, policy-period effective date, unit effective/expiration dates, valuation numbers, activity/correction/historical flags, premium set ID
Outputs Persisted US_POLICY_UNIT row; populated clsPolicyUnit or clsPolicyUnitCollection; derived reportability/report-type flags
Primary components clsPolicyUnit.Create, clsPolicyUnit.BeforeInsert/AfterInsert, clsPolicyUnit.BeforeUpdate/AfterUpdate, clsPolicyUnit.BeforeDelete/AfterDelete, clsPolicyUnit.BeforeRetrieve/AfterRetrieve, clsPolicyUnit.ActivatePolicyUnit, clsPolicyUnit.InactivatePolicyUnit, clsPolicyUnitCollection.BeforeRetrieve/AfterRetrieve
Entry point Business\SAIF.Business.UnitStat\clsPolicyUnit.vb, Business\SAIF.Business.UnitStat\clsPolicyUnitCollection.vb

Steps

  1. Create. NewPolicyUnit(dataPortal, policyNumber, policyPeriodEffectiveDate, unitEffectiveDate) invokes Create(), which allocates PolicyUnitSeqNum from the US_POLICY_UNIT_SEQ sequence and seeds the natural key (PolicyNumber, PolicyPeriodEffectiveDate, UnitEffectiveDate) from the criteria.
  2. New-object defaults. As properties are first read on a new object, getters substitute defaults instead of the blank initial value: ActiveUnitFlag → 'Y' (BR-US-014), LossEditFlag and ExposureEditFlag → 'Y' (BR-US-015, BR-US-026), UnitCorrectionFlag/ExposureCorrectionFlag/LossCorrectionFlag → 'N' (BR-US-016), HistoricalFlag → 'N' (BR-US-017).
  3. Validate. Save() calls ApplyEdit() then the framework validation pipeline runs ValidPolicyUnitSeqNum, requiring PolicyUnitSeqNum > 0 (BR-US-001).
  4. On failure: the broken-rule collection blocks the save; IsValid returns False.
  5. Insert. BeforeInsert sets UpdateNumber = 0, stamps UpdateUser/UpdateDate from the data-portal info, and builds the parameterized insert against every column (SQL-004, US_POLICY_UNIT). AfterInsert checks the rows-affected result:
  6. If RowsAffected <> 1: adds InsertError with the literal message "Insert Failed" (distinct from the update/delete contention message).
  7. Otherwise: MarkOld().
  8. Retrieve by sequence, natural key, or injury date. Criteria.RetrieveSQL dispatches on RetrieveType:
  9. By sequence number (SQL-022) — returns any row regardless of active status.
  10. By natural key (policy number, policy-period effective date, unit effective date) — the WHERE clause requires ACTIVE_UNIT_FLAG = 'Y' (SQL-021) (BR-US-006).
  11. By policy number and an injury/retrieve date falling within [UNIT_EFF_DATE, UNIT_EXP_DATE) — also requires ACTIVE_UNIT_FLAG = 'Y' (SQL-020) (BR-US-007).
  12. AfterRetrieve fills the object from the first result row when present and always calls MarkOld() — a no-match retrieve returns a blank but "old" object rather than raising a not-found error.
  13. Retrieve a collection. clsPolicyUnitCollection.GetPolicyUnits supports two public shapes — by policy number (SQL-024) and by policy number plus policy-period effective date (SQL-025) — both ordered by policy number, policy-period effective date, and unit effective date.
  14. A third internal retrieve type (RetrieveTypes.LossEditFlag, filtering LOSS_EDIT_FLAG = 'Y', SQL-023) is wired into Criteria.RetrieveSQL but has no corresponding public factory method on this class, so it is unreachable through the documented public surface.**
  15. Update. BeforeUpdate increments UpdateNumber, restamps UpdateUser/UpdateDate, and rebinds every column (SQL-029, US_POLICY_UNIT). AfterUpdate checks rows affected:
  16. If RowsAffected <> 1: adds UpdateError with clsConstants.Messages.DBContentionError (BR-US-020).
  17. Otherwise: MarkOld().
  18. Delete. BeforeDelete binds PolicyUnitSeqNum to the delete-by-sequence statement (SQL-035). AfterDelete checks rows affected:
  19. If RowsAffected <> 1: adds DeleteError with clsConstants.Messages.DBContentionError (BR-US-020).
  20. Otherwise: MarkNew().
  21. Activate/inactivate. ActivatePolicyUnit() sets ActiveUnitFlag, ExposureEditFlag, and LossEditFlag to 'Y'; if the unit IsReported (LastReportedValuationNumber > 0), it also sets ExposureCorrectionFlag and LossCorrectionFlag to 'Y' so the next cycle reports the reactivation as a correction (BR-US-012). InactivatePolicyUnit() sets only ActiveUnitFlag = 'N'.
  22. Derived reporting properties. Read-only properties used by later report-cycle logic: IsReportable(processDate) compares the process date to LastReportedValuationDate (BR-US-008); IsOriginalReport/IsOriginalFirstReport/IsCycleReport classify the report by UnitValuationNumber versus LastReportedValuationNumber (BR-US-009, BR-US-010, BR-US-011); IsSubjectToNonCompensableRules compares UnitEffectiveDate to the 2013-01-01 constant (BR-US-013).
    • NCCIPolicyNumber lazily derives its value through UnitStatServices.GetNCCIPolicyNumber(...) and LastReportedValuationDate lazily derives through UnitStatServices.GetLastValuationDate(...) — UnitStatServices is referenced but its implementation is not present in this library's source, so the exact derivation logic is unconfirmed.**
  23. Child collections. ClaimUnits and AuditConditions are lazily loaded on first access (clsClaimUnitCollection.GetClaimUnits, clsAuditConditionCollection.GetPolicyUnitAudits) and registered as child objects so IsValid, IsDirty, and the cascading SaveObject/SaveChildObjects pipeline include them automatically.

Process flow

The following diagram visualizes the policy-unit create/retrieve/update/delete lifecycle and the activation side effect.

flowchart TD
    Start([Caller creates or retrieves<br>a policy unit]) --> Which{Create, retrieve,<br>update, delete, or activate?}
    Which -->|Create| Seq[Allocate PolicyUnitSeqNum<br>from US_POLICY_UNIT_SEQ]
    Seq --> Defaults[Apply flag defaults:<br>ActiveUnitFlag=Y, edit flags=Y,<br>correction flags=N, HistoricalFlag=N]
    Defaults --> ValidateSeq{PolicyUnitSeqNum > 0?}
    ValidateSeq -->|No| Blocked([Broken rule blocks save])
    ValidateSeq -->|Yes| Insert[Insert US_POLICY_UNIT row]
    Insert --> InsRows{RowsAffected = 1?}
    InsRows -->|No| InsErr([InsertError: Insert Failed])
    InsRows -->|Yes| MarkOldA([MarkOld: object persisted])
    Which -->|Retrieve| RetKey{Sequence, natural key,<br>or injury date?}
    RetKey -->|Sequence| RetSeq[Select by sequence<br>any status]
    RetKey -->|Natural key| RetNat[Select by natural key<br>ACTIVE_UNIT_FLAG = Y]
    RetKey -->|Injury date| RetDate[Select by date range<br>ACTIVE_UNIT_FLAG = Y]
    RetSeq --> Fill[Fill object if a row found;<br>MarkOld regardless]
    RetNat --> Fill
    RetDate --> Fill
    Which -->|Update| Upd[Increment UpdateNumber;<br>update all columns]
    Upd --> UpdRows{RowsAffected = 1?}
    UpdRows -->|No| Contention([UpdateError: DB contention])
    UpdRows -->|Yes| MarkOldB([MarkOld])
    Which -->|Delete| Del[Delete by PolicyUnitSeqNum]
    Del --> DelRows{RowsAffected = 1?}
    DelRows -->|No| ContentionDel([DeleteError: DB contention])
    DelRows -->|Yes| MarkNewA([MarkNew])
    Which -->|Activate| Act[Set ActiveUnitFlag,<br>ExposureEditFlag, LossEditFlag = Y]
    Act --> Reported{IsReported?}
    Reported -->|Yes| Corr([Set ExposureCorrectionFlag,<br>LossCorrectionFlag = Y])
    Reported -->|No| DoneAct([Activation complete])

Failure and edge-case behavior

  • Insert failures use a distinct literal message ("Insert Failed") instead of the shared DBContentionError message used by update and delete failures.
  • The LossEditFlag collection retrieve type is reachable only through the internal Criteria/RetrieveType mechanism; no public factory method on clsPolicyUnitCollection exposes it, so SQL-023 currently has no confirmed caller inside this library.**
  • A retrieve that matches no row still marks the object Old rather than surfacing a not-found condition; callers must check the populated state themselves.
  • NCCIPolicyNumber and LastReportedValuationDate depend on UnitStatServices, whose implementing type is not present in the supplied source, so their exact derivation rules are unconfirmed.**
  • Optimistic concurrency (RowsAffected <> 1) is the only contention-detection mechanism for update and delete; no row versioning or locking is used.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • Business\SAIF.Business.UnitStat\clsPolicyUnit.vb
  • Business\SAIF.Business.UnitStat\clsPolicyUnitCollection.vb