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

# CollectionsService

Implements `ICollectionsService` (extending `ValidatingServiceBase`), the primary orchestration service for the Legal Collections module: it manages case/request creation and lookup, debtors and their addresses, notes, activities, transactions, collection tasks, and case search, and generates the PDF summary/notes/tasks reports used by the collections UI. It depends on `IValidationService` for FluentValidation-based edits, `IUnitOfWork` for all persistence and transactions, `ICollectionsRepository` for collections-specific queries, `IDocumentService` for PDF/email generation, `IUserProfileService` for the current user, `IWorkCalendarService` to compute note edit windows, `IWorkerDataApiClient` to resolve worker names/SSNs from Guidewire, and `ICCClaimApiService` to resolve claim/worker details for claim-based cases. Its static constructor calls `AutoMapperBootStrapper.Configure()` once to register the AutoMapper maps used throughout the class.

## Purpose
- Retrieves and summarizes collections cases (by ID or reference number), including PDF case-summary generation with activity, category-total, and transaction detail.
- Creates, updates, and deletes debtors and their associated mailing/physical locations, resolving addresses differently for policy, claim, third-party, and fraud/other case types.
- Manages case notes (create/save/delete/PDF export), enforcing an editable window computed via `IWorkCalendarService`.
- Validates and saves collections "requests" (new/edited cases), generating the appropriate debtor set for the case's collection code and mapping associated activities.
- Manages collection tasks (create/save/delete/list/PDF export) tied to a case's policy or claim.
- Manages transactions (create/save/delete), recomputing case balances and enforcing approval requirements based on transaction code.
- Performs cross-system worker/claim/policy searches by populating a temp table from the worker data API and delegating to `ICollectionsRepository.SearchCollections`.

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

