---
title: National drug validation
summary: Retrieves a national drug code's master record and price history and validates that the code resolves to a known drug.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.Bill
reference_type: package
operation_id: OP-CB-05
trigger: clsNationalDrug.GetNationalDrug(dpi, nationalDrugCode)
---

# National drug validation

National drug validation retrieves the master reference record for a national drug code (NDC) — product, generic, manufacturer, and dosage attributes — together with its price history, and enforces that the code resolves to a real record before the object is considered valid. It is a read-only reference lookup used elsewhere in bill and service auditing to confirm drug-related charges against known NDC data.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-CB-05 |
| **Trigger** | Caller calls `clsNationalDrug.GetNationalDrug(inDataportal, inNationalDrugCode)` to load a drug record |
| **Inputs** | `NationalDrugCode` |
| **Outputs** | Populated `clsNationalDrug` with product/generic/manufacturer/dosage fields and a `PriceList` of `clsNationalDrugPrice` entries; broken rule if the code does not resolve |
| **Primary components** | `clsNationalDrug.GetNationalDrug`, `clsNationalDrug.BeforeRetrieve`/`AfterRetrieve`, `clsNationalDrug.Fill`, `clsNationalDrug.AddBusinessRules`/`ValidateCode` |
| **Entry point** | `Business\SAIF.Business.Claim.Bill\AuditSupport\Services\clsNationalDrug.vb` |

## Steps

1. **Dispatch the retrieve.** `GetNationalDrug(inDataportal, inNationalDrugCode)` builds a `Criteria(...)` and calls `DataAccessLayer.RetrieveObject`, which the BOF data portal routes to `BeforeRetrieve`/`AfterRetrieve`.
2. **Build the primary select.** `BeforeRetrieve` sets the request type to `ResultSet`, assigns `MyCriteria.RetrieveSQL`, and binds the `NationalDrugCode` parameter against `CBP_NATIONAL_DRUG`.
3. **Hydrate the object (`AfterRetrieve` / `Fill`).** If the result set has at least one row, `Fill(Result(0))` maps roughly twenty-five columns onto the object — product name, generic code/name, manufacturer name, therapy class, dose form, package size/unit/quantity, DESI code, and disallow-record code — then `MarkOld()` runs.
4. **Mark the record valid and load price history.** Inside `Fill`, if `NationalDrugCode.Trim.Length > 0` after mapping, `m_Valid = True` is set and the price history is loaded by a separate query against `cbp_national_drug_price` filtered by `national_drug_code` ([SQL-016](../sql/SQL-016-saif-business-claim-bill.md), [CBP_NATIONAL_DRUG_PRICE](../database-tables.md#cbp_national_drug_price)); a `clsNationalDrugPrice(effectiveDate, expirationDate, amount)` is created per row and added to `PriceList`.
   - If no row was returned by the primary select: `Fill` is never called, so `m_Valid` remains `False` and `PriceList` stays empty.
5. **Enforce the resolution rule.** `AddBusinessRules()` registers `ValidateCode` against `NationalDrugCode`.
   - On failure (the code did not resolve to a valid record): add the formatted message `"Error:  Information not found for <{0}>"`, substituting `MyCriteria.NationalDrugCode` ([BR-003](../business-rules.md#br-003-national-drug-code-must-resolve-to-valid-information)).
6. **Resolve the current or as-of price.** `PriceList.Price` and `PriceList.Price(inDate)` return the latest `clsNationalDrugPrice` in effect — filtering to entries where `IsInEffect` is true, ordering descending by effective date, and taking the first result.
7. **Expose expiration and effect-date helpers.** Each `clsNationalDrugPrice` exposes `HasExpirationDate`, `IsExpired`, `IsActive`, and `IsInEffect(inDate)` so callers can reason about which price applies without re-querying the database. The parent `clsNationalDrug` object exposes the equivalent `HasExpirationDate`/`IsExpired`/`IsActive`/`IsInEffect(inDate)` for the drug record itself.

## Process flow

The following diagram visualizes retrieval, validation, and price-history loading for a national drug code.

```mermaid
flowchart TD
	Start([Caller retrieves NDC<br>via GetNationalDrug]) --> Select[Select CBP_NATIONAL_DRUG<br>by NationalDrugCode]
	Select --> Found{Row found?}
	Found -->|No| Invalid([m_Valid stays False;<br>PriceList empty])
	Found -->|Yes| Fill[Fill fields; set m_Valid = True]
	Fill --> Prices[Load cbp_national_drug_price<br>rows into PriceList]
	Prices --> Rule{ValidateCode passes?}
	Invalid --> Rule
	Rule -->|No| BrokenRule([Broken rule:<br>Information not found])
	Rule -->|Yes| Ready([Drug record ready;<br>Price / Price(date) available])
```

## Failure and edge-case behavior

- A national drug code with no matching `CBP_NATIONAL_DRUG` row produces a fully-default object with `m_Valid = False` rather than a distinct "not found" retrieval error; the caller only learns of the failure when `IsValid()`/`ValidateCode` runs ([BR-003](../business-rules.md#br-003-national-drug-code-must-resolve-to-valid-information)).
- `PriceList.Price` and `PriceList.Price(inDate)` return `Nothing`/default when no price entry is currently in effect, which callers must handle before using the amount.*
- The price-history load is a second, separate query executed only when the primary drug row was found, so a drug record retrieved without a match never issues the price query at all.

## 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.Bill\AuditSupport\Services\clsNationalDrug.vb`
- `Business\SAIF.Business.Claim.Bill\AuditSupport\Services\clsNationalDrugPrice.vb`
