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

# BillProcedureService

Manages the create, read, update, and delete lifecycle of procedure line items attached to a claim bill, coordinating with `IUnitOfWork` for transactional persistence, `IBillQueryProvider` for loading the owning bill, `IValidationService` for per-item validation, `IUserProfileService` to stamp the acting user, and `IProcedureService` to confirm procedure code validity. Reassigns sequential `BillProcedureId` values when adding new procedures and rejects concurrent updates by comparing `UpdateNumber` before applying changes.

## Purpose
- Creates new bill procedure line items on a bill, assigning sequential procedure IDs and validating each item before commit.
- Retrieves the procedures currently attached to a bill, annotating each with code-validity flags.
- Updates existing procedure line items while enforcing optimistic-concurrency checks against `UpdateNumber`.
- Deletes one, several, or all procedure line items from a bill.
- Exposes the reference list of primary procedure codes usable when entering procedures.

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

## Public members
| Member | Signature | Purpose |
| --- | --- | --- |
| BillProcedureService (constructor) | `public BillProcedureService(IUnitOfWork uow, IUserProfileService uprof, IValidationService val, IBillQueryProvider billQueryProvider, IProcedureService ProcedureService)` | Wires the unit of work, user-profile, validation, bill-query, and procedure-lookup collaborators, and captures the current user's ID (uppercased, prefix before the first `-`) for stamping audit fields.* |
| CreateProcedures | `public List<BillProcedure> CreateProcedures(long billId, List<BillProcedure> newProcedures, IMessageContainer messageContainer)` | Validates and appends new procedure lines to the bill, assigning each a sequential `BillProcedureId` continuing from the current maximum, then returns the newly added procedures with validity flags populated; returns an empty list and rolls back if validation fails. |
| GetProcedures | `public List<BillProcedure> GetProcedures(long billId, IMessageContainer messageContainer)` | Returns all procedure line items currently on the bill, each flagged with `IsValidCode` and `IsValidProcedureDate` based on lookup against `IProcedureService`. |
| UpdateProcedures | `public List<BillProcedure> UpdateProcedures(long billId, List<BillProcedure> updatedProcedures, IMessageContainer messageContainer)` | Applies edits to existing procedure lines after validation, rejecting the entire update (adding an error and returning an empty list) if a line's `UpdateNumber` no longer matches the persisted value, indicating a concurrent edit. |
| DeleteProcedures | `public void DeleteProcedures(long billId, long[] ProcedureIds, IMessageContainer messageContainer)` | Removes the specified procedure line items (by `BillProcedureId`) from the bill within a single transaction. |
| DeleteProcedures | `public void DeleteProcedures(long billId, IMessageContainer messageContainer)` | Removes every procedure line item from the bill. |
| GetPrimaryProcedureCodes | `public List<CbpPrimaryProcedureCode> GetPrimaryProcedureCodes()` | Returns the full reference list of primary procedure codes available for selection when entering a procedure. |

## Behavioral notes
- Wraps `CreateProcedures`, `UpdateProcedures`, and both `DeleteProcedures` overloads in `unitOfWork.Begin()`/`unitOfWork.Commit()`, disposing the unit of work without committing when validation or concurrency checks fail.
- Enforces optimistic concurrency on updates by comparing `UpdateNumber` and surfacing a conflict message identifying the last updating user before aborting.
- Normalizes procedure codes to uppercase and trims whitespace before validation via a private `CleanProcedures` step.*
- Uses `IValidationService.Validate` per procedure item and forwards each validation error into the supplied `IMessageContainer`.
- A static constructor calls `BillMappingHelper.MapBillService()`, registering AutoMapper mappings once per process before any instance is used.

## Constraints and usage notes
- Callers must supply a non-null `IUnitOfWork`, `IUserProfileService`, `IValidationService`, `IBillQueryProvider`, and `IProcedureService`; the constructor enforces this via `Enforce.ArgumentNotNull`.
- `UpdateProcedures` requires callers to pass back the `UpdateNumber` they last read; stale values abort the whole batch, not just the conflicting item.

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