---
title: SAIF.Services business rules
summary: Enumerated business rules with per-rule trigger, enforcement, and outcomes.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-09-24
library: SAIF.Services
reference_type: package
---

# SAIF.Services business rules

This page catalogues the 426 business rules identified in SAIF.Services, all prefixed `SVC-BR-*`. Enforcement locations are relative to `Services/SAIF.Services/` unless otherwise noted. Rules are grouped by functional area for readability; each rule is independently linkable by its heading anchor. Some rules are delegated to SAIF.Domain and catalogued there as `DOM-BR-*` (referenced by area introductions below, not duplicated here).

## Rule areas

| Area | Rule ID prefix | Rule count |
| --- | --- | --- |
| [Bills](#bills) | [`SVC-BR-BIL-*`](#bills) | 127 |
| [Claims](#claims) | [`SVC-BR-CLM-*`](#claims) | 78 |
| [Legal](#legal) | [`SVC-BR-LGL-*`](#legal) | 80 |
| [Policies and certificates](#policies-and-certificates) | [`SVC-BR-POL-*`](#policies-and-certificates) | 69 |
| [Collections](#collections) | [`SVC-BR-COL-*`](#collections) | 49 |
| [Documents](#documents) | [`SVC-BR-DOC-*`](#documents) | 8 |
| [Miscellaneous](#miscellaneous) | [`SVC-BR-MSC-*`](#miscellaneous) | 15 |

## Bills

## SVC-BR-BIL-001 Can be non-chargeable only if status is Reviewed, billing provider is IME, and audit IsChargeableCost

| Field | Value |
| --- | --- |
| **Statement** | Can be non-chargeable only if status is Reviewed, billing provider is IME, and audit IsChargeableCost |
| **Trigger** | check |
| **Enforcement** | BillService.cs L81-83 |
| **Outcome** | false otherwise |
| **Operation(s)** | CanBillBeNonChargeable |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillService.cs` — BillService.cs L81-83 |

---

## SVC-BR-BIL-002 True if the first WCD 'Closed' (denial) date ≤ StatementFromDate

| Field | Value |
| --- | --- |
| **Statement** | True if the first WCD "Closed" (denial) date ≤ StatementFromDate |
| **Trigger** | check |
| **Enforcement** | L86-93 |
| **Outcome** | true |
| **Operation(s)** | CanBillBeNonChargeable |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillService.cs` — L86-93* |

---

## SVC-BR-BIL-003 True if any 'Denied' condition DecisionDate ≤ StatementFromDate

| Field | Value |
| --- | --- |
| **Statement** | True if any "Denied*" condition DecisionDate ≤ StatementFromDate |
| **Trigger** | check |
| **Enforcement** | L97-102 |
| **Outcome** | true |
| **Operation(s)** | CanBillBeNonChargeable |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillService.cs` — L97-102* |

---

## SVC-BR-BIL-004 Amount = sum of AllowedAmount over audited services for claim/status list/payment category; null → 0

| Field | Value |
| --- | --- |
| **Statement** | Amount = sum of AllowedAmount over audited services for claim/status list/payment category; null → 0 |
| **Trigger** | call |
| **Enforcement** | L108-123 |
| **Outcome** | decimal |
| **Operation(s)** | GetBillAmounts |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillService.cs` — L108-123* |

---

## SVC-BR-BIL-010 Approve only when status = 'REV' - 'Error - Incorrect status for approval.'

| Field | Value |
| --- | --- |
| **Statement** | Approve only when status = "REV": "Error: Incorrect status for approval." |
| **Trigger** | ApproveBillRequest |
| **Enforcement** | ApproveBillRequestValidator |
| **Outcome** | invalid result |
| **Operation(s)** | ApproveBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/ApproveBillRequestValidator.cs` — ApproveBillRequestValidator |

---

## SVC-BR-BIL-020 SendtoMailId NotNull - 'Error - Mail id is required.'

| Field | Value |
| --- | --- |
| **Statement** | SendtoMailId NotNull: "Error: Mail id is required." |
| **Trigger** | SendPendRequest |
| **Enforcement** | SendPendRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | SendPendBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/SendPendRequestValidator.cs` — SendPendRequestValidator |

---

## SVC-BR-BIL-021 Mail id must be valid - 'Error - Invalid Mail Id.'

| Field | Value |
| --- | --- |
| **Statement** | Mail id must be valid: "Error: Invalid Mail Id." |
| **Trigger** | SendPendRequest |
| **Enforcement** | SendPendRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | SendPendBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/SendPendRequestValidator.cs` — SendPendRequestValidator |

---

## SVC-BR-BIL-022 PendDate < today+60: "Error: Bill cannot be pended more than 60 days into the future."

| Field | Value |
| --- | --- |
| **Statement** | PendDate < today+60: "Error: Bill cannot be pended more than 60 days into the future." |
| **Trigger** | SendPendRequest |
| **Enforcement** | SendPendRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | SendPendBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/SendPendRequestValidator.cs` — SendPendRequestValidator |

---

## SVC-BR-BIL-023 PendDate > yesterday - 'Error - Bill cannot be pended in the past.'

| Field | Value |
| --- | --- |
| **Statement** | PendDate > yesterday: "Error: Bill cannot be pended in the past." |
| **Trigger** | SendPendRequest |
| **Enforcement** | SendPendRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | SendPendBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/SendPendRequestValidator.cs` — SendPendRequestValidator |

---

## SVC-BR-BIL-024 Recipient must have confidential access: "Error: Send Pend Mailid does not have access to receive confidential bills"

| Field | Value |
| --- | --- |
| **Statement** | Recipient must have confidential access: "Error: Send Pend Mailid does not have access to receive confidential bills" |
| **Trigger** | SendPendRequest |
| **Enforcement** | SendPendRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | SendPendBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/SendPendRequestValidator.cs` — SendPendRequestValidator |

---

## SVC-BR-BIL-025 NoteText NotNull - 'Error - Bill note is required.'

| Field | Value |
| --- | --- |
| **Statement** | NoteText NotNull: "Error: Bill note is required." |
| **Trigger** | SendToAuditRequest |
| **Enforcement** | SendToAuditRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | SendToAudit |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/SendToAuditRequestValidator.cs` — SendToAuditRequestValidator |

---

## SVC-BR-BIL-026 NoteText ≤600 - 'Error - Text exceeds 600 characters.'

| Field | Value |
| --- | --- |
| **Statement** | NoteText ≤600: "Error: Text exceeds 600 characters." |
| **Trigger** | SendToAuditRequest |
| **Enforcement** | SendToAuditRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | SendToAudit |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/SendToAuditRequestValidator.cs` — SendToAuditRequestValidator |

---

## SVC-BR-BIL-027 All bills Status.IsCompleted - 'Error - Bill must be in completed status to regenerate'

| Field | Value |
| --- | --- |
| **Statement** | All bills Status.IsCompleted: "Error: Bill must be in completed status to regenerate" |
| **Trigger** | RegenerateRequest |
| **Enforcement** | RegenerateRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | RegenerateBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/RegenerateRequestValidator.cs` — RegenerateRequestValidator |

---

## SVC-BR-BIL-028 NoteText NotEmpty - 'Error - Text is required.'

| Field | Value |
| --- | --- |
| **Statement** | NoteText NotEmpty: "Error: Text is required." |
| **Trigger** | RegenerateRequest |
| **Enforcement** | RegenerateRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | RegenerateBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/RegenerateRequestValidator.cs` — RegenerateRequestValidator |

---

## SVC-BR-BIL-029 NoteText ≤600 - 'Error - Text exceeds 600 characters.'

| Field | Value |
| --- | --- |
| **Statement** | NoteText ≤600: "Error: Text exceeds 600 characters." |
| **Trigger** | RegenerateRequest |
| **Enforcement** | RegenerateRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | RegenerateBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/RegenerateRequestValidator.cs` — RegenerateRequestValidator |

---

## SVC-BR-BIL-030 Full-duplicate bills are skipped: "Bill {0} was not regenerated because it is a duplicate of bill {1}"

| Field | Value |
| --- | --- |
| **Statement** | Full-duplicate bills are skipped: "Bill {0} was not regenerated because it is a duplicate of bill {1}" |
| **Trigger** | regenerate |
| **Enforcement** | BillService.cs L206-211 |
| **Outcome** | message, skipped |
| **Operation(s)** | RegenerateBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillService.cs` — BillService.cs L206-211 |

---

## SVC-BR-BIL-031 Summary - 'Bill(s) regenerated with the exception of -' / 'Bill(s) successfully regenerated.'

| Field | Value |
| --- | --- |
| **Statement** | Summary: "Bill(s) regenerated with the exception of:" / "Bill(s) successfully regenerated." |
| **Trigger** | ≥1 success |
| **Enforcement** | L221-227 |
| **Outcome** | message |
| **Operation(s)** | RegenerateBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillService.cs` — L221-227* |

---

## SVC-BR-BIL-040 IssueDate NotEmpty - 'Error - Issue date is required!'

| Field | Value |
| --- | --- |
| **Statement** | IssueDate NotEmpty: "Error: Issue date is required!" |
| **Trigger** | PaymentOptionsRequest |
| **Enforcement** | PaymentOptionsRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | UpdatePaymentOptions |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/PaymentOptionsRequestValidator.cs` — PaymentOptionsRequestValidator |

---

## SVC-BR-BIL-041 IssueDate ≥ MA NextIssueDate: "Error: Issue date should not be less than the next available check run date."

| Field | Value |
| --- | --- |
| **Statement** | IssueDate ≥ MA NextIssueDate: "Error: Issue date should not be less than the next available check run date." |
| **Trigger** | PaymentOptionsRequest |
| **Enforcement** | PaymentOptionsRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | UpdatePaymentOptions |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/PaymentOptionsRequestValidator.cs` — PaymentOptionsRequestValidator |

---

## SVC-BR-BIL-042 IssueDate ≤ today+28: "Error: Issue date should not be more than 28 days into the future."

| Field | Value |
| --- | --- |
| **Statement** | IssueDate ≤ today+28: "Error: Issue date should not be more than 28 days into the future." |
| **Trigger** | PaymentOptionsRequest |
| **Enforcement** | PaymentOptionsRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | UpdatePaymentOptions |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/PaymentOptionsRequestValidator.cs` — PaymentOptionsRequestValidator |

---

## SVC-BR-BIL-043 IssueDate must be a working day: "Error: Issue date should be on a working day."

| Field | Value |
| --- | --- |
| **Statement** | IssueDate must be a working day: "Error: Issue date should be on a working day." |
| **Trigger** | PaymentOptionsRequest |
| **Enforcement** | PaymentOptionsRequestValidator (IWorkCalendarService) |
| **Outcome** | invalid |
| **Operation(s)** | UpdatePaymentOptions |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/PaymentOptionsRequestValidator.cs` — PaymentOptionsRequestValidator (IWorkCalendarService) |

---

## SVC-BR-BIL-060 Issue date = CurrentNextReviewDate if status is EXT/COM/SUS/APP, or if NextReviewDate ≥ MA NextIssueDate and the last status user contains "@"; otherwise GetNextIssueDate(today, MA NextIssueDate)

| Field | Value |
| --- | --- |
| **Statement** | Issue date = CurrentNextReviewDate if status is EXT/COM/SUS/APP, or if NextReviewDate ≥ MA NextIssueDate and the last status user contains "@"; otherwise GetNextIssueDate(today, MA NextIssueDate) |
| **Trigger** | approve/get |
| **Enforcement** | BillService.cs DeterminePaymentIssueDate |
| **Outcome** | date |
| **Operation(s)** | ApproveBill, GetPaymentOptions |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillService.cs` — BillService.cs DeterminePaymentIssueDate |

---

## SVC-BR-BIL-061 CanUpdate = status not in EXT/COM/SUS AND caller flag

| Field | Value |
| --- | --- |
| **Statement** | CanUpdate = status not in EXT/COM/SUS AND caller flag |
| **Trigger** | get |
| **Enforcement** | L425 |
| **Outcome** | flag |
| **Operation(s)** | GetPaymentOptions |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillService.cs` — L425* |

---

## SVC-BR-BIL-062 If today is not a working day, or today == nextIssueDate → NextWorkDay(nextIssueDate); else nextIssueDate

| Field | Value |
| --- | --- |
| **Statement** | If today is not a working day, or today == nextIssueDate → NextWorkDay(nextIssueDate); else nextIssueDate |
| **Trigger** | calc |
| **Enforcement** | L441-451 |
| **Outcome** | date |
| **Operation(s)** | GetNextIssueDate |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillService.cs` — L441-451* |

---

## SVC-BR-BIL-063 Header requires the claim in Claim Center, else throw "Claim does not exists in Claim Center"

| Field | Value |
| --- | --- |
| **Statement** | Header requires the claim in Claim Center, else throw "Claim does not exists in Claim Center" |
| **Trigger** | header |
| **Enforcement** | L281 |
| **Outcome** | exception |
| **Operation(s)** | GetBillHeader |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillService.cs` — L281* |

---

## SVC-BR-BIL-070 A queue task whose ImageId already exists on a CbpBill is a duplicate; fetch the next task

| Field | Value |
| --- | --- |
| **Statement** | A queue task whose ImageId already exists on a CbpBill is a duplicate; fetch the next task |
| **Trigger** | queue |
| **Enforcement** | BillEntryService.cs L131-136, L92-96 |
| **Outcome** | loop |
| **Operation(s)** | GetNextClaimBillFromQueue |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillEntryService.cs` — BillEntryService.cs L131-136, L92-96 |

---

## SVC-BR-BIL-071 Return code 0 = ok; 1 = empty ("No bills remain in the queue.  Break time!!"); 2 = throw an error stating the maximum number of autofeed retrieval attempts was met; other = throw "There was an unknown problem retrieving a bill from the queue."

| Field | Value |
| --- | --- |
| **Statement** | Return code 0 = ok; 1 = empty ("No bills remain in the queue.  Break time!!"); 2 = throw an error stating the maximum number of autofeed retrieval attempts was met; other = throw "There was an unknown problem retrieving a bill from the queue." |
| **Trigger** | queue |
| **Enforcement** | L145-159 |
| **Outcome** | warn/throw |
| **Operation(s)** | GetNextClaimBillFromQueue |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillEntryService.cs` — L145-159* |

---

## SVC-BR-BIL-072 Image not found: in production, log and skip to the next task; otherwise warn and still build the bill

| Field | Value |
| --- | --- |
| **Statement** | Image not found: in production, log and skip to the next task; otherwise warn and still build the bill |
| **Trigger** | image |
| **Enforcement** | L112-124 |
| **Outcome** | skip/warn |
| **Operation(s)** | GetNextClaimBillFromQueue |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillEntryService.cs` — L112-124* |

---

## SVC-BR-BIL-073 Other imaging errors: restore task to queue; warn "Problem reading image from OnBase.  Please contact support."

| Field | Value |
| --- | --- |
| **Statement** | Other imaging errors: restore task to queue; warn "Problem reading image from OnBase.  Please contact support." |
| **Trigger** | image |
| **Enforcement** | L172-180 |
| **Outcome** | warn, empty bill |
| **Operation(s)** | GetNextClaimBillFromQueue |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillEntryService.cs` — L172-180* |

---

## SVC-BR-BIL-074 New queue bill: type Standard, status PEN, claim# from image else task; worker autofill failure throws "Unable to autofill worker information"

| Field | Value |
| --- | --- |
| **Statement** | New queue bill: type Standard, status PEN, claim# from image else task; worker autofill failure throws "Unable to autofill worker information" |
| **Trigger** | build |
| **Enforcement** | L185-210 |
| **Outcome** | Add CbpBill |
| **Operation(s)** | GetNextClaimBillFromQueue |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillEntryService.cs` — L185-210* |

---

## SVC-BR-BIL-075 Bill not found → error "Unable to find bill with ID"; no ImageId/TowId → warn "This bill does not have an associated image."; ImageId preferred over TowId

| Field | Value |
| --- | --- |
| **Statement** | Bill not found → error "Unable to find bill with ID"; no ImageId/TowId → warn "This bill does not have an associated image."; ImageId preferred over TowId |
| **Trigger** | get |
| **Enforcement** | L226-252, L605-620 |
| **Outcome** | msg |
| **Operation(s)** | GetBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillEntryService.cs` — L226-252, L605-620* |

---

## SVC-BR-BIL-076 Provider-contact notes are excluded from bill notes

| Field | Value |
| --- | --- |
| **Statement** | Provider-contact notes are excluded from bill notes |
| **Trigger** | get |
| **Enforcement** | L265 |
| **Outcome** | filter |
| **Operation(s)** | GetBillNotes |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillEntryService.cs` — L265* |

---

## SVC-BR-BIL-080 BillTotalAmount NotNull - 'Error - Bill total amount is required.'

| Field | Value |
| --- | --- |
| **Statement** | BillTotalAmount NotNull: "Error: Bill total amount is required." |
| **Trigger** | Bill |
| **Enforcement** | BillValidator |
| **Outcome** | invalid |
| **Operation(s)** | SaveBill/SubmitBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — BillValidator |

---

## SVC-BR-BIL-081 BillTypeCode NotNull - 'Error - Bill type is required.'

| Field | Value |
| --- | --- |
| **Statement** | BillTypeCode NotNull: "Error: Bill type is required." |
| **Trigger** | Bill |
| **Enforcement** | BillValidator |
| **Outcome** | invalid |
| **Operation(s)** | SaveBill/SubmitBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — BillValidator |

---

## SVC-BR-BIL-082 DrgCode ≤3 - 'Error - DRG code can be a maximum 3 characters.'

| Field | Value |
| --- | --- |
| **Statement** | DrgCode ≤3: "Error: DRG code can be a maximum 3 characters." |
| **Trigger** | Bill |
| **Enforcement** | BillValidator |
| **Outcome** | invalid |
| **Operation(s)** | SaveBill/SubmitBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — BillValidator |

---

## SVC-BR-BIL-083 Claim number must be valid (ClaimQueryProvider.IsValidClaim) - 'Error - Claim not found.'

| Field | Value |
| --- | --- |
| **Statement** | Claim number must be valid (ClaimQueryProvider.IsValidClaim): "Error: Claim not found." |
| **Trigger** | Bill |
| **Enforcement** | BillValidator |
| **Outcome** | invalid |
| **Operation(s)** | SaveBill/SubmitBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — BillValidator |

---

## SVC-BR-BIL-084 UbBillTypeCode numeric - 'Error - UB Bill Type Code is invalid. Must be numeric.'

| Field | Value |
| --- | --- |
| **Statement** | UbBillTypeCode numeric: "Error: UB Bill Type Code is invalid. Must be numeric." |
| **Trigger** | Bill |
| **Enforcement** | BillValidator |
| **Outcome** | invalid |
| **Operation(s)** | SaveBill/SubmitBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — BillValidator |

---

## SVC-BR-BIL-085 CBPAdmissionTypeCode must be in the acceptable list - 'Error - CBP Admission Type Code is invalid.'

| Field | Value |
| --- | --- |
| **Statement** | CBPAdmissionTypeCode must be in the acceptable list: "Error: CBP Admission Type Code is invalid." |
| **Trigger** | Bill |
| **Enforcement** | BillValidator |
| **Outcome** | invalid |
| **Operation(s)** | SaveBill/SubmitBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — BillValidator |

---

## SVC-BR-BIL-086 Optimistic concurrency: UpdateNumber mismatch → "Bill has been updated by someone else. Please re-open the bill and try again. Last updated by: {user}."

| Field | Value |
| --- | --- |
| **Statement** | Optimistic concurrency: UpdateNumber mismatch → "Bill has been updated by someone else. Please re-open the bill and try again. Last updated by: {user}." |
| **Trigger** | save |
| **Enforcement** | L297-302 |
| **Outcome** | error, dispose |
| **Operation(s)** | SaveBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — L297-302* |

---

## SVC-BR-BIL-087 A bill with no existing row is created with status PEN, entry source CBE

| Field | Value |
| --- | --- |
| **Statement** | A bill with no existing row is created with status PEN, entry source CBE |
| **Trigger** | save |
| **Enforcement** | L291-295, L378-398 |
| **Outcome** | Add |
| **Operation(s)** | SaveBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — L291-295, L378-398* |

---

## SVC-BR-BIL-090 Submit requires a claim # - 'Error - Claim number is required.'

| Field | Value |
| --- | --- |
| **Statement** | Submit requires a claim #: "Error: Claim number is required." |
| **Trigger** | submit |
| **Enforcement** | L315 |
| **Outcome** | error |
| **Operation(s)** | SubmitBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — L315* |

---

## SVC-BR-BIL-091 Billing provider required unless type 'W' - 'Error - Billing Provider is required.'

| Field | Value |
| --- | --- |
| **Statement** | Billing provider required unless type "W": "Error: Billing Provider is required." |
| **Trigger** | submit |
| **Enforcement** | L318 |
| **Outcome** | error |
| **Operation(s)** | SubmitBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — L318* |

---

## SVC-BR-BIL-092 At least one service line - 'Error - At least one service line is required.'

| Field | Value |
| --- | --- |
| **Statement** | At least one service line: "Error: At least one service line is required." |
| **Trigger** | submit |
| **Enforcement** | L321 |
| **Outcome** | error |
| **Operation(s)** | SubmitBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — L321* |

---

## SVC-BR-BIL-093 Received date must be > today−9y and ≤ today - 'Error - Invalid received date'

| Field | Value |
| --- | --- |
| **Statement** | Received date must be > today−9y and ≤ today: "Error: Invalid received date" |
| **Trigger** | submit |
| **Enforcement** | L324-326 |
| **Outcome** | error |
| **Operation(s)** | SubmitBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — L324-326* |

---

## SVC-BR-BIL-094 Status code must exist, else throw InvalidDataException "Error: New bill status code is invalid: {code}"; new status effective today, responsible = recipient.ToUpper() or current user

| Field | Value |
| --- | --- |
| **Statement** | Status code must exist, else throw InvalidDataException "Error: New bill status code is invalid: {code}"; new status effective today, responsible = recipient.ToUpper() or current user |
| **Trigger** | status change |
| **Enforcement** | L348-360 |
| **Outcome** | AddStatus |
| **Operation(s)** | UpdateBillStatus |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — L348-360* |

---

## SVC-BR-BIL-095 TIN required ("Error: No tin was provided"); provider must exist ("Error: No Provider found with tin")

| Field | Value |
| --- | --- |
| **Statement** | TIN required ("Error: No tin was provided"); provider must exist ("Error: No Provider found with tin") |
| **Trigger** | lookup |
| **Enforcement** | L654-658 |
| **Outcome** | NoMatchingDataException |
| **Operation(s)** | GetProviderLocations |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — L654-658* |

---

## SVC-BR-BIL-096 Location must exist - 'Error - No Provider Location found with location id'

| Field | Value |
| --- | --- |
| **Statement** | Location must exist: "Error: No Provider Location found with location id" |
| **Trigger** | lookup |
| **Enforcement** | L696 |
| **Outcome** | exception |
| **Operation(s)** | GetRenderingProviders |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — L696* |

---

## SVC-BR-BIL-087b Unknown new bill type → throw 'Error - Unknown new bill type code.'

| Field | Value |
| --- | --- |
| **Statement** | Unknown new bill type → throw "Error: Unknown new bill type code." |
| **Trigger** | type change |
| **Enforcement** | L478 |
| **Outcome** | exception |
| **Operation(s)** | SaveBill |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillValidator.cs` — L478* |

---

## SVC-BR-BIL-100 DiagnosisCode NotNull/NotEmpty (DiagnosisCodeRequiredMessage)

| Field | Value |
| --- | --- |
| **Statement** | DiagnosisCode NotNull/NotEmpty (DiagnosisCodeRequiredMessage) |
| **Trigger** | BillDiagnosis |
| **Enforcement** | BillDiagnosisValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateDiagnoses |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillDiagnosisValidator.cs` — BillDiagnosisValidator |

---

## SVC-BR-BIL-101 DiagnosisType and its Code required (DiagnosisTypeRequiredMessage)

| Field | Value |
| --- | --- |
| **Statement** | DiagnosisType and its Code required (DiagnosisTypeRequiredMessage) |
| **Trigger** | BillDiagnosis |
| **Enforcement** | BillDiagnosisValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateDiagnoses |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillDiagnosisValidator.cs` — BillDiagnosisValidator |

---

## SVC-BR-BIL-102 DiagnosisType.Code must be a valid code (DiagnosisTypeInvalidMessage)

| Field | Value |
| --- | --- |
| **Statement** | DiagnosisType.Code must be a valid code (DiagnosisTypeInvalidMessage) |
| **Trigger** | BillDiagnosis |
| **Enforcement** | BillDiagnosisValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateDiagnoses |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillDiagnosisValidator.cs` — BillDiagnosisValidator |

---

## SVC-BR-BIL-103 Standard bills require a pointer - 'Error - Diagnosis Pointer is required on standard bills'

| Field | Value |
| --- | --- |
| **Statement** | Standard bills require a pointer: "Error: Diagnosis Pointer is required on standard bills" |
| **Trigger** | save |
| **Enforcement** | BillDiagnosisService ValidateDiagnoses |
| **Outcome** | error |
| **Operation(s)** | Create/UpdateDiagnoses |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillDiagnosisService.cs` — BillDiagnosisService ValidateDiagnoses |

---

## SVC-BR-BIL-104 Standard: duplicate code → "Error: Unable to save Diagnosis: {code}. Please remove duplicate diagnosis codes."

| Field | Value |
| --- | --- |
| **Statement** | Standard: duplicate code → "Error: Unable to save Diagnosis: {code}. Please remove duplicate diagnosis codes." |
| **Trigger** | save |
| **Enforcement** | DiagnosisIsDuplicate |
| **Outcome** | error |
| **Operation(s)** | Create/UpdateDiagnoses |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillDiagnosisService.cs` — DiagnosisIsDuplicate* |

---

## SVC-BR-BIL-105 Inpatient/Outpatient: duplicate code+type → throw an error citing duplicate diagnosis code/type combos; unknown type → throw "Error: Unknown bill type when checking for duplicate diagnoses."

| Field | Value |
| --- | --- |
| **Statement** | Inpatient/Outpatient: duplicate code+type → throw an error citing duplicate diagnosis code/type combos; unknown type → throw "Error: Unknown bill type when checking for duplicate diagnoses." |
| **Trigger** | save |
| **Enforcement** | DiagnosisIsDuplicate |
| **Outcome** | error/throw |
| **Operation(s)** | Create/UpdateDiagnoses |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillDiagnosisService.cs` — DiagnosisIsDuplicate* |

---

## SVC-BR-BIL-106 Codes trimmed and uppercased; IsValidCode = code found (including expired)

| Field | Value |
| --- | --- |
| **Statement** | Codes trimmed and uppercased; IsValidCode = code found (including expired) |
| **Trigger** | save/get |
| **Enforcement** | Clean/PopulateValidCodeAndDescription |
| **Outcome** | flags |
| **Operation(s)** | Create/UpdateDiagnoses |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillDiagnosisService.cs` — Clean/PopulateValidCodeAndDescription* |

---

## SVC-BR-BIL-110 ProcedureCode required (ProcedureCodeRequiredMessage)

| Field | Value |
| --- | --- |
| **Statement** | ProcedureCode required (ProcedureCodeRequiredMessage) |
| **Trigger** | BillProcedure |
| **Enforcement** | BillProcedureValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateProcedures |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillProcedureValidator.cs` — BillProcedureValidator |

---

## SVC-BR-BIL-111 ProcedureCode length 1-8 (ProcedureCodeToLongMessage)

| Field | Value |
| --- | --- |
| **Statement** | ProcedureCode length 1-8 (ProcedureCodeToLongMessage) |
| **Trigger** | BillProcedure |
| **Enforcement** | BillProcedureValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateProcedures |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillProcedureValidator.cs` — BillProcedureValidator |

---

## SVC-BR-BIL-112 PrimaryProcedure required and must be a valid code (PrimaryProcedureCodeRequired/InvalidMessage)

| Field | Value |
| --- | --- |
| **Statement** | PrimaryProcedure required and must be a valid code (PrimaryProcedureCodeRequired/InvalidMessage) |
| **Trigger** | BillProcedure |
| **Enforcement** | BillProcedureValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateProcedures |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillProcedureValidator.cs` — BillProcedureValidator |

---

## SVC-BR-BIL-113 ProcedureDate ≥ today−9y: "Error: Procedure date cannot be greater than 9 years in the past."

| Field | Value |
| --- | --- |
| **Statement** | ProcedureDate ≥ today−9y: "Error: Procedure date cannot be greater than 9 years in the past." |
| **Trigger** | BillProcedure |
| **Enforcement** | BillProcedureValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateProcedures |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillProcedureValidator.cs` — BillProcedureValidator |

---

## SVC-BR-BIL-114 ProcedureDate ≤ today (ProcedureDateInvalidMessage)

| Field | Value |
| --- | --- |
| **Statement** | ProcedureDate ≤ today (ProcedureDateInvalidMessage) |
| **Trigger** | BillProcedure |
| **Enforcement** | BillProcedureValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateProcedures |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillProcedureValidator.cs` — BillProcedureValidator |

---

## SVC-BR-BIL-120 ProviderServiceCode NotNull, length 1-11 - 'Error - Invalid Primary service code, value is too long.'

| Field | Value |
| --- | --- |
| **Statement** | ProviderServiceCode NotNull, length 1-11: "Error: Invalid Primary service code, value is too long." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-121 SecondaryProvServiceCode ≤11 - 'Error - Invalid Secondary service code, value is too long.'

| Field | Value |
| --- | --- |
| **Statement** | SecondaryProvServiceCode ≤11: "Error: Invalid Secondary service code, value is too long." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-122 DiagnosisPointerCode1-4 ≤1 char - 'Error - Invalid Diagnosis Pointer Code.'

| Field | Value |
| --- | --- |
| **Statement** | DiagnosisPointerCode1-4 ≤1 char: "Error: Invalid Diagnosis Pointer Code." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-123 Pointers unique - 'Error - Diagnosis Pointers must be unique.'

| Field | Value |
| --- | --- |
| **Statement** | Pointers unique: "Error: Diagnosis Pointers must be unique." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-124 ServiceDate ≤ today+30: "Error: Service date must be no more than 30 days in the future."

| Field | Value |
| --- | --- |
| **Statement** | ServiceDate ≤ today+30: "Error: Service date must be no more than 30 days in the future." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-125 EndDate ≥ ServiceDate - 'Error - Service End date must be a valid date.'

| Field | Value |
| --- | --- |
| **Statement** | EndDate ≥ ServiceDate: "Error: Service End date must be a valid date." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-126 PrescriptionWrittenDate > MinValue - 'Error - Prescription Written date must be a valid date.'

| Field | Value |
| --- | --- |
| **Statement** | PrescriptionWrittenDate > MinValue: "Error: Prescription Written date must be a valid date." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-127 Modifiers 1-4 ≤2 - 'Error - Modifiers can only be up to two characters.'

| Field | Value |
| --- | --- |
| **Statement** | Modifiers 1-4 ≤2: "Error: Modifiers can only be up to two characters." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-128 ServiceLocationCode ≤2 - 'Error - Service location code must be 2 digits long.'

| Field | Value |
| --- | --- |
| **Statement** | ServiceLocationCode ≤2: "Error: Service location code must be 2 digits long." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-129 Quantity ≥0 - 'Error - Service quantity can not be negative.'

| Field | Value |
| --- | --- |
| **Statement** | Quantity ≥0: "Error: Service quantity can not be negative." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-130 ToothNumber 0-32 - 'Error - Invalid tooth number.'

| Field | Value |
| --- | --- |
| **Statement** | ToothNumber 0-32: "Error: Invalid tooth number." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-131 DaysSupply 0-99999 - 'Error - Days supply quantity must be a number.'

| Field | Value |
| --- | --- |
| **Statement** | DaysSupply 0-99999: "Error: Days supply quantity must be a number." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-132 DAW length 1 - 'Error - Invalid DAW, can only be 1 character long.'

| Field | Value |
| --- | --- |
| **Statement** | DAW length 1: "Error: Invalid DAW, can only be 1 character long." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-133 PrescribingProviderId ≤10 - 'Error - Invalid Prescriber ID, can only be up to 10 characters.'

| Field | Value |
| --- | --- |
| **Statement** | PrescribingProviderId ≤10: "Error: Invalid Prescriber ID, can only be up to 10 characters." |
| **Trigger** | BillService |
| **Enforcement** | BillServiceValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateService |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillServiceValidator.cs` — BillServiceValidator |

---

## SVC-BR-BIL-136 Charged total = sum of ChargeAmount on the bill's lines

| Field | Value |
| --- | --- |
| **Statement** | Charged total = sum of ChargeAmount on the bill's lines |
| **Trigger** | call |
| **Enforcement** | BillServiceService L157 |
| **Outcome** | decimal? |
| **Operation(s)** | GetChargedServicesTotal |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillServiceService.cs` — BillServiceService L157 |

---

## SVC-BR-BIL-137 Service type from a non-expired CBP service code (uppercased), else National Drug code

| Field | Value |
| --- | --- |
| **Statement** | Service type from a non-expired CBP service code (uppercased), else National Drug code |
| **Trigger** | call |
| **Enforcement** | L162-175 |
| **Outcome** | code |
| **Operation(s)** | GetServiceTypeCode |
| **Source** | `Services/SAIF.Services/Claims/Bills/BillServiceService.cs` — L162-175* |

---

## SVC-BR-BIL-140 Valid CPT = a CbpServiceCode with ServiceType 'M'

| Field | Value |
| --- | --- |
| **Statement** | Valid CPT = a CbpServiceCode with ServiceType "M" |
| **Trigger** | call |
| **Enforcement** | AuthorizationService L70-75 |
| **Outcome** | bool |
| **Operation(s)** | ValidCptCode |
| **Source** | `Services/SAIF.Services/Claims/Bills/AuthorizationService.cs` — AuthorizationService L70-75 |

---

## SVC-BR-BIL-141 No duplicate surgery date per claim

| Field | Value |
| --- | --- |
| **Statement** | No duplicate surgery date per claim |
| **Trigger** | add |
| **Enforcement** | L104 |
| **Outcome** | false |
| **Operation(s)** | AddSurgeryDate |
| **Source** | `Services/SAIF.Services/Claims/Bills/AuthorizationService.cs` — L104* |

---

## SVC-BR-BIL-142 ClaimId NotNull - 'Error - Claim is required.'

| Field | Value |
| --- | --- |
| **Statement** | ClaimId NotNull: "Error: Claim is required." |
| **Trigger** | AuthorizationItem |
| **Enforcement** | AuthorizationItemValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateAuthorization |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/AuthorizationItemValidator.cs` — AuthorizationItemValidator |

---

## SVC-BR-BIL-143 BillingProviderName NotNull - 'Error - Billing Provider is required.'

| Field | Value |
| --- | --- |
| **Statement** | BillingProviderName NotNull: "Error: Billing Provider is required." |
| **Trigger** | AuthorizationItem |
| **Enforcement** | AuthorizationItemValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/UpdateAuthorization |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/AuthorizationItemValidator.cs` — AuthorizationItemValidator |

---

## SVC-BR-BIL-150 NoteText required - 'Error - Bill note is required.'

| Field | Value |
| --- | --- |
| **Statement** | NoteText required: "Error: Bill note is required." |
| **Trigger** | Note |
| **Enforcement** | BillNoteValidator |
| **Outcome** | invalid |
| **Operation(s)** | CreateNote/UpdateNote |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillNoteValidator.cs` — BillNoteValidator |

---

## SVC-BR-BIL-151 NoteText ≤600 - 'Error - Text exceeds 600 characters.'

| Field | Value |
| --- | --- |
| **Statement** | NoteText ≤600: "Error: Text exceeds 600 characters." |
| **Trigger** | Note |
| **Enforcement** | BillNoteValidator |
| **Outcome** | invalid |
| **Operation(s)** | CreateNote/UpdateNote |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/BillNoteValidator.cs` — BillNoteValidator |

---

## SVC-BR-BIL-152 'Error - Text is required.'

| Field | Value |
| --- | --- |
| **Statement** | "Error: Text is required." |
| **Trigger** | NoteModifyRequest |
| **Enforcement** | NoteModifyRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/EditAuditNote |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/NoteModifyRequestValidator.cs` — NoteModifyRequestValidator |

---

## SVC-BR-BIL-153 Length 1-600 - 'Error - The maximum length for a note is 600 characters.'

| Field | Value |
| --- | --- |
| **Statement** | Length 1-600: "Error: The maximum length for a note is 600 characters." |
| **Trigger** | NoteModifyRequest |
| **Enforcement** | NoteModifyRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/EditAuditNote |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/NoteModifyRequestValidator.cs` — NoteModifyRequestValidator |

---

## SVC-BR-BIL-154 'Error - Note must have a valid billId.'

| Field | Value |
| --- | --- |
| **Statement** | "Error: Note must have a valid billId." |
| **Trigger** | NoteModifyRequest |
| **Enforcement** | NoteModifyRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/EditAuditNote |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/NoteModifyRequestValidator.cs` — NoteModifyRequestValidator |

---

## SVC-BR-BIL-155 'Error - Type is required.' / 'Error - Category is required.'

| Field | Value |
| --- | --- |
| **Statement** | "Error: Type is required." / "Error: Category is required." |
| **Trigger** | NoteModifyRequest |
| **Enforcement** | NoteModifyRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/EditAuditNote |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/NoteModifyRequestValidator.cs` — NoteModifyRequestValidator |

---

## SVC-BR-BIL-156 'Error - Note must have a valid claimId.'

| Field | Value |
| --- | --- |
| **Statement** | "Error: Note must have a valid claimId." |
| **Trigger** | NoteModifyRequest |
| **Enforcement** | NoteModifyRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/EditAuditNote |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/NoteModifyRequestValidator.cs` — NoteModifyRequestValidator |

---

## SVC-BR-BIL-157 Type must belong to the category - 'Error - Invalid type code for selected category.'

| Field | Value |
| --- | --- |
| **Statement** | Type must belong to the category: "Error: Invalid type code for selected category." |
| **Trigger** | NoteModifyRequest |
| **Enforcement** | NoteModifyRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/EditAuditNote |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/NoteModifyRequestValidator.cs` — NoteModifyRequestValidator |

---

## SVC-BR-BIL-158 Id > 0 must exist - 'Error - Invalid note id.'

| Field | Value |
| --- | --- |
| **Statement** | Id > 0 must exist: "Error: Invalid note id." |
| **Trigger** | NoteModifyRequest |
| **Enforcement** | NoteModifyRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/EditAuditNote |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/NoteModifyRequestValidator.cs` — NoteModifyRequestValidator |

---

## SVC-BR-BIL-159 Concurrency - 'Error - Note has been updated by another user.'

| Field | Value |
| --- | --- |
| **Statement** | Concurrency: "Error: Note has been updated by another user." |
| **Trigger** | NoteModifyRequest |
| **Enforcement** | NoteModifyRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | Create/EditAuditNote |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/NoteModifyRequestValidator.cs` — NoteModifyRequestValidator |

---

## SVC-BR-BIL-160 Id required and must exist - 'Error - Invalid bill selected.'

| Field | Value |
| --- | --- |
| **Statement** | Id required and must exist: "Error: Invalid bill selected." |
| **Trigger** | NoteDeleteRequest |
| **Enforcement** | NoteDeleteRequestValidator |
| **Outcome** | invalid |
| **Operation(s)** | DeleteAuditNote |
| **Source** | `Services/SAIF.Services/Claims/Bills/Validators/NoteDeleteRequestValidator.cs` — NoteDeleteRequestValidator |

---

## SVC-BR-BIL-165 Service code insert/update not supported

| Field | Value |
| --- | --- |
| **Statement** | Service code insert/update not supported |
| **Trigger** | call |
| **Enforcement** | ServiceCodeService L55/60 |
| **Outcome** | NotImplementedException |
| **Operation(s)** | Update/InsertServiceCode |
| **Source** | `Services/SAIF.Services/Claims/Bills/ServiceCodeService.cs` — ServiceCodeService L55/60 |

---

## SVC-BR-BIL-200 Batch retrieved by type/status: 837/ACK for extract, 837/EXTR for index, 837/INDEX for CBP generation, 837/IMAGE for assign, 835/EOB for ack

| Field | Value |
| --- | --- |
| **Statement** | Batch retrieved by type/status: 837/ACK for extract, 837/EXTR for index, 837/INDEX for CBP generation, 837/IMAGE for assign, 835/EOB for ack |
| **Trigger** | batch ops |
| **Enforcement** | EBillingService RetrieveBatch calls |
| **Outcome** | batch or error |
| **Operation(s)** | 837/EOB/CBP/Index/Assign |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — EBillingService RetrieveBatch calls |

---

## SVC-BR-BIL-201 837 extraction success → batch Extracted and commit; failure → rollback and throw "Error in 837 extraction - review the log file"

| Field | Value |
| --- | --- |
| **Statement** | 837 extraction success → batch Extracted and commit; failure → rollback and throw "Error in 837 extraction - review the log file" |
| **Trigger** | process |
| **Enforcement** | L147-187 |
| **Outcome** | commit/throw |
| **Operation(s)** | Process837File |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L147-187* |

---

## SVC-BR-BIL-202 999 must contain AK9, else throw 'AK9 segment not found'

| Field | Value |
| --- | --- |
| **Statement** | 999 must contain AK9, else throw "AK9 segment not found" |
| **Trigger** | ack |
| **Enforcement** | L221 |
| **Outcome** | exception |
| **Operation(s)** | ProcessEOBAcknowledgementFile |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L221* |

---

## SVC-BR-BIL-203 AK9 R or A applies to the whole batch: R → ebills EOB-Rejected, A → Completed; counts success/failure

| Field | Value |
| --- | --- |
| **Statement** | AK9 R or A applies to the whole batch: R → ebills EOB-Rejected, A → Completed; counts success/failure |
| **Trigger** | ack |
| **Enforcement** | ProcessEntireEobBatch |
| **Outcome** | status |
| **Operation(s)** | ProcessEOBAcknowledgementFile |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — ProcessEntireEobBatch* |

---

## SVC-BR-BIL-204 Otherwise per IK5: R → EOB-Rejected plus reject log; else Completed (UpdateUser "EBN0009"); both 835 and 835AK batches → Completed

| Field | Value |
| --- | --- |
| **Statement** | Otherwise per IK5: R → EOB-Rejected plus reject log; else Completed (UpdateUser "EBN0009"); both 835 and 835AK batches → Completed |
| **Trigger** | ack |
| **Enforcement** | ProcessEobStatus, L257-260 |
| **Outcome** | status |
| **Operation(s)** | ProcessEOBAcknowledgementFile |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — ProcessEobStatus, L257-260* |

---

## SVC-BR-BIL-205 After CBP bills are generated, batch → Setup

| Field | Value |
| --- | --- |
| **Statement** | After CBP bills are generated, batch → Setup |
| **Trigger** | gen |
| **Enforcement** | L408-410 |
| **Outcome** | status |
| **Operation(s)** | CreateCbpBillsForBatch |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L408-410* |

---

## SVC-BR-BIL-206 After provider/patient/bill-service indexing, batch → Indexed

| Field | Value |
| --- | --- |
| **Statement** | After provider/patient/bill-service indexing, batch → Indexed |
| **Trigger** | index |
| **Enforcement** | L793-797 |
| **Outcome** | status |
| **Operation(s)** | IndexBatch |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L793-797* |

---

## SVC-BR-BIL-207 After assignment, batch → Completed; errors wrapped 'Batch Id - {id}'

| Field | Value |
| --- | --- |
| **Statement** | After assignment, batch → Completed; errors wrapped "Batch Id: {id}" |
| **Trigger** | assign |
| **Enforcement** | L843-873 |
| **Outcome** | status |
| **Operation(s)** | AssignBills |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L843-873* |

---

## SVC-BR-BIL-208 Matched images → ebill status Imaged; parent/child images cross-referenced

| Field | Value |
| --- | --- |
| **Statement** | Matched images → ebill status Imaged; parent/child images cross-referenced |
| **Trigger** | associate |
| **Enforcement** | L629, L681 |
| **Outcome** | status |
| **Operation(s)** | AssociateEbillImages |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L629, L681* |

---

## SVC-BR-BIL-209 EOB must exist - 'Invalid Eob - {id}'

| Field | Value |
| --- | --- |
| **Statement** | EOB must exist: "Invalid Eob: {id}" |
| **Trigger** | reject |
| **Enforcement** | L925 |
| **Outcome** | ArgumentException |
| **Operation(s)** | ExtractEobForReject |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L925* |

---

## SVC-BR-BIL-210 Clearinghouse/file must not be null (ArgumentNullException); sender resolved via GS SenderId tax id; bills already processed if the clearinghouse control number exists

| Field | Value |
| --- | --- |
| **Statement** | Clearinghouse/file must not be null (ArgumentNullException); sender resolved via GS SenderId tax id; bills already processed if the clearinghouse control number exists |
| **Trigger** | validate |
| **Enforcement** | L976-1060 |
| **Outcome** | bool/throw |
| **Operation(s)** | file validation ops |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L976-1060* |

---

## SVC-BR-BIL-220 An invoice month already processed and in balance → duplicate (throw ArgumentException); otherwise old errors, bills and invoice are deleted for a rerun

| Field | Value |
| --- | --- |
| **Statement** | An invoice month already processed and in balance → duplicate (throw ArgumentException); otherwise old errors, bills and invoice are deleted for a rerun |
| **Trigger** | invoice |
| **Enforcement** | L1147-1189 |
| **Outcome** | rerun/throw |
| **Operation(s)** | ProcessInvoiceFile |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L1147-1189* |

---

## SVC-BR-BIL-221 DCN found >1 time → error "Bill was found on ebill table {n} times"; 0 → "Bill was not found on ebill table"

| Field | Value |
| --- | --- |
| **Statement** | DCN found >1 time → error "Bill was found on ebill table {n} times"; 0 → "Bill was not found on ebill table" |
| **Trigger** | line |
| **Enforcement** | L1214-1223 |
| **Outcome** | InvoiceError |
| **Operation(s)** | ProcessInvoiceFile |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L1214-1223* |

---

## SVC-BR-BIL-222 Charge ≠ ebill.TotalAmount → 'Billed amount does not match invoice'

| Field | Value |
| --- | --- |
| **Statement** | Charge ≠ ebill.TotalAmount → "Billed amount does not match invoice" |
| **Trigger** | line |
| **Enforcement** | L1231 |
| **Outcome** | error |
| **Operation(s)** | ProcessInvoiceFile |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L1231* |

---

## SVC-BR-BIL-223 Receipt batch SubmissionDate outside the month → 'Bill received outside of invoice period'

| Field | Value |
| --- | --- |
| **Statement** | Receipt batch SubmissionDate outside the month → "Bill received outside of invoice period" |
| **Trigger** | line |
| **Enforcement** | L1235 |
| **Outcome** | error |
| **Operation(s)** | ProcessInvoiceFile |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L1235* |

---

## SVC-BR-BIL-224 Data starts after the header line; stops at an empty Submitter

| Field | Value |
| --- | --- |
| **Statement** | Data starts after the header line; stops at an empty Submitter |
| **Trigger** | parse |
| **Enforcement** | L1195-1206 |
| **Outcome** | control |
| **Operation(s)** | ProcessInvoiceFile |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L1195-1206* |

---

## SVC-BR-BIL-225 Month ebill missing from the invoice → 'Bill not included on invoice'

| Field | Value |
| --- | --- |
| **Statement** | Month ebill missing from the invoice → "Bill not included on invoice" |
| **Trigger** | post |
| **Enforcement** | L1245-1251 |
| **Outcome** | error |
| **Operation(s)** | ProcessInvoiceFile |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L1245-1251* |

---

## SVC-BR-BIL-226 Calculated = billCount × clearinghouse.TransactionFeeAmount; ≠ total → "Specified invoice amt ({0}) doesn't balance w/ calculated amt ({1})"

| Field | Value |
| --- | --- |
| **Statement** | Calculated = billCount × clearinghouse.TransactionFeeAmount; ≠ total → "Specified invoice amt ({0}) doesn't balance w/ calculated amt ({1})" |
| **Trigger** | post |
| **Enforcement** | L1253-1262 |
| **Outcome** | error |
| **Operation(s)** | ProcessInvoiceFile |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L1253-1262* |

---

## SVC-BR-BIL-227 Zero errors → add marker 'Invoice is in balance'; invoice saved

| Field | Value |
| --- | --- |
| **Statement** | Zero errors → add marker "Invoice is in balance"; invoice saved |
| **Trigger** | post |
| **Enforcement** | L1265-1271 |
| **Outcome** | Add |
| **Operation(s)** | ProcessInvoiceFile |
| **Source** | `Services/SAIF.Services/Claims/EBilling/EBillingService.cs` — L1265-1271* |

---

## SVC-BR-BIL-230 Image API returning 0 → throw 'Image API is returning Zero '

| Field | Value |
| --- | --- |
| **Statement** | Image API returning 0 → throw "Image API is returning Zero " |
| **Trigger** | image |
| **Enforcement** | DocumentManager.cs ThrowExceptionIfZero |
| **Outcome** | exception |
| **Operation(s)** | ImageDocuments |
| **Source** | `Services/SAIF.Services/Claims/EBilling/Imaging/DocumentManager.cs` — DocumentManager.cs ThrowExceptionIfZero |

---

## SVC-BR-BIL-231 After imaging, bill status → DocumentLoad

| Field | Value |
| --- | --- |
| **Statement** | After imaging, bill status → DocumentLoad |
| **Trigger** | image |
| **Enforcement** | DocumentManagementService L61-66 |
| **Outcome** | status |
| **Operation(s)** | UpdateBillStatus |
| **Source** | `Services/SAIF.Services/Claims/EBilling/Imaging/DocumentManagementService.cs` — DocumentManagementService L61-66 |

---

## SVC-BR-BIL-232 File must exist - 'File not found for document control number {0}'

| Field | Value |
| --- | --- |
| **Statement** | File must exist: "File not found for document control number {0}" |
| **Trigger** | file |
| **Enforcement** | DocumentFileService L24 |
| **Outcome** | exception |
| **Operation(s)** | GetFile |
| **Source** | `Services/SAIF.Services/Claims/EBilling/Imaging/DocumentFileService.cs` — DocumentFileService L24 |

---

## SVC-BR-BIL-233 File count must equal non-imaged docs in the batch, and names must match control numbers, else InvalidBatchException

| Field | Value |
| --- | --- |
| **Statement** | File count must equal non-imaged docs in the batch, and names must match control numbers, else InvalidBatchException |
| **Trigger** | validate |
| **Enforcement** | L40-46 |
| **Outcome** | exception |
| **Operation(s)** | ValidateDocuments |
| **Source** | `Services/SAIF.Services/Claims/EBilling/Imaging/DocumentFileService.cs` — L40-46* |

---

## SVC-BR-BIL-234 Source/destination directories must exist ('Directory path for documents to image/archive not found')

| Field | Value |
| --- | --- |
| **Statement** | Source/destination directories must exist ("Directory path for documents to image/archive not found") |
| **Trigger** | validate |
| **Enforcement** | L54/64 |
| **Outcome** | exception |
| **Operation(s)** | Validate*Directory |
| **Source** | `Services/SAIF.Services/Claims/EBilling/Imaging/DocumentFileService.cs` — L54/64* |

---

## SVC-BR-BIL-235 At least one document - 'No documents to image were found in directory'

| Field | Value |
| --- | --- |
| **Statement** | At least one document: "No documents to image were found in directory" |
| **Trigger** | list |
| **Enforcement** | L75 |
| **Outcome** | exception |
| **Operation(s)** | GetImageDocumentFileNames |
| **Source** | `Services/SAIF.Services/Claims/EBilling/Imaging/DocumentFileService.cs` — L75* |

---

## SVC-BR-BIL-240 StatementThruDate MinValue → null; transaction stamp applied; rollback on error

| Field | Value |
| --- | --- |
| **Statement** | StatementThruDate MinValue → null; transaction stamp applied; rollback on error |
| **Trigger** | edit/add |
| **Enforcement** | Edi/BillOverrideService.cs L93-94, L130 |
| **Outcome** | persist |
| **Operation(s)** | BillOverride Edit/Add (also AuditedServiceOverride) |
| **Source** | `Services/SAIF.Services/Edi/BillOverrideService.cs` — Edi/BillOverrideService.cs L93-94, L130 |

---

## SVC-BR-BIL-241 999 accepted based on the IK5 response code

| Field | Value |
| --- | --- |
| **Statement** | 999 accepted based on the IK5 response code |
| **Trigger** | check |
| **Enforcement** | MedicalEdiFileService L80-94 |
| **Outcome** | bool |
| **Operation(s)** | HasFileBeenAccepted |
| **Source** | `Services/SAIF.Services/Edi/MedicalEdiFileService.cs` — MedicalEdiFileService L80-94 |

---

## SVC-BR-BIL-250 ICD entry - PCS → procedure path; CM → diagnosis path; otherwise not processed (false)

| Field | Value |
| --- | --- |
| **Statement** | ICD entry: PCS → procedure path; CM → diagnosis path; otherwise not processed (false) |
| **Trigger** | load |
| **Enforcement** | Icd10CodeService L99-114 |
| **Outcome** | route |
| **Operation(s)** | ProcessIcdEntry |
| **Source** | `Services/SAIF.Services/Claims/ICDCodeService/Icd10CodeService.cs` — Icd10CodeService L99-114 |

---

## SVC-BR-BIL-251 Missing code that is not deleted → insert; existing code → update (procedure / Z service code / service description / diagnosis)

| Field | Value |
| --- | --- |
| **Statement** | Missing code that is not deleted → insert; existing code → update (procedure / Z service code / service description / diagnosis) |
| **Trigger** | load |
| **Enforcement** | L117-168 |
| **Outcome** | Add/Update |
| **Operation(s)** | ProcessProcedure/Diagnosis |
| **Source** | `Services/SAIF.Services/Claims/ICDCodeService/Icd10CodeService.cs` — L117-168* |

---

## SVC-BR-BIL-260 Legal bill required: "A valid legal bill was not used in the call to Create Legal Bill Financial Transaction"

| Field | Value |
| --- | --- |
| **Statement** | Legal bill required: "A valid legal bill was not used in the call to Create Legal Bill Financial Transaction" |
| **Trigger** | create |
| **Enforcement** | FinancialTransactionService L53-56 |
| **Outcome** | exception |
| **Operation(s)** | CreateLegalCheckTransaction |
| **Source** | `Services/SAIF.Services/Claims/Payments/FinancialTransactionService.cs` — FinancialTransactionService L53-56 |

---

## SVC-BR-BIL-261 Valid provider address required: "Error: No valid address available for Bill with Provider Location ID = {id}"

| Field | Value |
| --- | --- |
| **Statement** | Valid provider address required: "Error: No valid address available for Bill with Provider Location ID = {id}" |
| **Trigger** | create |
| **Enforcement** | L71-75 |
| **Outcome** | InvalidPaymentAddressException |
| **Operation(s)** | CreateLegalCheckTransaction |
| **Source** | `Services/SAIF.Services/Claims/Payments/FinancialTransactionService.cs` — L71-75* |

---

## SVC-BR-BIL-262 Special handling maps to a GW delivery method (Certified, Overnight, Foreign, DoNotMail, Registered), default Send

| Field | Value |
| --- | --- |
| **Statement** | Special handling maps to a GW delivery method (Certified, Overnight, Foreign, DoNotMail, Registered), default Send |
| **Trigger** | create |
| **Enforcement** | GetGwMappedDeliveryMethod |
| **Outcome** | mapping |
| **Operation(s)** | Legal/Subpoena checks |
| **Source** | `Services/SAIF.Services/Claims/Payments/FinancialTransactionService.cs` — GetGwMappedDeliveryMethod* |

---

## SVC-BR-BIL-263 Subpoena required: "A valid subpoena was not used in the call to Create a Subpoena Financial Transaction"

| Field | Value |
| --- | --- |
| **Statement** | Subpoena required: "A valid subpoena was not used in the call to Create a Subpoena Financial Transaction" |
| **Trigger** | create |
| **Enforcement** | L140-144 |
| **Outcome** | exception |
| **Operation(s)** | CreateSubpoenaCheckTransactions |
| **Source** | `Services/SAIF.Services/Claims/Payments/FinancialTransactionService.cs` — L140-144* |

---

## SVC-BR-BIL-264 All recipient provider addresses must be found, else no checks are made

| Field | Value |
| --- | --- |
| **Statement** | All recipient provider addresses must be found, else no checks are made |
| **Trigger** | create |
| **Enforcement** | L146 |
| **Outcome** | empty list |
| **Operation(s)** | CreateSubpoenaCheckTransactions |
| **Source** | `Services/SAIF.Services/Claims/Payments/FinancialTransactionService.cs` — L146* |

---

## SVC-BR-BIL-265 Only recipients with PaidAmount > 0 and not yet paid get a check; they are then marked paid (UpdateUser = approver)

| Field | Value |
| --- | --- |
| **Statement** | Only recipients with PaidAmount > 0 and not yet paid get a check; they are then marked paid (UpdateUser = approver) |
| **Trigger** | create |
| **Enforcement** | L148-187 |
| **Outcome** | GW check plus flag |
| **Operation(s)** | CreateSubpoenaCheckTransactions |
| **Source** | `Services/SAIF.Services/Claims/Payments/FinancialTransactionService.cs` — L148-187* |

---

## Claims

## SVC-BR-CLM-001 At least one limit (amount ≥ 0, or an expiration date that is set) is required

| Field | Value |
| --- | --- |
| **Statement** | At least one limit (amount ≥ 0, or an expiration date that is set) is required |
| **Trigger** | Payments/Reserve validation, valid function type |
| **Enforcement** | ClaimAuthorityValidator RuleFor(HasEitherLimit) |
| **Outcome** | "At least one payment limit is required" / "At least one incurred limit is required" (property InitiateLimit.MaximumAmount) |
| **Operation(s)** | IsValid*AuthorityEdits, AddEditAuthorityLimit, AddAuthorityLimit |
| **Source** | `Services/SAIF.Services/Claims/Authority/Validators/ClaimAuthorityValidator.cs` — ClaimAuthorityValidator RuleFor(HasEitherLimit) |

---

## SVC-BR-CLM-002 A function type is required

| Field | Value |
| --- | --- |
| **Statement** | A function type is required |
| **Trigger** | Any limit validated |
| **Enforcement** | ClaimAuthorityAuthorizationValidator / ClaimAuthorityValuesValidator RuleFor(IsValidFunctionType) |
| **Outcome** | "You must select a function" (functionType) |
| **Operation(s)** | IsValid*AuthorityEdits, AddEditAuthorityLimit, AddAuthorityLimit |
| **Source** | `Services/SAIF.Services/Claims/Authority/Validators/ClaimAuthorityAuthorizationValidator.cs` — ClaimAuthorityAuthorizationValidator / ClaimAuthorityValuesValidator RuleFor(IsValidFunctionType) |

---

## SVC-BR-CLM-003 The granting user must hold the same function type (in payment or reserve limits)

| Field | Value |
| --- | --- |
| **Statement** | The granting user must hold the same function type (in payment or reserve limits) |
| **Trigger** | Not override, AuthorizingEmployeePaymentAuthority set |
| **Enforcement** | ClaimAuthorityAuthorizationValidator RuleFor(FunctionType) |
| **Outcome** | "You are not authorized to grant this authority" |
| **Operation(s)** | IsValid*AuthorityEdits, AddEditAuthorityLimit, AddAuthorityLimit |
| **Source** | `Services/SAIF.Services/Claims/Authority/Validators/ClaimAuthorityAuthorizationValidator.cs` — ClaimAuthorityAuthorizationValidator RuleFor(FunctionType) |

---

## SVC-BR-CLM-004 The granting user must hold the same approval type for that function

| Field | Value |
| --- | --- |
| **Statement** | The granting user must hold the same approval type for that function |
| **Trigger** | as above |
| **Enforcement** | RuleFor(ApprovalType) |
| **Outcome** | "You are not authorized to grant this Approval type" |
| **Operation(s)** | IsValid*AuthorityEdits, AddEditAuthorityLimit, AddAuthorityLimit |
| **Source** | `Services/SAIF.Services/Claims/Authority/Validators/ClaimAuthorityAuthorizationValidator.cs` — RuleFor(ApprovalType)* |

---

## SVC-BR-CLM-005 The granted amount must be ≤ the granting user's limit for that function and approval type

| Field | Value |
| --- | --- |
| **Statement** | The granted amount must be ≤ the granting user's limit for that function and approval type |
| **Trigger** | as above |
| **Enforcement** | RuleFor(MaximumAmount) |
| **Outcome** | "You are not authorized to grant this amount" |
| **Operation(s)** | IsValid*AuthorityEdits, AddEditAuthorityLimit, AddAuthorityLimit |
| **Source** | `Services/SAIF.Services/Claims/Authority/Validators/ClaimAuthorityAuthorizationValidator.cs` — RuleFor(MaximumAmount)* |

---

## SVC-BR-CLM-006 The limit must be > 0

| Field | Value |
| --- | --- |
| **Statement** | The limit must be > 0 |
| **Trigger** | Authorization valid or override |
| **Enforcement** | ClaimAuthorityValuesValidator RuleFor(MaximumAmount).GreaterThan(0) |
| **Outcome** | "Payment limit must be greater than zero" / "Incurred limit must be greater than zero" |
| **Operation(s)** | IsValid*AuthorityEdits, AddEditAuthorityLimit, AddAuthorityLimit |
| **Source** | `Services/SAIF.Services/Claims/Authority/Validators/ClaimAuthorityValuesValidator.cs` — ClaimAuthorityValuesValidator RuleFor(MaximumAmount).GreaterThan(0) |

---

## SVC-BR-CLM-007 The expiration date may not be in the past

| Field | Value |
| --- | --- |
| **Statement** | The expiration date may not be in the past |
| **Trigger** | ExpirationDate ≠ MinValue |
| **Enforcement** | RuleFor(ExpirationDate) ≥ Today |
| **Outcome** | "Expiration date may not be in the past" |
| **Operation(s)** | IsValid*AuthorityEdits, AddEditAuthorityLimit, AddAuthorityLimit |
| **Source** | `Services/SAIF.Services/Claims/Authority/Validators/ClaimAuthorityValuesValidator.cs` — RuleFor(ExpirationDate) ≥ Today* |

---

## SVC-BR-CLM-008 The expiration date may be at most 1 year ahead

| Field | Value |
| --- | --- |
| **Statement** | The expiration date may be at most 1 year ahead |
| **Trigger** | ExpirationDate ≠ MinValue |
| **Enforcement** | RuleFor(ExpirationDate) ≤ Today+1y |
| **Outcome** | "Expiration date may not be more than a year in the future" |
| **Operation(s)** | IsValid*AuthorityEdits, AddEditAuthorityLimit, AddAuthorityLimit |
| **Source** | `Services/SAIF.Services/Claims/Authority/Validators/ClaimAuthorityValuesValidator.cs` — RuleFor(ExpirationDate) ≤ Today+1y* |

---

## SVC-BR-CLM-009 Value checks only run if the authorization checks pass (or override is set)

| Field | Value |
| --- | --- |
| **Statement** | Value checks only run if the authorization checks pass (or override is set) |
| **Trigger** | — |
| **Enforcement** | ClaimAuthorityValidator.HasValidAuthorization |
| **Outcome** | Values rules are skipped |
| **Operation(s)** | IsValid*AuthorityEdits, AddEditAuthorityLimit, AddAuthorityLimit |
| **Source** | `Services/SAIF.Services/Claims/Authority/Validators/ClaimAuthorityValidator.cs` — ClaimAuthorityValidator.HasValidAuthorization |

---

## SVC-BR-CLM-010 Override authority is disabled in production

| Field | Value |
| --- | --- |
| **Statement** | Override authority is disabled in production |
| **Trigger** | IsProduction |
| **Enforcement** | ClaimAuthorityService.ValidateAuthorityEdit |
| **Outcome** | IsOverrideAuthority = false |
| **Operation(s)** | all validating ops |
| **Source** | `Services/SAIF.Services/Claims/Authority/ClaimAuthorityService.cs` — ClaimAuthorityService.ValidateAuthorityEdit |

---

## SVC-BR-CLM-011 Approve/Initiate → Payments process; otherwise Reserve

| Field | Value |
| --- | --- |
| **Statement** | Approve/Initiate → Payments process; otherwise Reserve |
| **Trigger** | — |
| **Enforcement** | GetBusinessProcessFromApprovalType |
| **Outcome** | Chooses the validator branch |
| **Operation(s)** | AddEditAuthorityLimit, AddAuthorityLimit |
| **Source** | `Services/SAIF.Services/Claims/Authority/ClaimAuthorityService.cs` — GetBusinessProcessFromApprovalType* |

---

## SVC-BR-CLM-012 An unchanged limit is not updated

| Field | Value |
| --- | --- |
| **Statement** | An unchanged limit is not updated |
| **Trigger** | Same amount and expiration |
| **Enforcement** | HasAuthorityLimitChanged |
| **Outcome** | No-op |
| **Operation(s)** | AddEditAuthorityLimit |
| **Source** | `Services/SAIF.Services/Claims/Authority/ClaimAuthorityService.cs` — HasAuthorityLimitChanged* |

---

## SVC-BR-CLM-013 Optimistic concurrency on the authority limit

| Field | Value |
| --- | --- |
| **Statement** | Optimistic concurrency on the authority limit |
| **Trigger** | UpdateNumber mismatch |
| **Enforcement** | UpdateAuthorityLimit |
| **Outcome** | "Someone else has updated this data, please close edit window"; rollback |
| **Operation(s)** | AddEditAuthorityLimit |
| **Source** | `Services/SAIF.Services/Claims/Authority/ClaimAuthorityService.cs` — UpdateAuthorityLimit* |

---

## SVC-BR-CLM-014 Every add, update, delete or revert writes a history row

| Field | Value |
| --- | --- |
| **Statement** | Every add, update, delete or revert writes a history row |
| **Trigger** | — |
| **Enforcement** | AddLimitToHistory |
| **Outcome** | EmployeeAuthorityPaymentLimitHistory row (amount 0 stored as null) |
| **Operation(s)** | authority ops |
| **Source** | `Services/SAIF.Services/Claims/Authority/ClaimAuthorityService.cs` — AddLimitToHistory* |

---

## SVC-BR-CLM-015 An expired limit reverts to the latest earlier non-expiring history entry that has an amount; otherwise it is deleted

| Field | Value |
| --- | --- |
| **Statement** | An expired limit reverts to the latest earlier non-expiring history entry that has an amount; otherwise it is deleted |
| **Trigger** | Batch |
| **Enforcement** | DeleteOrRevertAuthority |
| **Outcome** | Revert or delete |
| **Operation(s)** | DeleteOrRevertExpiredAuthorities |
| **Source** | `Services/SAIF.Services/Claims/Authority/ClaimAuthorityService.cs` — DeleteOrRevertAuthority* |

---

## SVC-BR-CLM-016 Default audit user 'CMN0011' when there is no user id

| Field | Value |
| --- | --- |
| **Statement** | Default audit user "CMN0011" when there is no user id |
| **Trigger** | Batch |
| **Enforcement** | Delete/RevertAuthority |
| **Outcome** | UpdateUser |
| **Operation(s)** | batch ops |
| **Source** | `Services/SAIF.Services/Claims/Authority/ClaimAuthorityService.cs` — Delete/RevertAuthority* |

---

## SVC-BR-CLM-017 'Terminated' means EmployeeStatusCode ≠ 'A'

| Field | Value |
| --- | --- |
| **Statement** | "Terminated" means EmployeeStatusCode ≠ "A" |
| **Trigger** | — |
| **Enforcement** | GetTerminatedAuthorities |
| **Outcome** | Listed |
| **Operation(s)** | GetTerminatedAuthorities |
| **Source** | `Services/SAIF.Services/Claims/Authority/ClaimAuthorityService.cs` — GetTerminatedAuthorities* |

---

## SVC-BR-CLM-018 In production, inactive users or users with no employee id get no authority

| Field | Value |
| --- | --- |
| **Statement** | In production, inactive users or users with no employee id get no authority |
| **Trigger** | IsProduction |
| **Enforcement** | GetClaimAuthority |
| **Outcome** | "Unknown User<br/>Please enter a valid mailid" |
| **Operation(s)** | GetClaimAuthority |
| **Source** | `Services/SAIF.Services/Claims/Authority/ClaimAuthorityService.cs` — GetClaimAuthority* |

---

## SVC-BR-CLM-019 Updating authority requires ClaimAuthorityUpdate or ClaimAuthorityEAIPUpdate

| Field | Value |
| --- | --- |
| **Statement** | Updating authority requires ClaimAuthorityUpdate or ClaimAuthorityEAIPUpdate |
| **Trigger** | — |
| **Enforcement** | CanUserUpdate |
| **Outcome** | CanUpdate flag only; the service does not enforce it on writes |
| **Operation(s)** | GetClaimAuthority |
| **Source** | `Services/SAIF.Services/Claims/Authority/ClaimAuthorityService.cs` — CanUserUpdate* |

---

## SVC-BR-CLM-040 A security override is matched by employee id

| Field | Value |
| --- | --- |
| **Statement** | A security override is matched by employee id |
| **Trigger** | — |
| **Enforcement** | ClaimInformationService.HasSecurityOverride |
| **Outcome** | bool |
| **Operation(s)** | TaskService masking |
| **Source** | `Services/SAIF.Services/Claims/Information/ClaimInformationService.cs` — ClaimInformationService.HasSecurityOverride |

---

## SVC-BR-CLM-041 SSN is masked to the last 4 digits

| Field | Value |
| --- | --- |
| **Statement** | SSN is masked to the last 4 digits |
| **Trigger** | — |
| **Enforcement** | GetWorker |
| **Outcome** | "***-**-####" |
| **Operation(s)** | GetWorker |
| **Source** | `Services/SAIF.Services/Claims/Information/ClaimInformationService.cs` — GetWorker* |

---

## SVC-BR-CLM-042 Last payment = sum of TD, VocTD and SupTD details

| Field | Value |
| --- | --- |
| **Statement** | Last payment = sum of TD, VocTD and SupTD details |
| **Trigger** | — |
| **Enforcement** | GetLastPayment |
| **Outcome** | Amount |
| **Operation(s)** | GetLastPayment |
| **Source** | `Services/SAIF.Services/Claims/Information/ClaimInformationService.cs` — GetLastPayment* |

---

## SVC-BR-CLM-043 Pseudo-adjuster falls back to PseudoPhone / PseudoName

| Field | Value |
| --- | --- |
| **Statement** | Pseudo-adjuster falls back to PseudoPhone / PseudoName |
| **Trigger** | Pseudo user |
| **Enforcement** | GetResponsibleAdjuster |
| **Outcome** | Contact |
| **Operation(s)** | contacts |
| **Source** | `Services/SAIF.Services/Claims/Information/ClaimInformationService.cs` — GetResponsibleAdjuster* |

---

## SVC-BR-CLM-044 On a secure claim, the supervisor is the adjuster's manager

| Field | Value |
| --- | --- |
| **Statement** | On a secure claim, the supervisor is the adjuster's manager |
| **Trigger** | HostileWorker code set / IsSecureClaim |
| **Enforcement** | ClaimContactService.GetSupervisor; ContactsNodeBuilder.AddAdjusterSupervisor |
| **Outcome** | Manager contact |
| **Operation(s)** | GetSupervisor, BuildContactsNode |
| **Source** | `Services/SAIF.Services/Claims/Information/ClaimContactService.cs` — ClaimContactService.GetSupervisor; ContactsNodeBuilder.AddAdjusterSupervisor |

---

## SVC-BR-CLM-045 The supervisor is not shown if the same person as the adjuster

| Field | Value |
| --- | --- |
| **Statement** | The supervisor is not shown if the same person as the adjuster |
| **Trigger** | — |
| **Enforcement** | GetSupervisor |
| **Outcome** | Empty |
| **Operation(s)** | GetSupervisor, BuildContactsNode |
| **Source** | `Services/SAIF.Services/Claims/Information/ClaimContactService.cs` — GetSupervisor* |

---

## SVC-BR-CLM-046 Claim attribute labels (Fraud, Secured worker, Conflict, Overpayment, CDA [date], DCS, and others)

| Field | Value |
| --- | --- |
| **Statement** | Claim attribute labels (Fraud, Secured worker, Conflict, Overpayment, CDA [date], DCS, and others) |
| **Trigger** | — |
| **Enforcement** | ClaimNodeBuilder.AddClaimAttributes |
| **Outcome** | Labels |
| **Operation(s)** | BuildClaimNode |
| **Source** | `Services/SAIF.Services/Claims/Information/Api/ClaimNodeBuilder.cs` — ClaimNodeBuilder.AddClaimAttributes |

---

## SVC-BR-CLM-047 Legal node excludes Closed cases; 'None' / 'Unassigned' numbering

| Field | Value |
| --- | --- |
| **Statement** | Legal node excludes Closed cases; "None" / "Unassigned" numbering |
| **Trigger** | — |
| **Enforcement** | LegalNodeBuilder.AddLegalNode |
| **Outcome** | Node |
| **Operation(s)** | BuildLegalNode |
| **Source** | `Services/SAIF.Services/Claims/Information/Api/LegalNodeBuilder.cs` — LegalNodeBuilder.AddLegalNode |

---

## SVC-BR-CLM-048 A Guidewire 404 falls back to the non-converted claim

| Field | Value |
| --- | --- |
| **Statement** | A Guidewire 404 falls back to the non-converted claim |
| **Trigger** | 404 |
| **Enforcement** | GetClaimForOnBaseAsync |
| **Outcome** | 200 / 500 / passthrough |
| **Operation(s)** | BuildLegalNode |
| **Source** | `Services/SAIF.Services/Claims/Information/Api/LegalNodeBuilder.cs` — GetClaimForOnBaseAsync* |

---

## SVC-BR-CLM-050 Missing-timeloss payment = no 'Zero Prorate Letter' imaged today

| Field | Value |
| --- | --- |
| **Statement** | Missing-timeloss payment = no "Zero Prorate Letter" imaged today |
| **Trigger** | Batch |
| **Enforcement** | SendMissingTimeLossReport |
| **Outcome** | Email |
| **Operation(s)** | BuildLegalNode |
| **Source** | `Services/SAIF.Services/Claims/Information/Api/LegalNodeBuilder.cs` — SendMissingTimeLossReport* |

---

## SVC-BR-CLM-060 A fully processed batch (counts equal) is purged before the next one

| Field | Value |
| --- | --- |
| **Statement** | A fully processed batch (counts equal) is purged before the next one |
| **Trigger** | Counts equal |
| **Enforcement** | ProcessNextBatch |
| **Outcome** | Deletes beneficiaries and batch |
| **Operation(s)** | ProcessNextBatch |
| **Source** | `Services/SAIF.Services/Claims/Information/Api/LegalNodeBuilder.cs` — ProcessNextBatch* |

---

## SVC-BR-CLM-061 History is only updated when the new submission date is later

| Field | Value |
| --- | --- |
| **Statement** | History is only updated when the new submission date is later |
| **Trigger** | — |
| **Enforcement** | ProcessMedicareBeneficiarysStatelessMode |
| **Outcome** | Update or insert |
| **Operation(s)** | ProcessNextBatch |
| **Source** | `Services/SAIF.Services/Claims/Information/Api/LegalNodeBuilder.cs` — ProcessMedicareBeneficiarysStatelessMode* |

---

## SVC-BR-CLM-062 Beneficiary and history counts must match after processing

| Field | Value |
| --- | --- |
| **Statement** | Beneficiary and history counts must match after processing |
| **Trigger** | — |
| **Enforcement** | ProcessNextBatch |
| **Outcome** | throw "Counts Don't match" |
| **Operation(s)** | ProcessNextBatch |
| **Source** | `Services/SAIF.Services/Claims/Information/Api/LegalNodeBuilder.cs` — ProcessNextBatch* |

---

## SVC-BR-CLM-070 Severity activity role must be Adjuster, Supervisor or RTW Consultant

| Field | Value |
| --- | --- |
| **Statement** | Severity activity role must be Adjuster, Supervisor or RTW Consultant |
| **Trigger** | — |
| **Enforcement** | AssignActivityRole |
| **Outcome** | Error "Unknown Activity Action Role" |
| **Operation(s)** | CreateClaimActivities |
| **Source** | `Services/SAIF.Services/Claims/Information/Api/LegalNodeBuilder.cs` — AssignActivityRole* |

---

## SVC-BR-CLM-080 Only claims received after 01/03/2021

| Field | Value |
| --- | --- |
| **Statement** | Only claims received after 01/03/2021 |
| **Trigger** | — |
| **Enforcement** | GenerateMissingTaxIdActivities |
| **Outcome** | Lookback is capped |
| **Operation(s)** | ClaimTaskGenerationService.CreateClaimActivities |
| **Source** | `Services/SAIF.Services/Claims/Information/Api/LegalNodeBuilder.cs` — GenerateMissingTaxIdActivities* |

---

## SVC-BR-CLM-081 Skip Void, fatal, inmate and in-progress claims

| Field | Value |
| --- | --- |
| **Statement** | Skip Void, fatal, inmate and in-progress claims |
| **Trigger** | — |
| **Enforcement** | GenerateMissingTaxIdActivities |
| **Outcome** | Skip |
| **Operation(s)** | ClaimTaskGenerationService.CreateClaimActivities |
| **Source** | `Services/SAIF.Services/Claims/Information/Api/LegalNodeBuilder.cs` — GenerateMissingTaxIdActivities* |

---

## SVC-BR-CLM-082 REQ30 task at 30–59 days; REQ60 at 60+ days only if REQ30 exists; skip if the text config is empty

| Field | Value |
| --- | --- |
| **Statement** | REQ30 task at 30–59 days; REQ60 at 60+ days only if REQ30 exists; skip if the text config is empty |
| **Trigger** | — |
| **Enforcement** | GenerateMissingTaxIdActivities |
| **Outcome** | Task |
| **Operation(s)** | ClaimTaskGenerationService.CreateClaimActivities |
| **Source** | `Services/SAIF.Services/Claims/Information/Api/LegalNodeBuilder.cs` — GenerateMissingTaxIdActivities* |

---

## SVC-BR-CLM-090 Group filter must be in ClaimActivities.ValidGroups

| Field | Value |
| --- | --- |
| **Statement** | Group filter must be in ClaimActivities.ValidGroups |
| **Trigger** | "{" in user |
| **Enforcement** | TaskService.GetTasks |
| **Outcome** | Empty list |
| **Operation(s)** | GetTasks |
| **Source** | `Services/SAIF.Services/Claims/Tasks/TaskService.cs` — TaskService.GetTasks |

---

## SVC-BR-CLM-091 Needs an assigned user or a valid claim

| Field | Value |
| --- | --- |
| **Statement** | Needs an assigned user or a valid claim |
| **Trigger** | — |
| **Enforcement** | GetTasks |
| **Outcome** | Empty |
| **Operation(s)** | GetTasks |
| **Source** | `Services/SAIF.Services/Claims/Tasks/TaskService.cs` — GetTasks* |

---

## SVC-BR-CLM-092 External RTW users never see document (image) tasks

| Field | Value |
| --- | --- |
| **Statement** | External RTW users never see document (image) tasks |
| **Trigger** | IsExternal && RTWExternalUpdate |
| **Enforcement** | ApplyAdditionalFilters |
| **Outcome** | Filter |
| **Operation(s)** | GetTasks |
| **Source** | `Services/SAIF.Services/Claims/Tasks/TaskService.cs` — ApplyAdditionalFilters* |

---

## SVC-BR-CLM-093 Worker name is masked 'Confidential' for restricted claims without access or an override

| Field | Value |
| --- | --- |
| **Statement** | Worker name is masked "Confidential" for restricted claims without access or an override |
| **Trigger** | — |
| **Enforcement** | GetClaimWorkerName |
| **Outcome** | Masked name and text |
| **Operation(s)** | GetTasks |
| **Source** | `Services/SAIF.Services/Claims/Tasks/TaskService.cs` — GetClaimWorkerName* |

---

## SVC-BR-CLM-094 External users can only edit their own tasks and cannot reassign

| Field | Value |
| --- | --- |
| **Statement** | External users can only edit their own tasks and cannot reassign |
| **Trigger** | IsExternal |
| **Enforcement** | SetAdditionalClaimTaskData, CreateTask |
| **Outcome** | Flags |
| **Operation(s)** | GetTasks, CreateTask |
| **Source** | `Services/SAIF.Services/Claims/Tasks/TaskService.cs` — SetAdditionalClaimTaskData, CreateTask* |

---

## SVC-BR-CLM-095 A non-working due date moves to the previous work day

| Field | Value |
| --- | --- |
| **Statement** | A non-working due date moves to the previous work day |
| **Trigger** | — |
| **Enforcement** | AdjustTaskDate |
| **Outcome** | Date |
| **Operation(s)** | Create/Update/Reassign |
| **Source** | `Services/SAIF.Services/Claims/Tasks/TaskService.cs` — AdjustTaskDate* |

---

## SVC-BR-CLM-096 TaskUser 'INFO' → date MaxValue, Info priority

| Field | Value |
| --- | --- |
| **Statement** | TaskUser "INFO" → date MaxValue, Info priority |
| **Trigger** | — |
| **Enforcement** | Create/UpdateTask |
| **Outcome** | — |
| **Operation(s)** | Create/Update/Reassign |
| **Source** | `Services/SAIF.Services/Claims/Tasks/TaskService.cs` — Create/UpdateTask* |

---

## SVC-BR-CLM-097 Task concurrency on UpdateNumber

| Field | Value |
| --- | --- |
| **Statement** | Task concurrency on UpdateNumber |
| **Trigger** | Mismatch |
| **Enforcement** | UpdateTask |
| **Outcome** | "Error: This record has been updated by someone else." |
| **Operation(s)** | UpdateTask |
| **Source** | `Services/SAIF.Services/Claims/Tasks/TaskService.cs` — UpdateTask* |

---

## SVC-BR-CLM-098 A completed or notepad-required task creates a claim note

| Field | Value |
| --- | --- |
| **Statement** | A completed or notepad-required task creates a claim note |
| **Trigger** | — |
| **Enforcement** | DeleteTask(private) |
| **Outcome** | ClaimNote |
| **Operation(s)** | Complete/Delete/UpdateTask |
| **Source** | `Services/SAIF.Services/Claims/Tasks/TaskService.cs` — DeleteTask(private)* |

---

## SVC-BR-CLM-099 Note preferences are required before completing

| Field | Value |
| --- | --- |
| **Statement** | Note preferences are required before completing |
| **Trigger** | Missing prefs |
| **Enforcement** | CreateTaskNote |
| **Outcome** | throw ApplicationException "Error: Note preferences must be set before Completing tasks." |
| **Operation(s)** | Complete/Delete/UpdateTask |
| **Source** | `Services/SAIF.Services/Claims/Tasks/TaskService.cs` — CreateTaskNote* |

---

## SVC-BR-CLM-100 Claim must exist

| Field | Value |
| --- | --- |
| **Statement** | Claim must exist |
| **Trigger** | — |
| **Enforcement** | ClaimTaskValidator RuleFor(ClaimNumber) |
| **Outcome** | "Error: Invalid Claim Number." |
| **Operation(s)** | Create/UpdateTask |
| **Source** | `Services/SAIF.Services/Claims/Tasks/ClaimTaskValidator.cs` — ClaimTaskValidator RuleFor(ClaimNumber) |

---

## SVC-BR-CLM-101 Task user must have CTTaskUpdate or RTWExternalUpdate (unless INFO or a valid group)

| Field | Value |
| --- | --- |
| **Statement** | Task user must have CTTaskUpdate or RTWExternalUpdate (unless INFO or a valid group) |
| **Trigger** | — |
| **Enforcement** | RuleFor(TaskUser).Must(CanUserEdit) |
| **Outcome** | "Error: Invalid or unauthorized mail ID." |
| **Operation(s)** | Create/UpdateTask |
| **Source** | `Services/SAIF.Services/Claims/Tasks/ClaimTaskValidator.cs` — RuleFor(TaskUser).Must(CanUserEdit)* |

---

## SVC-BR-CLM-102 Task date between today and +2 years (when changed, not INFO)

| Field | Value |
| --- | --- |
| **Statement** | Task date between today and +2 years (when changed, not INFO) |
| **Trigger** | — |
| **Enforcement** | RuleFor(TaskDate) |
| **Outcome** | "Error: An activity must have a current date or a date not more than 2 years in the future." |
| **Operation(s)** | Create/UpdateTask (the base TaskValidator rules are outside scope) |
| **Source** | `Services/SAIF.Services/Claims/Tasks/ClaimTaskValidator.cs` — RuleFor(TaskDate)* |

---

## SVC-BR-CLM-110 On inmate or secure claims, the note author is recorded as the responsible adjuster

| Field | Value |
| --- | --- |
| **Statement** | On inmate or secure claims, the note author is recorded as the responsible adjuster |
| **Trigger** | — |
| **Enforcement** | CreateTaskNote, CreateNote, SaveNote |
| **Outcome** | CreateUser/UpdateUser = adjuster MailId |
| **Operation(s)** | notes/tasks |
| **Source** | `Services/SAIF.Services/Claims/Tasks/ClaimTaskValidator.cs` — CreateTaskNote, CreateNote, SaveNote* |

---

## SVC-BR-CLM-120 Note edit window: created fewer than 6 days ago and within 2 work days, and supervisor, creator or secure access

| Field | Value |
| --- | --- |
| **Statement** | Note edit window: created fewer than 6 days ago and within 2 work days, and supervisor, creator or secure access |
| **Trigger** | — |
| **Enforcement** | SetNoteAccessProperties |
| **Outcome** | CanEdit / CanEditNoteInfo |
| **Operation(s)** | GetNotes, GetNote |
| **Source** | `Services/SAIF.Services/Claims/Tasks/ClaimTaskValidator.cs` — SetNoteAccessProperties* |

---

## SVC-BR-CLM-121 Note concurrency on UpdateDate

| Field | Value |
| --- | --- |
| **Statement** | Note concurrency on UpdateDate |
| **Trigger** | — |
| **Enforcement** | SaveNote |
| **Outcome** | "Error: This record has been updated by someone else." |
| **Operation(s)** | SaveNote |
| **Source** | `Services/SAIF.Services/Claims/Tasks/ClaimTaskValidator.cs` — SaveNote* |

---

## SVC-BR-CLM-122 External RTW users are stamped 'USER-loadcode'

| Field | Value |
| --- | --- |
| **Statement** | External RTW users are stamped "USER-loadcode" |
| **Trigger** | — |
| **Enforcement** | SaveNote, CreateNote, GetUpdateUser |
| **Outcome** | Audit user |
| **Operation(s)** | notes |
| **Source** | `Services/SAIF.Services/Claims/Tasks/ClaimTaskValidator.cs` — SaveNote, CreateNote, GetUpdateUser* |

---

## SVC-BR-CLM-123 Delete requires CanEdit

| Field | Value |
| --- | --- |
| **Statement** | Delete requires CanEdit |
| **Trigger** | — |
| **Enforcement** | DeleteNote |
| **Outcome** | "Error: You don't have permission to delete this note, or the note is too old to delete." |
| **Operation(s)** | DeleteNote |
| **Source** | `Services/SAIF.Services/Claims/Tasks/ClaimTaskValidator.cs` — DeleteNote* |

---

## SVC-BR-CLM-125 Note text is required

| Field | Value |
| --- | --- |
| **Statement** | Note text is required |
| **Trigger** | — |
| **Enforcement** | ClaimNoteValidator RuleFor(Text).NotEmpty |
| **Outcome** | "Error: Text is required." |
| **Operation(s)** | Save/CreateNote |
| **Source** | `Services/SAIF.Services/Claims/Notes/Validators/ClaimNoteValidator.cs` — ClaimNoteValidator RuleFor(Text).NotEmpty |

---

## SVC-BR-CLM-126 Text ≤ 4000 characters

| Field | Value |
| --- | --- |
| **Statement** | Text ≤ 4000 characters |
| **Trigger** | — |
| **Enforcement** | RuleFor(Text).Length(0,4000) |
| **Outcome** | "Error: Text may not be more than 4000 characters." |
| **Operation(s)** | Save/CreateNote |
| **Source** | `Services/SAIF.Services/Claims/Notes/Validators/ClaimNoteValidator.cs` — RuleFor(Text).Length(0,4000)* |

---

## SVC-BR-CLM-127 Text + append + header ≤ 4000

| Field | Value |
| --- | --- |
| **Statement** | Text + append + header ≤ 4000 |
| **Trigger** | AppendText ≠ null |
| **Enforcement** | RuleFor(AppendText).Must |
| **Outcome** | "Error: Appended text must not cause text to be more than 4000 characters." |
| **Operation(s)** | Save/CreateNote |
| **Source** | `Services/SAIF.Services/Claims/Notes/Validators/ClaimNoteValidator.cs` — RuleFor(AppendText).Must* |

---

## SVC-BR-CLM-128 Category and type are required

| Field | Value |
| --- | --- |
| **Statement** | Category and type are required |
| **Trigger** | — |
| **Enforcement** | NoteCategoryValidator / NoteTypeValidator |
| **Outcome** | "Error: Category is required." / "Error: Type is required." |
| **Operation(s)** | Save/CreateNote |
| **Source** | `Services/SAIF.Services/Claims/Notes/Validators/ClaimNoteValidator.cs` — NoteCategoryValidator / NoteTypeValidator* |

---

## SVC-BR-CLM-124 Preferences are converted only for note editors

| Field | Value |
| --- | --- |
| **Statement** | Preferences are converted only for note editors |
| **Trigger** | — |
| **Enforcement** | NotePreferenceConversionService.SavePreferences |
| **Outcome** | Preference row |
| **Operation(s)** | ConvertNotePreferences |
| **Source** | `Services/SAIF.Services/Claims/Notes/NotePreferenceConversionService.cs` — NotePreferenceConversionService.SavePreferences |

---

## SVC-BR-CLM-130 External RTW users may only access claims whose RTW case matches their load code

| Field | Value |
| --- | --- |
| **Statement** | External RTW users may only access claims whose RTW case matches their load code |
| **Trigger** | RTWExternalUpdate |
| **Enforcement** | RTWService.CanAccessRTWClaim |
| **Outcome** | bool |
| **Operation(s)** | TaskService masking |
| **Source** | `Services/SAIF.Services/Claims/RTW/RTWService.cs` — RTWService.CanAccessRTWClaim |

---

## SVC-BR-CLM-140 A secure claim is HostileWorker 'R' or 'T'; conflict is IsWorkerConflict

| Field | Value |
| --- | --- |
| **Statement** | A secure claim is HostileWorker "R" or "T"; conflict is IsWorkerConflict |
| **Trigger** | — |
| **Enforcement** | SecurityOverrideService constructor mapping |
| **Outcome** | DTO flags |
| **Operation(s)** | Get* |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideService.cs` — SecurityOverrideService constructor mapping |

---

## SVC-BR-CLM-141 An override is editable if not yet expired, and deletable if not yet effective

| Field | Value |
| --- | --- |
| **Statement** | An override is editable if not yet expired, and deletable if not yet effective |
| **Trigger** | — |
| **Enforcement** | SetAdditionalProperties |
| **Outcome** | Flags only |
| **Operation(s)** | Get* |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideService.cs` — SetAdditionalProperties* |

---

## SVC-BR-CLM-142 Claim must be valid

| Field | Value |
| --- | --- |
| **Statement** | Claim must be valid |
| **Trigger** | — |
| **Enforcement** | SecurityOverrideValidator RuleFor(ClaimNumber) |
| **Outcome** | "Error: Invalid claim number." |
| **Operation(s)** | Create/UpdateOverride |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideValidator.cs` — SecurityOverrideValidator RuleFor(ClaimNumber) |

---

## SVC-BR-CLM-143 User must be valid

| Field | Value |
| --- | --- |
| **Statement** | User must be valid |
| **Trigger** | — |
| **Enforcement** | RuleFor(UserId) |
| **Outcome** | "Error: Invalid user name." |
| **Operation(s)** | Create/UpdateOverride |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideValidator.cs` — RuleFor(UserId)* |

---

## SVC-BR-CLM-144 Effective date between today and +1 month (when changed)

| Field | Value |
| --- | --- |
| **Statement** | Effective date between today and +1 month (when changed) |
| **Trigger** | — |
| **Enforcement** | RuleFor(EffDate).InclusiveBetween |
| **Outcome** | "Error: The effective date must be the current date or a date not more than one month in the future." |
| **Operation(s)** | Create/UpdateOverride |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideValidator.cs` — RuleFor(EffDate).InclusiveBetween* |

---

## SVC-BR-CLM-145 Effective date must be a working day

| Field | Value |
| --- | --- |
| **Statement** | Effective date must be a working day |
| **Trigger** | — |
| **Enforcement** | RuleFor(EffDate).Must(IsWorkingDay) |
| **Outcome** | "Error: The effective date must be a valid work day." |
| **Operation(s)** | Create/UpdateOverride |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideValidator.cs` — RuleFor(EffDate).Must(IsWorkingDay)* |

---

## SVC-BR-CLM-146 Expiration date ≥ effective date

| Field | Value |
| --- | --- |
| **Statement** | Expiration date ≥ effective date |
| **Trigger** | — |
| **Enforcement** | RuleFor(ExpDate).Must(IsValidExpDate) |
| **Outcome** | "Error: The expiration date must be after the effective date and a date not more than one year in the future." |
| **Operation(s)** | Create/UpdateOverride |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideValidator.cs` — RuleFor(ExpDate).Must(IsValidExpDate)* |

---

## SVC-BR-CLM-147 Override concurrency on UpdateDate

| Field | Value |
| --- | --- |
| **Statement** | Override concurrency on UpdateDate |
| **Trigger** | — |
| **Enforcement** | UpdateOverride |
| **Outcome** | "Error: This record has been updated by someone else." |
| **Operation(s)** | UpdateOverride |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideValidator.cs` — UpdateOverride* |

---

## SVC-BR-CLM-150 Void or denied claims are excluded from the pharmacy extract

| Field | Value |
| --- | --- |
| **Statement** | Void or denied claims are excluded from the pharmacy extract |
| **Trigger** | — |
| **Enforcement** | VerifyClaim |
| **Outcome** | Warning |
| **Operation(s)** | ProcessEligibilityExtract |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideValidator.cs` — VerifyClaim* |

---

## SVC-BR-CLM-151 First fill → transmit, then set back to Ineligible (user CMN0117)

| Field | Value |
| --- | --- |
| **Statement** | First fill → transmit, then set back to Ineligible (user CMN0117) |
| **Trigger** | — |
| **Enforcement** | UpdatePharmElig |
| **Outcome** | Update |
| **Operation(s)** | ProcessEligibilityExtract |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideValidator.cs` — UpdatePharmElig* |

---

## SVC-BR-CLM-152 A worker with no address is skipped

| Field | Value |
| --- | --- |
| **Statement** | A worker with no address is skipped |
| **Trigger** | — |
| **Enforcement** | VerifyWorker |
| **Outcome** | Address log |
| **Operation(s)** | ProcessEligibilityExtract |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideValidator.cs` — VerifyWorker* |

---

## SVC-BR-CLM-153 A foreign address is replaced with SAIF's address

| Field | Value |
| --- | --- |
| **Statement** | A foreign address is replaced with SAIF's address |
| **Trigger** | — |
| **Enforcement** | WriteExtract |
| **Outcome** | Substitution |
| **Operation(s)** | ProcessEligibilityExtract |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideValidator.cs` — WriteExtract* |

---

## SVC-BR-CLM-154 Status and group code mapping (A/T, 001–013)

| Field | Value |
| --- | --- |
| **Statement** | Status and group code mapping (A/T, 001–013) |
| **Trigger** | — |
| **Enforcement** | WriteExtract |
| **Outcome** | Record |
| **Operation(s)** | ProcessEligibilityExtract |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideValidator.cs` — WriteExtract* |

---

## SVC-BR-CLM-155 Language preference is only kept for codes 01–04

| Field | Value |
| --- | --- |
| **Statement** | Language preference is only kept for codes 01–04 |
| **Trigger** | — |
| **Enforcement** | WriteExtract |
| **Outcome** | — |
| **Operation(s)** | ProcessEligibilityExtract |
| **Source** | `Services/SAIF.Services/Claims/SecurityOverride/SecurityOverrideValidator.cs` — WriteExtract* |

---

## SVC-BR-CLM-160 A broken relationship is expired with no active replacement

| Field | Value |
| --- | --- |
| **Statement** | A broken relationship is expired with no active replacement |
| **Trigger** | — |
| **Enforcement** | ClaimReportDataRetriever.GetExpiredRelationships |
| **Outcome** | List |
| **Operation(s)** | GetBrokenProviderRelationshipDetails |
| **Source** | `Services/SAIF.Services/Claims/Reports/ClaimReportDataRetriever.cs` — ClaimReportDataRetriever.GetExpiredRelationships |

---

## SVC-BR-CLM-161 Only active claims with outstanding reserves are reported and tasked

| Field | Value |
| --- | --- |
| **Statement** | Only active claims with outstanding reserves are reported and tasked |
| **Trigger** | — |
| **Enforcement** | GetReportDetails / UpdateResults |
| **Outcome** | Filter |
| **Operation(s)** | GetBrokenProviderRelationshipDetails |
| **Source** | `Services/SAIF.Services/Claims/Reports/ClaimReportDataRetriever.cs` — GetReportDetails / UpdateResults* |

---

## SVC-BR-CLM-170 Conflict or secure access requires the ConflictClaim or SecureClaim resource

| Field | Value |
| --- | --- |
| **Statement** | Conflict or secure access requires the ConflictClaim or SecureClaim resource |
| **Trigger** | — |
| **Enforcement** | ClaimSecurityService.GetClaimSecurity, ClaimUserSecurityAccess |
| **Outcome** | Access flags |
| **Operation(s)** | GetClaimSecurity, LoadClaimSecurity |
| **Source** | `Services/SAIF.Services/Security/ClaimSecurityService.cs` — ClaimSecurityService.GetClaimSecurity, ClaimUserSecurityAccess |

---

## SVC-BR-CLM-180 Investigation subject name priority

| Field | Value |
| --- | --- |
| **Statement** | Investigation subject name priority |
| **Trigger** | — |
| **Enforcement** | FraudInvestigationService.GetSubjectNameAsync |
| **Outcome** | Name |
| **Operation(s)** | GetClaimSecurity, LoadClaimSecurity |
| **Source** | `Services/SAIF.Services/Investigations/FraudInvestigationService.cs` — FraudInvestigationService.GetSubjectNameAsync |

---

## Legal

## SVC-BR-LGL-001 Case/claim lookup must resolve to a claim

| Field | Value |
| --- | --- |
| **Statement** | Case/claim lookup must resolve to a claim |
| **Trigger** | Lookup |
| **Enforcement** | LegalService.GetClaimIdByClaimNumberOrCaseNumber |
| **Outcome** | Error "Case or claim not found" |
| **Operation(s)** | GetClaimSecurity, LoadClaimSecurity |
| **Source** | `Services/SAIF.Services/Legal/LegalService.cs` — LegalService.GetClaimIdByClaimNumberOrCaseNumber |

---

## SVC-BR-LGL-002 Legal case must exist

| Field | Value |
| --- | --- |
| **Statement** | Legal case must exist |
| **Trigger** | GetClaimNumber |
| **Enforcement** | LegalService.GetClaimNumber |
| **Outcome** | ArgumentException |
| **Operation(s)** | GetClaimSecurity, LoadClaimSecurity |
| **Source** | `Services/SAIF.Services/Legal/LegalService.cs` — LegalService.GetClaimNumber |

---

## SVC-BR-LGL-003 Users without LNConflict cannot view conflict-worker cases

| Field | Value |
| --- | --- |
| **Statement** | Users without LNConflict cannot view conflict-worker cases |
| **Trigger** | Case list |
| **Enforcement** | LegalService.GetCaseList |
| **Outcome** | Error "You are not authorized to view this claim"; conflict cases filtered out |
| **Operation(s)** | GetCaseList |
| **Source** | `Services/SAIF.Services/Legal/LegalService.cs` — LegalService.GetCaseList |

---

## SVC-BR-LGL-004 Default selected case is the primary case, else the first case

| Field | Value |
| --- | --- |
| **Statement** | Default selected case is the primary case, else the first case |
| **Trigger** | Case list |
| **Enforcement** | LegalService.SetSelectedCase |
| **Outcome** | SelectedCase set |
| **Operation(s)** | GetCaseList |
| **Source** | `Services/SAIF.Services/Legal/LegalService.cs` — LegalService.SetSelectedCase |

---

## SVC-BR-LGL-005 Opposing counsel address - Correspondence, then Physical; 'N/A' if absent

| Field | Value |
| --- | --- |
| **Statement** | Opposing counsel address: Correspondence, then Physical; "N/A" if absent |
| **Trigger** | Case list |
| **Enforcement** | LegalService.GetOpposingCounselInfo |
| **Outcome** | Display |
| **Operation(s)** | GetCaseList |
| **Source** | `Services/SAIF.Services/Legal/LegalService.cs` — LegalService.GetOpposingCounselInfo |

---

## SVC-BR-LGL-006 Assigned attorney - appeal attorney, then schedule attorney, then OUTSIDECNCL/other firm

| Field | Value |
| --- | --- |
| **Statement** | Assigned attorney: appeal attorney, then schedule attorney, then OUTSIDECNCL/other firm |
| **Trigger** | Case info / approval |
| **Enforcement** | LegalService.DetermineAssignedAttorney |
| **Outcome** | CaseInfo fields |
| **Operation(s)** | GetCaseList, SetApproverId, GetPendingBills |
| **Source** | `Services/SAIF.Services/Legal/LegalService.cs` — LegalService.DetermineAssignedAttorney |

---

## SVC-BR-LGL-007 Attorney list includes profiles expired within the last year

| Field | Value |
| --- | --- |
| **Statement** | Attorney list includes profiles expired within the last year |
| **Trigger** | List |
| **Enforcement** | LegalService.LegalAttorneyList |
| **Outcome** | Filtered list |
| **Operation(s)** | — |
| **Source** | `Services/SAIF.Services/Legal/LegalService.cs` — LegalService.LegalAttorneyList |

---

## SVC-BR-LGL-008 Historic case costs display as 'Paid'

| Field | Value |
| --- | --- |
| **Statement** | Historic case costs display as "Paid" |
| **Trigger** | Cost history |
| **Enforcement** | CaseCostService.PopulateCaseCostHistory |
| **Outcome** | Status text |
| **Operation(s)** | PopulateAdditionalCaseListProperties |
| **Source** | `Services/SAIF.Services/Legal/CaseCostService.cs` — CaseCostService.PopulateCaseCostHistory |

---

## SVC-BR-LGL-009 Subpoena recipients appear as prepaid cost rows; 'Returned' if ReturnedDate is set

| Field | Value |
| --- | --- |
| **Statement** | Subpoena recipients appear as prepaid cost rows; "Returned" if ReturnedDate is set |
| **Trigger** | Cost history |
| **Enforcement** | CaseCostService.MapRecipientsToCaseCost |
| **Outcome** | Rows |
| **Operation(s)** | PopulateAdditionalCaseListProperties |
| **Source** | `Services/SAIF.Services/Legal/CaseCostService.cs` — CaseCostService.MapRecipientsToCaseCost |

---

## SVC-BR-LGL-010 Conference/deposition units are 15-minute increments (hours = units×15/60, rounded away from zero)

| Field | Value |
| --- | --- |
| **Statement** | Conference/deposition units are 15-minute increments (hours = units×15/60, rounded away from zero) |
| **Trigger** | Cost/pending display |
| **Enforcement** | CaseCostService.CreateHistoryRow; BillServiceHelper.UnitsToQuantityString |
| **Outcome** | Hours |
| **Operation(s)** | multiple |
| **Source** | `Services/SAIF.Services/Legal/CaseCostService.cs` — CaseCostService.CreateHistoryRow; BillServiceHelper.UnitsToQuantityString |

---

## SVC-BR-LGL-011 Adjusted lines nest their parent chain as adjustment history

| Field | Value |
| --- | --- |
| **Statement** | Adjusted lines nest their parent chain as adjustment history |
| **Trigger** | Cost history |
| **Enforcement** | CaseCostService.MoveAmendedCaseCostsToAdjustedLists |
| **Outcome** | Restructured list |
| **Operation(s)** | multiple |
| **Source** | `Services/SAIF.Services/Legal/CaseCostService.cs` — CaseCostService.MoveAmendedCaseCostsToAdjustedLists |

---

## SVC-BR-LGL-012 Conflict claimant names are masked 'Confidential' without LNConflict

| Field | Value |
| --- | --- |
| **Statement** | Conflict claimant names are masked "Confidential" without LNConflict |
| **Trigger** | Inboxes |
| **Enforcement** | BillService.GetInboxItems/GetPendingBills; SubpoenaService.GetInboxItems |
| **Outcome** | Masked name |
| **Operation(s)** | multiple |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillService.cs` — BillService.GetInboxItems/GetPendingBills; SubpoenaService.GetInboxItems |

---

## SVC-BR-LGL-013 A bill is over authority when its total exceeds both the initiate and approve limits

| Field | Value |
| --- | --- |
| **Statement** | A bill is over authority when its total exceeds both the initiate and approve limits |
| **Trigger** | Pending bills |
| **Enforcement** | BillService.PopulatePendingBillsData |
| **Outcome** | IsPaidAmountOverAuthority |
| **Operation(s)** | GetPendingBills |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillService.cs` — BillService.PopulatePendingBillsData |

---

## SVC-BR-LGL-014 Legal support staff = Dept "005201", active, title starting with "Legal"; plus a hard-coded dev list outside production

| Field | Value |
| --- | --- |
| **Statement** | Legal support staff = Dept "005201", active, title starting with "Legal"; plus a hard-coded dev list outside production |
| **Trigger** | Lists |
| **Enforcement** | BillService.LegalSupportEmployeeList |
| **Outcome** | List |
| **Operation(s)** | BillUpdateEmployeesList, GetInboxItems |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillService.cs` — BillService.LegalSupportEmployeeList |

---

## SVC-BR-LGL-020 Approver = the assigned (or requesting) attorney if their profile is active, else the attorney's manager; no profile → no approver

| Field | Value |
| --- | --- |
| **Statement** | Approver = the assigned (or requesting) attorney if their profile is active, else the attorney's manager; no profile → no approver |
| **Trigger** | Submit/adjust |
| **Enforcement** | BillSaveService.SetApproverId |
| **Outcome** | ApprovedByEmployeeId; submit falls back to a plain save |
| **Operation(s)** | SubmitBill, AdjustBill |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — BillSaveService.SetApproverId |

---

## SVC-BR-LGL-021 Approval within the approver's initiate or approve limit → Approved; otherwise PendingApproval routed to the manager with a supervisor comment

| Field | Value |
| --- | --- |
| **Statement** | Approval within the approver's initiate or approve limit → Approved; otherwise PendingApproval routed to the manager with a supervisor comment |
| **Trigger** | Approve |
| **Enforcement** | BillSaveService.UpdateBillStatusCode |
| **Outcome** | Status transition |
| **Operation(s)** | ApproveBill |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — BillSaveService.UpdateBillStatusCode |

---

## SVC-BR-LGL-022 Approve-with-changes sets status ApprovedWithChange and appends a tag

| Field | Value |
| --- | --- |
| **Statement** | Approve-with-changes sets status ApprovedWithChange and appends a tag |
| **Trigger** | Action |
| **Enforcement** | BillSaveService.ApproveWithChanges |
| **Outcome** | Status |
| **Operation(s)** | ApproveBill |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — BillSaveService.ApproveWithChanges |

---

## SVC-BR-LGL-023 Disapprove returns the bill to InProgress, clears the approver, appends a tag

| Field | Value |
| --- | --- |
| **Statement** | Disapprove returns the bill to InProgress, clears the approver, appends a tag |
| **Trigger** | Action |
| **Enforcement** | BillSaveService.DisapproveBill |
| **Outcome** | Status |
| **Operation(s)** | ApproveBill |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — BillSaveService.DisapproveBill |

---

## SVC-BR-LGL-024 Adjustment creates a child bill with only the changed lines; a partial return, or a service change with unchanged amount, forces Approved; no approver → InProgress; no changes → error

| Field | Value |
| --- | --- |
| **Statement** | Adjustment creates a child bill with only the changed lines; a partial return, or a service change with unchanged amount, forces Approved; no approver → InProgress; no changes → error |
| **Trigger** | Adjust |
| **Enforcement** | BillSaveService.PrepareAdjustedBillForSave / AdjustBill |
| **Outcome** | New bill, comments |
| **Operation(s)** | AdjustBill |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — BillSaveService.PrepareAdjustedBillForSave / AdjustBill |

---

## SVC-BR-LGL-025 Deleting an adjustment un-amends the parent's lines

| Field | Value |
| --- | --- |
| **Statement** | Deleting an adjustment un-amends the parent's lines |
| **Trigger** | Delete |
| **Enforcement** | BillSaveService.DeleteBill |
| **Outcome** | IsAmended=false |
| **Operation(s)** | AdjustBill |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — BillSaveService.DeleteBill |

---

## SVC-BR-LGL-026 Bills in PaymentReturned/Paid status skip validation

| Field | Value |
| --- | --- |
| **Statement** | Bills in PaymentReturned/Paid status skip validation |
| **Trigger** | Save |
| **Enforcement** | BillSaveService.SaveLegalBill |
| **Outcome** | — |
| **Operation(s)** | all bill saves |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — BillSaveService.SaveLegalBill |

---

## SVC-BR-LGL-027 Received date must be between the date of injury and today

| Field | Value |
| --- | --- |
| **Statement** | Received date must be between the date of injury and today |
| **Trigger** | Save |
| **Enforcement** | BillSaveService.ValidateBill → BillServiceHelper.IsValidReceivedDate |
| **Outcome** | "Invalid date. Must be between the claim date of injury and today." |
| **Operation(s)** | saves |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — BillSaveService.ValidateBill → BillServiceHelper.IsValidReceivedDate |

---

## SVC-BR-LGL-028 Service-from date ≥ date of injury and ≤ today (prepayments ≤ +6 months)

| Field | Value |
| --- | --- |
| **Statement** | Service-from date ≥ date of injury and ≤ today (prepayments ≤ +6 months) |
| **Trigger** | Save |
| **Enforcement** | ValidateBillServices → IsValidServiceFromDate |
| **Outcome** | "Invalid date. From date must be between the claim date of injury and today. Prepays are within 6 months." |
| **Operation(s)** | saves |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — ValidateBillServices → IsValidServiceFromDate* |

---

## SVC-BR-LGL-029 Thru date ≥ from date and ≤ today (prepayments +6 months)

| Field | Value |
| --- | --- |
| **Statement** | Thru date ≥ from date and ≤ today (prepayments +6 months) |
| **Trigger** | Save |
| **Enforcement** | IsValidServiceThruDate |
| **Outcome** | "Invalid date.  Thru date must be after From date and before tomorrow. Prepays are within 6 months." |
| **Operation(s)** | saves |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — IsValidServiceThruDate* |

---

## SVC-BR-LGL-030a Zero allowed amount requires an explanation (lines with ParentBillServiceId == 0)

| Field | Value |
| --- | --- |
| **Statement** | Zero allowed amount requires an explanation (lines with ParentBillServiceId == 0) |
| **Trigger** | Save |
| **Enforcement** | ValidateBillServices |
| **Outcome** | "Explanation is required when allowed amount is zero." |
| **Operation(s)** | saves |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — ValidateBillServices* |

---

## SVC-BR-LGL-030b If the whole bill pays 0, the reason must be Duplicate, Freeform or Unknown

| Field | Value |
| --- | --- |
| **Statement** | If the whole bill pays 0, the reason must be Duplicate, Freeform or Unknown |
| **Trigger** | Save |
| **Enforcement** | ValidateBillServices |
| **Outcome** | "Explanation must be unknown service, duplicate bill or other." |
| **Operation(s)** | saves |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — ValidateBillServices* |

---

## SVC-BR-LGL-031 Optimistic concurrency on UpdateNumber

| Field | Value |
| --- | --- |
| **Statement** | Optimistic concurrency on UpdateNumber |
| **Trigger** | Save |
| **Enforcement** | BillSaveService.SaveLegalBill; SubpoenaSaveService.SaveSubpoena; LegalNotesService.UpdateNote; LegalTaskService.UpdateTask |
| **Outcome** | "Error: This record has been updated by someone else." + rollback |
| **Operation(s)** | saves |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — BillSaveService.SaveLegalBill; SubpoenaSaveService.SaveSubpoena; LegalNotesService.UpdateNote; LegalTaskService.UpdateTask |

---

## SVC-BR-LGL-032 Invoice text uppercased; witness info ≤100 chars; subpoena special delivery ≤1000 chars

| Field | Value |
| --- | --- |
| **Statement** | Invoice text uppercased; witness info ≤100 chars; subpoena special delivery ≤1000 chars |
| **Trigger** | Save |
| **Enforcement** | SaveLegalBill; SubpoenaSaveService.SetSubpoenaData |
| **Outcome** | Truncation |
| **Operation(s)** | saves |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — SaveLegalBill; SubpoenaSaveService.SetSubpoenaData* |

---

## SVC-BR-LGL-033 Status change writes a BillStatusHistory row; comments are annotated CREATED/ADDED

| Field | Value |
| --- | --- |
| **Statement** | Status change writes a BillStatusHistory row; comments are annotated CREATED/ADDED |
| **Trigger** | Save |
| **Enforcement** | SaveLegalBill; BillPaymentService.SetNewBillStatus |
| **Outcome** | History |
| **Operation(s)** | saves, batch |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillSaveService.cs` — SaveLegalBill; BillPaymentService.SetNewBillStatus* |

---

## SVC-BR-LGL-034 LegalBill: "Error: Billing provider is required." / "Error: Rendering provider is required." / "Error: Requesting attorney is required." / "Error: Comment may not be more than 4000 characters." / BillStatus.Code "Error: Bill Status is required."

| Field | Value |
| --- | --- |
| **Statement** | LegalBill: "Error: Billing provider is required." / "Error: Rendering provider is required." / "Error: Requesting attorney is required." / "Error: Comment may not be more than 4000 characters." / BillStatus.Code "Error: Bill Status is required." |
| **Trigger** | Validate |
| **Enforcement** | LegalBillValidator RuleFor ProviderData.BillingProviderId, RenderingProviderId, RequestedByEmployeeId, Comment, BillStatus→Code |
| **Outcome** | Errors |
| **Operation(s)** | bill saves |
| **Source** | `Services/SAIF.Services/Legal/Bills/LegalBillValidator.cs` — LegalBillValidator RuleFor ProviderData.BillingProviderId, RenderingProviderId, RequestedByEmployeeId, Comment, BillStatus→Code |

---

## SVC-BR-LGL-035 LegalBillService: BilledAmount>0 "Error: Billed amount is required"; BilledUnits>0 "Error: Billed units is required"; PaidAmount≥0 "Error: Paid amount cannot be negative"; PaidAmount≤BilledAmount "Error: Paid amount cannot be more than billed amount"; BillService.Code "Error: Service type is required."

| Field | Value |
| --- | --- |
| **Statement** | LegalBillService: BilledAmount>0 "Error: Billed amount is required"; BilledUnits>0 "Error: Billed units is required"; PaidAmount≥0 "Error: Paid amount cannot be negative"; PaidAmount≤BilledAmount "Error: Paid amount cannot be more than billed amount"; BillService.Code "Error: Service type is required." |
| **Trigger** | Validate |
| **Enforcement** | LegalBillServiceValidator |
| **Outcome** | Errors / CalculateAllowedAmount returns false |
| **Operation(s)** | saves, rating |
| **Source** | `Services/SAIF.Services/Legal/Bills/LegalBillServiceValidator.cs` — LegalBillServiceValidator |

---

## SVC-BR-LGL-040 Paid amount is capped at billed amount before rating

| Field | Value |
| --- | --- |
| **Statement** | Paid amount is capped at billed amount before rating |
| **Trigger** | Rate |
| **Enforcement** | BillRateService.CalculateAllowedAmount |
| **Outcome** | Cap |
| **Operation(s)** | saves, rating |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — BillRateService.CalculateAllowedAmount |

---

## SVC-BR-LGL-041 Copy services use the fee schedule; reason ElectronicCopies/PaperCopies if reduced

| Field | Value |
| --- | --- |
| **Statement** | Copy services use the fee schedule; reason ElectronicCopies/PaperCopies if reduced |
| **Trigger** | Rate |
| **Enforcement** | ApplyCopyRatesElectronic/Paper |
| **Outcome** | PaidAmount |
| **Operation(s)** | saves, rating |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — ApplyCopyRatesElectronic/Paper* |

---

## SVC-BR-LGL-042 Unknown service pays 0 with reason Unknown

| Field | Value |
| --- | --- |
| **Statement** | Unknown service pays 0 with reason Unknown |
| **Trigger** | Rate |
| **Enforcement** | ProcessUnknownService |
| **Outcome** | 0 |
| **Operation(s)** | saves, rating |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — ProcessUnknownService* |

---

## SVC-BR-LGL-043 IME rate type uses the IME-specific fee, capped at MaximumAmount; reason ImeContract when reduced

| Field | Value |
| --- | --- |
| **Statement** | IME rate type uses the IME-specific fee, capped at MaximumAmount; reason ImeContract when reduced |
| **Trigger** | Rate |
| **Enforcement** | ApplyImeRate |
| **Outcome** | PaidAmount |
| **Operation(s)** | saves, rating |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — ApplyImeRate* |

---

## SVC-BR-LGL-044 MCO rate applies when the worker's MCO covers the service date and the provider is in the MCO; capped; reason McoContract

| Field | Value |
| --- | --- |
| **Statement** | MCO rate applies when the worker's MCO covers the service date and the provider is in the MCO; capped; reason McoContract |
| **Trigger** | Rate |
| **Enforcement** | ApplyMcoRate/GetWorkerMcoPlan |
| **Outcome** | PaidAmount, rate type MCO |
| **Operation(s)** | saves, rating |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — ApplyMcoRate/GetWorkerMcoPlan* |

---

## SVC-BR-LGL-045 Fee formula - flat amount, else initial units×rate + additional blocks; ≤ billed

| Field | Value |
| --- | --- |
| **Statement** | Fee formula: flat amount, else initial units×rate + additional blocks; ≤ billed |
| **Trigger** | Rate |
| **Enforcement** | BillRateService.CalculateAllowedAmount(fee,line) |
| **Outcome** | PaidAmount |
| **Operation(s)** | saves, rating |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — BillRateService.CalculateAllowedAmount(fee,line) |

---

## SVC-BR-LGL-046 Fallback is the Standard rate - pays billed amount, clears contract reasons

| Field | Value |
| --- | --- |
| **Statement** | Fallback is the Standard rate: pays billed amount, clears contract reasons |
| **Trigger** | Rate |
| **Enforcement** | CalculateAllowedAmount / SetAdjustmentReason |
| **Outcome** | — |
| **Operation(s)** | saves, rating |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — CalculateAllowedAmount / SetAdjustmentReason* |

---

## SVC-BR-LGL-047 Exact duplicate (provider, case, code, from-date, amount) pays 0 with reason DuplicateBill; same provider/case/date flags a possible duplicate

| Field | Value |
| --- | --- |
| **Statement** | Exact duplicate (provider, case, code, from-date, amount) pays 0 with reason DuplicateBill; same provider/case/date flags a possible duplicate |
| **Trigger** | Rate |
| **Enforcement** | CheckForDuplicateService |
| **Outcome** | PaidAmount/flag |
| **Operation(s)** | saves, rating |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — CheckForDuplicateService* |

---

## SVC-BR-LGL-050 Batch - Approved → ReadyToPay, then checks created

| Field | Value |
| --- | --- |
| **Statement** | Batch: Approved → ReadyToPay, then checks created |
| **Trigger** | Batch |
| **Enforcement** | GenerateCheckTransactionsAsync |
| **Outcome** | Status |
| **Operation(s)** | saves, rating |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — GenerateCheckTransactionsAsync* |

---

## SVC-BR-LGL-051 Bills with total ≤0 are only counted as zero-pay

| Field | Value |
| --- | --- |
| **Statement** | Bills with total ≤0 are only counted as zero-pay |
| **Trigger** | Batch |
| **Enforcement** | GenerateCheckTransactionsAsync |
| **Outcome** | Count |
| **Operation(s)** | saves, rating |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — GenerateCheckTransactionsAsync* |

---

## SVC-BR-LGL-052 Invalid payment address → ApprovedWithChange + comment + email to the creator (prod) or devs

| Field | Value |
| --- | --- |
| **Statement** | Invalid payment address → ApprovedWithChange + comment + email to the creator (prod) or devs |
| **Trigger** | Batch |
| **Enforcement** | RejectBillForAddressCorrection |
| **Outcome** | Status/email |
| **Operation(s)** | check generation |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — RejectBillForAddressCorrection* |

---

## SVC-BR-LGL-053 Adjusted bill must have 1 line, a Paid-group parent and an amended original; the delta decides check vs recovery

| Field | Value |
| --- | --- |
| **Statement** | Adjusted bill must have 1 line, a Paid-group parent and an amended original; the delta decides check vs recovery |
| **Trigger** | Batch |
| **Enforcement** | GenerateTransactionsForAdjustedBillAsync |
| **Outcome** | Check / partial refund |
| **Operation(s)** | check generation |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — GenerateTransactionsForAdjustedBillAsync* |

---

## SVC-BR-LGL-054 Successful transaction → Paid

| Field | Value |
| --- | --- |
| **Statement** | Successful transaction → Paid |
| **Trigger** | Batch |
| **Enforcement** | SetNewBillStatus |
| **Outcome** | Status |
| **Operation(s)** | check generation |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — SetNewBillStatus* |

---

## SVC-BR-LGL-055 Zero-pay letters go to ReadyToPay bills with total 0 for lines with a reason; bills → Paid

| Field | Value |
| --- | --- |
| **Statement** | Zero-pay letters go to ReadyToPay bills with total 0 for lines with a reason; bills → Paid |
| **Trigger** | Batch |
| **Enforcement** | GenerateZeroPaymentLetters |
| **Outcome** | XML + status |
| **Operation(s)** | check generation |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — GenerateZeroPaymentLetters* |

---

## SVC-BR-LGL-056 Return payment only for Paid, non-amended bills; GW recovery; lines zeroed; PaymentReturned

| Field | Value |
| --- | --- |
| **Statement** | Return payment only for Paid, non-amended bills; GW recovery; lines zeroed; PaymentReturned |
| **Trigger** | User |
| **Enforcement** | ReturnBillPayment |
| **Outcome** | Status |
| **Operation(s)** | check generation |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillRateService.cs` — ReturnBillPayment* |

---

## SVC-BR-LGL-060 Authority limit = active EmployeeAuthorityLimit for Payments/function/purpose, else 0

| Field | Value |
| --- | --- |
| **Statement** | Authority limit = active EmployeeAuthorityLimit for Payments/function/purpose, else 0 |
| **Trigger** | Any |
| **Enforcement** | BillServiceHelper.UserAuthorityLevel |
| **Outcome** | Decimal |
| **Operation(s)** | approvals |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillServiceHelper.cs` — BillServiceHelper.UserAuthorityLevel |

---

## SVC-BR-LGL-061 Issue date must be ≥ next issue date, ≤ today+14, and a working day

| Field | Value |
| --- | --- |
| **Statement** | Issue date must be ≥ next issue date, ≤ today+14, and a working day |
| **Trigger** | Validate |
| **Enforcement** | IsValidIssueDate |
| **Outcome** | bool |
| **Operation(s)** | (caller outside scope) |
| **Source** | `Services/SAIF.Services/Legal/Bills/BillServiceHelper.cs` — IsValidIssueDate* |

---

## SVC-BR-LGL-070 Notes query requires a case id

| Field | Value |
| --- | --- |
| **Statement** | Notes query requires a case id |
| **Trigger** | Get |
| **Enforcement** | LegalNotesService.GetNotes |
| **Outcome** | ArgumentNullException |
| **Operation(s)** | GetNotes |
| **Source** | `Services/SAIF.Services/Legal/Notes/LegalNotesService.cs` — LegalNotesService.GetNotes |

---

## SVC-BR-LGL-071 Note editable only by supervisor (LNNoteSupervisor) or creator, within 2 working days, not system-created

| Field | Value |
| --- | --- |
| **Statement** | Note editable only by supervisor (LNNoteSupervisor) or creator, within 2 working days, not system-created |
| **Trigger** | Get |
| **Enforcement** | SetNoteAccessProperties |
| **Outcome** | CanEdit flags |
| **Operation(s)** | Get/Create/Update |
| **Source** | `Services/SAIF.Services/Legal/Notes/LegalNotesService.cs` — SetNoteAccessProperties* |

---

## SVC-BR-LGL-072 Create/update notes requires LNUpdate

| Field | Value |
| --- | --- |
| **Statement** | Create/update notes requires LNUpdate |
| **Trigger** | Write |
| **Enforcement** | CreateNote/UpdateNote |
| **Outcome** | Errors |
| **Operation(s)** | Get/Create/Update |
| **Source** | `Services/SAIF.Services/Legal/Notes/LegalNotesService.cs` — CreateNote/UpdateNote* |

---

## SVC-BR-LGL-073 Delete - not system-created and CanEdit

| Field | Value |
| --- | --- |
| **Statement** | Delete: not system-created and CanEdit |
| **Trigger** | Delete |
| **Enforcement** | DeleteNote |
| **Outcome** | Errors |
| **Operation(s)** | Get/Create/Update |
| **Source** | `Services/SAIF.Services/Legal/Notes/LegalNotesService.cs` — DeleteNote* |

---

## SVC-BR-LGL-074 LegalNote: Text "Error: Text is required."; Length 0–4000 "Error: Text may not be more than 4000 characters."; AppendText (text + append + header ≤4000) "Error: Appended text must not cause text to be more than 4000 characters."; Category.Code "Error: Category is required."; CaseId NotEmpty/NotNull/NotEqual(0) (default messages)

| Field | Value |
| --- | --- |
| **Statement** | LegalNote: Text "Error: Text is required."; Length 0–4000 "Error: Text may not be more than 4000 characters."; AppendText (text + append + header ≤4000) "Error: Appended text must not cause text to be more than 4000 characters."; Category.Code "Error: Category is required."; CaseId NotEmpty/NotNull/NotEqual(0) (default messages) |
| **Trigger** | Validate |
| **Enforcement** | LegalNoteValidator |
| **Outcome** | Errors |
| **Operation(s)** | Create/Update |
| **Source** | `Services/SAIF.Services/Legal/Notes/Validators/LegalNoteValidator.cs` — LegalNoteValidator |

---

## SVC-BR-LGL-080 Subpoena witness pay = flat fee + round(round-trip miles × mileage rate, 2), only when miles >0

| Field | Value |
| --- | --- |
| **Statement** | Subpoena witness pay = flat fee + round(round-trip miles × mileage rate, 2), only when miles >0 |
| **Trigger** | Calculation |
| **Enforcement** | SubpoenaService.GetCalculatedSubpoenaPayment |
| **Outcome** | Amounts |
| **Operation(s)** | Create/Update |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaService.cs` — SubpoenaService.GetCalculatedSubpoenaPayment |

---

## SVC-BR-LGL-081 Over-authority subpoenas are emailed to LegalSubpoenaApprovers@saif.com

| Field | Value |
| --- | --- |
| **Statement** | Over-authority subpoenas are emailed to LegalSubpoenaApprovers@saif.com |
| **Trigger** | Approval |
| **Enforcement** | GetApprovalEmail |
| **Outcome** | Email content |
| **Operation(s)** | Create/Update |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaService.cs` — GetApprovalEmail* |

---

## SVC-BR-LGL-082 Compliance date default = next LS issue +14 days; minimum +7 days

| Field | Value |
| --- | --- |
| **Statement** | Compliance date default = next LS issue +14 days; minimum +7 days |
| **Trigger** | UI |
| **Enforcement** | SubpoenaService properties |
| **Outcome** | Dates |
| **Operation(s)** | — |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaService.cs` — SubpoenaService properties |

---

## SVC-BR-LGL-083 Subpoena approved only if the user's limit ≥ max recipient paid amount

| Field | Value |
| --- | --- |
| **Statement** | Subpoena approved only if the user's limit ≥ max recipient paid amount |
| **Trigger** | Approve |
| **Enforcement** | SubpoenaSaveService.ApproveSubpoena |
| **Outcome** | Approved or unchanged |
| **Operation(s)** | — |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaSaveService.cs` — SubpoenaSaveService.ApproveSubpoena |

---

## SVC-BR-LGL-084 Opposing counsel firm must have an address

| Field | Value |
| --- | --- |
| **Statement** | Opposing counsel firm must have an address |
| **Trigger** | Save |
| **Enforcement** | SubpoenaSaveService.SaveSubpoena |
| **Outcome** | "Error: Opposing counsel must have a valid address." |
| **Operation(s)** | — |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaSaveService.cs` — SubpoenaSaveService.SaveSubpoena |

---

## SVC-BR-LGL-085 Issue date = next LS issue date; witness types +2 work days on approval

| Field | Value |
| --- | --- |
| **Statement** | Issue date = next LS issue date; witness types +2 work days on approval |
| **Trigger** | Save |
| **Enforcement** | SetSubpoenaData |
| **Outcome** | IssueDate |
| **Operation(s)** | save/approve |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaSaveService.cs` — SetSubpoenaData* |

---

## SVC-BR-LGL-086 Payment batch: only records/claims types get checks; invalid address → InProgress + email; witness types → ReadyToPay only

| Field | Value |
| --- | --- |
| **Statement** | Payment batch: only records/claims types get checks; invalid address → InProgress + email; witness types → ReadyToPay only |
| **Trigger** | Batch |
| **Enforcement** | SubpoenaPaymentService.GenerateCheckTransactionsAsync |
| **Outcome** | Status/checks |
| **Operation(s)** | save/approve |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaPaymentService.cs` — SubpoenaPaymentService.GenerateCheckTransactionsAsync |

---

## SVC-BR-LGL-087 Recipient payment return - not already returned; GW recovery; paid=0, ReturnedDate=today

| Field | Value |
| --- | --- |
| **Statement** | Recipient payment return: not already returned; GW recovery; paid=0, ReturnedDate=today |
| **Trigger** | User |
| **Enforcement** | ReturnSubpoenaPaymentAsync |
| **Outcome** | Update |
| **Operation(s)** | save/approve |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaPaymentService.cs` — ReturnSubpoenaPaymentAsync* |

---

## SVC-BR-LGL-088 Print: duplex for records/claims/other-medical; 2 copies for process server without email or zero-pay no-mail; witness paid → F269 to accounting

| Field | Value |
| --- | --- |
| **Statement** | Print: duplex for records/claims/other-medical; 2 copies for process server without email or zero-pay no-mail; witness paid → F269 to accounting |
| **Trigger** | Print |
| **Enforcement** | SubpoenaDocumentService.PrintSubpoena |
| **Outcome** | Print/email |
| **Operation(s)** | save/approve |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaDocumentService.cs` — SubpoenaDocumentService.PrintSubpoena |

---

## SVC-BR-LGL-089 Claim must exist in ClaimCenter to render a subpoena

| Field | Value |
| --- | --- |
| **Statement** | Claim must exist in ClaimCenter to render a subpoena |
| **Trigger** | Doc |
| **Enforcement** | CreateDocumentRecord |
| **Outcome** | Exception |
| **Operation(s)** | all doc gen |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaDocumentService.cs` — CreateDocumentRecord* |

---

## SVC-BR-LGL-090 Signature 'Special Assistant Attorney General' for state-entity policies, else 'Trial Counsel'

| Field | Value |
| --- | --- |
| **Statement** | Signature "Special Assistant Attorney General" for state-entity policies, else "Trial Counsel" |
| **Trigger** | Doc |
| **Enforcement** | SetAttorneyInfo |
| **Outcome** | Text |
| **Operation(s)** | doc gen |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaDocumentService.cs` — SetAttorneyInfo* |

---

## SVC-BR-LGL-091 Certified label failure → action email

| Field | Value |
| --- | --- |
| **Statement** | Certified label failure → action email |
| **Trigger** | Label |
| **Enforcement** | SubpoenaLabelService.SendEmailForInvalidAddress |
| **Outcome** | Email |
| **Operation(s)** | label gen |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaLabelService.cs` — SubpoenaLabelService.SendEmailForInvalidAddress |

---

## SVC-BR-LGL-092 Zero-pay subpoena docs for provider-type recipients with paid 0

| Field | Value |
| --- | --- |
| **Statement** | Zero-pay subpoena docs for provider-type recipients with paid 0 |
| **Trigger** | Batch |
| **Enforcement** | ZeroPaySubpoenaProcess |
| **Outcome** | XML |
| **Operation(s)** | label gen |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/ZeroPaySubpoenaProcess.cs` — ZeroPaySubpoenaProcess |

---

## SVC-BR-LGL-093 Witness docs split by process-server / zero-pay no-mail per ProcessName

| Field | Value |
| --- | --- |
| **Statement** | Witness docs split by process-server / zero-pay no-mail per ProcessName |
| **Trigger** | Batch |
| **Enforcement** | WitnessSubpoenaProcess.GetApprovedSubpoenas |
| **Outcome** | Selection |
| **Operation(s)** | label gen |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/WitnessSubpoenaProcess.cs` — WitnessSubpoenaProcess.GetApprovedSubpoenas |

---

## SVC-BR-LGL-094 Opposing counsel copies (excluding Claims+DoNotMail); all ReadyToPay → Paid, all-or-nothing

| Field | Value |
| --- | --- |
| **Statement** | Opposing counsel copies (excluding Claims+DoNotMail); all ReadyToPay → Paid, all-or-nothing |
| **Trigger** | Batch |
| **Enforcement** | OpposingCounselService |
| **Outcome** | Status |
| **Operation(s)** | label gen |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/OpposingCounselService.cs` — OpposingCounselService |

---

## SVC-BR-LGL-095 Subpoena: SubpoenaType.Code "Error: Subpoena type must be designated."; Recipients.Count>0 "Error: A subpoena must have at least one recipient."; AppearanceDate "Error: A subpoena must have an appearance date."; AppearanceTime "Error: A subpoena must have an appearance time."; HearingLocation "Error: A subpoena must have a hearing location selected."; ComplianceDate "Error: A subpoena must have a compliance date."; SpecialHandling "Error: A subpoena must have a special handling type selected."; RequestedByEmployeeId "Error: A subpoena must have a requesting attorney."; RecordsFromDate required when thru present; RecordsThruDate required when from present; thru ≥ from "Error: Records thru date cannot be before records from date."; recipient data "Error: Invalid or incomplete Witness information entered."

| Field | Value |
| --- | --- |
| **Statement** | Subpoena: SubpoenaType.Code "Error: Subpoena type must be designated."; Recipients.Count>0 "Error: A subpoena must have at least one recipient."; AppearanceDate "Error: A subpoena must have an appearance date."; AppearanceTime "Error: A subpoena must have an appearance time."; HearingLocation "Error: A subpoena must have a hearing location selected."; ComplianceDate "Error: A subpoena must have a compliance date."; SpecialHandling "Error: A subpoena must have a special handling type selected."; RequestedByEmployeeId "Error: A subpoena must have a requesting attorney."; RecordsFromDate required when thru present; RecordsThruDate required when from present; thru ≥ from "Error: Records thru date cannot be before records from date."; recipient data "Error: Invalid or incomplete Witness information entered." |
| **Trigger** | Validate |
| **Enforcement** | SubpoenaValidator |
| **Outcome** | Errors |
| **Operation(s)** | SaveSubpoena |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaValidator.cs` — SubpoenaValidator |

---

## SVC-BR-LGL-096 Recipient data: records/claims types need ProviderLocationId>0 and a 9-char TIN; OtherMedical/Parties/Nonparties need first name 1–20, last name 1–25, and a policy location or a full address (line1 5–40, line2 ≤40, city 2–30, state 2, zip 5, +4 empty or 4); other types invalid

| Field | Value |
| --- | --- |
| **Statement** | Recipient data: records/claims types need ProviderLocationId>0 and a 9-char TIN; OtherMedical/Parties/Nonparties need first name 1–20, last name 1–25, and a policy location or a full address (line1 5–40, line2 ≤40, city 2–30, state 2, zip 5, +4 empty or 4); other types invalid |
| **Trigger** | Validate |
| **Enforcement** | SubpoenaValidator.ContainsValidRecipientData |
| **Outcome** | Error |
| **Operation(s)** | SaveSubpoena |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaValidator.cs` — SubpoenaValidator.ContainsValidRecipientData |

---

## SVC-BR-LGL-097 Recipient: MileageCost ≥0 "Error: mileage cost cannot be negative."; MileageUnits ≥0 "Error: mileage units cannot be negative."; PaidAmount 0 or ≥ CalculatedPaidAmount "Error: The paid amount cannot be less than the calculated amount."

| Field | Value |
| --- | --- |
| **Statement** | Recipient: MileageCost ≥0 "Error: mileage cost cannot be negative."; MileageUnits ≥0 "Error: mileage units cannot be negative."; PaidAmount 0 or ≥ CalculatedPaidAmount "Error: The paid amount cannot be less than the calculated amount." |
| **Trigger** | Validate |
| **Enforcement** | SubpoenaRecipientValidator |
| **Outcome** | Errors |
| **Operation(s)** | SaveSubpoena |
| **Source** | `Services/SAIF.Services/Legal/Subpoenas/SubpoenaRecipientValidator.cs` — SubpoenaRecipientValidator |

---

## SVC-BR-LGL-100 Group-user task queries must use a configured valid group

| Field | Value |
| --- | --- |
| **Statement** | Group-user task queries must use a configured valid group |
| **Trigger** | Query |
| **Enforcement** | LegalTaskService.GetTasks |
| **Outcome** | Empty result |
| **Operation(s)** | GetTasks |
| **Source** | `Services/SAIF.Services/Legal/Tasks/LegalTaskService.cs` — LegalTaskService.GetTasks |

---

## SVC-BR-LGL-101 Tasks need a user or a valid claim filter

| Field | Value |
| --- | --- |
| **Statement** | Tasks need a user or a valid claim filter |
| **Trigger** | Query |
| **Enforcement** | GetTasks |
| **Outcome** | Empty |
| **Operation(s)** | GetTasks |
| **Source** | `Services/SAIF.Services/Legal/Tasks/LegalTaskService.cs` — GetTasks* |

---

## SVC-BR-LGL-102 Task list is capped at 300, newest first

| Field | Value |
| --- | --- |
| **Statement** | Task list is capped at 300, newest first |
| **Trigger** | Query |
| **Enforcement** | ApplyAdditionalFilters |
| **Outcome** | Limit |
| **Operation(s)** | GetTasks |
| **Source** | `Services/SAIF.Services/Legal/Tasks/LegalTaskService.cs` — ApplyAdditionalFilters* |

---

## SVC-BR-LGL-103 Worker name/text masked for conflict/secure claims without access or override

| Field | Value |
| --- | --- |
| **Statement** | Worker name/text masked for conflict/secure claims without access or override |
| **Trigger** | Query |
| **Enforcement** | GetClaimWorkerName |
| **Outcome** | "Confidential" |
| **Operation(s)** | GetTasks, Print |
| **Source** | `Services/SAIF.Services/Legal/Tasks/LegalTaskService.cs` — GetClaimWorkerName* |

---

## SVC-BR-LGL-104 LegalTask: ClaimNumber IsValidClaim "Error: Invalid Claim Number."; TaskUser CanUserEdit (LNUpdate) unless INFO or valid group "Error: Invalid or unauthorized mail ID."; TaskDate between AdjustTaskDate(today) and today+2 years when changed and not INFO "Error: An activity must have a current date or a date not more than 2 years in the future."; CaseId≠0 for LGLT "Error: A case number must be specified for Legal activities."; LegalNoteCategory NotNull for LGLT and not INFO "Error: Note category is required."

| Field | Value |
| --- | --- |
| **Statement** | LegalTask: ClaimNumber IsValidClaim "Error: Invalid Claim Number."; TaskUser CanUserEdit (LNUpdate) unless INFO or valid group "Error: Invalid or unauthorized mail ID."; TaskDate between AdjustTaskDate(today) and today+2 years when changed and not INFO "Error: An activity must have a current date or a date not more than 2 years in the future."; CaseId≠0 for LGLT "Error: A case number must be specified for Legal activities."; LegalNoteCategory NotNull for LGLT and not INFO "Error: Note category is required." |
| **Trigger** | Validate |
| **Enforcement** | LegalTaskValidator |
| **Outcome** | Errors |
| **Operation(s)** | Create/Update |
| **Source** | `Services/SAIF.Services/Legal/Tasks/LegalTaskValidator.cs` — LegalTaskValidator |

---

## SVC-BR-LGL-105 Completing an IMAGE LEGAL task requires a note category

| Field | Value |
| --- | --- |
| **Statement** | Completing an IMAGE LEGAL task requires a note category |
| **Trigger** | Complete |
| **Enforcement** | CompleteTask |
| **Outcome** | Error |
| **Operation(s)** | UpdateTask, CompleteTasks |
| **Source** | `Services/SAIF.Services/Legal/Tasks/LegalTaskValidator.cs` — CompleteTask* |

---

## SVC-BR-LGL-106 Completion writes a LegalNote (LGLT/LEGAL) or ClaimNote (LEGAL/UPDT); preferences required; secure/inmate claims attribute the note to the adjuster

| Field | Value |
| --- | --- |
| **Statement** | Completion writes a LegalNote (LGLT/LEGAL) or ClaimNote (LEGAL/UPDT); preferences required; secure/inmate claims attribute the note to the adjuster |
| **Trigger** | Complete/Delete |
| **Enforcement** | CreateTaskNote |
| **Outcome** | Note/exception |
| **Operation(s)** | Complete/Delete |
| **Source** | `Services/SAIF.Services/Legal/Tasks/LegalTaskValidator.cs` — CreateTaskNote* |

---

## SVC-BR-LGL-107 Task dates falling on non-working days move to the previous working day

| Field | Value |
| --- | --- |
| **Statement** | Task dates falling on non-working days move to the previous working day |
| **Trigger** | Create/Update/Reassign |
| **Enforcement** | AdjustTaskDate |
| **Outcome** | Date |
| **Operation(s)** | Complete/Delete |
| **Source** | `Services/SAIF.Services/Legal/Tasks/LegalTaskValidator.cs` — AdjustTaskDate* |

---

## SVC-BR-LGL-108 Restricted/secured tasks cannot be deleted or completed without access

| Field | Value |
| --- | --- |
| **Statement** | Restricted/secured tasks cannot be deleted or completed without access |
| **Trigger** | Delete |
| **Enforcement** | DeleteTask / GetTaskData |
| **Outcome** | Error / skip |
| **Operation(s)** | Complete/Delete |
| **Source** | `Services/SAIF.Services/Legal/Tasks/LegalTaskValidator.cs` — DeleteTask / GetTaskData* |

---

## Policies and certificates

## SVC-BR-POL-001 'A certificate holder is required'

| Field | Value |
| --- | --- |
| **Statement** | "A certificate holder is required" |
| **Trigger** | validate CertificateEdit |
| **Enforcement** | CertificateValidator.cs L20 |
| **Outcome** | SaifValidationException |
| **Operation(s)** | Add/Edit cert |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateValidator.cs` — CertificateValidator.cs L20 |

---

## SVC-BR-POL-002 'Certificate type is required.'

| Field | Value |
| --- | --- |
| **Statement** | "Certificate type is required." |
| **Trigger** | validate CertificateEdit |
| **Enforcement** | L22 |
| **Outcome** | SaifValidationException |
| **Operation(s)** | Add/Edit cert |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateValidator.cs` — L22* |

---

## SVC-BR-POL-003 Holder is validated with CertificateHolderValidator (conditional)

| Field | Value |
| --- | --- |
| **Statement** | Holder is validated with CertificateHolderValidator (conditional) |
| **Trigger** | validate CertificateEdit |
| **Enforcement** | L25 |
| **Outcome** | SaifValidationException |
| **Operation(s)** | Add/Edit cert |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateValidator.cs` — L25* |

---

## SVC-BR-POL-004 'A policy number is required'

| Field | Value |
| --- | --- |
| **Statement** | "A policy number is required" |
| **Trigger** | validate CertificateEdit |
| **Enforcement** | L33 |
| **Outcome** | SaifValidationException |
| **Operation(s)** | Add/Edit cert |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateValidator.cs` — L33* |

---

## SVC-BR-POL-005 'A policy period is required'

| Field | Value |
| --- | --- |
| **Statement** | "A policy period is required" |
| **Trigger** | validate CertificateEdit |
| **Enforcement** | L34 |
| **Outcome** | SaifValidationException |
| **Operation(s)** | Add/Edit cert |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateValidator.cs` — L34* |

---

## SVC-BR-POL-006 'The job description may not be more than {0} characters'

| Field | Value |
| --- | --- |
| **Statement** | "The job description may not be more than {0} characters" |
| **Trigger** | validate CertificateEdit |
| **Enforcement** | L36-38 |
| **Outcome** | SaifValidationException |
| **Operation(s)** | Add/Edit cert |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateValidator.cs` — L36-38* |

---

## SVC-BR-POL-007 'The other coverages may not be more than {0} characters.' (limit = MaxLengthJobDescription)

| Field | Value |
| --- | --- |
| **Statement** | "The other coverages may not be more than {0} characters." (limit = MaxLengthJobDescription) |
| **Trigger** | validate CertificateEdit |
| **Enforcement** | L41-43 |
| **Outcome** | SaifValidationException |
| **Operation(s)** | Add/Edit cert |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateValidator.cs` — L41-43* |

---

## SVC-BR-POL-008 'An OSC policy is required.' (OSC type)

| Field | Value |
| --- | --- |
| **Statement** | "An OSC policy is required." (OSC type) |
| **Trigger** | validate CertificateEdit |
| **Enforcement** | L49 |
| **Outcome** | SaifValidationException |
| **Operation(s)** | Add/Edit cert |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateValidator.cs` — L49* |

---

## SVC-BR-POL-009 'OSC limits are required.' (OSC type)

| Field | Value |
| --- | --- |
| **Statement** | "OSC limits are required." (OSC type) |
| **Trigger** | validate CertificateEdit |
| **Enforcement** | L50 |
| **Outcome** | SaifValidationException |
| **Operation(s)** | Add/Edit cert |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateValidator.cs` — L50* |

---

## SVC-BR-POL-011 'Certificate holder name is required' / 'Certificate holder name may not be more than 100 characters' (Name1)

| Field | Value |
| --- | --- |
| **Statement** | "Certificate holder name is required" / "Certificate holder name may not be more than 100 characters" (Name1) |
| **Trigger** | validate holder |
| **Enforcement** | CertificateHolderValidator.cs L15-16 |
| **Outcome** | exception |
| **Operation(s)** | holder Add/Save/Supersede, cert Add/Edit |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateHolderValidator.cs` — CertificateHolderValidator.cs L15-16 |

---

## SVC-BR-POL-012 Name2 ≤100, same message

| Field | Value |
| --- | --- |
| **Statement** | Name2 ≤100, same message |
| **Trigger** | validate holder |
| **Enforcement** | L18-19 |
| **Outcome** | exception |
| **Operation(s)** | holder Add/Save/Supersede, cert Add/Edit |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateHolderValidator.cs` — L18-19* |

---

## SVC-BR-POL-013 'The email address may not be more than 60 characters.'

| Field | Value |
| --- | --- |
| **Statement** | "The email address may not be more than 60 characters." |
| **Trigger** | validate holder |
| **Enforcement** | L21 |
| **Outcome** | exception |
| **Operation(s)** | holder Add/Save/Supersede, cert Add/Edit |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateHolderValidator.cs` — L21* |

---

## SVC-BR-POL-014 'The email address is not formatted correctly.' (when not empty)

| Field | Value |
| --- | --- |
| **Statement** | "The email address is not formatted correctly." (when not empty) |
| **Trigger** | validate holder |
| **Enforcement** | L24-25 |
| **Outcome** | exception |
| **Operation(s)** | holder Add/Save/Supersede, cert Add/Edit |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateHolderValidator.cs` — L24-25* |

---

## SVC-BR-POL-015 'The policy number cannot be blank'

| Field | Value |
| --- | --- |
| **Statement** | "The policy number cannot be blank" |
| **Trigger** | validate holder |
| **Enforcement** | L28 |
| **Outcome** | exception |
| **Operation(s)** | holder Add/Save/Supersede, cert Add/Edit |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateHolderValidator.cs` — L28* |

---

## SVC-BR-POL-016 'Fax number is not in the correct format'

| Field | Value |
| --- | --- |
| **Statement** | "Fax number is not in the correct format" |
| **Trigger** | validate holder |
| **Enforcement** | L31 |
| **Outcome** | exception |
| **Operation(s)** | holder Add/Save/Supersede, cert Add/Edit |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateHolderValidator.cs` — L31* |

---

## SVC-BR-POL-017 'You must enter at least an email, fax or complete address'

| Field | Value |
| --- | --- |
| **Statement** | "You must enter at least an email, fax or complete address" |
| **Trigger** | validate holder |
| **Enforcement** | L39-40 |
| **Outcome** | exception |
| **Operation(s)** | holder Add/Save/Supersede, cert Add/Edit |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateHolderValidator.cs` — L39-40* |

---

## SVC-BR-POL-018 Address: Line1/2/3 ≤80 and City ≤30 "Address line may not be more than {0} characters"; Zip ≤5 "The zip code must be 5 numbers" + "The zip code may only be numbers"; Plus4 ≤4 "The zip plus 4 must be 4 numbers" + "The zip plus 4 may only be numbers"

| Field | Value |
| --- | --- |
| **Statement** | Address: Line1/2/3 ≤80 and City ≤30 "Address line may not be more than {0} characters"; Zip ≤5 "The zip code must be 5 numbers" + "The zip code may only be numbers"; Plus4 ≤4 "The zip plus 4 must be 4 numbers" + "The zip plus 4 may only be numbers" |
| **Trigger** | validate holder |
| **Enforcement** | CertificateHolderAddressValidator.cs L13-22 |
| **Outcome** | exception |
| **Operation(s)** | holder Add/Save/Supersede, cert Add/Edit |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificateHolderAddressValidator.cs` — CertificateHolderAddressValidator.cs L13-22 |

---

## SVC-BR-POL-019a 'Delivery method is required'

| Field | Value |
| --- | --- |
| **Statement** | "Delivery method is required" |
| **Trigger** | validate preference |
| **Enforcement** | CertificatePreferenceValidator.cs L14 |
| **Outcome** | exception |
| **Operation(s)** | Add/SavePreference |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificatePreferenceValidator.cs` — CertificatePreferenceValidator.cs L14 |

---

## SVC-BR-POL-019b 'Renewal notification is required' (must not be NotSet)

| Field | Value |
| --- | --- |
| **Statement** | "Renewal notification is required" (must not be NotSet) |
| **Trigger** | validate preference |
| **Enforcement** | L17-20 |
| **Outcome** | exception |
| **Operation(s)** | Add/SavePreference |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificatePreferenceValidator.cs` — L17-20* |

---

## SVC-BR-POL-019c 'The email address is not formatted correctly.'

| Field | Value |
| --- | --- |
| **Statement** | "The email address is not formatted correctly." |
| **Trigger** | validate preference |
| **Enforcement** | L35 |
| **Outcome** | exception |
| **Operation(s)** | Add/SavePreference |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificatePreferenceValidator.cs` — L35* |

---

## SVC-BR-POL-019d 'Email address name may not be more than 60 characters'

| Field | Value |
| --- | --- |
| **Statement** | "Email address name may not be more than 60 characters" |
| **Trigger** | validate preference |
| **Enforcement** | L37-39 |
| **Outcome** | exception |
| **Operation(s)** | Add/SavePreference |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificatePreferenceValidator.cs` — L37-39* |

---

## SVC-BR-POL-019e 'Email is required' (depends on delivery method)

| Field | Value |
| --- | --- |
| **Statement** | "Email is required" (depends on delivery method) |
| **Trigger** | validate preference |
| **Enforcement** | L42-45 |
| **Outcome** | exception |
| **Operation(s)** | Add/SavePreference |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificatePreferenceValidator.cs` — L42-45* |

---

## SVC-BR-POL-019f 'Fax is required' (depends on delivery method)

| Field | Value |
| --- | --- |
| **Statement** | "Fax is required" (depends on delivery method) |
| **Trigger** | validate preference |
| **Enforcement** | L49-52 |
| **Outcome** | exception |
| **Operation(s)** | Add/SavePreference |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificatePreferenceValidator.cs` — L49-52* |

---

## SVC-BR-POL-019g 'Fax number is not in the correct format'

| Field | Value |
| --- | --- |
| **Statement** | "Fax number is not in the correct format" |
| **Trigger** | validate preference |
| **Enforcement** | L54 |
| **Outcome** | exception |
| **Operation(s)** | Add/SavePreference |
| **Source** | `Services/SAIF.Services/Policies/Certificates/Validators/CertificatePreferenceValidator.cs` — L54* |

---

## SVC-BR-POL-020 Standard/Bid add needs MaintainOthers, MaintainOwn or the Ext variant of either

| Field | Value |
| --- | --- |
| **Statement** | Standard/Bid add needs MaintainOthers, MaintainOwn or the Ext variant of either |
| **Trigger** | AddCertificate |
| **Enforcement** | CertificateSecurityService L318-325; CertificateService L627 |
| **Outcome** | "Error: You are not authorized to add certificates." |
| **Operation(s)** | AddCertificate |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateSecurityService.cs` — CertificateSecurityService L318-325; CertificateService L627 |

---

## SVC-BR-POL-021 OSC add needs MaintainOthersOsc, MaintainOwnOsc or the Ext variant of either

| Field | Value |
| --- | --- |
| **Statement** | OSC add needs MaintainOthersOsc, MaintainOwnOsc or the Ext variant of either |
| **Trigger** | AddCertificate |
| **Enforcement** | L300-307 |
| **Outcome** | "Error: You are not authorized to add certificates." |
| **Operation(s)** | AddCertificate |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateSecurityService.cs` — L300-307* |

---

## SVC-BR-POL-022 Edit/delete: MaintainOthers(Osc) = any certificate; MaintainOwn(Osc) = only if the current user is CreateUser (case-insensitive)

| Field | Value |
| --- | --- |
| **Statement** | Edit/delete: MaintainOthers(Osc) = any certificate; MaintainOwn(Osc) = only if the current user is CreateUser (case-insensitive) |
| **Trigger** | Edit/Delete |
| **Enforcement** | L364-378 |
| **Outcome** | "Error: Certificate cannot be modified." (CertificateService L634) |
| **Operation(s)** | Edit, Delete |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateSecurityService.cs` — L364-378* |

---

## SVC-BR-POL-023 Delete rights equal edit rights

| Field | Value |
| --- | --- |
| **Statement** | Delete rights equal edit rights |
| **Trigger** | Delete |
| **Enforcement** | L375 |
| **Outcome** | "Error: Certificate cannot be modified." (CertificateService L634) |
| **Operation(s)** | Delete |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateSecurityService.cs` — L375* |

---

## SVC-BR-POL-024 Cutoff: editable/deletable only while CreateDate + 9 days (SecurityResources.MaximumEditibleDays = 9) > today. Cutoff date = today − 9

| Field | Value |
| --- | --- |
| **Statement** | Cutoff: editable/deletable only while CreateDate + 9 days (`SecurityResources.MaximumEditibleDays = 9`) > today. Cutoff date = today − 9 |
| **Trigger** | Edit/Delete |
| **Enforcement** | L391-405 |
| **Outcome** | "Error: Certificate cannot be modified." (CertificateService L634) |
| **Operation(s)** | Edit, Delete, GetCertificateModificationCutoff |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateSecurityService.cs` — L391-405* |

---

## SVC-BR-POL-025 A certificate already renewed (HasBeenRenewed) cannot be renewed again

| Field | Value |
| --- | --- |
| **Statement** | A certificate already renewed (HasBeenRenewed) cannot be renewed again |
| **Trigger** | Renew |
| **Enforcement** | CertificateService L637-642 |
| **Outcome** | "Error: Certificate cannot be renewed." |
| **Operation(s)** | RenewCertificate |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateService.cs` — CertificateService L637-642 |

---

## SVC-BR-POL-026 Renew authority: Standard needs CertificatesRenew or CertificatesRenewExt; OSC needs CertificatesRenewOSC or CertificatesRenewOSCExt (not called by RenewCertificate)

| Field | Value |
| --- | --- |
| **Statement** | Renew authority: Standard needs CertificatesRenew or CertificatesRenewExt; OSC needs CertificatesRenewOSC or CertificatesRenewOSCExt (not called by RenewCertificate) |
| **Trigger** | CertificateCanBeRenewed |
| **Enforcement** | L196-224, 355-362 |
| **Outcome** | bool |
| **Operation(s)** | UI checks |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateService.cs` — L196-224, 355-362* |

---

## SVC-BR-POL-027 Resend is always allowed (cancel-date rule is commented out)

| Field | Value |
| --- | --- |
| **Statement** | Resend is always allowed (cancel-date rule is commented out) |
| **Trigger** | Resend |
| **Enforcement** | L349-353 |
| **Outcome** | true |
| **Operation(s)** | ResendCertificate |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateService.cs` — L349-353* |

---

## SVC-BR-POL-030 A holder id of 0 forces holder action Add

| Field | Value |
| --- | --- |
| **Statement** | A holder id of 0 forces holder action Add |
| **Trigger** | Add |
| **Enforcement** | CertificateService L212 |
| **Outcome** | new holder |
| **Operation(s)** | Add |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateService.cs` — CertificateService L212 |

---

## SVC-BR-POL-031 Bid certificates get no holder processing

| Field | Value |
| --- | --- |
| **Statement** | Bid certificates get no holder processing |
| **Trigger** | create |
| **Enforcement** | L585 |
| **Outcome** | no holder |
| **Operation(s)** | Add/Renew |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateService.cs` — L585* |

---

## SVC-BR-POL-032 Holder Expire / Supersede go through the domain object; Supersede only when the current holder id ≠ 0

| Field | Value |
| --- | --- |
| **Statement** | Holder Expire / Supersede go through the domain object; Supersede only when the current holder id ≠ 0 |
| **Trigger** | holder action |
| **Enforcement** | L676-700 |
| **Outcome** | old holder expired/superseded |
| **Operation(s)** | Add/Edit |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateService.cs` — L676-700* |

---

## SVC-BR-POL-040 Batch print - both statuses DoNotPrint; certificate holder ReadyToPrint if MailToCertificateHolder; stop there on Resend

| Field | Value |
| --- | --- |
| **Statement** | Batch print: both statuses DoNotPrint; certificate holder ReadyToPrint if MailToCertificateHolder; stop there on Resend |
| **Trigger** | save |
| **Enforcement** | L556-570 |
| **Outcome** | status |
| **Operation(s)** | Add/Edit/Renew/Resend |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateService.cs` — L556-570* |

---

## SVC-BR-POL-041 Policyholder copy ReadyToPrint if delivery ≠ None and either (non-renewal and Mail) or (renewal and RenewalNotificationType Copy or Digest)

| Field | Value |
| --- | --- |
| **Statement** | Policyholder copy ReadyToPrint if delivery ≠ None and either (non-renewal and Mail) or (renewal and RenewalNotificationType Copy or Digest) |
| **Trigger** | save |
| **Enforcement** | L572-580 |
| **Outcome** | status |
| **Operation(s)** | Add/Edit/Renew/Resend |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateService.cs` — L572-580* |

---

## SVC-BR-POL-042 Re-image, new issue date/user and distribution point New only if tracked fields changed; otherwise Resend

| Field | Value |
| --- | --- |
| **Statement** | Re-image, new issue date/user and distribution point New only if tracked fields changed; otherwise Resend |
| **Trigger** | Edit |
| **Enforcement** | L296-331 |
| **Outcome** | image or none |
| **Operation(s)** | Edit |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateService.cs` — L296-331* |

---

## SVC-BR-POL-043 Resend resets print status only when mailing to the certificate holder

| Field | Value |
| --- | --- |
| **Statement** | Resend resets print status only when mailing to the certificate holder |
| **Trigger** | Resend |
| **Enforcement** | L405 |
| **Outcome** | update |
| **Operation(s)** | Resend |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateService.cs` — L405* |

---

## SVC-BR-POL-044 Cancellation certificate if the policy or period is in cancellation status

| Field | Value |
| --- | --- |
| **Statement** | Cancellation certificate if the policy or period is in cancellation status |
| **Trigger** | map |
| **Enforcement** | L534 |
| **Outcome** | flag |
| **Operation(s)** | Add/Edit |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateService.cs` — L534* |

---

## SVC-BR-POL-050 View OSC needs CertificatesViewOSC or CertificatesViewOSCExt

| Field | Value |
| --- | --- |
| **Statement** | View OSC needs CertificatesViewOSC or CertificatesViewOSCExt |
| **Trigger** | OSC view |
| **Enforcement** | CertificateSecurityService L84-90 |
| **Outcome** | bool |
| **Operation(s)** | CanCurrentUserViewOsc |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateSecurityService.cs` — CertificateSecurityService L84-90 |

---

## SVC-BR-POL-051 OSC policy access: agents only if OSC AgentId or AgentAgencyId equals the external CustomerId; non-agents allowed; needs POL-050

| Field | Value |
| --- | --- |
| **Statement** | OSC policy access: agents only if OSC AgentId or AgentAgencyId equals the external CustomerId; non-agents allowed; needs POL-050 |
| **Trigger** | OSC access |
| **Enforcement** | L98-110 |
| **Outcome** | bool |
| **Operation(s)** | CanCurrentUserAccess |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateSecurityService.cs` — L98-110* |

---

## SVC-BR-POL-052 Other coverages editable with CertificatesOtherCoverages or CertificatesOtherCoveragesExt

| Field | Value |
| --- | --- |
| **Statement** | Other coverages editable with CertificatesOtherCoverages or CertificatesOtherCoveragesExt |
| **Trigger** | edit |
| **Enforcement** | L183-190 |
| **Outcome** | bool |
| **Operation(s)** | UI |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificateSecurityService.cs` — L183-190* |

---

## SVC-BR-POL-060 Save preference needs CertificatesPreferences, CertificatesPreferencesExt or 'Certs'

| Field | Value |
| --- | --- |
| **Statement** | Save preference needs CertificatesPreferences, CertificatesPreferencesExt or "Certs" |
| **Trigger** | Add/SavePreference |
| **Enforcement** | CertificatePreferenceService L158-166 |
| **Outcome** | "Error: You are not authorized to update preferences" |
| **Operation(s)** | Add/SavePreference |
| **Source** | `Services/SAIF.Services/Policies/Certificates/CertificatePreferenceService.cs` — CertificatePreferenceService L158-166 |

---

## SVC-BR-POL-070 SAIF employee = Domain 'SAIF' and not external; all policies except SAIF-secure ones

| Field | Value |
| --- | --- |
| **Statement** | SAIF employee = Domain "SAIF" and not external; all policies except SAIF-secure ones |
| **Trigger** | policy access |
| **Enforcement** | PolicySecurityService L336-341, 272-279 |
| **Outcome** | bool |
| **Operation(s)** | IsValidPolicy* |
| **Source** | `Services/SAIF.Services/Policies/SecurityServices/PolicySecurityService.cs` — PolicySecurityService L336-341, 272-279 |

---

## SVC-BR-POL-071 Policy with SecurePolicyCode 'SAIF' needs 'SAIFPolicyInfo' (employees, MCO, MedProvider)

| Field | Value |
| --- | --- |
| **Statement** | Policy with SecurePolicyCode "SAIF" needs "SAIFPolicyInfo" (employees, MCO, MedProvider) |
| **Trigger** | policy access |
| **Enforcement** | L233-238, 272 |
| **Outcome** | bool |
| **Operation(s)** | IsValidPolicy* |
| **Source** | `Services/SAIF.Services/Policies/SecurityServices/PolicySecurityService.cs` — L233-238, 272* |

---

## SVC-BR-POL-072 Agent (external + AgencyExternal / ARPAgencyExternal / ProducerExternal). Producer (ProducerExternal and CustomerGroupId ≠ CustomerId): policy's AgentId = CustomerId and agency = group. Agency: policy's agency = group = CustomerId. List form uses the producer book or the agency book (active producers, not expired)

| Field | Value |
| --- | --- |
| **Statement** | Agent (external + AgencyExternal / ARPAgencyExternal / ProducerExternal). Producer (ProducerExternal and CustomerGroupId ≠ CustomerId): policy's AgentId = CustomerId and agency = group. Agency: policy's agency = group = CustomerId. List form uses the producer book or the agency book (active producers, not expired) |
| **Trigger** | policy access |
| **Enforcement** | L143-155, 214-230, 375-385 |
| **Outcome** | bool/filter |
| **Operation(s)** | IsValidPolicy* |
| **Source** | `Services/SAIF.Services/Policies/SecurityServices/PolicySecurityService.cs` — L143-155, 214-230, 375-385* |

---

## SVC-BR-POL-073 Policyholder (external + ClaimProfileExternalPolicyholder): CustomerId = policy number, or policy is in the user's association list (parent or self)

| Field | Value |
| --- | --- |
| **Statement** | Policyholder (external + ClaimProfileExternalPolicyholder): CustomerId = policy number, or policy is in the user's association list (parent or self) |
| **Trigger** | policy access |
| **Enforcement** | L136-141, 257-266, 413-420 |
| **Outcome** | bool/filter |
| **Operation(s)** | IsValidPolicy* |
| **Source** | `Services/SAIF.Services/Policies/SecurityServices/PolicySecurityService.cs` — L136-141, 257-266, 413-420* |

---

## SVC-BR-POL-074 MCO (external + 'MCO') → SAIF-secure rule

| Field | Value |
| --- | --- |
| **Statement** | MCO (external + "MCO") → SAIF-secure rule |
| **Trigger** | policy access |
| **Enforcement** | L390-396 |
| **Outcome** | bool/filter |
| **Operation(s)** | IsValidPolicy* |
| **Source** | `Services/SAIF.Services/Policies/SecurityServices/PolicySecurityService.cs` — L390-396* |

---

## SVC-BR-POL-075 Medical provider (external + MedicalProvidersExternal) → SAIF-secure rule

| Field | Value |
| --- | --- |
| **Statement** | Medical provider (external + MedicalProvidersExternal) → SAIF-secure rule |
| **Trigger** | policy access |
| **Enforcement** | L402-408 |
| **Outcome** | bool/filter |
| **Operation(s)** | IsValidPolicy* |
| **Source** | `Services/SAIF.Services/Policies/SecurityServices/PolicySecurityService.cs` — L402-408* |

---

## SVC-BR-POL-076 List validation - any other user type gets an empty result

| Field | Value |
| --- | --- |
| **Statement** | List validation: any other user type gets an empty result |
| **Trigger** | list |
| **Enforcement** | L105-130 |
| **Outcome** | filter |
| **Operation(s)** | GetPolicy etc. |
| **Source** | `Services/SAIF.Services/Policies/SecurityServices/PolicySecurityService.cs` — L105-130* |

---

## SVC-BR-POL-080 Payroll report id invalid if the report is null or ReportId = 0

| Field | Value |
| --- | --- |
| **Statement** | Payroll report id invalid if the report is null or ReportId = 0 |
| **Trigger** | GetPayrollReport |
| **Enforcement** | PolicyDocumentsApiService L223-233 |
| **Outcome** | InvalidReportId, empty PDF |
| **Operation(s)** | GetPayrollReport |
| **Source** | `Services/SAIF.Services/Policies/PolicyDocumentsApi/PolicyDocumentsApiService.cs` — PolicyDocumentsApiService L223-233 |

---

## SVC-BR-POL-081 Null docs → UnknownError; no docs → HistoricalReportNotFound; any not released → ReportNotReleased

| Field | Value |
| --- | --- |
| **Statement** | Null docs → UnknownError; no docs → HistoricalReportNotFound; any not released → ReportNotReleased |
| **Trigger** | GetPayrollReport |
| **Enforcement** | L240-257 |
| **Outcome** | empty PDF |
| **Operation(s)** | GetPayrollReport |
| **Source** | `Services/SAIF.Services/Policies/PolicyDocumentsApi/PolicyDocumentsApiService.cs` — L240-257* |

---

## SVC-BR-POL-082 Policyholder can view documents unless PolicyStatusGroup = 'APP'

| Field | Value |
| --- | --- |
| **Statement** | Policyholder can view documents unless PolicyStatusGroup = "APP" |
| **Trigger** | view |
| **Enforcement** | L106-109 |
| **Outcome** | bool |
| **Operation(s)** | AreDocumentsViewableToPolicyholder |
| **Source** | `Services/SAIF.Services/Policies/PolicyDocumentsApi/PolicyDocumentsApiService.cs` — L106-109* |

---

## SVC-BR-POL-083 API access if PolicyPayrollReportExternal, PolInfoMntUpdtExt or Domain 'SAIF'

| Field | Value |
| --- | --- |
| **Statement** | API access if PolicyPayrollReportExternal, PolInfoMntUpdtExt or Domain "SAIF" |
| **Trigger** | API |
| **Enforcement** | L150-189 |
| **Outcome** | bool |
| **Operation(s)** | HasValidCurrentUserAccess |
| **Source** | `Services/SAIF.Services/Policies/PolicyDocumentsApi/PolicyDocumentsApiService.cs` — L150-189* |

---

## SVC-BR-POL-084 A single validated association is shown as none; applications are excluded

| Field | Value |
| --- | --- |
| **Statement** | A single validated association is shown as none; applications are excluded |
| **Trigger** | GetPolicy |
| **Enforcement** | PolicyDocumentsService L156-160 |
| **Outcome** | empty list |
| **Operation(s)** | GetPolicy |
| **Source** | `Services/SAIF.Services/OutputDocuments/PolicyDocumentsService.cs` — PolicyDocumentsService L156-160 |

---

## SVC-BR-POL-085 Demo users see masked names ('Policyholder', 'Policyholder Legal Name', 'SAIF Appointed Agent')

| Field | Value |
| --- | --- |
| **Statement** | Demo users see masked names ("Policyholder", "Policyholder Legal Name", "SAIF Appointed Agent") |
| **Trigger** | read |
| **Enforcement** | L168-180, 278-282 |
| **Outcome** | masked |
| **Operation(s)** | GetPolicy, GetDocumentsForAgency |
| **Source** | `Services/SAIF.Services/OutputDocuments/PolicyDocumentsService.cs` — L168-180, 278-282* |

---

## SVC-BR-POL-086 Inbox release cutoff = system date − DaysBack

| Field | Value |
| --- | --- |
| **Statement** | Inbox release cutoff = system date − DaysBack |
| **Trigger** | inbox |
| **Enforcement** | L268-269 |
| **Outcome** | filter |
| **Operation(s)** | GetDocumentsForAgency |
| **Source** | `Services/SAIF.Services/OutputDocuments/PolicyDocumentsService.cs` — L268-269* |

---

## SVC-BR-POL-087 LEASE → 'Client of - #'; WRAP → 'Subcontractor of - #' description prefix

| Field | Value |
| --- | --- |
| **Statement** | LEASE → "Client of: #"; WRAP → "Subcontractor of: #" description prefix |
| **Trigger** | inbox |
| **Enforcement** | L291-301 |
| **Outcome** | text |
| **Operation(s)** | GetDocumentsForAgency |
| **Source** | `Services/SAIF.Services/OutputDocuments/PolicyDocumentsService.cs` — L291-301* |

---

## SVC-BR-POL-088 Optimistic concurrency - UpdateNumber must match

| Field | Value |
| --- | --- |
| **Statement** | Optimistic concurrency: UpdateNumber must match |
| **Trigger** | Delete/Replace |
| **Enforcement** | L347-348, 400-404 |
| **Outcome** | "Error: Document updated by another user." |
| **Operation(s)** | Delete, Replace |
| **Source** | `Services/SAIF.Services/OutputDocuments/PolicyDocumentsService.cs` — L347-348, 400-404* |

---

## SVC-BR-POL-089 Hold toggles Held/Pending; no change at all → "There are no document holds to save."

| Field | Value |
| --- | --- |
| **Statement** | Hold toggles Held/Pending; no change at all → "There are no document holds to save." |
| **Trigger** | hold |
| **Enforcement** | L356-387 |
| **Outcome** | exception |
| **Operation(s)** | HoldDocuments |
| **Source** | `Services/SAIF.Services/OutputDocuments/PolicyDocumentsService.cs` — L356-387* |

---

## SVC-BR-POL-090 Packet requires a released document: "{id} document is not released"; include child documents when the policy is its own relationship parent

| Field | Value |
| --- | --- |
| **Statement** | Packet requires a released document: "{id} document is not released"; include child documents when the policy is its own relationship parent |
| **Trigger** | packet |
| **Enforcement** | L482-499 |
| **Outcome** | exception |
| **Operation(s)** | GetDocumentsForPacket |
| **Source** | `Services/SAIF.Services/OutputDocuments/PolicyDocumentsService.cs` — L482-499* |

---

## SVC-BR-POL-091 Release pending documents with DocumentDate ≤ document system date

| Field | Value |
| --- | --- |
| **Statement** | Release pending documents with DocumentDate ≤ document system date |
| **Trigger** | batch |
| **Enforcement** | PolicyDocumentsBatchService L76-104 |
| **Outcome** | Released |
| **Operation(s)** | ReleaseDocuments |
| **Source** | `Services/SAIF.Services/OutputDocuments/PolicyDocumentsBatchService.cs` — PolicyDocumentsBatchService L76-104 |

---

## SVC-BR-POL-092 Direct-writer notifications only if SAIF agency IsPaperlessForPolicyHolderCopyOfDocuments

| Field | Value |
| --- | --- |
| **Statement** | Direct-writer notifications only if SAIF agency IsPaperlessForPolicyHolderCopyOfDocuments |
| **Trigger** | batch |
| **Enforcement** | L251-257 |
| **Outcome** | tasks |
| **Operation(s)** | ReleaseDocuments |
| **Source** | `Services/SAIF.Services/OutputDocuments/PolicyDocumentsBatchService.cs` — L251-257* |

---

## SVC-BR-POL-093 reportOnly means rollback and no emails/updates

| Field | Value |
| --- | --- |
| **Statement** | reportOnly means rollback and no emails/updates |
| **Trigger** | batch |
| **Enforcement** | L97-100, 283 |
| **Outcome** | dry run |
| **Operation(s)** | Release / RevertUserless / notifications |
| **Source** | `Services/SAIF.Services/OutputDocuments/PolicyDocumentsBatchService.cs` — L97-100, 283* |

---

## SVC-BR-POL-094 Policy context: the policy must exist, the user must pass PolicySecurity, and the status group must not be "APP"

| Field | Value |
| --- | --- |
| **Statement** | Policy context: the policy must exist, the user must pass PolicySecurity, and the status group must not be "APP" |
| **Trigger** | view doc |
| **Enforcement** | ContextValidator L22-31; ViewDocumentService L60-65 |
| **Outcome** | exceptions / "You are not authorized to view this document." |
| **Operation(s)** | GetImageFile |
| **Source** | `Services/SAIF.Services/OutputDocuments/ContextValidator.cs` — ContextValidator L22-31; ViewDocumentService L60-65 |

---

## SVC-BR-POL-100 Service plan policy must exist - 'Error - The PolicyNumber '{n}' is not valid'

| Field | Value |
| --- | --- |
| **Statement** | Service plan policy must exist: "Error: The PolicyNumber '{n}' is not valid" |
| **Trigger** | RCT CSV |
| **Enforcement** | RctServicePlanService L77-88 |
| **Outcome** | error count |
| **Operation(s)** | ProcessAllServicePlans |
| **Source** | `Services/SAIF.Services/Rct/RctServicePlanService.cs` — RctServicePlanService L77-88 |

---

## SVC-BR-POL-101 Service plan code must exist in RctServicePlanCode or be "na" (removal): "Error: The ServicePlanCode '{c}' is not valid"

| Field | Value |
| --- | --- |
| **Statement** | Service plan code must exist in RctServicePlanCode or be "na" (removal): "Error: The ServicePlanCode '{c}' is not valid" |
| **Trigger** | RCT CSV |
| **Enforcement** | L92-104 |
| **Outcome** | error count |
| **Operation(s)** | ProcessAllServicePlans |
| **Source** | `Services/SAIF.Services/Rct/RctServicePlanService.cs` — L92-104* |

---

## SVC-BR-POL-102 A per-row processing failure rolls back the whole batch

| Field | Value |
| --- | --- |
| **Statement** | A per-row processing failure rolls back the whole batch |
| **Trigger** | RCT CSV |
| **Enforcement** | L108-122 |
| **Outcome** | rollback |
| **Operation(s)** | ProcessAllServicePlans |
| **Source** | `Services/SAIF.Services/Rct/RctServicePlanService.cs` — L108-122* |

---

## Collections

## SVC-BR-COL-001 Case type from code - WRKR=Claim; FOTH=ClaimOther; THRD/CTHRD=ThirdParty; POL/CPOL/FPOL and anything else=Policy

| Field | Value |
| --- | --- |
| **Statement** | Case type from code: WRKR=Claim; FOTH=ClaimOther; THRD/CTHRD=ThirdParty; POL/CPOL/FPOL and anything else=Policy |
| **Trigger** | Case read or save |
| **Enforcement** | `CollectionsService.GetCaseType` |
| **Outcome** | Drives how debtors and addresses are handled |
| **Operation(s)** | GetCase*, GenerateDebtors, GetDebtorContactInfo |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — `CollectionsService.GetCaseType` |

---

## SVC-BR-COL-002 A 7 or 8 character reference is shortened to 7 characters

| Field | Value |
| --- | --- |
| **Statement** | A 7 or 8 character reference is shortened to 7 characters |
| **Trigger** | Reference search |
| **Enforcement** | GetCasesByReference |
| **Outcome** | Check character removed (inferred) |
| **Operation(s)** | GetCasesByReference |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GetCasesByReference* |

---

## SVC-BR-COL-003 Debtor name and SSN fall back to the worker API when the database value is blank

| Field | Value |
| --- | --- |
| **Statement** | Debtor name and SSN fall back to the worker API when the database value is blank |
| **Trigger** | Debtor read |
| **Enforcement** | GetDebtorName/GetDebtorSsn |
| **Outcome** | Name or TaxID comes from WorkerData |
| **Operation(s)** | GetDebtor(s) |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GetDebtorName/GetDebtorSsn* |

---

## SVC-BR-COL-004 For POL/FPOL, debtor LocID defaults to the policy "POL" mailing location. A non-active location shows "-- Invalid address --"

| Field | Value |
| --- | --- |
| **Statement** | For POL/FPOL, debtor LocID defaults to the policy "POL" mailing location. A non-active location shows "-- Invalid address --" |
| **Trigger** | Debtor read |
| **Enforcement** | GetAdditionalDebtorData |
| **Outcome** | Address shown |
| **Operation(s)** | GetDebtor(s) |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GetAdditionalDebtorData* |

---

## SVC-BR-COL-005 SSN is masked to xxx-xx-#### unless the user has LegalColUpdate

| Field | Value |
| --- | --- |
| **Statement** | SSN is masked to `xxx-xx-####` unless the user has LegalColUpdate |
| **Trigger** | GetDebtors |
| **Enforcement** | IsUpdateUser |
| **Outcome** | Masked SSN |
| **Operation(s)** | GetDebtors |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — IsUpdateUser* |

---

## SVC-BR-COL-006 When a statement is not held (or is released), LastStatementDate = first of the month and the balance comes from DebtorLastStatementBalance(date-1)

| Field | Value |
| --- | --- |
| **Statement** | When a statement is not held (or is released), LastStatementDate = first of the month and the balance comes from `DebtorLastStatementBalance(date-1)` |
| **Trigger** | Create or save debtor |
| **Enforcement** | CreateDebtor/SaveDebtor/UpdateDebtors |
| **Outcome** | Statement baseline set |
| **Operation(s)** | GetDebtors |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — CreateDebtor/SaveDebtor/UpdateDebtors* |

---

## SVC-BR-COL-007 For POL/FPOL, choosing the default mailing location stores LocID as null

| Field | Value |
| --- | --- |
| **Statement** | For POL/FPOL, choosing the default mailing location stores LocID as null |
| **Trigger** | UpdateDebtors |
| **Enforcement** | UpdateDebtors |
| **Outcome** | Null LocID |
| **Operation(s)** | UpdateDebtors |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — UpdateDebtors* |

---

## SVC-BR-COL-008 A note can be edited until 2 working days after it was created

| Field | Value |
| --- | --- |
| **Statement** | A note can be edited until 2 working days after it was created |
| **Trigger** | Note read |
| **Enforcement** | GetNotes/GetNote |
| **Outcome** | CanEdit flag |
| **Operation(s)** | Notes |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GetNotes/GetNote* |

---

## SVC-BR-COL-009 Appended note text gets a 'ADDED date by USER' annotation

| Field | Value |
| --- | --- |
| **Statement** | Appended note text gets a "*ADDED date by USER*" annotation |
| **Trigger** | SaveNote |
| **Enforcement** | SaveNote |
| **Outcome** | Text appended |
| **Operation(s)** | SaveNote |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — SaveNote* |

---

## SVC-BR-COL-010 Optimistic concurrency on UpdateNum - 'Error - This record has been updated by someone else.'

| Field | Value |
| --- | --- |
| **Statement** | Optimistic concurrency on UpdateNum: "Error: This record has been updated by someone else." |
| **Trigger** | Save request or transaction |
| **Enforcement** | SaveRequest/SaveTransaction |
| **Outcome** | Rejected |
| **Operation(s)** | SaveNote |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — SaveRequest/SaveTransaction* |

---

## SVC-BR-COL-011 County C7 means state WA, otherwise OR. County list = OR plus synthetic C7

| Field | Value |
| --- | --- |
| **Statement** | County C7 means state WA, otherwise OR. County list = OR plus synthetic C7 |
| **Trigger** | SaveRequest |
| **Enforcement** | SaveRequest/GetCountyCodes |
| **Outcome** | State set |
| **Operation(s)** | SaveNote |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — SaveRequest/GetCountyCodes* |

---

## SVC-BR-COL-012 New Claim case - one debtor linked to the claim worker

| Field | Value |
| --- | --- |
| **Statement** | New Claim case: one debtor linked to the claim worker |
| **Trigger** | New case |
| **Enforcement** | GenerateClaimDebtor |
| **Outcome** | Debtor created |
| **Operation(s)** | SaveRequest |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GenerateClaimDebtor* |

---

## SVC-BR-COL-013 New CPOL case: one generic debtor. Other policy codes: one debtor per active type "1" business affiliate

| Field | Value |
| --- | --- |
| **Statement** | New CPOL case: one generic debtor. Other policy codes: one debtor per active type "1" business affiliate |
| **Trigger** | New case |
| **Enforcement** | GeneratePolicyDebtor |
| **Outcome** | Debtors created |
| **Operation(s)** | SaveRequest |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GeneratePolicyDebtor* |

---

## SVC-BR-COL-014 THRD - third parties that have a Person. CTHRD - third parties with no Person

| Field | Value |
| --- | --- |
| **Statement** | THRD: third parties that have a Person. CTHRD: third parties with no Person |
| **Trigger** | New case |
| **Enforcement** | GenerateThirdPartyDebtor |
| **Outcome** | Debtors created |
| **Operation(s)** | SaveRequest |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GenerateThirdPartyDebtor* |

---

## SVC-BR-COL-015 FOTH cases get no automatic debtors. Generated debtors are held and not on SOIL

| Field | Value |
| --- | --- |
| **Statement** | FOTH cases get no automatic debtors. Generated debtors are held and not on SOIL |
| **Trigger** | New case |
| **Enforcement** | GenerateDebtors |
| **Outcome** | — |
| **Operation(s)** | SaveRequest |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GenerateDebtors* |

---

## SVC-BR-COL-016 Search wildcards: StartsWith → x%, otherwise %x%. A missing first or last name becomes %

| Field | Value |
| --- | --- |
| **Statement** | Search wildcards: StartsWith → `x%`, otherwise `%x%`. A missing first or last name becomes `%` |
| **Trigger** | Search |
| **Enforcement** | GetSearchCriteria |
| **Outcome** | Search pattern |
| **Operation(s)** | GetSearchResults |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GetSearchCriteria* |

---

## SVC-BR-COL-017 Search results limited to 300

| Field | Value |
| --- | --- |
| **Statement** | Search results limited to 300 |
| **Trigger** | Search |
| **Enforcement** | GetSearchResults |
| **Outcome** | Truncated |
| **Operation(s)** | GetSearchResults |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GetSearchResults* |

---

## SVC-BR-COL-018 Manual collection tasks - TaskUser 'SYSTEM', COLL/COLL/NONE/MED. Context is the policy or the claim

| Field | Value |
| --- | --- |
| **Statement** | Manual collection tasks: TaskUser "SYSTEM", COLL/COLL/NONE/MED. Context is the policy or the claim |
| **Trigger** | CreateTask |
| **Enforcement** | CreateTask |
| **Outcome** | Task created |
| **Operation(s)** | CreateTask |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — CreateTask* |

---

## SVC-BR-COL-019 Task list - source COLL, not deleted, first 300 by date descending

| Field | Value |
| --- | --- |
| **Statement** | Task list: source COLL, not deleted, first 300 by date descending |
| **Trigger** | GetTasks |
| **Enforcement** | GetTasks |
| **Outcome** | — |
| **Operation(s)** | GetTasks, GetTasksForPdf |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GetTasks* |

---

## SVC-BR-COL-020 A transaction can't be edited if it is on or before the last statement, has a PaymentRef, has PayDownOrder 0, or is system generated

| Field | Value |
| --- | --- |
| **Statement** | A transaction can't be edited if it is on or before the last statement, has a PaymentRef, has PayDownOrder 0, or is system generated |
| **Trigger** | GetTransactions |
| **Enforcement** | GetTransactions |
| **Outcome** | CanEdit=false |
| **Operation(s)** | GetTransactions |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GetTransactions* |

---

## SVC-BR-COL-021 Inserting a transaction with PayDownOrder 0 (payment) lowers the balance; any other category raises it

| Field | Value |
| --- | --- |
| **Statement** | Inserting a transaction with PayDownOrder 0 (payment) lowers the balance; any other category raises it |
| **Trigger** | InsertTransaction |
| **Enforcement** | InsertTransaction |
| **Outcome** | Balance changed |
| **Operation(s)** | InsertTransaction |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — InsertTransaction* |

---

## SVC-BR-COL-022 After an insert, CollectionsRepo.ApplyPayments(caseId, date) runs

| Field | Value |
| --- | --- |
| **Statement** | After an insert, `CollectionsRepo.ApplyPayments(caseId, date)` runs |
| **Trigger** | Insert or cash batch |
| **Enforcement** | InsertTransaction, ProcessBatch |
| **Outcome** | Outstanding amounts re-applied |
| **Operation(s)** | InsertTransaction |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — InsertTransaction, ProcessBatch* |

---

## SVC-BR-COL-023 ApprovedByUser is cleared when the code doesn't require approval

| Field | Value |
| --- | --- |
| **Statement** | ApprovedByUser is cleared when the code doesn't require approval |
| **Trigger** | Save or insert |
| **Enforcement** | Save/InsertTransaction |
| **Outcome** | — |
| **Operation(s)** | InsertTransaction |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — Save/InsertTransaction* |

---

## SVC-BR-COL-024 Interest allowed only when PayDownOrder ≠ 0

| Field | Value |
| --- | --- |
| **Statement** | Interest allowed only when PayDownOrder ≠ 0 |
| **Trigger** | Codes lookup |
| **Enforcement** | GetTransactionCodes |
| **Outcome** | Flag |
| **Operation(s)** | — |
| **Source** | `Services/SAIF.Services/Collections/CollectionsService.cs` — GetTransactionCodes* |

---

## SVC-BR-COL-025 Activity: "Error: Activity date must be greater than 01/01/1982 and no more than 7 days in the future." (exclusive between 1982-01-01 and Today+7)

| Field | Value |
| --- | --- |
| **Statement** | Activity: "Error: Activity date must be greater than 01/01/1982 and no more than 7 days in the future." (exclusive between 1982-01-01 and Today+7) |
| **Trigger** | Validate |
| **Enforcement** | ActivityValidator |
| **Outcome** | Error |
| **Operation(s)** | SaveRequest |
| **Source** | `Services/SAIF.Services/Collections/Validators/ActivityValidator.cs` — ActivityValidator |

---

## SVC-BR-COL-026 'Error - Activity type is required.'

| Field | Value |
| --- | --- |
| **Statement** | "Error: Activity type is required." |
| **Trigger** | Validate |
| **Enforcement** | ActivityValidator |
| **Outcome** | Error |
| **Operation(s)** | SaveRequest |
| **Source** | `Services/SAIF.Services/Collections/Validators/ActivityValidator.cs` — ActivityValidator |

---

## SVC-BR-COL-027 'Error - Activity amount must be between zero and one million.' (exclusive)

| Field | Value |
| --- | --- |
| **Statement** | "Error: Activity amount must be between zero and one million." (exclusive) |
| **Trigger** | Validate |
| **Enforcement** | ActivityValidator |
| **Outcome** | Error |
| **Operation(s)** | SaveRequest |
| **Source** | `Services/SAIF.Services/Collections/Validators/ActivityValidator.cs` — ActivityValidator |

---

## SVC-BR-COL-028 Task - 'Error - A valid case number is required.' (case must exist)

| Field | Value |
| --- | --- |
| **Statement** | Task: "Error: A valid case number is required." (case must exist) |
| **Trigger** | Validate |
| **Enforcement** | CollectionTaskValidator |
| **Outcome** | Error |
| **Operation(s)** | Create/SaveTask |
| **Source** | `Services/SAIF.Services/Collections/Validators/CollectionTaskValidator.cs` — CollectionTaskValidator |

---

## SVC-BR-COL-029 "Error: Due date must be between today and one year in the future." (inclusive), plus base TaskValidator rules (SVC-BR-MSC-060/061)

| Field | Value |
| --- | --- |
| **Statement** | "Error: Due date must be between today and one year in the future." (inclusive), plus base TaskValidator rules (SVC-BR-MSC-060/061) |
| **Trigger** | Validate |
| **Enforcement** | CollectionTaskValidator |
| **Outcome** | Error |
| **Operation(s)** | Create/SaveTask |
| **Source** | `Services/SAIF.Services/Collections/Validators/CollectionTaskValidator.cs` — CollectionTaskValidator |

---

## SVC-BR-COL-030 "Error: First name is required." / "Error: Last name is required." when there is no Case or the case is FOTH

| Field | Value |
| --- | --- |
| **Statement** | "Error: First name is required." / "Error: Last name is required." when there is no Case or the case is FOTH |
| **Trigger** | Validate |
| **Enforcement** | DebtorValidator |
| **Outcome** | Error |
| **Operation(s)** | Create/Save/UpdateDebtor(s) |
| **Source** | `Services/SAIF.Services/Collections/Validators/DebtorValidator.cs` — DebtorValidator |

---

## SVC-BR-COL-031 'Error - A valid SSN is required when including on SOIL.' (11 characters when IsIncludedOnSoil)

| Field | Value |
| --- | --- |
| **Statement** | "Error: A valid SSN is required when including on SOIL." (11 characters when IsIncludedOnSoil) |
| **Trigger** | Validate |
| **Enforcement** | DebtorValidator |
| **Outcome** | Error |
| **Operation(s)** | Create/Save/UpdateDebtor(s) |
| **Source** | `Services/SAIF.Services/Collections/Validators/DebtorValidator.cs` — DebtorValidator |

---

## SVC-BR-COL-032 Length limits: first name 20 ("Error: First name cannot be more than 20 characters."), last name 25, middle initial 1, suffix 3 (matching messages)

| Field | Value |
| --- | --- |
| **Statement** | Length limits: first name 20 ("Error: First name cannot be more than 20 characters."), last name 25, middle initial 1, suffix 3 (matching messages) |
| **Trigger** | Validate |
| **Enforcement** | DebtorValidator |
| **Outcome** | Error |
| **Operation(s)** | Create/Save/UpdateDebtor(s) |
| **Source** | `Services/SAIF.Services/Collections/Validators/DebtorValidator.cs` — DebtorValidator |

---

## SVC-BR-COL-033 Note - 'Error - Text is required.' (NoteText not null)

| Field | Value |
| --- | --- |
| **Statement** | Note: "Error: Text is required." (NoteText not null) |
| **Trigger** | Validate |
| **Enforcement** | NoteValidator |
| **Outcome** | Error |
| **Operation(s)** | Create/SaveNote |
| **Source** | `Services/SAIF.Services/Collections/Validators/NoteValidator.cs` — NoteValidator |

---

## SVC-BR-COL-034 "Error: Text must be greater than three characters and no more than 4000." (4–4000 when AppendText is null)

| Field | Value |
| --- | --- |
| **Statement** | "Error: Text must be greater than three characters and no more than 4000." (4–4000 when AppendText is null) |
| **Trigger** | Validate |
| **Enforcement** | NoteValidator |
| **Outcome** | Error |
| **Operation(s)** | Create/SaveNote |
| **Source** | `Services/SAIF.Services/Collections/Validators/NoteValidator.cs` — NoteValidator |

---

## SVC-BR-COL-035 AppendText required when CanEdit is false - 'Error - Text is required.'

| Field | Value |
| --- | --- |
| **Statement** | AppendText required when CanEdit is false: "Error: Text is required." |
| **Trigger** | Validate |
| **Enforcement** | NoteValidator |
| **Outcome** | Error |
| **Operation(s)** | SaveNote |
| **Source** | `Services/SAIF.Services/Collections/Validators/NoteValidator.cs` — NoteValidator |

---

## SVC-BR-COL-036 'Error - Combined text may not be more than 4000 characters.'

| Field | Value |
| --- | --- |
| **Statement** | "Error: Combined text may not be more than 4000 characters." |
| **Trigger** | Validate |
| **Enforcement** | NoteValidator |
| **Outcome** | Error |
| **Operation(s)** | SaveNote |
| **Source** | `Services/SAIF.Services/Collections/Validators/NoteValidator.cs` — NoteValidator |

---

## SVC-BR-COL-037 Request: "Error: Collection type is required.", "Error: Case status is required.", "Error: County is required.", "Error: Credit representative is required.", "Error: Judgment Years is required.", "Error: Interest Rate is required."

| Field | Value |
| --- | --- |
| **Statement** | Request: "Error: Collection type is required.", "Error: Case status is required.", "Error: County is required.", "Error: Credit representative is required.", "Error: Judgment Years is required.", "Error: Interest Rate is required." |
| **Trigger** | Validate |
| **Enforcement** | RequestValidator |
| **Outcome** | Error |
| **Operation(s)** | SaveRequest |
| **Source** | `Services/SAIF.Services/Collections/Validators/RequestValidator.cs` — RequestValidator |

---

## SVC-BR-COL-038 "Error: A valid policy number is required." (codes containing POL, checked with ValidateContext); "Error: A valid claim number is required." (other codes)

| Field | Value |
| --- | --- |
| **Statement** | "Error: A valid policy number is required." (codes containing POL, checked with ValidateContext); "Error: A valid claim number is required." (other codes) |
| **Trigger** | Validate |
| **Enforcement** | RequestValidator |
| **Outcome** | Error |
| **Operation(s)** | SaveRequest |
| **Source** | `Services/SAIF.Services/Collections/Validators/RequestValidator.cs` — RequestValidator |

---

## SVC-BR-COL-039 "Error: Request date must be greater than 1/1/1982 and no more than 7 days in the future." (the code actually uses 1980-01-01)

| Field | Value |
| --- | --- |
| **Statement** | "Error: Request date must be greater than 1/1/1982 and no more than 7 days in the future." (the code actually uses 1980-01-01) |
| **Trigger** | Validate |
| **Enforcement** | RequestValidator |
| **Outcome** | Error |
| **Operation(s)** | SaveRequest |
| **Source** | `Services/SAIF.Services/Collections/Validators/RequestValidator.cs` — RequestValidator |

---

## SVC-BR-COL-039a Transaction - "Date can only be after the last statement date and up to 7 days in the future." (when CanEdit; if there's no statement, after 1980-01-01); "Transaction type is required."; "Approved by name required for selected type."; "Reference # may be up to 30 characters in length."; "Transaction amount must be between zero and one million."

| Field | Value |
| --- | --- |
| **Statement** | Transaction: "Date can only be after the last statement date and up to 7 days in the future." (when CanEdit; if there's no statement, after 1980-01-01); "Transaction type is required."; "Approved by name required for selected type."; "Reference # may be up to 30 characters in length."; "Transaction amount must be between zero and one million." |
| **Trigger** | Validate |
| **Enforcement** | TransactionValidator |
| **Outcome** | Error |
| **Operation(s)** | Save/InsertTransaction |
| **Source** | `Services/SAIF.Services/Collections/Validators/TransactionValidator.cs` — TransactionValidator |

---

## SVC-BR-COL-040 No unbalanced batches for the run date → report only, return code 6

| Field | Value |
| --- | --- |
| **Statement** | No unbalanced batches for the run date → report only, return code 6 |
| **Trigger** | Cash receipts batch |
| **Enforcement** | ApplyCashReceipts |
| **Outcome** | RC 6 |
| **Operation(s)** | ApplyCashReceipts |
| **Source** | `Services/SAIF.Services/Collections/Validators/TransactionValidator.cs` — ApplyCashReceipts* |

---

## SVC-BR-COL-041 Any batch that doesn't balance → return code 5

| Field | Value |
| --- | --- |
| **Statement** | Any batch that doesn't balance → return code 5 |
| **Trigger** | Cash receipts batch |
| **Enforcement** | ApplyCashReceipts |
| **Outcome** | RC 5 |
| **Operation(s)** | ApplyCashReceipts |
| **Source** | `Services/SAIF.Services/Collections/Validators/TransactionValidator.cs` — ApplyCashReceipts* |

---

## SVC-BR-COL-042 A batch must match BatchCount and BatchAmount, or its postings are rolled back

| Field | Value |
| --- | --- |
| **Statement** | A batch must match BatchCount and BatchAmount, or its postings are rolled back |
| **Trigger** | ProcessBatch |
| **Enforcement** | ProcessBatch |
| **Outcome** | Rollback |
| **Operation(s)** | ApplyCashReceipts |
| **Source** | `Services/SAIF.Services/Collections/Validators/TransactionValidator.cs` — ProcessBatch* |

---

## SVC-BR-COL-043 Each receipt creates a system "Payment" transaction (user LCB0009), lowers the balance and is marked processed Y. The batch is marked balanced Y

| Field | Value |
| --- | --- |
| **Statement** | Each receipt creates a system "Payment" transaction (user LCB0009), lowers the balance and is marked processed Y. The batch is marked balanced Y |
| **Trigger** | ProcessBatch |
| **Enforcement** | ProcessBatch |
| **Outcome** | Posted |
| **Operation(s)** | ApplyCashReceipts |
| **Source** | `Services/SAIF.Services/Collections/Validators/TransactionValidator.cs` — ProcessBatch* |

---

## SVC-BR-COL-044 Report groups - fraud (WRKR/FPOL/FOTH) and third party (THRD/CTHRD)

| Field | Value |
| --- | --- |
| **Statement** | Report groups: fraud (WRKR/FPOL/FOTH) and third party (THRD/CTHRD) |
| **Trigger** | Report |
| **Enforcement** | GenerateReport |
| **Outcome** | PDF LCB0009 |
| **Operation(s)** | ApplyCashReceipts |
| **Source** | `Services/SAIF.Services/Collections/Validators/TransactionValidator.cs` — GenerateReport* |

---

## SVC-BR-COL-045 Interest = amount returned by GetInterest. It's added to the balance as an INT system transaction ref "LCB00003" dated runDate

| Field | Value |
| --- | --- |
| **Statement** | Interest = amount returned by `GetInterest`. It's added to the balance as an INT system transaction ref "LCB00003" dated runDate |
| **Trigger** | Interest batch |
| **Enforcement** | CalculateInterest |
| **Outcome** | Balance increased |
| **Operation(s)** | CalculateInterest |
| **Source** | `Services/SAIF.Services/Collections/Validators/TransactionValidator.cs` — CalculateInterest* |

---

## SVC-BR-COL-046 Interest report (PDF LCB0003) is always emailed, including in report-only mode, before posting

| Field | Value |
| --- | --- |
| **Statement** | Interest report (PDF LCB0003) is always emailed, including in report-only mode, before posting |
| **Trigger** | Interest batch |
| **Enforcement** | SendReport |
| **Outcome** | Email |
| **Operation(s)** | CalculateInterest |
| **Source** | `Services/SAIF.Services/Collections/Validators/TransactionValidator.cs` — SendReport* |

---

## SVC-BR-COL-050 to 056 Task generation rules (see 1.4)

| Field | Value |
| --- | --- |
| **Statement** | Task generation rules (see 1.4) |
| **Trigger** | Batch |
| **Enforcement** | GenerateTasksService |
| **Outcome** | Tasks created |
| **Operation(s)** | BatchTasks |
| **Source** | `Services/SAIF.Services/Collections/GenerateTasksService.cs` — GenerateTasksService |

---

## SVC-BR-COL-060 to 064 SOIL rules (see 1.5)

| Field | Value |
| --- | --- |
| **Statement** | SOIL rules (see 1.5) |
| **Trigger** | Batch |
| **Enforcement** | SoilService |
| **Outcome** | Files and tables |
| **Operation(s)** | SOIL operations |
| **Source** | `Services/SAIF.Services/Collections/SoilService.cs` — SoilService |

---

## Documents

## SVC-BR-DOC-001 Template must exist - 'Error - Template does not exist.'

| Field | Value |
| --- | --- |
| **Statement** | Template must exist: "Error: Template does not exist." |
| **Trigger** | submit |
| **Enforcement** | DocumentRequestService L591 |
| **Outcome** | exception |
| **Operation(s)** | SubmitDocumentRequest |
| **Source** | `Services/SAIF.Services/Documents/DocumentRequestService.cs` — DocumentRequestService L591 |

---

## SVC-BR-DOC-002 Request status must exist in DocRequestLogStatusCode - 'This request status is invalid - {s}.'

| Field | Value |
| --- | --- |
| **Statement** | Request status must exist in DocRequestLogStatusCode: "This request status is invalid - {s}." |
| **Trigger** | update |
| **Enforcement** | L558-561 |
| **Outcome** | exception |
| **Operation(s)** | UpdateRequestStatus |
| **Source** | `Services/SAIF.Services/Documents/DocumentRequestService.cs` — L558-561* |

---

## SVC-BR-DOC-003 Request must exist - 'This document request does not exist[ - id].'

| Field | Value |
| --- | --- |
| **Statement** | Request must exist: "This document request does not exist[ - id]." |
| **Trigger** | update |
| **Enforcement** | L543, 570 |
| **Outcome** | exception |
| **Operation(s)** | SetRequestAsComplete, UpdateRequestStatus |
| **Source** | `Services/SAIF.Services/Documents/DocumentRequestService.cs` — L543, 570* |

---

## SVC-BR-DOC-004 Distribution log must exist - 'This document distribution does not exist - {id}.'

| Field | Value |
| --- | --- |
| **Statement** | Distribution log must exist: "This document distribution does not exist - {id}." |
| **Trigger** | update |
| **Enforcement** | L335, 354, 368 |
| **Outcome** | exception |
| **Operation(s)** | UpdateStatus / UpdateXml / UpdateCompleted |
| **Source** | `Services/SAIF.Services/Documents/DocumentRequestService.cs` — L335, 354, 368* |

---

## SVC-BR-DOC-010 A VOC coordinator is needed when a request parameter has DataType 'SELECTVOC'

| Field | Value |
| --- | --- |
| **Statement** | A VOC coordinator is needed when a request parameter has DataType "SELECTVOC" |
| **Trigger** | param |
| **Enforcement** | DocumentParameterService L221-223 |
| **Outcome** | bool |
| **Operation(s)** | NeedVocCoordinators |
| **Source** | `Services/SAIF.Services/Documents/DocumentParameterService.cs` — DocumentParameterService L221-223 |

---

## SVC-BR-DOC-020 Users with DocCenterDevAdmin or DocCenterProdAdmin see all templates; others get a filtered set

| Field | Value |
| --- | --- |
| **Statement** | Users with DocCenterDevAdmin or DocCenterProdAdmin see all templates; others get a filtered set |
| **Trigger** | search |
| **Enforcement** | TemplateSearchService L58-66 |
| **Outcome** | filter |
| **Operation(s)** | template searches |
| **Source** | `Services/SAIF.Services/Documents/TemplateSearchService.cs` — TemplateSearchService L58-66 |

---

## SVC-BR-DOC-021 Template must exist - 'That document template does not exist.'

| Field | Value |
| --- | --- |
| **Statement** | Template must exist: "That document template does not exist." |
| **Trigger** | delete/disable/sql |
| **Enforcement** | L899, 919, 951 |
| **Outcome** | exception |
| **Operation(s)** | Delete/Disable/GetDocumentSqlLines |
| **Source** | `Services/SAIF.Services/Documents/TemplateSearchService.cs` — L899, 919, 951* |

---

## SVC-BR-DOC-022 Create/Update template validation - the first error message is thrown

| Field | Value |
| --- | --- |
| **Statement** | Create/Update template validation: the first error message is thrown |
| **Trigger** | save |
| **Enforcement** | L353-355, 706-708 |
| **Outcome** | Exception |
| **Operation(s)** | Create/UpdateTemplate |
| **Source** | `Services/SAIF.Services/Documents/TemplateSearchService.cs` — L353-355, 706-708* |

---

## Miscellaneous

## SVC-BR-MSC-001 Demo users see producer and agent names as 'Producer'

| Field | Value |
| --- | --- |
| **Statement** | Demo users see producer and agent names as "Producer" |
| **Trigger** | GetAgency |
| **Enforcement** | AgencyService.GetAgency |
| **Outcome** | Masked |
| **Operation(s)** | GetAgency and callers |
| **Source** | `Services/SAIF.Services/Agencies/AgencyService.cs` — AgencyService.GetAgency |

---

## SVC-BR-MSC-002 Search result ordering

| Field | Value |
| --- | --- |
| **Statement** | Search result ordering |
| **Trigger** | Search |
| **Enforcement** | GetAgencySearchResults |
| **Outcome** | Sorted, Take(maxHits) |
| **Operation(s)** | — |
| **Source** | `Services/SAIF.Services/Agencies/AgencyService.cs` — GetAgencySearchResults* |

---

## SVC-BR-MSC-003 Paperless agency with no active external users → reverting

| Field | Value |
| --- | --- |
| **Statement** | Paperless agency with no active external users → reverting |
| **Trigger** | Batch (inferred) |
| **Enforcement** | GetRevertingAgencies |
| **Outcome** | List |
| **Operation(s)** | — |
| **Source** | `Services/SAIF.Services/Agencies/AgencyService.cs` — GetRevertingAgencies* |

---

## SVC-BR-MSC-004 In production, test users and production test users don't count as active

| Field | Value |
| --- | --- |
| **Statement** | In production, test users and production test users don't count as active |
| **Trigger** | Status check |
| **Enforcement** | GetAgencyActiveUserStatus |
| **Outcome** | Filter |
| **Operation(s)** | GetRevertingAgencies |
| **Source** | `Services/SAIF.Services/Agencies/AgencyService.cs` — GetAgencyActiveUserStatus* |

---

## SVC-BR-MSC-005 Notification emails only for opted-in, active, non-deleted users with an email address

| Field | Value |
| --- | --- |
| **Statement** | Notification emails only for opted-in, active, non-deleted users with an email address |
| **Trigger** | Notification |
| **Enforcement** | GetEmailListFor* |
| **Outcome** | Email list |
| **Operation(s)** | — |
| **Source** | `Services/SAIF.Services/Agencies/AgencyService.cs` — GetEmailListFor** |

---

## SVC-BR-MSC-006 Paperless confirmation: email plus image of the email plus image of the agreement in AGENCY / "AG - ADMINISTRATION"

| Field | Value |
| --- | --- |
| **Statement** | Paperless confirmation: email plus image of the email plus image of the agreement in AGENCY / "AG - ADMINISTRATION" |
| **Trigger** | Confirmation |
| **Enforcement** | ProcessConfirmationEmail |
| **Outcome** | Docs imaged |
| **Operation(s)** | — |
| **Source** | `Services/SAIF.Services/Agencies/AgencyService.cs` — ProcessConfirmationEmail* |

---

## SVC-BR-MSC-007 Agency image description ≤ 256: "Error: Description may not be more than 256 characters."; "Error: Category is required."; "Error: Type is required."

| Field | Value |
| --- | --- |
| **Statement** | Agency image description ≤ 256: "Error: Description may not be more than 256 characters."; "Error: Category is required."; "Error: Type is required." |
| **Trigger** | EditImage |
| **Enforcement** | `Agencies/Imaging/Validators/ImageEditValidator.cs` |
| **Outcome** | Error |
| **Operation(s)** | EditImage |
| **Source** | `Services/SAIF.Services/Agencies/Imaging/Validators/ImageEditValidator.cs` — `Agencies/Imaging/Validators/ImageEditValidator.cs` |

---

## SVC-BR-MSC-010 Image security filter - deleted images need AgencyImagingDeleted; SecurityLevel ≠ 0 needs AgencyImagingConfidential

| Field | Value |
| --- | --- |
| **Statement** | Image security filter: deleted images need AgencyImagingDeleted; SecurityLevel ≠ 0 needs AgencyImagingConfidential |
| **Trigger** | Image read |
| **Enforcement** | GetImageAgency/GetImageAgencies |
| **Outcome** | Hidden |
| **Operation(s)** | GetImage(s), EditImage, DeleteImage |
| **Source** | `Services/SAIF.Services/Agencies/Imaging/Validators/ImageEditValidator.cs` — GetImageAgency/GetImageAgencies* |

---

## SVC-BR-MSC-011 Editing an image needs AgencyImagingEdit

| Field | Value |
| --- | --- |
| **Statement** | Editing an image needs AgencyImagingEdit |
| **Trigger** | EditImage |
| **Enforcement** | EditImage |
| **Outcome** | Error |
| **Operation(s)** | EditImage |
| **Source** | `Services/SAIF.Services/Agencies/Imaging/Validators/ImageEditValidator.cs` — EditImage* |

---

## SVC-BR-MSC-020 Group image list is filtered by the confidential and deleted roles

| Field | Value |
| --- | --- |
| **Statement** | Group image list is filtered by the confidential and deleted roles |
| **Trigger** | GetImages |
| **Enforcement** | ImageService.CreateGroupImageRepositoryFilter, then the repository |
| **Outcome** | Hidden |
| **Operation(s)** | GetImages |
| **Source** | `Services/SAIF.Services/Claims/Imaging/ImageService.cs` — ImageService.CreateGroupImageRepositoryFilter, then the repository* |

---

## SVC-BR-MSC-021 'Error - User not authorized to edit images.' (GroupImagingEdit)

| Field | Value |
| --- | --- |
| **Statement** | "Error: User not authorized to edit images." (GroupImagingEdit) |
| **Trigger** | Update |
| **Enforcement** | `Groups/Imaging/Validators/ImageEditValidator.cs` |
| **Outcome** | Throws |
| **Operation(s)** | UpdateImage |
| **Source** | `Services/SAIF.Services/Groups/Imaging/Validators/ImageEditValidator.cs` — `Groups/Imaging/Validators/ImageEditValidator.cs` |

---

## SVC-BR-MSC-022 'Error - Image could not be found.'

| Field | Value |
| --- | --- |
| **Statement** | "Error: Image could not be found." |
| **Trigger** | Update/Delete |
| **Enforcement** | ImageEditValidator, ImageDeleteValidator |
| **Outcome** | Throws |
| **Operation(s)** | Update/DeleteImage |
| **Source** | `Services/SAIF.Services/Groups/Imaging/Validators/ImageEditValidator.cs` — ImageEditValidator, ImageDeleteValidator* |

---

## SVC-BR-MSC-023 'Error - Image updated by another user.' (UpdateDate must equal the stored value)

| Field | Value |
| --- | --- |
| **Statement** | "Error: Image updated by another user." (UpdateDate must equal the stored value) |
| **Trigger** | Update |
| **Enforcement** | ImageEditValidator |
| **Outcome** | Throws |
| **Operation(s)** | UpdateImage |
| **Source** | `Services/SAIF.Services/Groups/Imaging/Validators/ImageEditValidator.cs` — ImageEditValidator* |

---

## SVC-BR-MSC-024 "Error: Description may not be more than {Image.MaxDescriptionLength} characters."; "Error: Category is required."; "Error: Type is required."; "Error: Type not found."; "Error: Group could not be found."

| Field | Value |
| --- | --- |
| **Statement** | "Error: Description may not be more than {Image.MaxDescriptionLength} characters."; "Error: Category is required."; "Error: Type is required."; "Error: Type not found."; "Error: Group could not be found." |
| **Trigger** | Update |
| **Enforcement** | ImageEditValidator |
| **Outcome** | Throws |
| **Operation(s)** | UpdateImage |
| **Source** | `Services/SAIF.Services/Groups/Imaging/Validators/ImageEditValidator.cs` — ImageEditValidator* |

---

## SVC-BR-MSC-025 Delete doesn't require the edit or delete role (the validator only checks that the image exists)

| Field | Value |
| --- | --- |
| **Statement** | Delete doesn't require the edit or delete role (the validator only checks that the image exists) |
| **Trigger** | Delete |
| **Enforcement** | ImageDeleteValidator |
| **Outcome** | — |
| **Operation(s)** | DeleteImage |
| **Source** | `Services/SAIF.Services/Groups/Imaging/Validators/ImageDeleteValidator.cs` — ImageDeleteValidator |

---

## Notes
- Rules whose Statement, Trigger, Enforcement, or Outcome text says "same" in the source analysis have been resolved to the nearest preceding concrete value in this catalog for readability.
- Delegated rules referenced by area introductions (`DOM-BR-*`) are catalogued in the `saif-domain` library documentation, not duplicated here.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Configuration](configuration.md)
- [Operations and processes](operations-processes.md)
- [Security and authorization](security-authorization.md)
- [Database tables](database-tables.md)
- [SQL catalog](sql/index.md)
- [API reference](api/index.md)

## Sources
- `Services/SAIF.Services/`
