---
title: Bill search criteria validation
summary: Validates a medical bill search request across thirteen rules — claim, provider, name, date, and identifier constraints — before the caller submits it for retrieval.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.MedicalBill
reference_type: package
operation_id: OP-MB-02
trigger: Caller populates clsBillSearchCriteria properties and reads IsValid (directly or through IDataErrorInfo binding) before calling medical bill retrieval
---

# Bill search criteria validation

`clsBillSearchCriteria` is a rules-manager object (not a persisted business object) that a caller populates with search inputs — claim number, provider location, worker name/DOB, service date range, bill/check number — before submitting a medical bill search. Reading `IsValid` (or any bound `IDataErrorInfo` property) re-runs all thirteen registered rules and returns whether the criteria are consistent enough to submit. The object also exposes an `IsMedicalBillSearch` flag that activates an additional mutual-exclusion rule used by the worker/provider-location bill-search UI path.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-MB-02 |
| **Trigger** | Caller sets `clsBillSearchCriteria` properties (`ClaimNumber`, `ProviderLocID`, `WorkerFirstName`/`WorkerLastName`, `ServiceBeginDate`/`ServiceEndDate`, `WorkerBirthDate`, `SAIFBillNumber`, `CheckNumber`, `IsMedicalBillSearch`, `WorkerID`) and reads `IsValid` |
| **Inputs** | All searchable criteria fields listed above, plus the constructor-supplied `isExternal` flag that gates the internal-search-info rule |
| **Outputs** | Boolean validity (`BrokenRules.ErrorCount = 0`); populated `BrokenRules`/`IDataErrorInfo` error messages; as a side effect of provider-location validation, a resolved `ProviderID` |
| **Primary components** | `clsBillSearchCriteria.IsValid`, `clsBillSearchCriteria.AddBusinessRules`, the thirteen `IsValid*`/`Is*NotFuture` rule methods |
| **Entry point** | `Business\SAIF.Business.Claim.MedicalBill\clsBillSearchCriteria.vb` |

## Steps

