---
title: Claim targeting and eligibility screening
summary: Records the EAIP eligibility screening decision for a claim, validating the reviewer, the claim status and completed dates, the wage-subsidy start date, and the uniqueness of the screening record.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.EAIP
reference_type: package
operation_id: OP-EAIP-09
trigger: Reviewer creates or opens a targeting record through clsTargeting, sets the eligibility outcome, and calls Save
---

# Claim targeting and eligibility screening

Before a claim can enter the Employer-at-Injury Program it is screened: a reviewer looks at the claim's status, decides whether the worker is eligible, potentially eligible, or ineligible, and records when that decision was made. This operation is that screening record. It is deliberately strict about dates — nothing may predate the injury, nothing may postdate today — and it refuses to store two screenings that share a claim, claim-status date, and completed date, because that combination is what downstream reporting treats as the identity of a screening.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-EAIP-09 |
| **Trigger** | `clsTargeting.NewTargeting(dpi)` or `GetTargeting`/`GetTargetings` for an existing record, followed by edits and `Save()` |
| **Inputs** | `IDataPortalInfo`; claim number; EAIP targeting (eligibility) code; reviewer user mail identifier; completed date; claim status code and claim status effective date; optional begin and end dates; wage-subsidy begin date; conflict-access indicator on the criteria |
| **Outputs** | An EAIP claim targeting row with the eligibility outcome, reviewer, and dates; a resolved claim identifier, injury date, worker name, and policy name for display; rule violations for invalid claims, reviewers, dates, and duplicate screenings; DB contention errors when a statement affects no rows |
| **Primary components** | `clsTargeting` (`Create`, `ClaimNumber`, `InjuryDate`, `WorkerName`, `PolicyName`, `AddBusinessRules`, `AddInsertUpdateParms`, `GetTargetingByClaim`), the collection rules `Rule_ValidUniqueIDs` and `Rule_DuplicateTargetings` |
| **Entry point** | `Business\SAIF.Business.Claim.EAIP\Targeting\clsTargeting.vb` |

## Steps

1. **Create the screening record.** `Create()` takes the next value of `eaip_claim_targeting_seq` as the targeting identifier, records the create stamp, seeds the reviewer user with the acting user's identifier, and defaults the eligibility outcome to the ineligible targeting code — a screening is not eligible until someone says so.
2. **Attach the claim.** Setting `ClaimNumber` re-runs the claim security lookup for the new number, resets the claim identifier and injury date from the result, and marks the object dirty. Every subsequent date rule measures against the injury date resolved here, so changing the claim number implicitly re-baselines the whole record.
   > **Origin**: Claim security resolution, the injury date, and the formatted worker name are implemented by `clsClaimSecurity` and `clsClaimData` in `SAIF.Business.View.Claim` 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-claim/operations-processes.md) in the `SAIF.Business.View.Claim` documentation set.
3. **Mask conflicted workers.** `WorkerName` returns the confidential mask instead of the real name whenever the claim carries a worker-conflict flag and the criteria does not grant conflict access. The underlying name is never loaded into the property in that case, so a screen bound to it cannot leak it.
4. **Resolve the employer for display.** `PolicyName` lazily reads the policy behind the claim the first time it is asked for, so the reviewer sees the employer without a second round trip on every record.
   > **Origin**: Policy name resolution is implemented by `clsPolicyData` in `SAIF.BOF.Business.Policy` 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-claim/operations-processes.md) in the `SAIF.Business.Claim` documentation set.
