---
title: MCO billing
summary: Creates and maintains a managed-care-organization bill for a claim, resolving claim context, MCO eligibility history, and provider-type admin fee applicability.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.Bill
reference_type: package
operation_id: OP-CB-03
trigger: clsMCOBill.NewMCOBill(dpi, claimID) or clsMCOBill.NewMCOBill(dpi, claimData)
---

# MCO billing

MCO billing creates a bill for a managed-care organization, seeding it from claim context and standard MCO defaults, and supports maintaining a collection of MCO bills filtered and grouped by plan. It shares the underlying bill persistence and audit cascade documented in [Bill CRUD](bill-crud.md) and [Audit and audited services](audit-and-audited-services.md) — `clsMCOBill` inherits from the same bill hierarchy — and adds MCO-specific claim seeding, eligibility-history resolution, and provider-type admin-fee applicability lookups.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-CB-03 |
| **Trigger** | Caller calls `clsMCOBill.NewMCOBill(inDataportal, inClaimID)` (or the `clsClaimData` overload) to create a bill for a claim, or retrieves an existing collection with `NewMCOBillCollection` |
| **Inputs** | `ClaimID` or a pre-loaded `clsClaimData`; MCO plan ID for filtering; effective date for eligibility resolution; provider location for admin-fee validation |
| **Outputs** | New `clsMCOBill` seeded with claim and default fields; filtered/grouped `clsMCOBillCollection`; resolved `clsMCOEligibility` for an effective date; validated `clsMCOProviderTypeAdminFee` |
| **Primary components** | `clsMCOBill.Create`, `clsMCOBill.NewMCOBill`, `clsMCOBill.AddBusinessRules`/`validbill`, `clsMCOBillCollection.ListByMco`, `clsMCOBillCollection.UniqueMCOPlanIds`, `clsClaimMCO.GetMCOEligibility`, `clsMCOProviderTypeAdminFee.SetLocation`/`IsInEffect` |
| **Entry point** | `Business\SAIF.Business.Claim.Bill\MCOSupport\clsMCOBill.vb` |

## Steps

1. **Create a new MCO bill.** `Create()` calls `MyBase.Create()` (the shared bill-creation path from [Bill CRUD](bill-crud.md)), then sets `ClaimID` from the criteria and loads claim context.
   - Sub-step: `clsClaimData.GetData(MyCriteria.DataPortalInfo, MyCriteria.ClaimID)` retrieves the claim identified by `ClaimID` and returns the populated claim data used to seed the bill.

   > **Origin**: The claim-data retrieval is implemented by `clsClaimData.GetData` in `SAIF.Business.View.Claim` and executed on behalf of this operation. That library is a same-repo NuGet dependency documented in the previous format; see [Operations and processes](../../saif-business-view-claim/operations-processes.md) in the `SAIF.Business.View.Claim` documentation set.
