---
title: Denial and fraud eligibility
summary: Evaluates whether a claim's injury claim is denied-final and whether a claim unit is fully fraudulent, restricted to policy units effective on or after the non-compensable rule change date.
status: draft
owner: SAIF
last_reviewed: 2026-07-30
library: SAIF.Business.UnitStat
reference_type: package
operation_id: OP-US-03
trigger: Caller reads clsClaimUnit.IsDeniedFinal or clsClaimUnit.IsFullyFraudulent(clmData) for a claim unit
---

# Denial and fraud eligibility

These two read-only properties on `clsClaimUnit` answer NCCI non-compensable reporting questions: whether the claim's injury claim has been denied final, and whether the claim unit is considered fully fraudulent. Both apply the same 2013-01-01 eligibility cutoff and both cache their looked-up value on the instance after first evaluation.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-US-03 |
| **Trigger** | Caller reads `clsClaimUnit.IsDeniedFinal` or `clsClaimUnit.IsFullyFraudulent(clmData)` |
| **Inputs** | `ClaimID` (from the claim unit itself); for fully-fraudulent, also a `clsClaimData` instance supplying `FraudConvictionFlag` |
| **Outputs** | Cached boolean flags (`m_DenialFinalFlag`, `m_FullyFraudulentFlag`) reflecting denied-final and fully-fraudulent status |
| **Primary components** | `clsClaimUnit.IsDeniedFinal`, `clsClaimUnit.IsFullyFraudulent` |
| **Entry point** | `Business\SAIF.Business.UnitStat\clsClaimUnit.vb` |

## Steps

1. **Denied-final lookup.** `IsDeniedFinal` checks whether `m_DenialFinalFlag` is already populated; if empty, it runs a scalar query against `CL_INJURY_CLAIM.DENIED_FINAL_FLAG` for the claim unit's `ClaimID` ([SQL-014](../sql/SQL-014-cl-injury-claim-denial-final-lookup.md), [CL_INJURY_CLAIM](../database-tables.md#cl-injury-claim)) and caches the result (defaulting to an empty string if the query returns no value).
2. **Denied-final result.** The property returns `True` only when the cached flag equals the framework's `Y` constant; any other value (including the empty-string default from a missing row) evaluates to `False`.
3. **Fully-fraudulent lookup.** `IsFullyFraudulent(clmData As clsClaimData)` checks whether `m_FullyFraudulentFlag` is already populated; if empty, it runs a scalar query that joins `US_CLAIM_UNIT` to `US_POLICY_UNIT` on `PolicyUnitSeqNum`, requiring the policy unit to be active (`ACTIVE_UNIT_FLAG = 'Y'`), non-historical (`HISTORICAL_FLAG = 'N'`), and effective on or after the non-compensable start date ([SQL-015](../sql/SQL-015-us-claim-unit-us-policy-unit-fraud-flag-eligibility-lookup.md), [US_CLAIM_UNIT](../database-tables.md#us-claim-unit), [US_POLICY_UNIT](../database-tables.md#us-policy-unit)).
4. **External fraud-conviction input.** The query binds the caller-supplied `clmData.FraudConvictionFlag` (from `SAIF.Business.View.Claim.clsClaimData`) directly as the value returned by the query when the eligibility join matches — effectively, the property echoes back the caller's own fraud-conviction flag but only when the policy unit is eligible under the non-compensable rule.** No docs currently exist for `SAIF.Business.View.Claim` in this repository, so the exact semantics and lifecycle of `FraudConvictionFlag` on the caller's side are unconfirmed.
5. **Fully-fraudulent result.** The property returns `True` only when the cached flag equals the framework's `Y` constant; a policy unit that fails the eligibility join (inactive, historical, or effective before 2013-01-01) yields no row and therefore an empty cached value, which evaluates to `False`.
6. **Eligibility cutoff.** Both properties' documentation comments state they apply only to policy units effective on or after 2013-01-01 ([BR-US-027](../business-rules.md#br-us-027-denial-final-checks-and-fully-fraudulent-checks-only-apply-to-policy-units-effective-on-or-after-2013-01-01)) — for `IsDeniedFinal` this is asserted by the remarks only, since the underlying query does not itself filter by policy unit date* (it queries `CL_INJURY_CLAIM` directly, unscoped by unit effective date); for `IsFullyFraudulent` the cutoff is enforced directly in the SQL join predicate.
7. **Caching semantics.** Because the cached fields are private instance state seeded from the first query execution, the same claim unit instance never re-queries the database for subsequent reads. Callers needing a fresh read (for example, after another process changes `CL_INJURY_CLAIM` or `US_POLICY_UNIT`) must retrieve a new `clsClaimUnit` instance.

## Process flow

```mermaid
flowchart TD
	Start([Caller reads IsDeniedFinal<br>or IsFullyFraudulent]) --> Which{Which property?}
	Which -->|IsDeniedFinal| CachedA{DenialFinalFlag<br>already cached?}
	CachedA -->|Yes| ReturnA([Return cached result])
	CachedA -->|No| QueryA[Query CL_INJURY_CLAIM<br>DENIED_FINAL_FLAG by ClaimID]
	QueryA --> CacheA[Cache result;<br>default to empty string]
	CacheA --> ReturnA
	Which -->|IsFullyFraudulent| CachedB{FullyFraudulentFlag<br>already cached?}
	CachedB -->|Yes| ReturnB([Return cached result])
	CachedB -->|No| Elig{Policy unit active,<br>non-historical, and<br>effective on/after 2013-01-01?}
	Elig -->|No| EmptyB[No row returned;<br>cache empty string]
	Elig -->|Yes| EchoB[Query returns caller-supplied<br>FraudConvictionFlag]
	EchoB --> CacheB[Cache result]
	EmptyB --> ReturnB
	CacheB --> ReturnB
```

## Failure and edge-case behavior

- `IsDeniedFinal`'s underlying query is not itself scoped to the 2013-01-01 cutoff; the cutoff is documented only in code remarks, so a caller could technically read a denied-final flag for a policy unit effective before that date even though the rule states it should not apply.*
- `IsFullyFraudulent` does not independently verify fraud; it reflects the caller-supplied `clmData.FraudConvictionFlag` back only when the policy-unit eligibility join succeeds, so the correctness of the result depends entirely on the caller passing an accurate `clsClaimData` instance.
- The exact semantics of `SAIF.Business.View.Claim.clsClaimData.FraudConvictionFlag` are unconfirmed, since no documentation exists for that library in this repository.**
- Both flags are cached for the lifetime of the `clsClaimUnit` instance; there is no cache-invalidation or refresh mechanism.

## 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. Statements
> marked with `**` could not be confirmed; treat as unknown until verified.

## Sources

- `Business\SAIF.Business.UnitStat\clsClaimUnit.vb`
