Skip to content

SAIF.Business.Policy.Agency architecture

SAIF.Business.Policy.Agency is a mid-tier BOF library that models the policy distribution channel. Its object graph centers on agencies and exposes contracts, office locations, and producers through retrieve-only business objects that execute Oracle reads through the framework data portal.

Responsibilities

  • Model agencies as the aggregate root for contracts, offices, and producers.
  • Support both lazy navigation and bulk-load patterns for related data.
  • Overlay office and producer semantics on the shared AGENT table.
  • Keep persistence responsibilities out of this library by exposing retrieve-only criteria classes.

Component boundaries

  • clsAgency / clsAgencyCollection: agency retrieval, collection filtering, and bulk distribution of related producers and contracts.
  • clsAgencyContract / clsAgencyContractCollection: contract retrieval plus code-to-enum translation for appointment and commission classifications.
  • clsAgencyOffice / clsAgencyOfficeCollection: office-specific filtering over AGENT rows.
  • clsProducer / clsProducerCollection: producer retrieval plus the direct POLICY agent-of-record lookup.
  • clsAgentUnderwritingData: simple value carrier that packages producer, agency, license, FEID, and address data for callers.
  • Institutions: generated reference-data dataset included in the assembly but not part of the core agency workflow.

Interaction model

  • Single-object retrieves build criteria, execute BOF BeforeRetrieve / AfterRetrieve, and hydrate one business object from a data reader.
  • Collection retrieves execute one SQL statement, iterate the returned rows, and load each item into an in-memory BOF collection.
  • clsAgency.Contracts, clsAgency.Offices, and clsAgency.Producers lazy-load related collections on first access.
  • clsAgencyCollection.RetrieveContracts() and RetrieveProducers() issue one unfiltered child query each, then distribute rows to matching agencies in memory.
  • clsProducer.GetAgent() bypasses the normal business-object criteria path and performs an application-layer scalar lookup against POLICY.

Architecture diagram

The following diagram shows the aggregate root and the retrieve paths used to populate related collections.

flowchart TD
  Caller[Caller] --> AgencyColl[clsAgencyCollection]
  Caller --> Agency[clsAgency]
  AgencyColl --> Agency
  Agency -.lazy load.-> Contracts[clsAgencyContractCollection]
  Agency -.lazy load.-> Offices[clsAgencyOfficeCollection]
  Agency -.lazy load.-> Producers[clsProducerCollection]
  AgencyColl -.bulk load.-> Contracts
  AgencyColl -.bulk load.-> Producers
  Producers --> PolicyLookup[clsProducer.GetAgent]
  Agency --> Portal[IDataPortalInfo / BOF data portal]
  Contracts --> Portal
  Offices --> Portal
  Producers --> Portal
  PolicyLookup --> Portal
  Portal --> Oracle[(Oracle: AGENCY, AGENCY_CONTRACT, AGENT, POLICY)]

Sequence diagram

The following diagram shows the bulk producer-loading path that avoids issuing one producer query per agency.

sequenceDiagram
  participant Client
  participant Agencies as clsAgencyCollection
  participant Portal as BOF data portal
  participant Oracle
  Client->>Agencies: GetAgencyCollection(dpi, criteria)
  Agencies->>Portal: RetrieveObject(criteria)
  Portal->>Oracle: Execute agency retrieval SQL
  Oracle-->>Portal: IDataReader rows
  Portal-->>Agencies: Hydrated clsAgencyCollection
  Client->>Agencies: RetrieveProducers()
  Agencies->>Portal: GetProducerCollection(dpi)
  Portal->>Oracle: Execute producer retrieval SQL
  Oracle-->>Portal: Producer rows
  Portal-->>Agencies: Hydrated clsProducerCollection
  Agencies-->>Client: Producers assigned to matching agencies

Design constraints

  • All criteria classes are retrieve-only; create, insert, update, and delete SQL paths throw invalid-SQL exceptions.
  • clsAgencyCollection.Criteria.RetrieveSQL assembles optional predicates dynamically, including a contract-type IN list rendered as string literals instead of bind variables.
  • clsAgencyOffice and clsProducer both project from AGENT, so schema changes to that table affect two distinct business views.
  • Lazy navigation is convenient for single-object use but can trigger N+1 database access if callers iterate many agencies without using the bulk-load helpers.

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