---
title: PolicyAssociationService
summary: API reference for PolicyAssociationService.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-09-24
library: SAIF.Services
reference_type: package
---

# PolicyAssociationService

Resolves the set of policies associated with a given policy — manual policyholder affiliations, relationship-policy links, and experience-rate-account links — by querying `IUnitOfWork` repositories for `PolicyRelationship`/`Policy` data and mapping results to the `PolicyAssociation` contract type via AutoMapper maps registered in its static constructor, consulting `IUserProfileService` to special-case policyholder external users.

## Purpose
- Returns all policies associated with a policy number, trying manual policyholder affiliations first (for external policyholder users), then relationship links, then experience-rating (rate account) links.
- Returns associations restricted to a single, explicitly requested association type (`ManualAffiliation`, `Relationship`, or `RateAccount`).
- Aggregates every association type together (`GetAllPolicyAssociations`) for use by callers, such as `PolicySecurityService`, that need the complete affiliation graph for a policy.
- Computes derived status flags (`IsActive`, `IsPendingCancellation`, `IsCancelled`, `IsApplication`, `StatusGroup`) and parent/child (`IsParent`) relationships on each mapped association.

## Context
- Namespace: `SAIF.Services.Policies.PolicyAssociations`
- Assembly/package: `SAIF.Services` (packaged inside the `SAIF.SAIFCode.Core` NuGet package).

## Public members
| Member | Signature | Purpose |
| --- | --- | --- |
| PolicyAssociationService (constructor) | `public PolicyAssociationService(IUnitOfWork uow, IUserProfileService userProfileService)` | Wires the unit of work and user-profile service used to query policy/relationship data and classify the current caller. |
| GetPolicyAssociations(long) | `public IEnumerable<PolicyAssociationContract> GetPolicyAssociations(long policyNumber)` | For an external policyholder user, returns manual affiliations if any exist; otherwise falls back to relationship-policy associations, then to experience-rate-account associations, returning the first non-empty set found (or an empty sequence). |
| GetPolicyAssociations(long, AssociationTypes) | `public IEnumerable<PolicyAssociationContract> GetPolicyAssociations(long policyNumber, AssociationTypes policyAssociationType)` | Returns only the associations of the specified type (manual affiliation, relationship, or rate account); an unrecognized type falls back to the default `GetPolicyAssociations(long)` behavior. |
| GetAllPolicyAssociations | `public IEnumerable<PolicyAssociationContract> GetAllPolicyAssociations(long policyNumber)` | Concatenates manual-affiliation, relationship, and rate-account associations for the policy and maps the combined set to `PolicyAssociationContract[]`, returning an empty sequence if none exist. |

## Behavioral notes
- A static constructor registers AutoMapper maps from `PolicyRelationship`/`Policy` data types to the `PolicyAssociation` contract, including derived `PolicyNumber`, `ParentPolicyNumber`, title-cased `PolicyName`, and `IsParent` fields.
- `GetPolicyAssociations(long)` checks whether the current user is an external policyholder (`UserTypeCode.Code == "POLCY"`) before attempting manual-affiliation lookup; all other user types skip straight to relationship/rate-account lookup.
- Relationship and rate-account associations exclude policies with status code `"PC"` (policy-cancelled/pending-cancel) both for the queried policy and, where applicable, its related policy.
- `MapPolicyAssociation` throws a plain `Exception` for any `associationType` other than `RateAccount` or `Relationship`, since manual affiliations are mapped through a separate path.*
- Manual-affiliation lookup unions four separately queried `PolicyRelationship` sets (parent-as-single-match, parent list, member list variants) filtered on `AffiliateTypeCode == "PHP"` and non-cancelled status.

## Constraints and usage notes
- Both constructor parameters are null-checked via `Enforce.ArgumentNotNull`.
- `GetAllPolicyAssociations` issues up to three separate repository queries per call (one per association type) with no caching across calls.*

> **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
- `Services/SAIF.Services/Policies/PolicyAssociation/PolicyAssociationService.cs`