## Public members
| Member | Signature | Purpose |
| --- | --- | --- |
| UnitOfWork | `protected readonly IUnitOfWork UnitOfWork` | Repository/transaction gateway used for essentially all persistence in this service. |
| ValidationService | `protected readonly IValidationService ValidationService` | Runs FluentValidation rules against domain models before they are persisted, collecting errors into an `IMessageContainer`. |
| CollectionsRepo | `protected readonly ICollectionsRepository CollectionsRepo` | Supplies collections-specific queries (category totals, addresses, name/SSN lookups, search, payment application). |
| DocumentService | `protected readonly IDocumentService DocumentService` | Generates PDF case-summary, notes, and tasks reports. |
| UserProfileService | `protected readonly IUserProfileService UserProfileService` | Resolves the current user for create/update attribution and authorization checks. |
| WorkCalendarService | `protected readonly IWorkCalendarService WorkCalendarService` | Computes the next work day used to determine whether a note is still within its editable window. |
| CollectionsService(...) | `public CollectionsService(IValidationService validationService, IUnitOfWork unitOfWork, ICollectionsRepository collectionsRepo, IDocumentService documentService, IUserProfileService userProfileService, IWorkCalendarService workCalendarService, IWorkerDataApiClient workerDataApiClient, ICCClaimApiService ccClaimApiService)` | Wires in all collaborators (enforcing non-null validation service and unit of work) needed to service case, debtor, note, request, task, transaction, and search operations. |
| GetActivities | `public IEnumerable<Activity> GetActivities(long caseId)` | Returns all activity records recorded against a case. |
| GetActivityCodes | `public IEnumerable<ActivityCode> GetActivityCodes()` | Returns the activity type reference list ordered by description, with a leading blank `"--Select--"` placeholder entry. |
| GetCaseById | `public Case GetCaseById(long caseId)` | Returns the mapped case with its derived `CaseType`, or `null` if the case does not exist. |
| GetCaseSummaryById | `public Case GetCaseSummaryById(long caseId)` | Returns the case populated with category totals, market type (for policy cases), county, and derived case type, for summary display. |
| GetCasesByReference | `public IEnumerable<CaseHeader> GetCasesByReference(string referenceId)` | Returns case headers matching a (possibly check-digit-trimmed) reference number, resolving the debtor/worker display name — including a live Guidewire claim lookup for claim-related collection codes — and derived case type for each. |
| GetSummaryPdf | `public byte[] GetSummaryPdf(long caseId)` | Builds the case-summary XML (header, activities, category totals, transactions) and returns the rendered "Corporate_Collections_Summary" PDF, or `null` if the case reference cannot be found. |
| GetDebtor | `public Debtor GetDebtor(long id)` | Returns a single debtor mapped to its domain contract with contact info, name, and SSN populated, or an empty `Debtor` if not found. |
| GetDebtors | `public ICollection<Debtor> GetDebtors(long caseId)` | Returns all debtors for a case with contact info populated, masking the SSN to the last four digits for users who are not authorized "update" users. |
| GetPolicyFormattedAddresses | `public ICollection<DebtorAddress> GetPolicyFormattedAddresses(long policyNum)` | Returns every active location for a policy with a fully formatted address string. |
| GetDebtorName | `public string GetDebtorName(long id)` | Returns the debtor's display name, falling back to a Guidewire worker lookup (last, first, middle) when no name is stored for a worker-linked debtor. |
| GetPrimaryDebtorName | `public string GetPrimaryDebtorName(long id)` | Returns the case's primary debtor's display name, with the same Guidewire worker fallback as `GetDebtorName`. |
| GetDebtorSsn | `public string GetDebtorSsn(long id)` | Returns the debtor's SSN, falling back to the Guidewire worker's tax ID when no SSN is stored for a worker-linked debtor. |
| GetPolicyLocations | `public ICollection<Location> GetPolicyLocations(long policyNum)` | Returns all non-expired locations for a policy, ordered by address line 1. |
| GetPolicyMailingLocation | `public Location GetPolicyMailingLocation(long policyNum)` | Returns the policy's non-expired location flagged with location code `"POL"` (the mailing address). |
| CreateDebtor | `public Debtor CreateDebtor(long caseId, DebtorEdit debtorEdit, IMessageContainer messageContainer)` | Validates the new debtor, and if valid, creates a new manually entered address location plus a `Debtor` record in one transaction, refreshing the last-statement balance in a second transaction unless the debtor's statement is held. |
| DeleteDebtor | `public bool DeleteDebtor(long id, IMessageContainer messageContainer)` | Deletes the debtor (and its dedicated location, if any) inside one transaction; returns `false` if the debtor does not exist. |
| SaveDebtor | `public bool SaveDebtor(long id, long caseId, DebtorEdit debtorEdit, IMessageContainer messageContainer)` | Validates the edited debtor, and if valid, updates (or creates) the associated location and debtor record — refreshing the last-statement balance when the statement hold is being released — inside one transaction. |
| UpdateDebtors | `public bool UpdateDebtors(long caseId, IEnumerable<DebtorEdit> debtorEditList, IMessageContainer messageContainer)` | Validates and updates the SSN, SOIL inclusion, statement-hold flag, and mailing address (nulled out when it matches the policy's default mailing location) for each debtor in the list, in one transaction; stops and returns `false` at the first invalid debtor. |
| GetNotes | `public IEnumerable<Note> GetNotes(long caseId, NoteFilter filter)` | Returns notes for a case within the given date filter, newest first, each flagged `CanEdit` based on whether today is still within the work-calendar editable window. |
| GetNote | `public Note GetNote(long noteId)` | Returns a single note with its `CanEdit` flag computed from the work-calendar editable window. |
| SaveNote | `public bool SaveNote(long noteId, NoteEdit noteEdit, string appendText, IMessageContainer messageContainer)` | Validates the edited note, and if valid, updates its text (appending a timestamped `"*ADDED ... by ..."` annotation when append text is supplied) and commits the change. |
| CreateNote | `public Note CreateNote(long caseId, NoteEdit noteEdit, IMessageContainer messageContainer)` | Validates and, if valid, creates a new note attributed to the current user and returns the persisted note (with `CanEdit` recomputed). |
| DeleteNote | `public bool DeleteNote(long noteId, IMessageContainer messageContainer)` | Deletes the specified note inside one transaction; always returns `true`. |
| GetNotePdf | `public byte[] GetNotePdf(long caseId, NoteFilter filter)` | Builds the filtered notes XML (with a date-range summary) and returns the rendered "Corporate_Collections_Notes" PDF. |
| GetRequestById | `public Request GetRequestById(long caseId)` | Returns the case mapped to a `Request` contract, with market type (for policy cases) and county resolved, for edit/display purposes. |
| CreateRequest | `public Request CreateRequest()` | Returns a new, empty `Request` mapped from a blank case, for use when initiating a new collections case. |
| ValidateContext | `public bool ValidateContext(string caseType, string caseContext, out string contextName)` | For policy-type case codes, resolves and returns the policy name for a policy number; otherwise resolves and returns the worker's formatted name via `ICCClaimApiService`; returns `false` with an explanatory `contextName` message if the policy/claim cannot be found. |
| GetCollectionCodes | `public IEnumerable<CollectionCode> GetCollectionCodes()` | Returns the collection-type reference list ordered by description. |
| GetJudgmentCodes | `public IEnumerable<JudgmentCode> GetJudgmentCodes()` | Returns the judgment-type reference list ordered by description. |
| GetJudgmentYears | `public IEnumerable<JudgmentYearsValue> GetJudgmentYears()` | Returns the allowed judgment-duration values ordered by number of years. |
| GetInterestCalcCodes | `public IEnumerable<InterestCalcCode> GetInterestCalcCodes()` | Returns the interest-calculation-method reference list ordered by description. |
| GetInterestRates | `public IEnumerable<InterestRateValue> GetInterestRates()` | Returns the allowed annual interest rates ordered by rate. |
| GetCountyCodes | `public IEnumerable<County> GetCountyCodes()` | Returns Oregon county reference codes ordered by name, plus a synthetic `"C7" / "Out of state"` entry for Washington. |
| GetStatusCodes | `public IEnumerable<StatusCode> GetStatusCodes()` | Returns the case-status reference list ordered by description. |
| GetStateCodes | `public IEnumerable<StateCode> GetStateCodes()` | Returns the US state reference list ordered by code. |
| GetCreditReps | `public IEnumerable<CreditRepUser> GetCreditReps()` | Returns active (non-expired) credit representative users ordered by employee last name. |
| SaveRequest | `public bool SaveRequest(long caseId, Request request, ICollection<Activity> activities, IMessageContainer messages)` | Validates the request and its activities; if valid, updates (or, for `caseId == 0`, creates and generates debtors for) the case's core fields, reconciles its activities, and commits inside one transaction; fails with a concurrency error if the stored `UpdateNum` no longer matches the submitted request. |
| CreateActivity | `public Activity CreateActivity(long caseId)` | Returns a new, empty `Activity` contract pre-populated with the given case ID. |
| DeleteActivity | `public bool DeleteActivity(long activityId)` | Deletes the specified activity inside one transaction; returns `false` if the activity does not exist. |
| GetSearchResults | `public async Task<IEnumerable<SearchResult>> GetSearchResults(SearchCriteria criteria)` | For non-policy-name searches, first stages matching Guidewire claim/worker data into a temp table, then (after normalizing and wildcard-formatting the criteria) delegates to `ICollectionsRepository.SearchCollections`, returning up to 300 results with debtor names backfilled where missing. |
| CreateTask | `public CollectionTask CreateTask(CollectionTaskEdit taskEdit, IMessageContainer messageContainer)` | Validates the task edit, resolves the owning policy or claim for the case, and — if valid both before and after enrichment — creates the task (attributed to `"SYSTEM"`) inside one transaction, returning the persisted task with its debtor name populated. |
| DeleteTask | `public bool DeleteTask(long id, IMessageContainer messageContainer)` | Soft-deletes (`IsDeleted = true`) the specified task and increments its update number inside one transaction; always returns `true`. |
| GetTask | `public CollectionTask GetTask(long id)` | Returns the task mapped to its domain contract with the case's primary debtor name populated. |
| GetTasks | `public IEnumerable<CollectionTask> GetTasks(CollectionTaskCriteria criteria)` | Returns up to 300 non-deleted Collections-source tasks matching the date range/case/reference-number filters, ordered by due date descending, each with its debtor name resolved. |
| GetTasksForPdf | `public byte[] GetTasksForPdf(CollectionTaskCriteria criteria)` | Builds the filtered tasks XML (with a date-range and filter summary) and returns the rendered "Corporate_Collections_Tasks" PDF. |
| SaveTask | `public bool SaveTask(long id, CollectionTaskEdit collectionTaskEdit, IMessageContainer messageContainer)` | Validates the edited task's date/text, and if valid, updates and commits the change inside one transaction. |
| ValidateCollectionTaskCriteria | `public bool ValidateCollectionTaskCriteria(ref CollectionTaskCriteria criteria, IMessageContainer messageContainer)` | Defaults an unset through-date to `DateTime.MaxValue`, or adds a validation error and returns `false` when the from-date is after the through-date. |
| GetTransactions | `public ICollection<Transaction> GetTransactions(long caseId)` | Returns all transactions for a case, each flagged with whether it `CanEdit` (based on statement date, prior payment application, category, and system-generated status) and whether approval `IsApprovalRequired`. |
| GetTransaction | `public Transaction GetTransaction(long id)` | Returns a single transaction mapped to its domain contract. |
| DeleteTransaction | `public bool DeleteTransaction(long id)` | Deletes the transaction and reverses its amount from the case's current balance inside one transaction; returns `false` if the transaction does not exist. |
| SaveTransaction | `public bool SaveTransaction(long transactionId, TransactionEdit transEdit, IMessageContainer messages)` | Validates the edited transaction; if the stored update number no longer matches, rolls back and fails with a concurrency error; otherwise (when editable) adjusts the case balance by the amount delta and commits the change inside one transaction. |
| InsertTransaction | `public long InsertTransaction(TransactionEdit transEdit, IMessageContainer messages)` | Validates and, if valid, inserts a new transaction, adjusts the case's current balance up or down based on the transaction code's pay-down order, commits, then reapplies payments via `CollectionsRepo.ApplyPayments`; returns `-1` if validation fails, otherwise the new transaction ID. |
| CheckForRequiredApproval | `public bool CheckForRequiredApproval(TransactionCode tranCode)` | Returns whether the given transaction code is flagged as requiring approval in the transaction-code reference list. |
| GetTransactionCategoryCodes | `public IEnumerable<TransactionCategoryCode> GetTransactionCategoryCodes()` | Returns the full transaction-category reference list. |
| GetTransactionCodes | `public ICollection<TransactionCode> GetTransactionCodes()` | Returns the transaction-type reference list ordered by description, each flagged `IsInterestAllowed` based on its category's pay-down order. |
| GetWriteOffApprovalUsers | `public ICollection<WriteOffApprovalUser> GetWriteOffApprovalUsers()` | Returns active (non-expired) write-off approval users ordered by employee last name. |
| IsUpdateUser | `public bool IsUpdateUser()` | Returns whether the current user holds the `"LegalColUpdate"` security permission. |

## Behavioral notes
- Wraps nearly every write operation (debtor, note, request, task, and transaction create/save/delete) in a `UnitOfWork.Begin()`/`Commit()` pair, and rolls back on optimistic-concurrency failures detected by comparing a submitted `UpdateNum` to the stored value (`SaveRequest`, `SaveTransaction`).
- Validates domain models before persisting via the private `ValidateAndAddErrors` helper, which delegates to `ValidationService.Validate` (backed by the Collections FluentValidation validators) and appends any failures to the caller's `IMessageContainer`.
- Resolves debtor contact information differently per case type (`GetDebtorContactInfo`): fraud/other and policy cases query `CollectionsRepo`, claim cases call `ICCClaimApiService.GetWorkerAddress`, and third-party cases call `CollectionsRepo.GetThirdPartyAddress`.
- `GetDebtors` masks the stored SSN to `"xxx-xx-####"` for any user who is not an authorized update user (per `IsUpdateUser`), enforcing field-level data protection.
- `CreateTask`/`GetTask`/`GetTasks` resolve and cache a per-case debtor name lookup (`DebtorNameItem`) to avoid re-querying per task row when listing multiple tasks for the same case.

> **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/Collections/CollectionsService.cs