2. **Copy claim fields onto the bill.** `ClaimNumber`, `ClaimCheckValue`, `WorkerFirstName`, `WorkerLastName`, and `WorkerTaxID` are copied from the loaded claim data onto the new bill.
3. **Apply MCO bill defaults.** `Create()` hard-sets `BillTypeCode = "S"` (Standard), `RebillFlag = "N"`, `MailRoomReceivedDate = Today`, and `PriorityNumber = "5"`.
4. **Enforce the bill-ID rule.** `AddBusinessRules()` registers `validbill()`, which requires `BillID > 0` under rule code `"CBPBill01"`.
   - On failure: add `"Invalid bill"` ([BR-001](../business-rules.md#br-001-bill-id-must-be-valid-non-zero)).
5. **Persist the bill.** Insert, update, and delete of the header and its child collections reuse the same `CBP_BILL` persistence path, audit generation, and rows-affected concurrency contract described in [Bill CRUD](bill-crud.md) steps 5–14 ([BR-004](../business-rules.md#br-004-optimistic-concurrency-updates-fail-if-rowsaffected-does-not-equal-1)).
6. **Retrieve the claim's MCO plan bill collection.** `clsMCOBillCollection` retrieves bills for a claim via `RetrieveSQL` selecting `CBP_BILL` rows by `CLAIM_ID` ([SQL-001](../sql/SQL-001-saif-business-claim-bill.md) family, [CBP_BILL](../database-tables.md#cbp_bill)).
7. **Filter and summarize the collection.** `ListByMco(inMCOPlan)` copies `ProcessDate` and returns a new collection containing only items where `McoPlanId.ToLower = inMCOPlan.ToLower`; `UniqueMCOPlanIds()` returns the distinct plan IDs across the collection. Both are in-memory operations with no additional database access.
8. **Resolve the claim's MCO eligibility history.** `clsClaimMCO.New(inDataportal, claimId)` issues an inline read against `CL_CLAIM_MCO_ELIGIBILITY` ([SQL-014](../sql/SQL-014-saif-business-claim-bill.md), [CL_CLAIM_MCO_ELIGIBILITY](../database-tables.md#cl_claim_mco_eligibility)). For each row, it resolves the MCO's location and builds a `clsMCOEligibilityDetail`.
   - Alternate constructor: `clsClaimMCO.New(inDataportal, claimId, mcoHistory)` builds the same eligibility-detail list from an in-memory `List(Of clsMcoData)` instead of querying the database.

   > **Origin**: The MCO-location resolution (`GetMCOInfo(DPI).MCO(mcoID)`) is implemented by the provider-view lookup in `SAIF.BOF.Business.View.Provider`. That library is a same-repo NuGet dependency documented in the previous format; see [Operations and processes](../../saif-business-view-provider/operations-processes.md) in the `SAIF.BOF.Business.View.Provider` documentation set.
9. **Resolve eligibility for a specific effective date (`GetMCOEligibility`).** The eligibility-detail history is sorted descending by effective date, and the latest record on or before the requested date is selected as the working record.
   - If no record matches the date and the working record's status is `Pending` or `PendingUnassigned`: the working record is qualified as-is.*
   - If the matched record's status is `PendingUnassigned`: look at the next (more recent) record —
     - if the next record's status is `NotEligible`, `Pending`, or `PendingUnassigned`: promote the next record's status onto the result.*
     - if the next record's status is `Eligible`: copy only the date and MCO from the next record, not its status.*
   - If the result is still `PendingUnassigned` and a more-recent record exists beyond that: repeat the same promotion — full copy for `PendingUnassigned`/`Pending`/`NotEligible`, date/MCO-only copy for `Eligible`.*
   - This effective-date promotion logic resolves a claim's working MCO eligibility status even when the nearest historical record is itself unassigned, by looking forward through subsequent history entries.*
10. **Validate a provider-type admin fee's location.** `clsMCOProviderTypeAdminFee.SetLocation(inLocation)` assigns the location, then compares the fee's own `McoID` (trimmed, lowercased) against the assigned location's `McoID`.
    - On mismatch: throw `"MCO location submitted does not match location assigned."` ([BR-006](../business-rules.md#br-006-mco-location-submitted-must-match-the-location-assigned-to-the-provider-type-admin-fee)).
11. **Determine admin-fee applicability for a date (`IsInEffect`).** Returns `False` before the fee's effective date; `True` if the fee has no expiration; otherwise `True` only while the requested date is on or before the expiration date.
12. **Load the provider-type admin fee list.** `clsMCOProviderTypeAdminFeeList`'s constructor issues an inline read against `MCO_TYPE_ADMIN_FEE` ([SQL-015](../sql/SQL-015-saif-business-claim-bill.md), [MCO_TYPE_ADMIN_FEE](../database-tables.md#mco_type_admin_fee)), builds one `clsMCOProviderTypeAdminFee` per row, and binds each to its resolved MCO location via the provider-view lookup.

## Process flow

The following diagram visualizes MCO bill creation and the eligibility-resolution logic used to determine a claim's working MCO status.

```mermaid
flowchart TD
	Start([Caller creates MCO bill<br>for a claim]) --> LoadClaim[Load claim data<br>via clsClaimData.GetData]
	LoadClaim --> Seed[Copy claim fields;<br>apply MCO defaults]
	Seed --> Rule{BillID > 0?}
	Rule -->|No| Fail([Broken rule;<br>invalid bill])
	Rule -->|Yes| Save[Persist via Bill CRUD<br>save cascade]
	Save --> Elig[Resolve eligibility history<br>for effective date]
	Elig --> Match{Matched record<br>PendingUnassigned?}
	Match -->|Yes| Next{Next record status?}
	Next -->|Eligible| CopyDateOnly[Copy date/MCO only]
	Next -->|Other| Promote[Promote next record<br>status and fields]
	Match -->|No| UseMatch[Use matched record]
	CopyDateOnly --> Done([Working eligibility returned])
	Promote --> Done
	UseMatch --> Done
```

## Failure and edge-case behavior

- `SetLocation` throws immediately on a location/MCO mismatch rather than adding a broken rule, so callers must catch the exception ([BR-006](../business-rules.md#br-006-mco-location-submitted-must-match-the-location-assigned-to-the-provider-type-admin-fee)).
- The `PendingUnassigned` promotion logic in `GetMCOEligibility` has several nested conditional branches; because the exact business intent behind each promotion path is not documented outside the code, the behavior is described here as observed rather than as a named business rule.*
- `clsMCOEligibilityDetail.IsUnassigned` treats an MCO ID of `"99"` as the sentinel for "unassigned," a convention not otherwise documented in this library.*
- MCO bill creation depends on `clsClaimData.GetData` successfully returning claim data; the trace does not show an explicit guard if the claim lookup fails or returns an invalid claim.*

## 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\MCOSupport\clsMCOBill.vb`
- `Business\SAIF.Business.Claim.Bill\MCOSupport\clsMCOBillCollection.vb`
- `Business\SAIF.Business.Claim.Bill\AuditSupport\MCO\clsClaimMCO.vb`
- `Business\SAIF.Business.Claim.Bill\AuditSupport\MCO\clsMCOEligibility.vb`
- `Business\SAIF.Business.Claim.Bill\AuditSupport\MCO\clsMCOEligibilityDetail.vb`
- `Business\SAIF.Business.Claim.Bill\AuditSupport\MCO\clsMCOProviderTypeAdminFee.vb`