1. **Construct the criteria object.** The caller creates `clsBillSearchCriteria` via `New(dataPortalInfo, isExternal)`, which registers all thirteen rules through `AddBusinessRules`.
2. **Populate search fields.** The caller sets any combination of claim number, provider location, worker name/DOB, service dates, bill number, check number, and (for the worker/provider-location search path) `IsMedicalBillSearch` plus exactly one of `WorkerID` or `ProviderLocID`.
3. **Evaluate validity.** Reading `IsValid` clears propagated rules and calls `CheckRules(Me, "")`, running every registered rule against the current property values, then returns `BrokenRules.ErrorCount = 0`.
4. **Claim number validation.** If `ClaimNumber` is not empty, `IsValidClaim` resolves it via `clsClaimSecurity.GetClaimSecurity(dpi, ClaimNumber)` and requires `IsValid` on the result ([BR-MB-005](../business-rules.md#br-mb-005-bill-search-claim-number-must-resolve-to-a-valid-saif-claim)).
   - Sub-step: `clsClaimSecurity.GetClaimSecurity` resolves claim and worker-conflict data for the entered claim number.

   > **Origin**: `clsClaimSecurity.GetClaimSecurity` is implemented in `SAIF.Business` and executed on behalf of this operation. See [Claim information and authorization support](../../saif-business/operations/claim-information-and-authorization-support.md) (`OP-SB-07`) in the `SAIF.Business` documentation set. This operation calls the direct claim-number overload rather than the CCClaimData API route described as the primary path on that operation page.*
5. **Provider location validation.** If `ProviderLocID` is empty, the rule passes automatically; otherwise `IsValidProviderLocation` resolves `Provider.clsProviderLocation.GetProviderLocation(dpi, ProviderLocID)` and requires `ProviderLocationID > 0`, setting `ProviderID` from the resolved location as a side effect ([BR-MB-006](../business-rules.md#br-mb-006-bill-search-provider-location-must-be-valid-when-entered)).

   > **Origin**: `Provider.clsProviderLocation.GetProviderLocation` is implemented in `SAIF.BOF.Business.View.Provider` and executed on behalf of this operation. That library is documented in the previous format, so no per-operation page exists; see [Operations and processes](../../saif-business-view-provider/operations/provider-location-retrieval.md) in the `SAIF.BOF.Business.View.Provider` documentation set.
6. **Worker first/last name pairing.** `IsValidFirstName` fails when `WorkerFirstName` is entered without `WorkerLastName` ([BR-MB-007](../business-rules.md#br-mb-007-bill-search-worker-last-name-is-required-when-a-first-name-is-entered)).
7. **Service date pairing.** `IsValidDatesOfService` fails when exactly one of `ServiceBeginDate`/`ServiceEndDate` is entered without the other ([BR-MB-008](../business-rules.md#br-mb-008-bill-search-service-begin-and-end-dates-must-both-be-entered-together)).
8. **Service begin date not future.** `IsFromDateNotFuture` fails when `ServiceBeginDate` is entered and is later than today ([BR-MB-009](../business-rules.md#br-mb-009-bill-search-service-begin-date-may-not-be-in-the-future)).
9. **Service end date not before begin date.** `IsValidThruDate` fails when both dates are entered and `ServiceEndDate` precedes `ServiceBeginDate` ([BR-MB-010](../business-rules.md#br-mb-010-bill-search-service-end-date-may-not-precede-the-begin-date)).
10. **Date range cap.** `IsValidDateRange` fails when `ClaimNumber`, `SAIFBillNumber`, and `CheckNumber` are all empty and the six-month window from `ServiceBeginDate` is exceeded by `ServiceEndDate` ([BR-MB-011](../business-rules.md#br-mb-011-bill-search-date-range-may-not-exceed-six-months-unless-an-identifier-is-given)).
    - If `ServiceBeginDate` itself is empty in that same no-identifier scenario: the rule also fails.
11. **Service end date not future.** `IsThruDateNotFuture` fails when `ServiceEndDate` is entered and is later than today ([BR-MB-012](../business-rules.md#br-mb-012-bill-search-service-end-date-may-not-be-in-the-future)).
12. **Worker birth date not future.** `IsValidDob` fails when `WorkerBirthDate` is entered and is later than today ([BR-MB-013](../business-rules.md#br-mb-013-bill-search-worker-birth-date-may-not-be-in-the-future)).
    - Note: this rule's `RuleData` attribute text reads `"clsBillSearchCriteria.IsFromDateNotFuture"`, copied from the service-begin-date rule, even though the bound function and message describe the birth-date check; this appears to be a copy-paste artifact rather than an intentional dual-purpose rule.*
13. **Internal search-info requirement.** If the criteria object was constructed with `isExternal = False`, `IsValidSearchInfo` fails unless at least one of `ClaimNumber`, `SAIFBillNumber`, or `ProviderLocID` is entered; external criteria skip this check entirely ([BR-MB-014](../business-rules.md#br-mb-014-internal-bill-search-requires-a-claim-number-bill-number-or-provider-number)).
14. **Check-number requires provider.** `IsValidCheckNum` fails when `CheckNumber` is entered but `ProviderID` is still empty ([BR-MB-015](../business-rules.md#br-mb-015-bill-search-by-check-number-requires-a-provider-number)).
15. **Wildcard minimum length.** `IsValidWildCard` fails when `StartsWith` is true, `WorkerLastName` is entered, and its trimmed length is less than three characters ([BR-MB-016](../business-rules.md#br-mb-016-bill-search-starts-with-option-requires-at-least-three-characters)).
16. **Medical-bill-search mutual exclusion.** If `IsMedicalBillSearch` is true, `IsValidMedicalBillSearch` fails when both `WorkerID = 0` and `ProviderLocID = 0`, and also fails when `WorkerID <> 0` and `ProviderLocID > 0` — exactly one of the two must be supplied ([BR-MB-017](../business-rules.md#br-mb-017-medical-bill-search-requires-exactly-one-of-worker-id-or-provider-location)).
17. **Surface errors to the UI.** `IDataErrorInfo.Error` and the indexed `Item(columnName)` property expose `BrokenRules.ErrorMessage` so data-bound controls can display validation feedback without the caller explicitly calling `IsValid`.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Caller populates search criteria]) --> Eval[IsValid clears rules<br>and runs CheckRules]
	Eval --> Claim{ClaimNumber entered?}
	Claim -->|Yes| ClaimCheck[Resolve via clsClaimSecurity;<br>require IsValid]
	Claim -->|No| ProvLoc
	ClaimCheck --> ProvLoc{ProviderLocID entered?}
	ProvLoc -->|Yes| ProvCheck[Resolve via clsProviderLocation;<br>require found, set ProviderID]
	ProvLoc -->|No| Names
	ProvCheck --> Names[Name, date, range,<br>DOB, search-info,<br>check-num, wildcard rules]
	Names --> Medical{IsMedicalBillSearch?}
	Medical -->|Yes| Exclusive[Require exactly one of<br>WorkerID or ProviderLocID]
	Medical -->|No| Result
	Exclusive --> Result{ErrorCount = 0?}
	Result -->|Yes| Valid([Criteria considered valid;<br>caller may submit search])
	Result -->|No| Invalid([Broken rules returned;<br>IDataErrorInfo surfaces messages])
```

## Failure and edge-case behavior

- Every rule is evaluated on each `IsValid` read; there is no early exit, so all applicable broken rules accumulate together for display.
- The date-range cap rule ([BR-MB-011](../business-rules.md#br-mb-011-bill-search-date-range-may-not-exceed-six-months-unless-an-identifier-is-given)) only activates when claim number, bill number, and check number are all empty — a search with any one of those identifiers can span any date range.
- The internal search-info rule ([BR-MB-014](../business-rules.md#br-mb-014-internal-bill-search-requires-a-claim-number-bill-number-or-provider-number)) is completely bypassed when the criteria object is constructed as external, so external callers can search with only name/date criteria.
- Provider-location and claim-number validation both make a live lookup call on every `IsValid` evaluation; repeated validation during interactive data entry issues repeated lookups rather than caching results.*
- The DOB rule's mismatched `RuleData` label does not change its runtime behavior (the bound function and message are correct), but it could confuse anyone reading rule metadata directly rather than the rule engine's evaluated output.*

## Related documentation

- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

> **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.Claim.MedicalBill\clsBillSearchCriteria.vb`
