Skip to content

SubpoenaSaveService

Owns the create/update/approve/disapprove/delete lifecycle for a subpoena and its recipients, translating between the contract Subpoena model and the SAIF.Data.Model.Legal.Subpoenas.Subpoena entity graph. It checks the requesting employee's initiate/approve authority limits via IBillServiceHelper.UserAuthorityLevel before auto-approving a subpoena, computes issue dates via IBillServiceHelper.GetNextIssueDate/IWorkCalendarService.NextWorkDay, and validates the incoming model with IValidationService before any persistence occurs.

Purpose

  • Approves a subpoena automatically when the requesting employee's initiate or approve authority limit covers the highest recipient paid amount, then saves it.
  • Reverts a subpoena to in-progress status and saves it (disapproval).
  • Deletes a subpoena outright when found.
  • Validates and persists a subpoena (new or existing), including optimistic-concurrency checking via UpdateNumber, opposing-counsel address validation, recipient synchronization (add/update/remove, including witness legal-person and address upsert), and issue-date computation — all inside a single transaction.

Context

  • Namespace: SAIF.Services.Legal.Subpoenas
  • Assembly/package: SAIF.Services (packaged inside the SAIF.SAIFCode.Core NuGet package).

Public members

Member Signature Purpose
SubpoenaSaveService (constructor) public SubpoenaSaveService(IUnitOfWork unitOfWork, IUserProfileService userProfileService, IValidationService validationService, IBillServiceHelper billServiceHelper, IWorkCalendarService workCalendarService) Wires the unit of work, current-user profile (captured as an uppercased static _currentUser), the validation service, the authority-limit/issue-date helper, and the work-calendar service; null-checks all five collaborators.
ApproveSubpoena public long ApproveSubpoena(Subpoena subpoena, IMessageContainer messageContainer) Defaults the subpoena to in-progress status if unset, then — if the current employee's initiate or approve authority limit is at least the highest recipient PaidAmount — marks it approved, sets ApprovedByEmployeeId/ApprovedDate to the current employee/today, and delegates to SaveSubpoena to validate and persist; otherwise saves it unapproved. Returns the persisted subpoena's ID, or 0 on validation failure.
DisapproveSubpoena public bool DisapproveSubpoena(Subpoena subpoena, IMessageContainer messageContainer) Sets the subpoena's status to in-progress and saves it via SaveSubpoena, returning true only if the save produced a nonzero ID.
DeleteSubpoena public bool DeleteSubpoena(long subpoenaId, IMessageContainer messageContainer) Looks up the subpoena by ID and, if found, deletes it inside a transaction and returns true; returns false if no matching subpoena exists.
SaveSubpoena public long SaveSubpoena(Subpoena subpoena, IMessageContainer messageContainer) Defaults status (in-progress) and type (medical records) when unset, validates the subpoena (unless already paid) via ValidateSubpoena/IValidationService — returning 0 and adding errors to messageContainer on failure — then within a transaction: rejects with an optimistic-concurrency error if UpdateNumber is stale, rejects if the linked legal case's opposing-counsel firm has no address, copies all subpoena fields onto the data entity (computing issue date via IBillServiceHelper/IWorkCalendarService for approvals and witness types), synchronizes recipients (add/update/remove, including legal-person and address upsert for witness recipients), adds the entity if new, commits, and returns its ID.

Behavioral notes

  • ApproveSubpoena's auto-approval decision compares the recipient's maximum PaidAmount against the current employee's initiate and approve authority limits (IBillServiceHelper.UserAuthorityLevel); if neither limit covers it, the subpoena is saved without approval.
  • SaveSubpoena skips its own ValidateSubpoena call entirely when the subpoena's current status is PaidCode, allowing paid subpoenas to be re-saved (e.g., recipient corrections) without full re-validation.*
  • Recipient synchronization (SaveRecipients) removes data recipients no longer present in the incoming model, then for each incoming recipient short-circuits (continue) unless it is new or HasRecipientChanged detects a material difference, avoiding unnecessary update-user/date stamping.
  • Witness recipients' LegalPerson/LegalPersonAddress records are created via CreateNewLegalPerson for brand-new recipients or people, and updated in place via UpdateLegalPerson otherwise; provider-type recipients instead resolve ProviderLocation/RegisteredAgentLocation by ID.
  • Issue date defaults to IBillServiceHelper.GetNextIssueDate("LS") for every new/updated subpoena, but is recomputed (and pushed forward two work days via IWorkCalendarService.NextWorkDay for witness-type subpoenas) whenever the status transitions to approved.
  • _currentUser is a static field assigned from the constructor's injected IUserProfileService, so it reflects whichever instance was constructed most recently within the process rather than being strictly per-instance state.*

Constraints and usage notes

  • ApproveSubpoena, DisapproveSubpoena, DeleteSubpoena, and SaveSubpoena all throw via Enforce.ArgumentNotNull if messageContainer is null; ApproveSubpoena and SaveSubpoena additionally throw if subpoena is null. DisapproveSubpoena carries a CA1062 suppression acknowledging it does not null-check subpoena itself.
  • SpecialDeliveryText is truncated to at most 1000 characters before being stored.
  • SaveSubpoena rolls back (without committing) and returns 0 both on stale UpdateNumber and on a missing opposing-counsel address, leaving the caller to surface the added messageContainer errors.

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/Subpoenas/SubpoenaSaveService.cs