Skip to content

EOB preference management

clsProviderEOB represents one provider location's paperless-EOB (Explanation of Benefits) delivery preference — which external user receives EOB correspondence and whether delivery is electronic or paper. clsProviderEOBCollection lists every location for a provider, including locations that have never configured a preference, by left-outer-joining PROVIDER_LOCATION to PROVIDER_EOB_INTERFACE. Retrieval, creation, update, and deletion all share the same optimistic-concurrency and default-flag rules, so they are documented together.

Field Value
Operation ID OP-PP-01
Trigger Caller invokes GetProviderEOBs/NewProviderEOBs (collection) or GetProviderEOB/NewProviderEOB (single object), edits the returned object(s), and calls Save()
Inputs ProviderSeqNum, ProviderLocationSeqNum, ExtUserTypeSeqNum, PaperlessEOBFlag, DefaultPrimaryFlag
Outputs Populated clsProviderEOB / clsProviderEOBCollection; persisted PROVIDER_EOB_INTERFACE row on save; InsertError/DBContentionError on save failure
Primary components clsProviderEOB.GetProviderEOB, clsProviderEOB.NewProviderEOB, clsProviderEOB.BeforeInsert/AfterInsert, clsProviderEOB.BeforeUpdate/AfterUpdate, clsProviderEOB.BeforeDelete/AfterDelete, clsProviderEOBCollection.GetProviderEOBs/NewProviderEOBs, clsProviderEOBCollection.AfterRetrieve
Entry point Business\SAIF.Business.Provider.PaymentPreference\clsProviderEOB.vb, Business\SAIF.Business.Provider.PaymentPreference\clsProviderEOBCollection.vb

Steps

  1. Retrieve the collection for a provider. GetProviderEOBs/NewProviderEOBs(dpi, providerSeqNum) build a Criteria and fetch every location for the provider, left-outer-joined to any existing PROVIDER_EOB_INTERFACE row and the external-user/email/person chain (SQL-007, PROVIDER_LOCATION, PROVIDER_EOB_INTERFACE, EXT_USER_TYPE, EXT_USER, EMAIL_ADDRESS, PERSON).
  2. AfterRetrieve iterates each row, constructs a new clsProviderEOB, and calls its Load method to fill it from that row before adding it to the collection.
  3. Fill each row and determine new-vs-old state. Fill() copies all columns onto the object, and the constant UserName fallback resolves to PAPER_EOB ("Paper EOB") whenever the joined person name is blank, signaling no external user is linked (BR-17).
  4. Fill() marks the object New when UpdateNum = 0 and Old otherwise, so a location with no prior EOB preference row (left-outer-joined nulls) is still returned as an editable object that will Insert rather than Update on save (BR-18).
  5. Retrieve a single preference. GetProviderEOB(dpi, providerSeqNum, providerLocationSeqNum) builds a Criteria and fetches one row.
  6. If ProviderSeqNum <> 0: BeforeRetrieve binds both ProviderSeqNum and ProviderLocationSeqNum and issues the by-provider-and-location query (SQL-005, PROVIDER_EOB_INTERFACE).
  7. If ProviderSeqNum = 0: BeforeRetrieve binds only ProviderLocationSeqNum and issues the location-only variant instead (SQL-006).
  8. AfterRetrieve fills the first returned row, applying the same New/Old determination as step 2 (BR-18).
  9. Create. NewProviderEOB(dpi, providerSeqNum, providerLocationSeqNum) constructs a new object and Create() seeds the keys, update user, and defaults PaperlessEOBFlag/DefaultPrimaryFlag to "N".
  10. BeforeInsert re-derives PaperlessEOBFlag: "Y" only when ExtUserTypeSeqNum is populated and non-zero at insert time, otherwise "N" (BR-01); DefaultPrimaryFlag is always reset to "N" on insert regardless of any caller-set value (BR-02).
  11. AfterInsert executes the insert (SQL-001, PROVIDER_EOB_INTERFACE) and checks the rows-affected count.
    • On a rows-affected value other than 1: add InsertError ("Insert Failed") and leave the object marked New (BR-03).
    • On success: MarkOld().
  12. Update. BeforeUpdate refreshes UpdateDate/UpdateUser and binds all mutable fields plus the in-memory UpdateNum as a WHERE predicate.
  13. AfterUpdate executes the update, which increments UPDATE_NUM at the database and requires the bound UpdateNum to match the current row (SQL-013, PROVIDER_EOB_INTERFACE).
    • On a rows-affected value other than 1: add DBContentionError (BR-04).
    • On success: MarkOld().
    • Note: unlike clsProviderEFT.AfterUpdate, clsProviderEOB.AfterUpdate does not increment the in-memory UpdateNum after a successful update, even though the database value advances; a subsequent update against the same in-memory instance would then fail contention until the object is re-retrieved.*
  14. Delete. BeforeDelete binds the provider/location keys; AfterDelete executes the delete (SQL-015, PROVIDER_EOB_INTERFACE).
  15. On a rows-affected value other than 1: add DBContentionError (BR-05).
  16. On success: MarkNew().
  17. Collection save. clsProviderEOBCollection.Save() calls ApplyEdit() and delegates to the base collection save, which persists each changed child clsProviderEOB through steps 4–6.

