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

# BillEntryService

Drives the manual and auto-feed bill intake workflow: pulling the next scanned bill image/task off the imaging queue via `IClaimBillEntryRepository` and `IImagingClient`, building a new `CbpBill` record pre-filled with worker/claim data resolved through `IClaimInformationService`, `IClaimQueryProvider`, and `ICCClaimApiService`, and validating and persisting bill edits through `IUnitOfWork`/`IValidationService`. It also resolves provider location and rendering-provider lookups (via `IProviderQueryProvider`) for the bill entry UI, and applies conflict-of-interest filtering to the responsible-party inbox using `ClaimUserSecurityAccess` built from the current user's `IUserProfileService` profile.

## Purpose
- Retrieves the next queued bill image/claim-bill task for entry, skipping duplicate images already recorded against a bill and logging or warning when an image cannot be located depending on environment.
- Creates, saves, and submits bills, applying optimistic-concurrency checks and re-deriving worker/claim/provider data on relevant field changes.
- Advances a bill's status history with a new `CbpBillStatus` entry, stamped with the acting or default responsible party.
- Filters a responsible party's bill inbox to exclude bills for workers flagged as a conflict of interest, unless the current user has conflict access.
- Resolves billing/rendering provider locations and their active addresses for bill entry provider lookups.
- Exposes bill type, bill status, and note category/type reference tables for bill entry forms.

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

## Public members
| Member | Signature | Purpose |
| --- | --- | --- |
| BillEntryService (constructor) | `public BillEntryService(IUnitOfWork uow, IUserProfileService uprof, IValidationService val, IClaimBillEntryRepository repo, IImagingClient imagingClient, IBillService billService, IEnvironmentService environmentService, ILogService logService, INoteService noteService, IClaimInformationService claimInformationService, IProviderQueryProvider providerQueryProvider, IClaimQueryProvider claimQueryProvider, ICCClaimApiService ccclaimApiService)` | Wires all repository, imaging, claim, provider, note, logging, and environment dependencies used by the service, throws if `uow` is null, and pre-computes the current user ID for update stamping. |
| GetNewBill | `public Bill GetNewBill(IMessageContainer messageContainer)` | Creates and immediately saves a new blank standard-type bill, returning the persisted result. |
| GetNextClaimBillFromQueue | `public Bill GetNextClaimBillFromQueue(bool hasConflictAccess, IMessageContainer messageContainer)` | Pulls the next non-duplicate bill task from the imaging queue, retrieves its image, and builds a new bill record from it; returns an empty `Bill` with a warning when the queue is empty, retries automatically (in production) or returns a partially built record with a warning (outside production) when the associated image cannot be found. |
| GetClaimBillQueueRemainingCount | `public long GetClaimBillQueueRemainingCount()` | Returns the count of active, non-deleted auto-feed queue tasks assigned to the `{CBPAPP}` task user. |
| GetBill | `public Bill GetBill(long billId, IMessageContainer messageContainer)` | Retrieves a bill by ID and, if it has an associated image, resolves and attaches its image URL; adds an error if the bill does not exist or a warning if it has no linked image. |
| GetBillNotes | `public IList<Note> GetBillNotes(long id, IMessageContainer messageContainer)` | Returns the bill's notes excluding provider-contact-type notes; adds an error and returns an empty list if the bill does not exist. |
| GetNoteCategories | `public IEnumerable<NoteCategoryCode> GetNoteCategories()` | Returns the audit note category code reference list sourced from `INoteService`. |
| GetNoteTypes | `public IEnumerable<NoteTypeCode> GetNoteTypes()` | Returns the audit note type code reference list sourced from `INoteService`. |
| SaveBill | `public Bill SaveBill(Bill bill, IMessageContainer messageContainer, bool saveOnSubmit = false)` | Validates and persists a bill, creating a new `CbpBill` if it does not yet exist or updating the existing record; rejects the save with a concurrency error if the persisted `UpdateNumber` no longer matches the caller's, and applies submit-time date normalization when `saveOnSubmit` is true. |
| SubmitBill | `public Bill SubmitBill(Bill bill, IMessageContainer messageContainer)` | Validates submission-specific business rules (claim number present, billing provider present unless bill type "W", at least one service line, received date within the last 9 years and not in the future) before delegating to `SaveBill` with `saveOnSubmit: true`; returns an empty `Bill` if any rule fails. |
| UpdateBillStatus | `public Bill UpdateBillStatus(long billId, string recipientId, string billStatusCode)` | Appends a new status history entry to the bill for the given status code and responsible party (defaulting to the current user), commits it, and returns the refreshed bill; throws `InvalidDataException` if the status code is not recognized. |
| GetBillTypeCodes | `public IList<CbpBillTypeCode> GetBillTypeCodes()` | Returns all bill type codes ordered by description. |
| GetBillStatusCodes | `public IList<CbpBillStatusCode> GetBillStatusCodes()` | Returns all bill status codes ordered by description. |
| GetInboxBillsByResponsiblePartyId | `public BillEntryInboxResult GetInboxBillsByResponsiblePartyId(string responsiblePartyId)` | Returns the bills currently assigned to the given responsible party, filtering out bills for workers flagged as a conflict of interest unless the current user has conflict access, and reports whether any results were security-filtered. |
| GetProviderLocations | `public IEnumerable<BillEntryProviderLocation> GetProviderLocations(string tin)` | Resolves the provider matching the given tax ID and returns its locations that have an active physical address, including formatted physical/payment addresses and primary service description; throws `NoMatchingDataException` if the tin is empty or no matching provider is found. |
| GetRenderingProviders | `public IEnumerable<BillEntryProviderLocation> GetRenderingProviders(long providerLocationId)` | Returns the given provider location plus its non-business working-provider relationships as of today, each with formatted address, primary service, and expiration status; throws `NoMatchingDataException` if the location does not exist. |

