Maintain provider address¶
clsProviderAddress maintains dated address records (physical, mailing, etc.) per provider location. Every address type keeps its own effective/expiration timeline, addresses are normalized against USPS standards through CleanAddressHelper, and address changes for the current, unexpired record are synchronized to Contact Manager through clsAddressApi.
| Field | Value |
|---|---|
| Operation ID | OP-PRV-04 |
| Trigger | Caller calls NewProviderAddress/GetProviderAddress, edits properties, and calls Save() or Delete() |
| Inputs | ProviderLocationSeqNum, AddressTypeCode, EffDate/ExpDate, ForeignAddressFlag, address lines 1–3, CityName, StateCode, ZipCode/ZipCodeExt, CountryCode |
| Outputs | Persisted PROVIDER_ADDRESS row; USPS-standardized address content; Contact Manager AddressDto sync |
| Primary components | clsProviderAddress.Create, BeforeInsert/BeforeUpdate/BeforeDelete, CleanAddressHelper.DetermineAddressLinesToClean, clsAddressApi.Add/Update/RemoveAddress |
| Entry point | Business\SAIF.Business.Provider\clsProviderAddress.vb |
Steps¶
- Create.
Create()assignsProviderLocationSeqNumand a newProviderAddressSeqNumviaGetNextSeqNum("PROVIDER_ADDRESS_SEQ")when created from a location, or uses the criteria's address seq num directly for other construction paths. - Retrieve.
BeforeRetrieve/AfterRetrieveread PROVIDER_ADDRESS byPROVIDER_ADDRESS_SEQ_NUM(SQL-043); if the retrieved row is flagged foreign (ForeignAddressFlag = "Y"),StateCodeis cleared in memory immediately after fill. - Foreign/domestic toggling. Setting
ForeignAddressFlag = "Y"clearsStateCodeas a side effect of the property setter, before save is even attempted. - Validate dates and content before save.
ValidateEffDate: hard error if the effective date is invalid, or (when modified) is before today.ValidateExpDate: hard error if the expiration date is today or in the future, or more than 30 years old; also blocks clearing an expiration date when a later same-type address already exists (BR-026).ValidateEffDateVsExpDate: hard error if the effective date is after the expiration date.ValidateExistingDates/ValidateEffOverlapingDates/ValidateExpOverlapingDates: hard errors that scanRelatedAddresses(same address type only) and reject a new open-ended address when another open-ended row of the same type exists, or when effective/expiration ranges overlap (BR-007).ValidateAddress/ValidateCity/ValidateState/ValidateZip/ValidateZipExt: hard errors requiring address line 1 always, and city/state (validated against the state code list)/ZIP (≥5 digits)/ZIP+4 (exactly 4 digits when present) only for domestic addresses (ForeignAddressFlag = "N") (BR-008).- Normalize the address (warning-only).
ValidateCleanAddresscallsCleanAddressHelper: DetermineAddressLinesToClean()sends only two lines to the cleansing service — lines 2+3 if line 3 is populated, otherwise lines 1+2 — and callsservice.CleanAddress(line1, line2, city, state, zip, zip4, True).- If the service reports the address was cleaned:
CheckForDroppedAddressLine()restores the original line 1 if the cleanser appears to have dropped it (detected by comparing the first three characters of the old line 2 against the old line 1), thenUpdateAddressLines()writes the proper-cased, standardized lines/city/state/zip/zip4 back onto the object. - The rule raises a warning either way:
"Warning: Address has been updated to postal standards."when cleaned, or"Warning: Address may be incorrect."when the cleanser could not standardize it — neither blocks the save. - Insert.
BeforeInsertwrites address type, dates, lines, city/state/zip/zip4/country,ForeignAddressFlag, and audit fields to PROVIDER_ADDRESS (SQL-019). FillAdressDto()buildsAddressDtowith resolvedaddressTypedescription,providerNumber, andisPrimary(viaclsProviderUtility).- On success,
AddContactManagerAddress()calls the API only ifExpDate = Date.MinValue(the address is current/effective); an expired address on creation is not synced.* - Update.
BeforeUpdatewrites the same fields to PROVIDER_ADDRESS (SQL-067) with concurrency checkWHERE PROVIDER_ADDRESS_SEQ_NUM = :ProviderAddressSeqNum AND UPDATE_NUM = :UpdateNum. UpdateContactManagerAddress()branches on the transition between the originally retrieved expiration date and the new one:- Was open-ended, now expired → calls
RemoveContactManagerAddressApi(). - Was open-ended, still open-ended → calls
UpdateContactManagerAddressApi(). - Was expired, now open-ended → calls
AddContactManagerAddressApi(). - Was expired, still expired → no API call.
- Was open-ended, now expired → calls
clsAddressApiroutes: insert/updateprovider/{providerLocationSeqNumber}/address, deleteprovider/{providerLocationSeqNumber}/address/remove; exceptions are caught byCreateErrorMessage(), which logs the serialized DTO and adds anInsertError/UpdateError/DeleteError.- Delete.
BeforeDeletedeletes the PROVIDER_ADDRESS row byProviderAddressSeqNum(SQL-089);AfterDeleteonly checks rows affected and marks the object new — no Contact Manager remove call is made on delete, unlike the expiration-transition sync used during update.*
Process flow¶
flowchart TD
Start([Caller edits address]) --> Domestic{Foreign or domestic?}
Domestic -->|Domestic| ReqFields[Require line1, city, state, zip]
Domestic -->|Foreign| SkipFields[Skip city/state/zip requirement;<br>state forced blank]
ReqFields --> Overlap{Overlaps or duplicates<br>same-type open-ended address?}
SkipFields --> Overlap
Overlap -->|Yes| Fail([Overlapping effective period<br>blocks save])
Overlap -->|No| Clean[Send 2 lines to CleanAddressHelper]
Clean --> Cleaned{Standardized?}
Cleaned -->|Yes| WarnClean([Warning: updated to postal standards])
Cleaned -->|No| WarnBad([Warning: address may be incorrect])
WarnClean --> Persist[Insert or update PROVIDER_ADDRESS]
WarnBad --> Persist
Persist --> Rows{RowsAffected = 1?}
Rows -->|No| Contention([Insert Failed / DB contention error])
Rows -->|Yes| ExpTransition{Expiration transition?}
ExpTransition -->|Open to expired| ApiRemove[Contact Manager remove]
ExpTransition -->|Expired to open| ApiAdd[Contact Manager add]
ExpTransition -->|No material change| NoApi([No Contact Manager call])
ApiRemove --> Done([Save complete])
ApiAdd --> Done
NoApi --> Done
Failure and edge-case behavior¶
- Deleting an address never issues a Contact Manager removal call, so a deleted current address can remain visible in Contact Manager until a subsequent update elsewhere triggers a sync.*
- USPS standardization always raises a warning (success or failure) but never blocks the save — an unrecognized address can still be persisted.
- Overlap and duplicate-open-ended checks are scoped to addresses of the same type only; different address types on the same location do not interact.
- Insert-time Contact Manager sync is skipped entirely for a brand-new address that is already expired.*
Related documentation¶
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\clsProviderAddress.vbBusiness\SAIF.Business.Provider\CleanAddressHelper.vbBusiness\SAIF.Business.Provider\Api\clsAddressApi.vb