Process flow

flowchart TD
    Start([Caller requests EOB preference]) --> Which{Single or collection?}
    Which -->|Collection| ListQ[Query provider locations<br>left-joined to PROVIDER_EOB_INTERFACE]
    ListQ --> Fill1[Fill each row;<br>UpdateNum = 0 marks New]
    Which -->|Single, ProviderSeqNum not 0| ByBoth[Query by provider + location]
    Which -->|Single, ProviderSeqNum is 0| ByLoc[Query by location only]
    ByBoth --> Fill2[Fill row; UpdateNum = 0 marks New]
    ByLoc --> Fill2
    Fill1 --> Edit[Caller edits fields]
    Fill2 --> Edit
    Edit --> IsNew{Object marked New?}
    IsNew -->|Yes| Insert[Insert: derive PaperlessEOBFlag,<br>reset DefaultPrimaryFlag]
    IsNew -->|No, edited| Update[Update with UpdateNum<br>as WHERE predicate]
    IsNew -->|No, removed| Delete[Delete by provider + location]
    Insert --> Rows1{RowsAffected = 1?}
    Update --> Rows2{RowsAffected = 1?}
    Delete --> Rows3{RowsAffected = 1?}
    Rows1 -->|No| ErrIns([InsertError added])
    Rows1 -->|Yes| Old([MarkOld])
    Rows2 -->|No| ErrUpd([DBContentionError added])
    Rows2 -->|Yes| Old
    Rows3 -->|No| ErrDel([DBContentionError added])
    Rows3 -->|Yes| New([MarkNew])

Failure and edge-case behavior

  • Insert, update, and delete all treat any rows-affected value other than 1 as a failure and add an error message instead of throwing; the object's in-memory state (New/Old) only advances on success.
  • clsProviderEOB.AfterUpdate never increments the in-memory UpdateNum on success, unlike the EFT object's equivalent hook; reusing the same in-memory instance for a second update without re-retrieving it will likely fail the WHERE UPDATE_NUM = :UpdateNum predicate and surface a false contention error.*
  • Because the collection query left-outer-joins every provider location, a provider with no configured EOB preference for a location still yields a row (all EOB columns null) rather than omitting it; UpdateNum = 0 on that null row is what causes the object to be treated as New (BR-18).
  • clsProviderEOB's own Criteria.RetrieveSQL/RetrieveSqlLoc selection is driven purely by whether the caller passed ProviderSeqNum = 0; passing an explicit 0 is the only way to reach the location-only query.

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.Provider.PaymentPreference\clsProviderEOB.vb
  • Business\SAIF.Business.Provider.PaymentPreference\clsProviderEOBCollection.vb