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

# BillServiceService

Manages the create, read, update, and delete lifecycle of billed-service line items (`CbpBillService`) attached to a claim bill, and resolves service-type classification for a given service code. It depends on `IUnitOfWork` for transactional repository access, `IBillQueryProvider` to load the owning bill, `IValidationService` to validate contract-level service data before persistence, and `IUserProfileService` to stamp the acting user on new and updated records.

## Purpose
- Creates a new billed-service line on a bill after normalizing and validating the incoming data, resolving its pharmacy dispense-as-written code and servicing provider location.
- Retrieves all billed-service lines for a bill.
- Updates an existing billed-service line while enforcing optimistic-concurrency checks against `UpdateNumber`.
- Deletes a billed-service line from a bill.
- Supplies reference data used by service entry: prescribing-provider codes and the sum of charged amounts for a bill.
- Classifies a service code as a procedure ("U"/service-type code), or a pharmacy product ("P") based on code length and lookup against CBP service codes or national drug data.

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

## Public members
| Member | Signature | Purpose |
| --- | --- | --- |
| BillServiceService (constructor) | `public BillServiceService(IUnitOfWork uow, IUserProfileService uprof, IValidationService val, IBillQueryProvider billQueryProvider)` | Wires the unit of work, user-profile, validation, and bill-query collaborators, and captures the current user's ID (uppercased, prefix before the first `-`) for stamping audit fields.* |
| CreateService | `public ClaimBillContracts.BillService CreateService(long billId, ClaimBillContracts.BillService newService, IMessageContainer messageContainer)` | Normalizes and validates the incoming service line, then persists it on the bill with a newly assigned sequential line ID, resolved pharmacy dispense-as-written code, and resolved servicing provider location; returns an empty `BillService` without persisting if validation fails. |
| GetServices | `public ClaimBillContracts.BillService[] GetServices(long billId, IMessageContainer messageContainer)` | Returns all billed-service lines currently attached to the bill. |
| UpdateService | `public ClaimBillContracts.BillService UpdateService(long billId, ClaimBillContracts.BillService updatedServiceLine, IMessageContainer messageContainer)` | Applies edits to an existing service line's fields (dates, codes, quantities, amounts, prescriber/provider details) after validation, rejecting the update (adding an error and returning an empty `BillService`) if the line's `UpdateNumber` no longer matches the persisted value. |
| DeleteService | `public void DeleteService(long billId, long serviceId, IMessageContainer messageContainer)` | Removes the specified service line from the bill if it still exists, tolerating the case where it has already been deleted. |
| GetPrescribingPrescriberCodes | `public IEnumerable<PrescribingProviderCode> GetPrescribingPrescriberCodes()` | Returns the reference list of prescribing-provider codes available for pharmacy service entry. |
| GetChargedServicesTotal | `public decimal? GetChargedServicesTotal(long billId)` | Returns the sum of `ChargeAmount` across all service lines on the bill, or `null` if there are none. |
| GetServiceTypeCode | `public string GetServiceTypeCode(string serviceCode)` | Classifies the given code: for codes of 5 characters or fewer, looks up the CBP service code's service-type (defaulting to `"U"` when not typed); for longer codes, returns `"P"` if it resolves to a named national drug product, otherwise `"U"`. |

## Behavioral notes
- Wraps `CreateService`, `UpdateService`, and `DeleteService` in `unitOfWork.Begin()`/`unitOfWork.Commit()`, disposing the unit of work without committing when a concurrency conflict is detected in `UpdateService`.
- Enforces optimistic concurrency on updates by comparing `UpdateNumber` and surfacing a conflict message identifying the last updating user before aborting.
- `PrepareServiceForValidator` normalizes incoming service data before validation: converts `DateTime.MinValue` sentinel values to `null`, uppercases several code fields, defaults `CompoundDrugFlag` to `"N"`, and pads blank service-modifier codes to a single space.*
- Uses `IValidationService.Validate` and forwards validation errors into the supplied `IMessageContainer`.
- A static constructor calls `BillMappingHelper.MapBillService()`, registering AutoMapper mappings once per process before any instance is used.
- Contains a `TODO` comment noting that pharmacy dispense-as-written code resolution could instead be handled via an AutoMapper `.AfterMap` configuration.*

## Constraints and usage notes
- The constructor does not null-check `uprof` or `billQueryProvider` (only `uow` is checked via `Enforce.ArgumentNotNull`); passing nulls for those defers failure to first use.*
- `UpdateService` requires callers to pass back the `UpdateNumber` they last read; a stale value aborts the update entirely.

> **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/BillServiceService.cs`
