---
title: Claim-person address management
summary: Maintains home, mailing, and payment addresses for a claim person, validating address content while delegating actual persistence to the worker-address API.
status: draft
owner: SAIF
last_reviewed: 2026-07-30
library: SAIF.Business.Claim.Person
reference_type: package
operation_id: OP-PER-03
trigger: Caller retrieves address history for a person, edits a home, mailing, or payment address, and saves the collection or a single address.
---

# Claim-person address management

Claim-person address management is a two-layer operation. `clsClaimPersonAddress` and `clsClaimPersonAddressCollection` present the address as a BOF business object — with home, mailing, and payment address types, effective/expiration dates for the payment address, and address-content validation — but neither layer executes a real Oracle read or write against an address table. Instead, retrieval and persistence are delegated to `clsWorkerAddress`, which calls the `CCClaimDataApi` worker-address endpoints. The BOF insert/update lifecycle issues a harmless `SELECT 1 FROM DUAL` placeholder purely to satisfy the base-class SQL-request contract, then performs the real work in the `After*` hook by calling the API.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-PER-03 |
| **Trigger** | Caller retrieves a person's address collection (optionally with history), edits a home, mailing, or payment address, and calls `Save()` |
| **Inputs** | `PersonID`; optional `ClaimID`; `AddressCode` (`H`, `M`, `P`); address line/city/state/zip fields; `DirectDepositBankAcctID`, `EffDate`, `ExpDate` for payment addresses; `RetrieveHistory` flag |
| **Outputs** | `clsClaimPersonAddressCollection` of `clsClaimPersonAddress` objects; a call to the `CCClaimDataApi` worker-address update endpoint on save; broken rules on invalid address content |
| **Primary components** | `clsClaimPersonAddressCollection.GetClaimPersonAddressCollection`, `clsClaimPersonAddress.BeforeInsert`, `clsClaimPersonAddress.AfterInsert`, `clsClaimPersonAddress.AfterUpdate`, `clsClaimPersonAddress.CreateWorkerAddress`, `clsWorkerAddress.GetWorkerAddresses`, `clsWorkerAddress.UpdateAddress` |
| **Entry point** | `Business\SAIF.Business.Claim.Person\clsClaimPersonAddressCollection.vb` |

## Steps

1. **Retrieve the person's addresses through the worker-address API.** The collection calls `clsWorkerAddress.GetWorkerAddresses(DataPortalInfo, PersonID)`, which configures the `CCClaimDataApi` route `V1/GeneralWorkerData/WorkerAddresses/{0}` for controller `GeneralWorkerData` and returns the API's list of `WorkerAddress` payloads.
2. **Map each returned address into a claim-person address object.** For each `WorkerAddress` row, `clsClaimPersonAddress.Fill` copies address lines, city, country, state, zip and zip-plus-4, the foreign-format flag, and the update date, pads a numeric zip code to five digits or clears it when it is `"0"`, and associates the row with `PersonID`.
3. **Initialize a new address for creation.** `Create()` pulls `AddressCode`, `PersonID`, and the acting user from the criteria, defaults `County` to `0`, sets `EffDate` to today only for payment addresses, clears the foreign flag, and sets up address-specific validation through `SetupAddressObject`.
4. **Configure address-type-specific validation.** `SetupAddressObject` sets the error-message prefix per address type (home, mailing, or payment) and always enables zip, zip-plus-4, and state-code validation from the base `clsAddress` rule set; when the address is a payment address, `AddBusinessRules` additionally registers effective-date, expiration-date, and domestic-address rules.
5. **Validate payment-address effective and expiration dates.** For a dirty payment address, the effective date must not be blank or in the past ([BR-PER-033](../business-rules.md#br-per-033-payment-address-effective-date-must-be-present-and-not-in-the-past)); the expiration date, when set, must not precede the effective date and must not be in the past if it was just modified ([BR-PER-034](../business-rules.md#br-per-034-payment-address-expiration-date-cannot-precede-the-effective-date-or-be-in-the-past)).
6. **Validate domestic address completeness.** For a dirty, non-foreign payment address that has any address content entered, address line 1, city, state, and zip code are all required together ([BR-PER-035](../business-rules.md#br-per-035-domestic-payment-addresses-require-address-line-1-city-state-and-zip)).
7. **Issue the placeholder SQL request on insert or update.** `BeforeInsert` and `BeforeUpdate` both set the request to a non-query `SELECT 1 FROM DUAL` statement — this satisfies the BOF criteria contract without reading or writing any address table directly ([SQL-006](../sql/sql-006-select.md), [SQL-007](../sql/sql-007-select.md), [DUAL](../database-tables.md#dual)).
8. **Persist the address through the worker-address API.** `AfterInsert` and `AfterUpdate` both call `CreateWorkerAddress` to map the in-memory fields into a `WorkerAddress` DTO, then call `clsWorkerAddress.UpdateAddress(DataPortalInfo, workerAddress, PersonID)`, which configures the route `V1/GeneralWorkerData/WorkerAddress/{0}` and submits the update through the API access layer.
   - On failure: no explicit rows-affected or API-status check is performed after this call in this source set, so save-failure detection for the address write itself is not visible at this layer.*
9. **Support address duplication for a clean copy.** `Copy()`/`OnCopy()` clear existing rules, rerun `SetupAddressObject`, stamp a fresh update date and user, and mark the copy clean — used when the caller needs a duplicate address instance without inheriting dirty state.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
    Start([Request addresses for a person]) --> Api[Call worker-address API to retrieve addresses]
    Api --> Fill[Map each WorkerAddress into clsClaimPersonAddress]
    Fill --> Edit{Caller edits home, mailing, or payment address?}
    Edit -->|Payment address| PayRules[Validate effective and expiration dates]
    Edit -->|Any address| DomRules[Validate domestic address completeness]
    PayRules --> Valid{Validation passes?}
    DomRules --> Valid
    Valid -->|No| Fail([Broken rules returned])
    Valid -->|Yes| Stub[Issue placeholder DUAL request]
    Stub --> Persist[Call worker-address update API]
    Persist --> Done([Address change submitted through API])
```

## Failure and edge-case behavior

- The `SELECT 1 FROM DUAL` call in `BeforeInsert`/`BeforeUpdate` does not persist any address data by itself; all real persistence happens afterward in the `After*` hook through the `CCClaimDataApi` update call.
- No return value from `clsWorkerAddress.UpdateAddress` is checked by `AfterInsert`/`AfterUpdate`, so contention or API failures on the address write are not surfaced as broken rules at this layer.*
- Payment addresses use a different emptiness check (`IsPaymentAddressEmpty`) than home and mailing addresses (`IsEmpty`) because payment addresses keep no history rows.
- `IsForeignFormat` clears city/state/zip when set to foreign and clears address line 4 when cleared back to domestic, so switching formats discards the fields associated with the previous format.
- `clsClaimPersonAddress.IsValid` short-circuits to `True` when the object is not dirty, so unmodified addresses are never re-validated on save.

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts.

## 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\clsClaimPersonAddress.vb`
- `Business\SAIF.Business.Claim.Person\clsClaimPersonAddressCollection.vb`
- `Business\SAIF.Business.Claim.Person\clsWorkerAddress.vb`
