---
title: Maintain provider location periods
summary: Persists date-bounded provider location attributes — ineligibility periods and DCBS cost/charge factors — each governed by its own date-range and value validation.
status: draft
owner: SAIF
last_reviewed: 2026-07-30
library: SAIF.Business.Provider
reference_type: package
operation_id: OP-PRV-11
trigger: Caller creates or retrieves clsProviderIneligibilityPeriod or clsProviderDcbsCostCharge, edits properties, and calls Save() or Delete()
---

# Maintain provider location periods

Two structurally similar classes are documented together because both maintain a simple, date-bounded period record directly against a provider location: `clsProviderIneligibilityPeriod` records when a location was ineligible and why, and `clsProviderDcbsCostCharge` records the cost/charge factor effective for a location over a date range. Both follow the same create/retrieve/insert/update/delete pipeline with `UPDATE_NUM` concurrency on update only.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-PRV-11 |
| **Trigger** | Caller calls `NewProviderIneligibilityPeriod`/`GetProviderIneligibilityPeriod` or `NewProviderDcbsCostCharge`/`GetProviderDcbsCostCharge`, edits properties, and calls `Save()` or `Delete()` |
| **Inputs** | Ineligibility: `ProviderLocationID`, `IneligibilityReasonCode`, `StartDate`/`TerminationDate`. DCBS: `ProviderLocationSeqNum`, `EffDate`/`ExpDate`, `CostChargeFactor` |
| **Outputs** | Persisted [PROVIDER_INELIG_PERIOD](../database-tables.md#provider_inelig_period) or [PROVIDER_DCBS_COST_CHARGE](../database-tables.md#provider_dcbs_cost_charge) row |
| **Primary components** | `clsProviderIneligibilityPeriod.AddBusinessRules`, `clsProviderDcbsCostCharge.AddBusinessRules` |
| **Entry point** | `Business\SAIF.Business.Provider\clsProviderIneligibilityPeriod.vb` |

## Steps

### Provider ineligibility period

1. **Create.** Assigns a new seq num via `GetNextSeqNum("PROVIDER_INELIG_PERIOD_SEQ")` and stamps the acting user.
2. **Retrieve.** `BeforeRetrieve` first calls `CreateUpdateInfo(UserID)`, then reads [PROVIDER_INELIG_PERIOD](../database-tables.md#provider_inelig_period) by `PROVIDER_INELIG_PERIOD_SEQ_NUM` ([SQL-050](../sql/SQL-050-retrieve-provider-ineligibility-period.md)); `AfterRetrieve` uses `clsSAIFDataReader` and, if a row exists, fills the object including a nested `clsUpdateInfo`.
3. **Validate before save** ([BR-022](../business-rules.md#br-022-provider-ineligibility-periods-must-fall-within-a-reasonable-non-future-date-range)):
   - `ValidReason`: hard error requiring a resolved, nonblank ineligibility reason description.
   - `ValidStartDate`/`UnreasonableStartDate`: hard errors requiring a start date not before 01/01/1850.
   - `ValidTerminationDate`: hard error if termination precedes the start date.
   - `LateStartDate`/`LateTerminationDate`: hard errors if either date is in the future.
   - `EarlyTerminationDate`: hard error if termination is more than 30 years old.
   - `EarlyStartDate` (warning only): warns if the start date is before 01/01/2002.
4. **Insert/update/delete.** Writes `PROVIDER_INELIG_PERIOD_SEQ_NUM`, `PROVIDER_LOCATION_SEQ_NUM`, `PROVIDER_INELIG_REASON_CODE`, `EFF_DATE`/`EXP_DATE`, and audit fields to [PROVIDER_INELIG_PERIOD](../database-tables.md#provider_inelig_period) ([SQL-026](../sql/SQL-026-insert-provider-ineligibility-period.md), [SQL-074](../sql/SQL-074-update-provider-ineligibility-period.md)); update checks `UPDATE_NUM`, delete does not.
5. **Null-termination helpers.** `SetTerminationDateNull()`/`IsTerminationDateNull()` manage an open-ended (still-ineligible) period.

### Provider DCBS cost/charge

1. **Create.** Only stamps the acting user — there is no sequence assignment; the key is the location plus effective date.
2. **Retrieve.** Reads [PROVIDER_DCBS_COST_CHARGE](../database-tables.md#provider_dcbs_cost_charge) by `PROVIDER_LOCATION_SEQ_NUM` and `EFF_DATE` ([SQL-047](../sql/SQL-047-retrieve-provider-dcbs-cost-charge.md)); `Fill(...)` stores `m_OriginalEffDate` for the update/delete key, since the effective date is itself editable.
3. **Validate before save** ([BR-023](../business-rules.md#br-023-provider-dcbs-costcharge-factor-must-be-between-0000-and-1000-inclusive)):
   - `ValidCostChargeFactor`: hard error requiring the factor to be between `0` and `1` inclusive.
   - `MissingEffDate`: hard error requiring an effective date.
   - `EarlyEffDate`/`LateEffDate`: hard errors bounding the effective date to `Today - 30 years` through `Today + 10 years`.
   - `LateExpDate`: hard error if the expiration exceeds `Today + 10 years`.
   - `ValidEffExpDate`: hard error if the expiration precedes the effective date.
4. **Insert/update/delete.** Writes `PROVIDER_LOCATION_SEQ_NUM`, `EFF_DATE`, `COST_CHARGE_FACTOR`, `EXP_DATE`, and audit fields to [PROVIDER_DCBS_COST_CHARGE](../database-tables.md#provider_dcbs_cost_charge) ([SQL-023](../sql/SQL-023-insert-provider-dcbs-cost-charge.md), [SQL-071](../sql/SQL-071-update-provider-dcbs-cost-charge.md)); update keys on `PROVIDER_LOCATION_SEQ_NUM + OriginalEffDate + UPDATE_NUM`, delete on `PROVIDER_LOCATION_SEQ_NUM + OriginalEffDate` only.

## Process flow

```mermaid
flowchart TD
	Start([Caller edits location period]) --> Which{Ineligibility or DCBS cost/charge?}
	Which -->|Ineligibility| DateCheck1{Dates within 1850-today,<br>termination not before start,<br>not >30yrs old?}
	DateCheck1 -->|No| Fail([Out-of-range or invalid<br>date bounds block save])
	DateCheck1 -->|Yes| ReasonCheck{Reason resolved?}
	ReasonCheck -->|No| Fail
	ReasonCheck -->|Yes| SaveInelig[Insert/update PROVIDER_INELIG_PERIOD]
	Which -->|DCBS cost/charge| FactorCheck{Factor 0.000-1.000?}
	FactorCheck -->|No| Fail2([Factor outside<br>0.000-1.000 blocks save])
	FactorCheck -->|Yes| DateCheck2{Eff/exp dates within bounds?}
	DateCheck2 -->|No| Fail2
	DateCheck2 -->|Yes| SaveDcbs[Insert/update PROVIDER_DCBS_COST_CHARGE]
	SaveInelig --> Rows{RowsAffected = 1?}
	SaveDcbs --> Rows
	Rows -->|No| Contention([Insert Failed / DB contention error])
	Rows -->|Yes| Done([Save complete])
```

## Failure and edge-case behavior

- Both classes allow delete without an `UPDATE_NUM` concurrency check, so a concurrent update between the caller's read and their delete call is not detected.
- DCBS cost/charge update and delete both key on the **original** effective date, so an in-flight edit that also changes the effective date relies on the originally retrieved value being preserved correctly in memory.*
- The ineligibility period's `EarlyStartDate` rule is warning-only, so a start date before 2002 is still saved, just flagged.

## 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.Provider\clsProviderIneligibilityPeriod.vb`
- `Business\SAIF.Business.Provider\clsProviderDcbsCostCharge.vb`
