BillSaveService¶
Owns the create/update/approve/adjust/delete lifecycle for legal bills, validating each request via IValidationService and IBillServiceHelper date rules, resolving the correct approver through ILegalService.DetermineAssignedAttorney and ILegalQueryProvider.GetAttorneyProfile, and persisting changes inside IUnitOfWork transactions with optimistic-concurrency checks on UpdateNumber.
Purpose¶
- Creates and updates legal bills (
SaveBill), reconciling submitted bill-service lines against the database and recording status-history entries on status changes. - Submits a bill for approval (
SubmitBill), resolving the assigned attorney/approver or falling back to in-progress status when none can be determined. - Approves a bill (
ApproveBill) and auto-approves when the resolved approver's payment authority covers the billed amount, or escalates to the approver's manager otherwise (UpdateBillStatusCode). - Approves a bill with changes (
ApproveWithChanges) and returns/disapproves a bill for rework (DisapproveBill). - Creates an adjusted copy of a paid bill for correction (
AdjustBill), carrying forward only changed service lines and building an audit-trail comment describing each change. - Deletes a bill (
DeleteBill), un-amending any parent-bill service lines that referenced it. - Validates a bill and its service lines against date-range and adjustment-reason business rules (
ValidateBill/ValidateBillServices) before allowing a save.
Context¶
- Namespace:
SAIF.Services.Legal.Bills - Assembly/package:
SAIF.Services(packaged inside theSAIF.SAIFCode.CoreNuGet package).
Public members¶
| Member | Signature | Purpose |
|---|---|---|
| BillSaveService (constructor) | public BillSaveService(IUnitOfWork unitOfWork, IUserProfileService userProfileService, IValidationService validationService, ILegalQueryProvider legalQueryProvider, IBillServiceHelper billServiceHelper, ILegalService legalService) |
Wires the unit of work, user-profile, validation, legal-query, bill-service-helper, and legal-service collaborators, and captures the current user ID (as a static field shared across instances). |
| AdjustBill | public long AdjustBill(LegalBill bill, IMessageContainer messageContainer, string newStatus) |
Builds an adjusted copy of the bill (new bill ID, ParentBillId set to the original, only changed service lines retained) and saves it as a new bill; adds a "no changes" error and returns 0 if no service lines changed. |
| ApproveBill | public long ApproveBill(LegalBill bill, IMessageContainer messageContainer) |
Sets approver/approved-date (unless already ApprovedWithChange), determines the resulting status via authority-limit comparison, and saves the bill. |
| ApproveWithChanges | public long ApproveWithChanges(LegalBill bill, IMessageContainer messageContainer) |
Sets approver/approved-date, forces status to ApprovedWithChange, appends an "[APPROVED WITH CHANGES]" comment marker, and saves the bill. |
| DeleteBill | public bool DeleteBill(long billId, IMessageContainer messageContainer) |
Deletes the bill transactionally and, if it was an adjustment of a parent bill, clears the IsAmended flag on the parent's corresponding service lines; returns false if the bill does not exist. |
| DisapproveBill | public long DisapproveBill(LegalBill bill, IMessageContainer messageContainer) |
Clears approver/approved-date, sets status to InProgress, appends a "[Returned by approver]" comment marker, and saves the bill. |
| SaveBill | public long SaveBill(LegalBill bill, IMessageContainer messageContainer) |
Defaults a null bill status to InProgress and saves the bill (insert or update based on bill.Id). |
| SubmitBill | public long SubmitBill(LegalBill bill, IMessageContainer messageContainer) |
Resolves an approver via SetApproverId; if none can be resolved, falls back to a plain SaveBill, otherwise sets status to PendingApproval and saves. |
Behavioral notes¶
SaveLegalBill(the shared private persistence path for all public mutation methods) skips business-rule validation for bills already inPaymentReturned/Paidstatus, but always enforces optimistic concurrency by comparingbill.UpdateNumberagainst the current database value and rolling back with an error if they differ.- New bills get a fresh
BillStatusHistories/BillServicescollection, a create-annotation comment, today's issue date, and a status-history entry; updates append comments via append-annotation formatting and add a new status-history entry only when the status code actually changes. PrepareAdjustedBillForSavecomputes a human-readable comment describing each service-line change (partial return, additional payment, service code change, from/thru date changes) and reverts the new bill toApprovedstatus when the amount was only partially returned or the service code changed without an amount change.UpdateBillStatusCodeauto-approves when either the approver's initiate or approve authority limit covers the billed amount; otherwise it escalates the request to the attorney's manager and appends a note explaining the escalation.ValidateBill/ValidateBillServicescombine FluentValidation results withIBillServiceHelperdate-range checks and adjustment-reason business rules (e.g., a zero-paid, zero-total bill's adjustment reason must be one of duplicate/unknown/free-form).SetApproverIdresolves the assigned attorney viaILegalService.DetermineAssignedAttorney, falling back to the bill's requesting employee, then looks up that attorney's profile; if the attorney profile has an expiration date, the bill is routed to the attorney's manager instead of the attorney.
Constraints and usage notes¶
- Only
unitOfWork,userProfileService,validationService,legalQueryProvider,billServiceHelper, andlegalServiceare null-checked in the constructor viaEnforce.ArgumentNotNull; the constructor also assigns astatic string _currentUserfield, so the "current user" reflects the most recently constructed instance rather than being strictly per-instance.* - All public mutation methods require non-null
billandmessageContainerarguments, enforced viaEnforce.ArgumentNotNull.
Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.
Sources¶
Services/SAIF.Services/Legal/Bills/BillSaveService.cs