---
title: Beneficiary management
summary: Retrieves beneficiary contacts for a worker, validates beneficiary and related-warning rules, and lazy-loads guardian, address, and award-eligibility details.
status: draft
owner: SAIF
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.Person
reference_type: package
operation_id: OP-PER-06
trigger: Caller requests beneficiaries for a worker or claim context, inspects or edits the loaded beneficiary object, and optionally calls `Save()`.
---

# Beneficiary management

Beneficiary management is primarily an API-backed retrieval and validation flow. The collection retrieves worker beneficiary contacts from `CCClaimDataApi`, materializes each contact into `clsBeneficiary`, and lazy-loads related eligibility periods, claim-person addresses, and guardian data when those child properties are accessed. The class still exposes `Save()`, but the current implementation returns success without issuing a persistence request.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-PER-06 |
| **Trigger** | Caller requests beneficiaries for a worker, optionally scoped to a claim, then reads child details or validates the beneficiary object |
| **Inputs** | `WorkerID`; optional `ClaimID`; `OnlyActiveClaim`; contact payload fields from `CCClaimDataApi`; optional edits to demographic, relationship, date, tax ID, address, guardian, and award-eligibility fields |
| **Outputs** | `clsBeneficiaryCollection`; hydrated `clsBeneficiary` objects; lazy-loaded award eligibility and claim-person addresses; rule errors and warnings; `Save()`/`savechild()` currently return `True` without persistence |
| **Primary components** | `clsBeneficiaryCollection.GetBeneficiariesForWorker`, `clsBeneficiaryCollection.BeforeRetrieve`, `clsBeneficiary.Load`, `clsBeneficiary.AwardEligibility`, `clsBeneficiary.Addresses`, `clsBeneficiary.Save` |
| **Entry point** | `Business\SAIF.Business.Claim.Person\clsBeneficiaryCollection.vb` |

## Steps

1. **Retrieve beneficiary contacts for the worker.** `clsBeneficiaryCollection.BeforeRetrieve` formats the `CCClaimDataApi` route `v1/GeneralWorkerData/Contacts/{WorkerID}?onlyActiveClaim={OnlyActiveClaim}` and requests claim-contact data for the worker.
2. **Materialize each returned beneficiary contact.** `AfterRetrieve` iterates `claimContacts(0).Data.Beneficiary.Beneficiary`, creates a `clsBeneficiary` for each contact, loads the contact fields, optionally preserves the caller-supplied `ClaimID`, copies the response `ClaimID` onto the object, and adds the child to the collection.
3. **Map contact data into beneficiary state.** `clsBeneficiary.Fill` copies birth and death dates, email, gender, phones, tax ID, dependent type, worker and person identifiers, termination date, active flag, name components, and update date from the API contact, and it loads a guardian object immediately when the contact already contains guardian data.
4. **Lazy-load child eligibility and address details when requested.**
   - Accessing `AwardEligibility` retrieves the beneficiary's period rows through the local eligibility collection operation ([SQL-005](../sql/sql-005-select.md), [CL_AWARD_ELIGIBILITY](../database-tables.md#cl_award_eligibility)).
   - Accessing `Addresses` retrieves claim-person addresses only when `ClaimID <> 0`, then assigns home, mailing, and payment-specific error prefixes based on address code.
