Search providers¶
clsProviderSearch builds a conditional SQL statement one clause at a time based on which search fields the caller populated, executes it through the generic SqlHelper.ResultSetQuery helper (not the BOF CRUD data portal), and caps the result set at 300 rows.
| Field | Value |
|---|---|
| Operation ID | OP-PRV-02 |
| Trigger | Caller populates clsSearchCriteria (nested class) and calls clsProviderSearch.searchForProvider() |
| Inputs | ProviderName, TaxId, OtherId, ProviderType, ServiceType, MCOName, Street, City, State, ZipCode, AreaCode, PhoneNum, BusinessPerson, EligibleSearchFlag |
| Outputs | clsProviders collection of clsSearchResults rows, capped at 300 |
| Primary components | clsProviderSearch.searchForProvider, clsProviderSearch.clsSearchCriteria, SqlHelper.ResultSetQuery, clsProviderSearch.FormatSortName |
| Entry point | Business\SAIF.Business.Provider\clsProviderSearch.vb |
Steps¶
- Caller sets criteria. The caller populates one or more fields on the nested
clsSearchCriteriaobject;resetSearchCriteria()is available to clear a prior search. - Business/person filter. Based on
BusinessPerson("BUSINESS", "PERSON", or any other value), the baseWHEREclause is seeded withpl.BUSINESS_FLAG = :BusinessFlagor left asWHERE 1 = 1so every subsequent condition can be appended withAND. - Conditional joins are appended only for populated fields:
TaxId→ joins PROVIDER_TAX_ID asTINonTIN.TAX_ID = :TaxIDNumber(hyphens stripped before binding).OtherId→ joinsprovider_identityasIDonRTRIM(ID.IDENTITY_VALUE) = :OtherID.ServiceType→ joins PROVIDER_SERVICE asSVCon a trimmed service-code match.MCOName→ joinsmco_providerasMPonMP.MCO_PLAN_ID = :MCOPlan.- Each present join is appended to
SQLPrimaryJoinand applied identically to both the primary query and, when a name search is active, the registered-name union query. - Name search adds a UNION. When
ProviderNameis populated, the search also executesPRVSearchRegName, which joins PROVIDER_TAX_ID to resolveREGISTERED_NAMEmatches, and combines it with the primary result set viaUNION. - Remaining fields append straightforward
WHEREpredicates (mirrored onto the union query when active):ProviderType,Street(prefixLIKE),City,State,ZipCode,AreaCode,PhoneNum(digits only, prefixLIKE), andEligibleSearchFlag(pl.INELIGIBILITY_FLAG = 'N'). - The ZIP-numeric requirement (BR-002) is enforced by the caller populating a numeric ZIP before this step;
clsProviderSearchitself binds whatever ZIP value is supplied without re-validating format.* - Assemble and execute. The primary query, its join clause, and its
WHEREclause are appended in order; if a name search is active, the registered-name union query is appended next; the combined statement is ordered byfullNAME ASCand executed viaSqlHelper.ResultSetQuery.Execute(...)against PROVIDER_LOCATION joined to PROVIDER_ADDRESS andprovider_type_code. - Validation before this step is enforced by BR-001 (at least one criterion) and BR-002 (numeric ZIP), both raised by
clsProviderSearchrule methods beforesearchForProvider()is expected to run. - Materialize each row. For every row returned, a
clsSearchResultsis constructed with location seq num, primary/business flags, provider type description, resolved full name, formatted phone, and physical address columns;FormatSortNamederives a "Last, First" sort key for individuals (business names sort as-is). - Stop at 300 rows. The loop exits as soon as
m_Providers.Count > 299, silently truncating any remaining matches — the comment in the source notes an attempted warning here "didnt work", so no truncation notice reaches the caller.* - Return the collection.
m_Providers.OrderBy(...)is called but its result is not reassigned back tom_Providersin this VB code, so the final ordering exposed to the caller is the SQLORDER BY fullNAME ASCorder, not the in-memoryOrderBy.*
Process flow¶
flowchart TD
Start([Caller populates clsSearchCriteria]) --> AtLeastOne{At least one criterion?}
AtLeastOne -->|No| Blocked([Missing criteria<br>blocks search])
AtLeastOne -->|Yes| ZipCheck{ZIP supplied?}
ZipCheck -->|Yes, non-numeric| BlockedZip([Non-numeric ZIP<br>blocks search])
ZipCheck -->|Numeric or blank| BuildJoins[Append conditional joins:<br>TIN, identity, service, MCO]
BuildJoins --> BuildWhere[Append WHERE predicates<br>for populated fields]
BuildWhere --> NameSearch{ProviderName supplied?}
NameSearch -->|Yes| Union[UNION registered-name query]
NameSearch -->|No| Execute
Union --> Execute[Execute combined query,<br>ORDER BY fullNAME]
Execute --> Loop[Materialize clsSearchResults rows]
Loop --> Cap{Count > 299?}
Cap -->|Yes| Truncate([Stop; remaining rows silently dropped])
Cap -->|No| More{More rows?}
More -->|Yes| Loop
More -->|No| Done([Return clsProviders collection])
Failure and edge-case behavior¶
- Searches with more than 300 matching rows are silently truncated; the code comments confirm an attempted warning mechanism was never wired up.*
- The final
OrderBycall on the returned collection does not reassign its result, so callers effectively receive SQL-order results rather than a client-side re-sort.* - The registered-name union path duplicates every join and filter condition against a second
FROMclause; a mismatch between the two clause-building blocks would silently omit matches from one side of the union.* searchForProvider()usesSqlHelper.ResultSetQuerydirectly rather than the BOF CRUD data portal, so there is noRowsAffected/concurrency handling — this operation is read-only.
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\clsProviderSearch.vb