Provider search¶
Provider search is a dedicated orchestrator (clsProviderSearch), distinct from the standard business-object/criteria retrieval pattern used elsewhere in this library. It builds its SQL entirely at runtime from a StringBuilder, adding a join and a bind parameter only for each search field the caller actually populated (BR-003). When the caller supplies a provider name, the query becomes a UNION of a name-based branch (matching last/business name) and a registered-name branch (matching the tax ID record's registered name), so a provider can be found by either its display name or its registered tax name.
| Field | Value |
|---|---|
| Operation ID | OP-VP-08 |
| Trigger | Caller sets fields on clsProviderSearch.SearchCriteria (a nested clsSearchCriteria business object) and calls searchForProvider() |
| Inputs | SearchCriteria.BusinessPerson ("BUSINESS", "PERSON", or blank for both), TaxId, OtherId, ServiceType, MCOName, ProviderName, ProviderType, Street, City, State, ZipCode, AreaCode, PhoneNum — all optional |
| Outputs | Providers — a clsProviders collection of clsSearchResults, each carrying the provider location ID, primary-location flag, business flag, type description, resolved full name, sort name, physical address fields, and phone number, ordered by sort name; capped at 300 results |
| Primary components | clsProviderSearch.searchForProvider, clsProviderSearch.FormatSortName, clsProviderSearch.PRVSearch, clsProviderSearch.PRVSearchRegName |
| Entry point | Business\SAIF.Business.View.Provider\clsProviderSearch.vb |
Steps¶
- Reset accumulated results.
searchForProvider()starts by replacingm_Providerswith a fresh, emptyclsProviderscollection, discarding any prior search results before running the new search. - Apply the business/person filter. Based on
SearchCriteria.BusinessPerson:"BUSINESS"addsWHERE pl.BUSINESS_FLAG = :BusinessFlagbound to"Y";"PERSON"binds"N"; any other value starts theWHEREclause as1 = 1so every subsequent condition can be appended as anANDwith no business-flag filter applied (BR-003). - Add a tax ID join when supplied. If
TaxIdis non-blank: joinprovider_tax_id TINon the provider ID and bind:TaxIDNumberto the trimmed tax ID with dashes removed (SQL-015, PROVIDER_TAX_ID) (BR-003). - Add an other-identifier join when supplied. If
OtherIdis non-blank: joinprovider_identity IDon the provider location ID and bind:OtherIDto the upper-cased, trimmed value (PROVIDER_IDENTITY) (BR-003). - Add a service-type join when supplied. If
ServiceTypeis non-blank: joinprovider_service SVCon the provider location ID, filtering the service code to the supplied value, and bind:ServiceType(PROVIDER_SERVICE) (BR-003). - Add an MCO plan join when supplied. If
MCONameis non-blank: joinmco_provider MPon the provider location ID, filtering the MCO plan ID, and bind:MCOPlan(MCO_PROVIDER) (BR-003). - Append name, type, address, and phone predicates when supplied. For each of
ProviderName,ProviderType,Street,City,State,ZipCode,AreaCode, andPhoneNumthat is non-blank, append the matchingANDpredicate (and, when a provider name is supplied, the parallel predicate on the registered-name branch) and bind the corresponding parameter (PROVIDER_LOCATION, PROVIDER_ADDRESS) (BR-003). - The provider-name predicate matches
LAST_NAME_UPPER_CASEorBUSINESS_NAME_UPPER_CASEwith a trailing-wildcardLIKE, so it is effectively a starts-with search on the upper-cased name. - Assemble the final query. The base name-search branch (
PRVSearch) and, only when a provider name was supplied, the registered-name branch (PRVSearchRegName) joined byUNION, each with the same dynamically built join andWHEREclauses appended, then a fixedORDER BY fullNAME ASC(SQL-015, PROVIDER_LOCATION, PROVIDER_TYPE_CODE). - Execute and map results. Each returned row is mapped into a
clsSearchResultswith the location ID, primary-location flag, business flag, type description, full name, a computed sort name, physical address line/city/state/zip, and phone number. - Sub-step:
FormatSortNamere-orders a "Last, First Middle" display name into "First Last, ..." for sorting purposes when the row is a person (not flagged as a business) and the name contains a comma; business names pass through unchanged. - Cap the result set. If more than 299 results have already been added, the mapping loop exits immediately (
Exit For), leaving the result set capped at 300 rows and silently truncating any further matches. - Sort the final result set.
m_Providers.OrderBy(...)sorts by the computed sort name — the return value ofOrderByis discarded (LINQ'sOrderBydoes not mutate the source collection in place), so this sort call has no observable effect on the returnedProviderscollection order.*
Process flow¶
The following diagram visualizes this operation's control flow.
flowchart TD
Start([searchForProvider called]) --> Reset[Reset Providers collection]
Reset --> BizFlag{BusinessPerson filter?}
BizFlag -->|Business| WhereBiz[WHERE BUSINESS_FLAG = Y]
BizFlag -->|Person| WherePerson[WHERE BUSINESS_FLAG = N]
BizFlag -->|Neither| WhereAll[WHERE 1 = 1]
WhereBiz --> Joins
WherePerson --> Joins
WhereAll --> Joins
Joins[Add joins only for supplied filters:<br>tax ID, other ID, service type, MCO plan] --> Preds[Append predicates only for supplied filters:<br>name, type, street, city, state, zip, area code, phone]
Preds --> NameCheck{Provider name supplied?}
NameCheck -->|Yes| Union[UNION base branch<br>with registered name branch]
NameCheck -->|No| Single[Use base branch only]
Union --> Exec[Execute assembled query,<br>ORDER BY fullNAME]
Single --> Exec
Exec --> Loop[Map each row to clsSearchResults;<br>compute sort name]
Loop --> Cap{More than 299 results added?}
Cap -->|Yes| Stop([Stop mapping; result set capped at 300])
Cap -->|No| More{More rows?}
More -->|Yes| Loop
More -->|No| Done([Providers collection returned])
Stop --> Done
Failure and edge-case behavior¶
- The result set is silently capped at 300 rows; a search that matches more providers than that returns only the first 300 encountered, with no indication to the caller that results were truncated.
- The final
m_Providers.OrderBy(...)call discards its return value, so it does not actually reorder theProviderscollection; the effective result order is whateverORDER BY fullNAME ASCproduced from the database.* - When no provider name is supplied, only the base name-search branch runs; a provider findable only by registered tax name (and not by last/business name) will not appear in a search that omits the name filter.
- The single-quote replacement on the provider name search value (
SearchName.Replace("'", "''")) discards its result rather than reassigning it back toSearchName, so embedded single quotes are not actually escaped before being bound as a parameter value — though because the value is passed as a bind parameter rather than concatenated into the SQL text, this does not create a SQL-injection risk, only a functional no-op.*
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.View.Provider\clsProviderSearch.vb