Skip to content

BillValidator

Validates a Bill aggregate before persistence, requiring a total amount and bill type, bounding the DRG code's length, and — for three optional fields that may be blank — deferring to IClaimQueryProvider or format checks only when a value is actually supplied: a SAIF claim number must resolve to an existing claim via IClaimQueryProvider.IsValidClaim, a UB bill type code must be purely numeric, and a CBP admission type code must be one of a fixed allow-list of single digits.

Purpose

  • Requires BillTotalAmount and BillTypeCode to be non-null; limits DrgCode to at most 3 characters.
  • When SaifClaimNumber is supplied (non-null/non-empty), requires it to resolve to an existing claim via IClaimQueryProvider.IsValidClaim; blank values are treated as valid (skip the check).
  • When UbBillTypeCode is supplied, requires it to contain only numeric characters via ContainsOnlyNumericCharacters(); blank values are treated as valid.
  • When CBPAdmissionTypeCode is supplied, requires it to be one of the allow-listed values 1, 2, 3, 4, 5, 9; blank values are treated as valid.

Context

  • Namespace: SAIF.Services.Claims.Bills.Validators
  • Assembly/package: SAIF.Services (packaged inside the SAIF.SAIFCode.Core NuGet package)

Public members

Member Signature Purpose
BillValidator BillValidator(IClaimQueryProvider claimQueryProvider) Wires required/length rules for BillTotalAmount, BillTypeCode, DrgCode, plus conditional Must predicates for SaifClaimNumber (claim existence lookup), UbBillTypeCode (numeric-only format), and CBPAdmissionTypeCode (fixed allow-list).*

Inherited members

BillValidator inherits its full public surface from FluentValidation's AbstractValidator<Bill> base class (FluentValidation.AbstractValidator<T>), which is declared in the external FluentValidation NuGet package and is not otherwise documented in this repository. The table below gives the full signature and purpose of each inherited public member actually used to build the rule set in the constructor, so the type remains self-contained without requiring the reader to consult the FluentValidation package directly.

Member Signature Purpose
RuleFor IRuleBuilderInitial<Bill, TProperty> RuleFor<TProperty>(Expression<Func<Bill, TProperty>> expression) Begins a validation rule chain for a specific property of the Bill instance being validated; used here for BillTotalAmount, BillTypeCode, DrgCode, SaifClaimNumber, UbBillTypeCode, and CBPAdmissionTypeCode.*
NotNull IRuleBuilderOptions<Bill, TProperty> NotNull() Fails validation when the property value is null; used for BillTotalAmount and BillTypeCode.*
MaximumLength IRuleBuilderOptions<Bill, string> MaximumLength(int maximumLength) Fails validation when a string property exceeds the given character length; bounds DrgCode to 3 characters.*
Must IRuleBuilderOptions<Bill, TProperty> Must(Func<Bill, TProperty, bool> predicate) Fails validation when the supplied predicate returns false for the current Bill and property value; used for the claim-existence, numeric-format, and allow-list checks on SaifClaimNumber, UbBillTypeCode, and CBPAdmissionTypeCode.*
When IRuleBuilderOptions<Bill, TProperty> When(Func<Bill, bool> predicate, Action action) Applies the rules registered inside action only when predicate evaluates true for the current Bill, letting the conditional fields skip validation when blank.*
Validate ValidationResult Validate(Bill instance) Runs every configured rule against instance synchronously and returns a ValidationResult listing any failures; the primary entry point callers invoke.*
ValidateAsync Task<ValidationResult> ValidateAsync(Bill instance, CancellationToken cancellation = default) Runs every configured rule against instance asynchronously, required when a rule performs async work such as the SaifClaimNumber claim-existence lookup.*

Behavioral notes

  • Validation is enforced via FluentValidation's AbstractValidator<T> base.*
  • The SaifClaimNumber, UbBillTypeCode, and CBPAdmissionTypeCode rules each use an inline null/empty short-circuit (via IsNullOrEmpty()) inside the Must predicate so the field is only actively checked when a value is present; each treats a blank value as valid.*
  • The SaifClaimNumber rule performs a live existence lookup against IClaimQueryProvider, so validation outcome depends on external claim data at validation time rather than only the request's own fields.*

Constraints and usage notes

  • Requires an IClaimQueryProvider implementation to be supplied via constructor injection for the claim-existence check.

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/Validators/BillValidator.cs