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

# LegalNotesService

Owns the create/update/delete lifecycle and printable-report generation for legal case notes, computing per-note edit permissions from the current user's supervisor authorization, note age, and the work-calendar-derived 2-business-day edit window, and persisting changes inside `IUnitOfWork` transactions with optimistic-concurrency checks on `UpdateNumber`.

## Purpose
- Retrieves notes for a case, optionally filtered by date range and category, each annotated with computed `CanEdit`/`CanEditNoteInfo` permissions.
- Creates and updates legal notes (append or full-text replace), validating input via `IValidationService` and rejecting edits from unauthorized users.
- Deletes a note, refusing system-created notes and notes outside the user's edit window/permissions.
- Generates a printable PDF of a filtered note list via `IDocumentService.GeneratePdf`, using an XML report payload.
- Reports whether the current user holds note-update authorization (`LNUpdate`) and returns the list of legal note categories.

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

## Public members
| Member | Signature | Purpose |
| --- | --- | --- |
| LegalNotesService (constructor) | `public LegalNotesService(IUnitOfWork unitOfWork, IUserProfileService userProfileService, IValidationService validationService, IDocumentService documentService, IWorkCalendarService workCalendarService)` | Wires the unit of work, user-profile, validation, document, and work-calendar collaborators (exposed as `protected` fields for subclass reuse), and captures the current user and user ID at construction time. |
| IsUpdateUser | `public bool IsUpdateUser()` | Returns whether the current user holds `LNUpdate` authorization. |
| GetNotes | `public IEnumerable<LegalNote> GetNotes(LegalNoteSearchCriteria criteria)` | Returns notes for the case matching optional from/thru date and category-code filters, each with `CanEdit`/`CanEditNoteInfo` computed; throws `ArgumentNullException` if `criteria.CaseId` is `0`. |
| GetNote | `public LegalNote GetNote(long noteId)` | Returns the single note mapped with computed edit permissions, or `null` if not found. |
| UpdateNote | `public LegalNote UpdateNote(LegalNote note, IMessageContainer messageContainer)` | Validates and updates the note (appending or replacing text, updating category) inside a transaction with an `UpdateNumber` concurrency check; returns an empty `LegalNote` (with an error added) if the user is unauthorized, validation fails, or the record was concurrently modified; throws `Exception` if the note cannot be found. |
| DeleteNote | `public void DeleteNote(long noteId, IMessageContainer messageContainer)` | Deletes the note transactionally after confirming it is not system-created and the current user's computed `CanEdit` permission allows it; adds the corresponding error and returns without deleting otherwise. |
| GetCategories | `public IEnumerable<NoteCategory> GetCategories()` | Returns all legal note categories ordered by description. |
| PrintNotes | `public byte[] PrintNotes(LegalNoteSearchCriteria filter)` | Generates a PDF of the filtered note list via `IDocumentService.GeneratePdf`, using an XML representation built from `GetNotes`. |
| CreateNote | `public LegalNote CreateNote(LegalNote note, IMessageContainer messageContainer)` | Validates and creates a new note tied to the resolved legal case inside a transaction; returns an empty `LegalNote` (with an error added) if the user is unauthorized or validation fails; throws `ArgumentException` if the case cannot be found. |

## Behavioral notes
- A static constructor calls `CreateMappings()`, registering the `LegalNote`/`LegalNoteCategory` AutoMapper mappings and `LegalMappingHelper.MapLegalService()` once per process.
- `SetNoteAccessProperties` computes `CanEdit` as: the note is less than 2 *business* days old (via `IWorkCalendarService.NextWorkDay` applied twice, with a less-than-7-calendar-days pre-filter for performance) **and** the current user is the note's creator or a supervisor (`LNNoteSupervisor`) **and** the note is not system-created.
- `UpdateNote`/`CreateNote` both reject the call up front (before validation or persistence) when the current user is not authorized for `LNUpdate`.
- `UpdateNote` supports append-mode: when `AppendText` is non-blank, the new text is appended (via `AppendNoteText`, with a formatted timestamp/user header) rather than replacing `Text` outright.
- `CleanseNoteText` strips non-ASCII Unicode characters and replaces vertical-tab characters with the platform newline before persisting note text.
- `DeleteNote` refuses to delete a note flagged `IsSystemCreatedNote`, and separately refuses if the note's computed `CanEdit` is `false` (too old or unauthorized), each with a distinct error message.

## Constraints and usage notes
- Only `unitOfWork`, `userProfileService`, `validationService`, and `documentService` are null-checked in the constructor via `Enforce.ArgumentNotNull`; `workCalendarService` is not validated for null.*
- Several protected fields/collaborators (`UnitOfWork`, `UserProfileService`, `ValidationService`, `DocumentService`, `WorkCalendarService`, `CurrentUserId`, `CurrentUser`) are exposed with `protected` accessibility rather than `private`, suggesting the class is designed to be subclassed or extended within the assembly.*

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