5. **Validate required identity, relationship, and date fields.** The beneficiary rules require a last name, require orphan-coded beneficiaries to carry the child relationship code, reject future-dated birth or death values, require a birth date when an eligibility end date exists, and require death dates to be later than birth dates ([BR-PER-015](../business-rules.md#br-per-015-beneficiary-last-name-is-required), [BR-PER-016](../business-rules.md#br-per-016-orphan-codes-require-the-child-relationship-code), [BR-PER-017](../business-rules.md#br-per-017-beneficiary-birth-dates-cannot-be-future-dated-and-are-required-when-eligibility-periods-exist), [BR-PER-018](../business-rules.md#br-per-018-beneficiary-death-dates-cannot-be-future-dated-and-must-be-after-the-birth-date)).
6. **Validate certificate, gender, tax ID, and fatal-benefit prerequisites.** The rules reject future-dated birth-certificate receipt dates, allow only `M`, `F`, or `U` gender codes, require nine-digit tax IDs when a value is present, and require a recorded worker death date when the claim injury date is on or after `10/23/1999` ([BR-PER-019](../business-rules.md#br-per-019-birth-certificate-received-dates-cannot-be-future-dated), [BR-PER-020](../business-rules.md#br-per-020-beneficiary-gender-codes-must-be-m-f-or-u), [BR-PER-021](../business-rules.md#br-per-021-beneficiary-tax-ids-must-contain-exactly-nine-digits-when-provided), [BR-PER-022](../business-rules.md#br-per-022-post-1999-ptd-beneficiary-claims-require-a-recorded-worker-death-date)).
7. **Raise non-blocking warnings for payment-address and death-date changes.** The object warns when both a special payment address and a guardian payment address exist, and it warns when the beneficiary death date has been modified because the current eligibility period may need review ([BR-PER-023](../business-rules.md#br-per-023-conflicting-payment-addresses-generate-a-warning), [BR-PER-024](../business-rules.md#br-per-024-beneficiary-death-date-changes-generate-an-eligibility-review-warning)).
8. **Validate higher-education and orphan combinations.** Higher education is only accepted when orphan code `2` is present, and the rule set also checks higher-education status for twice-orphaned child beneficiaries ([BR-PER-025](../business-rules.md#br-per-025-higher-education-requires-orphan-code-2), [BR-PER-026](../business-rules.md#br-per-026-twice-orphaned-child-beneficiaries-must-resolve-higher-education-status)).
9. **Return save success without persisting beneficiary changes.** Both `Save()` and `savechild()` call `SaveBeneficiary()`, and `SaveBeneficiary()` immediately returns `True` without building a portal request or API request.
10. **Report aggregate dirty state from related child objects.** `clsBeneficiary.IsDirty` returns `True` when the beneficiary itself is dirty or when `AwardEligibility`, `Addresses`, or `Guardian` report pending changes.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
    Start([Request beneficiaries for a worker]) --> Api[Call worker contacts API]
    Api --> Load[Load each beneficiary contact]
    Load --> Child{Child details accessed?}
    Child -->|Award eligibility| Elig[Load eligibility periods]
    Child -->|Addresses| Addr[Load claim-person addresses]
    Child -->|No| Validate[Run beneficiary rules when checked]
    Elig --> Validate
    Addr --> Validate
    Validate --> Save{Caller invokes Save?}
    Save -->|No| Done([Return loaded beneficiary state])
    Save -->|Yes| NoOp[SaveBeneficiary returns True]
    NoOp --> Done
```

## Failure and edge-case behavior

- `Addresses` are never loaded when `ClaimID` is zero, because the getter short-circuits before calling the address collection.
- Guardian data is only instantiated during `Fill` when the incoming contact already contains a guardian object.
- `Save()` and `savechild()` do not persist beneficiary edits, so callers must not treat a `True` result as confirmation of database or API writes.
- `IsDirty` forces evaluation of `AwardEligibility`, `Addresses`, and `Guardian`, so child getters can affect dirty-state checks by loading related objects.
- The commented-out primary-tax-ID uniqueness rule is not active and is not enforced by this operation.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

## Sources
- `Business\SAIF.Business.Claim.Person\clsBeneficiary.vb`
- `Business\SAIF.Business.Claim.Person\clsBeneficiaryCollection.vb`
- `Business\SAIF.Business.Claim.Person\CCClaimDataApi\clsBeneficiaryAddress.vb`
- `Business\SAIF.Business.Claim.Person\CCClaimDataApi\Dto\BeneficiaryData.vb`