## Behavioral notes
- A static constructor registers AutoMapper mappings once per app domain via `BillMappingHelper.MapBillService()`, `BillMappingHelper.MapForSearchQuery()`, and `ProviderMappingHelper.MapCodeTables()`/`MapTables()`.
- `GetNextClaimBillFromQueue` recurses on itself when an image lookup fails in production, after logging the exception via `ILogService`, effectively retrying the next queue item automatically.*
- Mutating operations (`SaveBill`, `UpdateBillStatus`, and the private bill-build helper) wrap changes in `unitOfWork.Begin()`/`unitOfWork.Commit()`; `SaveBill` calls `unitOfWork.Dispose()` instead of committing on a concurrency conflict.
- `SaveBill` compares the incoming and persisted bill via `CollectionComparer<Bill>.GetChanges` to decide whether to re-derive bill type/provider/date-dependent fields, and a `TODO` comment in source notes this change-detection is currently always reporting changes due to lossy DB↔UI↔DB mapping.*
- Changing a bill's `BillTypeCode` clears type-specific service fields (diagnosis pointer codes for non-standard bills, secondary service/provider codes for non-outpatient bills) and resets each service's location code based on the new bill type.
- `ClaimUserSecurityAccess`, built from the current user's profile, governs whether conflict-of-interest bills are visible in `GetInboxBillsByResponsiblePartyId`.*

## Constraints and usage notes
- `SaveBill` requires both `bill` and `messageContainer` to be non-null and throws via `Enforce.ArgumentNotNull` otherwise.
- `SubmitBill` enforces a hard 9-year lower bound and a not-in-the-future upper bound on the mail room received date, in addition to requiring at least one bill service line and (for non-"W" bill types) a billing provider.
- `GetProviderLocations` and `GetRenderingProviders` only report an address as "active" when its `ExpirationDate` is null or in the future.

> **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/Claims/Bills/BillEntryService.cs`