5. **Validate the claim and the outcome.** `Rule_ValidClaimID` requires a resolved claim identifier, and `Rule_ValidEaipTargetingCode` requires a recognized eligibility code from the targeting code table.
6. **Validate the reviewer.** `Rule_ReviewerUserRequired` requires a reviewer, and `Rule_ValidReviewerUser` resolves that mail identifier to an employee record and requires it to be both valid and active — a departed employee cannot be recorded as the reviewer of a new screening.
7. **Validate the completed date.** `Rule_CompletedDateRequired` requires a value, and `Rule_ValidCompletedDate` requires it to fall on or after the injury date and on or before today. That second rule is registered at the secondary severity level, so it reports without blocking the primary save path in the same way a required-field violation does.*
8. **Validate the claim status.** `Rule_ClaimStatusRequired` requires a claim status code, `Rule_ClaimStatusDateRequired` requires its effective date, and `Rule_ValidClaimStatusDate` — also at the secondary level — requires that date to fall on or after the injury date.
9. **Validate the date range.** `Rule_ValidBeginDate` and the two end-date rules check each endpoint individually, and `Rule_ValidDateRange` checks that the begin date does not fall after the end date.
10. **Require a wage-subsidy start when eligibility is potential.** `Rule_ValidWageSubsidyBeginDate` requires the wage-subsidy begin date only when the eligibility outcome is the potentially-eligible code. A screening that is outright eligible or ineligible does not need one.
11. **Skip validation on unchanged records.** Several of these rules short-circuit when the object is not dirty, so opening and closing an old screening does not surface violations created by rules added after it was written.
12. **Enforce uniqueness against the database.** `Rule_ValidUniqueID` runs an inline count over the targeting table for rows with the same claim identifier, completed date, and claim status effective date, excluding the record's own identifier. A non-zero count is a violation ([BR-PROC-014](../business-rules.md#br-proc-014-targeting-records-must-be-unique-by-claim-status-date-and-completed-date)).
13. **Enforce uniqueness within the collection.** Because an unsaved sibling is invisible to that query, the collection adds `Rule_ValidUniqueIDs` and `Rule_DuplicateTargetings`, which group the in-memory records by claim identifier, claim status date, and completed date and flag any group with more than one member. The two rules together cover both the saved and the pending duplicate ([BR-PROC-014](../business-rules.md#br-proc-014-targeting-records-must-be-unique-by-claim-status-date-and-completed-date)).
14. **Persist.** `AddInsertUpdateParms` binds the targeting identifier, claim identifier, eligibility code, reviewer, completed date, claim status code and effective date, begin and end dates, wage-subsidy begin date, and audit stamp; `BeforeUpdate` additionally binds `LastUpdateNum` and increments the update information. Insert targets `pk82500_eaip.eaip_targeting_insert` ([SQL-017](../sql/SQL-017.md), [Details](../procedures/pk82500_eaip.md#eaip_targeting_insert)), update targets `eaip_targeting_update` ([SQL-037](../sql/SQL-037.md), [Details](../procedures/pk82500_eaip.md#eaip_targeting_update)), and delete targets `eaip_targeting_delete` ([SQL-047](../sql/SQL-047.md), [Details](../procedures/pk82500_eaip.md#eaip_targeting_delete)). Each `After*` handler checks the affected row count and raises a DB contention error when it is not one.
15. **Read back.** A claim's screenings are loaded through `pk82500_eaip.GetTargetingByClaim` ([SQL-026](../sql/SQL-026.md), [Details](../procedures/pk82500_eaip.md#gettargetingbyclaim_new)). A code comment records that this collection reader is called from the claim Activity tab and is expected to be removed once the platform conversion completes, so the read path is transitional.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Reviewer opens or creates a screening]) --> New[Create: eaip_claim_targeting_seq nextval,<br>reviewer = acting user,<br>outcome = Ineligible]
	New --> Claim[Set ClaimNumber: reload claim security,<br>reset claim id and injury date]
	Claim --> Mask{Worker conflict and<br>no conflict access?}
	Mask -->|Yes| Conf[WorkerName returns<br>the confidential mask]
	Mask -->|No| Edit
	Conf --> Edit[Reviewer sets outcome, completed date,<br>claim status and dates]
	Edit --> Save([Save])
	Save --> Rules{Rules pass?}
	Rules -->|Claim or outcome invalid| Rej([Save rejected])
	Rules -->|Reviewer missing, invalid,<br>or inactive| Rej
	Rules -->|Dates outside DOI..today<br>or range inverted| Rej
	Rules -->|Potential eligibility without<br>wage subsidy begin date| Rej
	Rules -->|Duplicate in database<br>or in collection| Rej
	Rules -->|Yes| Write[Insert or update with<br>LastUpdateNum check]
	Write --> Rows{RowsAffected = 1?}
	Rows -->|No| Err([DB contention error])
	Rows -->|Yes| Done([Screening recorded])
```

## Failure and edge-case behavior

- The uniqueness check queries the database, so two users saving matching screenings concurrently can both pass validation; the collection-level rules only catch duplicates held in the same in-memory collection.
- Rules that short-circuit on `Not IsDirty` mean an existing record can violate a current rule indefinitely as long as nobody edits it.
- The completed-date and claim-status-date range checks are registered at the secondary severity level, so they surface differently from the required-field checks and may not stop a save on their own.*
- The reviewer defaults to whoever created the record. Nothing re-checks it on update, so a record created by an employee who has since left keeps that reviewer unless it is edited — at which point the active-employee rule rejects it.*
- The confidential mask is applied by the property, not by the query. Any consumer that reads the underlying storage rather than the property bypasses the masking.*
- The collection reader is documented in code as transitional and slated for removal after the platform conversion, so this read path should be treated as unstable.
- Every statement checks its affected row count and raises a DB contention error when it is not one, so a concurrent edit is detected on save rather than silently overwritten.

## Related documentation

- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.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.EAIP\Targeting\clsTargeting.vb`
- `Business\SAIF.Business.Claim.EAIP\mdlCodeTables.vb`
