---
title: SAIF.Business.Policy.Agency business rules
summary: Enumerated business rules for SAIF.Business.Policy.Agency.
status: draft
owner: Technical Writer
last_reviewed: 2026-07-31
library: SAIF.Business.Policy.Agency
reference_type: package
---

# SAIF.Business.Policy.Agency business rules

This page captures the rules enforced by `SAIF.Business.Policy.Agency` and the inherited BOF behavior it relies on.

## BR-001: Missing-key retrieval returns a default object

| Field | Value |
| --- | --- |
| **Statement** | Retrieval of a non-existent agency, contract, office, or producer returns a default-initialized object instead of raising a not-found error. |
| **Trigger** | A keyed retrieve completes without a matching row. |
| **Enforcement** | `AfterRetrieve` reads and fills only when a row is present. |
| **Outcome** | Callers receive an object whose key and data fields remain at their initial values. |
| **Tables** | [AGENCY](database-tables.md#agency), [AGENCY_CONTRACT](database-tables.md#agency_contract), [AGENT](database-tables.md#agent) |
| **SQL** | [SQL-001](sql/SQL-001-retrieve-agency-by-sequence-number.md), [SQL-003](sql/SQL-003-retrieve-agency-contract-by-sequence-number.md), [SQL-005](sql/SQL-005-retrieve-agency-office-by-agent-number.md), [SQL-007](sql/SQL-007-retrieve-producer-by-agent-number.md) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgency.vb`, `clsAgencyContract.vb`, `clsAgencyOffice.vb`, `clsProducer.vb` |

---

## BR-002: Agency sequence number is required

| Field | Value |
| --- | --- |
| **Statement** | An agency is invalid when its sequence number is empty. |
| **Trigger** | The framework validates a `clsAgency` instance. |
| **Enforcement** | `clsAgency.IsValidAgencySeqNum` is registered through rule `clsAgency01`. |
| **Outcome** | The object is marked invalid until a sequence number is present. |
| **Tables** | [AGENCY](database-tables.md#agency) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgency.vb` |

---

## BR-003: Agency FEID filters agency collections

| Field | Value |
| --- | --- |
| **Statement** | Agency collections can be filtered by a non-blank federal employer ID. |
| **Trigger** | A caller uses the FEID overload of `GetAgencyCollection`. |
| **Enforcement** | `clsAgencyCollection.Criteria.RetrieveSQL` appends `AGENCY.AGENCY_FEID = :FederalEmployerID` and binds the parameter. |
| **Outcome** | Only agencies with the requested FEID are returned. |
| **Tables** | [AGENCY](database-tables.md#agency) |
| **SQL** | [SQL-002](sql/SQL-002-search-agencies-by-feid-and-contract-types.md) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyCollection.vb` |

---

## BR-004: Contract-type filters use correlated contract existence

| Field | Value |
| --- | --- |
| **Statement** | Agency collections can be filtered to agencies that hold at least one contract of a selected type. |
| **Trigger** | A caller uses the contract-type overload of `GetAgencyCollection`. |
| **Enforcement** | `clsAgencyCollection.Criteria.RetrieveSQL` appends a correlated `EXISTS` predicate over `AGENCY_CONTRACT`. |
| **Outcome** | Only agencies with at least one matching contract type are returned. |
| **Tables** | [AGENCY](database-tables.md#agency), [AGENCY_CONTRACT](database-tables.md#agency_contract) |
| **SQL** | [SQL-002](sql/SQL-002-search-agencies-by-feid-and-contract-types.md) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyCollection.vb`, `Business\SAIF.Business.Policy.Agency\clsAgencyContract.vb` |

---

## BR-005: Empty collection criteria returns every agency

| Field | Value |
| --- | --- |
| **Statement** | The parameterless agency collection retrieve returns every agency row because no `WHERE` clause is added. |
| **Trigger** | A caller invokes `GetAgencyCollection(inDataportal)` with no FEID or contract-type filters. |
| **Enforcement** | `clsAgencyCollection.Criteria.RetrieveSQL` returns the base agency SQL unchanged. |
| **Outcome** | The collection retrieve performs an unfiltered `AGENCY` read. |
| **Tables** | [AGENCY](database-tables.md#agency) |
| **SQL** | [SQL-002](sql/SQL-002-search-agencies-by-feid-and-contract-types.md) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyCollection.vb` |

---

## BR-006: Bulk loaders discard orphan child rows

| Field | Value |
| --- | --- |
| **Statement** | Bulk-loaded producer and contract rows are discarded when their owning agency is not already present in the target collection. |
| **Trigger** | `RetrieveProducers()` or `RetrieveContracts()` distributes child rows after the bulk query completes. |
| **Enforcement** | The collection adds a child row only when the parent agency lookup succeeds. |
| **Outcome** | Child rows whose parent agency is missing are silently ignored. |
| **Tables** | [AGENT](database-tables.md#agent), [AGENCY_CONTRACT](database-tables.md#agency_contract) |
| **SQL** | [SQL-004](sql/SQL-004-retrieve-agency-contracts.md), [SQL-009](sql/SQL-009-retrieve-producers.md) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyCollection.vb` |

---

## BR-007: Bulk loaders replace N-plus-1 child retrieval

| Field | Value |
| --- | --- |
| **Statement** | Producers and contracts for a set of agencies are loaded with one query per child type and then distributed in memory. |
| **Trigger** | `RetrieveProducers()` or `RetrieveContracts()` is called on an agency collection. |
| **Enforcement** | The collection first retrieves all producers or all contracts, resets each agency's child collection, and then assigns rows by agency sequence number. |
| **Outcome** | Callers can avoid issuing one child query per agency. |
| **Tables** | [AGENT](database-tables.md#agent), [AGENCY_CONTRACT](database-tables.md#agency_contract) |
| **SQL** | [SQL-004](sql/SQL-004-retrieve-agency-contracts.md), [SQL-009](sql/SQL-009-retrieve-producers.md) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyCollection.vb` |

---

## BR-008: Active status uses effective and expiration windows

| Field | Value |
| --- | --- |
| **Statement** | Agencies, contracts, offices, and producers are active when the effective date is on or before the as-of date and the expiration date is empty or later than the as-of date. |
| **Trigger** | Any `IsActive(inDate)` or collection `Active(inDate)` helper is evaluated. |
| **Enforcement** | Each type compares the requested date against its effective and expiration fields. |
| **Outcome** | Callers receive a consistent date-window interpretation across the library. |
| **Tables** | [AGENCY](database-tables.md#agency), [AGENCY_CONTRACT](database-tables.md#agency_contract), [AGENT](database-tables.md#agent) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgency.vb`, `clsAgencyContract.vb`, `clsAgencyOffice.vb`, `clsProducer.vb`, `clsAgencyContractCollection.vb`, `clsAgencyOfficeCollection.vb`, `clsProducerCollection.vb` |

---

## BR-009: Missing active contracts mean unassigned contract type

| Field | Value |
| --- | --- |
| **Statement** | An agency returns `Unassigned` when no active contract exists for the requested date. |
| **Trigger** | `clsAgency.ContractType(inDate)` is evaluated. |
| **Enforcement** | The method filters to active contracts and returns the first contract type only when at least one row remains. |
| **Outcome** | Agencies without an active appointment on the date are classified as unassigned. |
| **Tables** | [AGENCY_CONTRACT](database-tables.md#agency_contract) |
| **SQL** | [SQL-004](sql/SQL-004-retrieve-agency-contracts.md) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgency.vb`, `Business\SAIF.Business.Policy.Agency\clsAgencyContractCollection.vb` |

---

## BR-010: Agency contract collection scope depends on agency sequence number

| Field | Value |
| --- | --- |
| **Statement** | Contract retrieval is scoped to one agency when a sequence number is supplied, and returns all contracts otherwise. |
| **Trigger** | A caller selects one of the `GetAgencyContractCollection` overloads. |
| **Enforcement** | `clsAgencyContractCollection.Criteria.RetrieveSQL` and `InitRetrievalArguments` bind `:AgencySeqNum` only when the overload supplies it; otherwise the base `AGENCY_CONTRACT` query runs unfiltered. |
| **Outcome** | Callers get either a single agency's contracts or every contract row, depending on which overload they invoke. |
| **Tables** | [AGENCY_CONTRACT](database-tables.md#agency_contract) |
| **SQL** | [SQL-004](sql/SQL-004-retrieve-agency-contracts.md) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyContractCollection.vb` |

---

## BR-011: Agency contract and commission codes map to fixed domain values

| Field | Value |
| --- | --- |
| **Statement** | Agency contract type codes map to fixed domain values: `ARP`→Assigned Risk, `DW`→Direct Writer, `FULL`→Full Appointment, `GRP`→Group Agency, `GPM`→Group Agency Manager, `LIMIT`→Limited Appointment, `PREM`→Premier Appointment, `SERV`→Service Center Only, `SA`→Servicing Agent, `NCCI`→VCAP and Assigned Risk Depopulation, and an empty code→Unassigned. |
| **Trigger** | `clsAgencyContract.Convert` translates a persisted contract-type or commission-GL-type code. |
| **Enforcement** | `clsAgencyContract.vb`'s `Convert` `Select Case` block maps each recognized code to its enum value. |
| **Outcome** | Callers receive a strongly typed `AgencyContractTypes` enum (or code, for the reverse conversion) instead of the raw persisted code. |
| **Tables** | [AGENCY_CONTRACT](database-tables.md#agency_contract) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyContract.vb` |

---

## BR-012: Unknown contract or commission codes become unassigned

| Field | Value |
| --- | --- |
| **Statement** | An unrecognized contract-type or commission-GL-type code translates to `Unassigned` rather than raising an error. |
| **Trigger** | `Convert(String)` or `ConvertCommissionGeneralLedgerType(String)` receives a code outside the mapped set. |
| **Enforcement** | `clsAgencyContract.vb`'s `Case Else` branch returns the `Unassigned` enum member. |
| **Outcome** | Callers receive a safe default classification instead of an exception. |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyContract.vb` |

---

## BR-013: Producer-commission contracts require GL code AGT

| Field | Value |
| --- | --- |
| **Statement** | A contract is a producer-commission contract only when its commission general-ledger type code is `AGT`. |
| **Trigger** | `clsAgencyContract.IsProducerCommissionContract` is read. |
| **Enforcement** | The property compares the contract's mapped commission GL type to `CommissionGeneralLedgerTypes.ProducerCommission` (code `AGT`). |
| **Outcome** | Only contracts carrying the `AGT` GL code are treated as producer-commission-bearing for eligibility checks. |
| **Tables** | [AGENCY_CONTRACT](database-tables.md#agency_contract) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyContract.vb` |

---

## BR-014: Unmapped enum-to-code conversions raise exceptions

| Field | Value |
| --- | --- |
| **Statement** | Converting an enum value outside the mapped set back to a persisted code is an error. |
| **Trigger** | `Convert(AgencyContractTypes)` or `ConvertCommissionGeneralLedgerType(enum)` is called with a value that has no corresponding persisted code. |
| **Enforcement** | `clsAgencyContract.vb`'s `Case Else` branch raises `ApplicationException("Invalid AgencyContractType")` or `ApplicationException("Invalid CommissionGeneralLedgerType")`. |
| **Outcome** | The conversion fails loudly instead of returning a misleading default code. |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyContract.vb` |

---

## BR-015: Agency office retrieval requires non-LOV-excluded office rows

| Field | Value |
| --- | --- |
| **Statement** | An `AGENT` row qualifies as an agency office only when it is not excluded from lists of values (`EXCLUDE_LOV_FLAG = 'N'`) and it is either the agency's own row (`AGENCY_SEQ_NUM = AGENT_NUM`) or explicitly flagged as a location (`AGENCY_LOCATION_FLAG = 'Y'`). |
| **Trigger** | Any agency office retrieval executes. |
| **Enforcement** | `clsAgencyOffice.Criteria.RetrieveAgencyOfficeSQL` applies the LOV-exclusion and agency/location predicate. |
| **Outcome** | Only qualifying office rows are returned to the caller. |
| **Tables** | [AGENT](database-tables.md#agent) |
| **SQL** | [SQL-005](sql/SQL-005-retrieve-agency-office-by-agent-number.md), [SQL-006](sql/SQL-006-retrieve-agency-offices-for-an-agency.md) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyOffice.vb` |

---

## BR-016: Agency office number is required

| Field | Value |
| --- | --- |
| **Statement** | An agency office is invalid when its agent number is empty. |
| **Trigger** | The framework validates a `clsAgencyOffice` instance. |
| **Enforcement** | `clsAgencyOffice.IsValidAgencyOfficeNumber` is registered through rule `clsAgencyOffice01`. |
| **Outcome** | The object carries the broken rule "Error: Invalid AgencyOfficeNumber" until an agent number is present. |
| **Tables** | [AGENT](database-tables.md#agent) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyOffice.vb` |

---

## BR-017: Agent of record is read from POLICY.AGENT_NUM

| Field | Value |
| --- | --- |
| **Statement** | The agent of record for a policy is `POLICY.AGENT_NUM`, and the scalar lookup is unguarded against a missing policy row.** |
| **Trigger** | A caller invokes `clsProducer.GetAgent` for a policy number. |
| **Enforcement** | `clsProducer.vb` issues a scalar query against `POLICY.AGENT_NUM` and parses the result directly. |
| **Outcome** | Returns the decimal agent number; a missing policy row would fail the unguarded parse rather than returning a safe default.** |
| **Tables** | [POLICY](database-tables.md#policy) |
| **SQL** | [SQL-008](sql/SQL-008-retrieve-agent-of-record-for-a-policy.md) |
| **Confidence** | Unknown |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsProducer.vb` |

---

## BR-018: Y/N flags convert through framework Boolean helpers

| Field | Value |
| --- | --- |
| **Statement** | `Y`/`N` flag columns (paperless, direct writer, EFT, check-limit override, producer detail, exclude-from-LOV, exclude-from-service-center, agency location, exclude-from-no-touch-quote) are interpreted through the framework `ToBoolean` extension. |
| **Trigger** | Any corresponding Boolean predicate property is read. |
| **Enforcement** | `clsAgency.vb`, `clsAgencyOffice.vb`, and `clsProducer.vb` each call the shared `ToBoolean` extension on the persisted flag value. |
| **Outcome** | Callers receive a consistent Boolean interpretation of every `Y`/`N` flag across the library. |
| **Tables** | [AGENCY](database-tables.md#agency), [AGENT](database-tables.md#agent) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgency.vb`, `Business\SAIF.Business.Policy.Agency\clsAgencyOffice.vb`, `Business\SAIF.Business.Policy.Agency\clsProducer.vb` |

---

## BR-019: Special agency sequence numbers identify SAIF and not-yet-appointed agencies

| Field | Value |
| --- | --- |
| **Statement** | Agency sequence number `0` identifies SAIF itself; sequence number `944` identifies the "SAIF not yet appointed" agency. |
| **Trigger** | `clsAgency.IsSAIF` or `IsSAIFNotYetAppointedAgency` is read. |
| **Enforcement** | `clsAgency.vb` compares the loaded sequence number against the `SAIFAgencySeqNum` and `SAIFNotYetAppointedAgencySeqNum` constants. |
| **Outcome** | Callers get a Boolean classification identifying these two special agency rows. |
| **Tables** | [AGENCY](database-tables.md#agency) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgency.vb` |

---

## BR-020: Agency and producer display names are title-cased and abbreviated consistently

| Field | Value |
| --- | --- |
| **Statement** | Agency and producer names are displayed in title case; the abbreviated form additionally shortens "Insurance" to "Ins" and "Services" to "Svcs". |
| **Trigger** | `Name` or `NameAbbreviated` is read. |
| **Enforcement** | `clsAgency.vb` and `clsProducer.vb` apply title-casing and the fixed word-shortening substitutions when building the display name. |
| **Outcome** | Callers receive a consistently formatted display name across agencies and producers. |
| **Tables** | [AGENCY](database-tables.md#agency) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgency.vb`, `Business\SAIF.Business.Policy.Agency\clsProducer.vb` |

---

## BR-021: Regional-office eligibility rejects service-center-only appointments

| Field | Value |
| --- | --- |
| **Statement** | A regional office may not be served by an agency whose active contract is a service-center-only appointment. |
| **Trigger** | A caller invokes `clsAgency.IsValidForOffice(date, isRegionalOffice:=True)`. |
| **Enforcement** | `clsAgency.vb` inspects the agency's first active contract and returns `False` when its type is `ServiceCenterOnlyAppointment`. |
| **Outcome** | Service-center-only agencies are rejected as eligible for regional-office assignment. |
| **Tables** | [AGENCY_CONTRACT](database-tables.md#agency_contract) |
| **SQL** | [SQL-004](sql/SQL-004-retrieve-agency-contracts.md) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgency.vb` |

---

## BR-022: Active-office aggregation clones offices without data portal context

| Field | Value |
| --- | --- |
| **Statement** | An agency office copied into an aggregated cross-agency collection is cloned and stripped of its data portal context. |
| **Trigger** | `clsAgencyCollection.ActiveAgencyOffices` builds a detached collection via `clsAgencyOfficeCollection.AddClone`. |
| **Enforcement** | `clsAgencyOfficeCollection.vb`'s `AddClone` copies office field values into a new instance without the originating `IDataPortalInfo`. |
| **Outcome** | The aggregated collection contains detached office clones that cannot independently re-fetch or persist through the original data portal. |
| **Tables** | [AGENT](database-tables.md#agent) |
| **SQL** | [SQL-006](sql/SQL-006-retrieve-agency-offices-for-an-agency.md) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgencyOfficeCollection.vb` |

---

## BR-023: Producer agencies are detected when agency sequence number equals agent number

| Field | Value |
| --- | --- |
| **Statement** | A producer whose agency sequence number equals its own agent number represents the agency itself rather than an individual producer. |
| **Trigger** | `clsProducer.IsProducerAgency` is read. |
| **Enforcement** | `clsProducer.vb` compares the loaded `AgencySeqNum` to the producer's own `AgentNum`. |
| **Outcome** | Callers receive a Boolean distinguishing agency-level producer rows from individual producers. |
| **Tables** | [AGENT](database-tables.md#agent) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsProducer.vb` |

---

## BR-024: The library is retrieve-only

| Field | Value |
| --- | --- |
| **Statement** | Agency, contract, office, and producer data is read-only through this library; no criteria class provides create, insert, update, or delete SQL. |
| **Trigger** | Any attempt to persist a change through one of the eight `Criteria` classes. |
| **Enforcement** | All eight `Criteria` classes throw for every CRUD SQL property except `RetrieveSQL`. |
| **Outcome** | Attempted mutation raises `ApplicationException(BOC.Messages.InvalidSQLProperty)`; no persistence occurs. |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgency.vb`, `clsAgencyCollection.vb`, `clsAgencyContract.vb`, `clsAgencyContractCollection.vb`, `clsAgencyOffice.vb`, `clsAgencyOfficeCollection.vb`, `clsProducer.vb`, `clsProducerCollection.vb` |

---

## BR-025: Identity keys are agency seq, contract seq, and agent number

| Field | Value |
| --- | --- |
| **Statement** | Agency identity is `AGENCY_SEQ_NUM`; contract identity is `AGENCY_CONTRACT_SEQ_NUM`; office and producer identity is `AGENT_NUM`. |
| **Trigger** | `Equals`, `GetHashCode`, or a collection lookup is invoked on any of the four business objects. |
| **Enforcement** | `clsAgency.vb`, `clsAgencyContract.vb`, `clsAgencyOffice.vb`, and `clsProducer.vb` each key equality and hashing on the type's respective identity field. |
| **Outcome** | Equality and membership tests are consistent with each type's persisted primary key. |
| **Tables** | [AGENCY](database-tables.md#agency), [AGENCY_CONTRACT](database-tables.md#agency_contract), [AGENT](database-tables.md#agent) |
| **Confidence** | Verified |
| **Source** | `Business\SAIF.Business.Policy.Agency\clsAgency.vb`, `clsAgencyContract.vb`, `clsAgencyOffice.vb`, `clsProducer.vb` |

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Database tables](database-tables.md)
- [SQL catalog](sql/index.md)
- [API reference](api/index.md)
- [Configuration](configuration.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.Policy.Agency\clsAgency.vb`
- `Business\SAIF.Business.Policy.Agency\clsAgencyCollection.vb`
- `Business\SAIF.Business.Policy.Agency\clsAgencyContract.vb`
- `Business\SAIF.Business.Policy.Agency\clsAgencyContractCollection.vb`
- `Business\SAIF.Business.Policy.Agency\clsAgencyOffice.vb`
- `Business\SAIF.Business.Policy.Agency\clsAgencyOfficeCollection.vb`
- `Business\SAIF.Business.Policy.Agency\clsProducer.vb`
- `Business\SAIF.Business.Policy.Agency\clsProducerCollection.vb`
