Skip to content

Provider address retrieval

Provider address retrieval reads every PROVIDER_ADDRESS row for a location (left-outer-joined so a location with no addresses still returns a placeholder row of location-only data), then offers in-memory filtering to find the active correspondence, physical, or payment address as of a given date. A separate set of shared GetAddress overloads resolves a billing address across a child/parent location pair, preferring the parent's address when one is set.

Field Value
Operation ID OP-VP-03
Trigger clsProviderAddressCollection.GetProviderAddressCollection(inDataportal, inProviderLocationID) — invoked directly or via clsProviderLocation.Addresses; clsProviderAddress.GetAddress(dpi, providerLocationID, parentProviderLocationID, addressType) and its overloads
Inputs Provider location ID (Decimal); for GetAddress, a child provider location or ID, a parent provider location ID, and an optional AddressTypes (Correspondence, Payment, or Physical; defaults to Correspondence)
Outputs A populated clsProviderAddressCollection; ActiveAddresses()/ActiveAddresses(date), CorrespondenceAddress, PhysicalAddress, PaymentAddress derived subsets; a single resolved clsProviderAddress from GetAddress
Primary components clsProviderAddressCollection.GetProviderAddressCollection, clsProviderAddressCollection.CalculatePrimaryAddress, clsProviderAddressCollection.FilterAddress, clsProviderAddress.GetAddress (three overloads)
Entry point Business\SAIF.Business.View.Provider\clsProviderAddressCollection.vb

Steps

  1. Request all addresses for a location. GetProviderAddressCollection builds a criteria carrying the provider location ID and retrieves through the standard data-portal path.
  2. Bind the location parameter. BeforeRetrieve binds :ProviderLocationID and caches it on the collection instance.
  3. Execute the join query. The shared retrieve SQL left-outer-joins PROVIDER_LOCATION to PROVIDER_ADDRESS on location ID, so a location with zero addresses still returns exactly one row of NULL address fields (SQL-005, SQL-006, PROVIDER_LOCATION, PROVIDER_ADDRESS). The same SQL constant (clsProviderAddress.RETRIEVE_SQL) is shared by both the collection's own criteria and a per-item clsProviderAddress.Criteria, so SQL-005 and SQL-006 are the same statement catalogued from each criteria's perspective.*
  4. Populate the collection. AfterRetrieve iterates the result set, constructs a clsProviderAddress per row (seeded with the location ID), calls Load, and adds each to the collection.
  5. Each row's termination date defaults to Date.MaxValue when the underlying EXP_DATE is null, so an address with no expiration is treated as open-ended rather than immediately expired.
  6. Filter to active addresses. ActiveAddresses() (defaulting to now) or ActiveAddresses(activeDate) returns the subset whose start/termination window contains the target date, and records that date on the returned sub-collection.
  7. Resolve a primary address by type. CorrespondenceAddress, PhysicalAddress, and PaymentAddress each call CalculatePrimaryAddress with their respective AddressTypes value:
  8. Correspondence: prefer an active row coded COR; if none, fall back to a PHY (physical) row.
  9. Payment: prefer an active row coded PAY; if none, fall back to PHY; if still none, fall back to COR.
  10. Physical (or any other type): prefer PHY; if none, fall back to COR.
  11. If no address matches any fallback: return a new, empty clsProviderAddress rather than Nothing.
  12. Resolve a billing address across a location pair. GetAddress (single-provider-location overload) retrieves both the child and parent provider locations and delegates to the pair-based overload.

Origin: The child and parent location retrievals delegate to the Provider location retrieval operation implemented in this library. 8. Compare child and parent addresses. The pair-based GetAddress reads each location's ActiveAddresses.PrimaryAddress(addressType) (step 6, evaluated against each location independently) and prefers the parent's address when it is not empty, cloning it and overwriting its display name and location ID with the child's business name and location ID so the billing address still reads as belonging to the child. - If the parent's resolved address is empty: return the child's own resolved address unchanged.

Process flow

The following diagram visualizes this operation's control flow.

flowchart TD
    Start([Addresses requested for a location]) --> Exec[Execute left outer join query<br>PROVIDER_LOCATION to PROVIDER_ADDRESS]
    Exec --> Loop[For each row: create clsProviderAddress,<br>Load, add to collection]
    Loop --> Done([Populated collection returned])
    Done --> Use{Consumer request}
    Use -->|ActiveAddresses at date| Filter[Filter to rows whose window<br>covers the target date]
    Use -->|CorrespondenceAddress| CalcC[Prefer COR; fallback to PHY]
    Use -->|PaymentAddress| CalcP[Prefer PAY; fallback to PHY;<br>fallback to COR]
    Use -->|PhysicalAddress| CalcPh[Prefer PHY; fallback to COR]
    CalcC --> Found{Match found?}
    CalcP --> Found
    CalcPh --> Found
    Found -->|No| Empty([Empty clsProviderAddress returned])
    Found -->|Yes| Return([Matching address returned])
    Use -->|GetAddress child/parent| Pair[Resolve primary address<br>for each location independently]
    Pair --> ParentSet{Parent address empty?}
    ParentSet -->|No| UseParent[Clone parent address;<br>overwrite name and location ID with child's]
    ParentSet -->|Yes| UseChild[Return child's own resolved address]

Failure and edge-case behavior

  • A location with zero address rows still returns a one-row result (via the left outer join), so callers cannot distinguish "no addresses" from "one placeholder row" without inspecting the address fields for null.*
  • CalculatePrimaryAddress never returns Nothing; a location with no address of any matching type receives a new, empty clsProviderAddress, so downstream code must check for emptiness rather than a null reference.
  • The billing-address resolution in GetAddress always prefers a non-empty parent address over the child's own, even when the child has its own valid address of the requested type — this is by design for locations that bill through a parent.
  • IsActive on clsProviderAddress is hard-coded to always return True ("For now, only worry about Active Addresses"), so it does not reflect the address's actual effective/termination window; callers rely on ActiveAddresses(date) filtering instead.*

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.View.Provider\clsProviderAddress.vb
  • Business\SAIF.Business.View.Provider\clsProviderAddressCollection.vb