Skip to content

NoteService

Implements INoteService for agency notepad entries, coordinating retrieval, filtering, adding, appending, editing, and deleting notes attached to agencies (AgencyNote/Notepad), returning outcomes and errors through a caller-supplied IMessageContainer rather than throwing. It depends on IUnitOfWork for repository access and transactions, IValidationService for FluentValidation-based edit validation, IUserProfileService for current-user identity and role checks, and IWorkCalendarService to compute the "two work days ago" cutoff that gates edit/delete/append permissions. Its static constructor registers AutoMapper maps for AgencyNote/Notepad→Note and reuses AgenciesMappingHelper.CreateAgencyMap().

Purpose

  • Retrieves a single note or all notes for an agency, filtering out confidential notes unless the current user is authorized to see them.
  • Adds a new note (as the current user or, via AddNoteBySystem, attributed to "SYSTEM"), enforcing edit authorization (for the user-attributed path) and validation.
  • Appends text to an existing note (only allowed once the note is older than two work days) or edits a note's text directly (only allowed within two work days of creation), enforcing optimistic-concurrency checks and optional producer association.
  • Deletes a note, allowing unrestricted deletion for super-delete users and time-limited deletion (within two work days) for regular edit users.
  • Reports whether the current user can add notes or see confidential notes, and returns the available note categories.

Context

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

Public members

Member Signature Purpose
NoteService(...) public NoteService(IUnitOfWork unitOfWork, IValidationService validationService, IUserProfileService userProfileService, IWorkCalendarService workCalendarService) Validates all four collaborators are non-null and stores them for use by every other member.
CanUserAddNote public bool CanUserAddNote { get; } Returns whether the current user is authorized to add notes (same check used to gate AddNote/AppendNote/EditNote).
CanUserSeeConfidentialNotes public bool CanUserSeeConfidentialNotes { get; } Returns whether the current user holds the confidential-notes role.
GetNotes(agencyId, criteria) public IEnumerable<Note> GetNotes(long agencyId, NoteFilterCriteria criteria) Returns the agency's notes narrowed by criteria via the shared Filter extension.
GetNotes(agencyId) public IEnumerable<Note> GetNotes(long agencyId) Returns all visible notes for the agency, mapped to Note contracts, each flagged IsProducerNote when a producer is associated.
GetNote public Note GetNote(long noteId) Returns the mapped Note for noteId, or null if not found or the caller lacks confidential-note visibility.
GetCategories public IEnumerable<Category> GetCategories() Returns the note categories scoped to the agency-note context (NotepadContext.AgencyNoteContextCode).
AddNote public long? AddNote(NoteEdit noteEdit, IMessageContainer messages) Adds a new note attributed to the current user if authorized and valid, committing within a transaction; returns the new note ID, or null (with messages populated) on authorization/validation failure.
AddNoteBySystem public long? AddNoteBySystem(NoteEdit noteEdit, IMessageContainer messages) Adds a new note attributed to "SYSTEM" without the edit-authorization check (validation still applies), committing within a transaction; returns the new note ID, or null (with messages populated) on validation failure.
DeleteExpiredNotes public bool DeleteExpiredNotes() Always throws NotImplementedException; this capability is not implemented for agency notes.
DeleteNote public bool DeleteNote(long noteId, IMessageContainer messages) Deletes the note without considering concurrency if found, and if the caller is a super-delete user or the note was created within the last two work days; returns whether the delete succeeded.
EditNote public bool EditNote(long noteId, NoteEdit noteEdit, IMessageContainer messages) Edits an existing note's agency/producer, confidentiality, type, and text (with an "Updated by " suffix) if the caller is authorized, there is no intervening update, the edit window has not passed when text changed, and validation succeeds; returns whether the edit succeeded.
AppendNote public bool AppendNote(long noteId, NoteEdit noteEdit, IMessageContainer messages) Appends new text (with an "Added by " prefix) to an existing note if the caller is authorized, the note is older than two work days, there is no intervening update, and the appended text validates; returns whether the append succeeded.
AppendPrefixTextLength public int AppendPrefixTextLength { get; } Returns the character length of the "Added by " prefix that will be inserted when appending.
EditSuffixTextLength public int EditSuffixTextLength { get; } Returns the character length of the "Updated by " suffix appended when a note's text is edited.

Behavioral notes

  • AddNote, AddNoteBySystem, AppendNote, EditNote, and DeleteNote each wrap their write in unitOfWork.Begin()/Commit(); none explicitly call Rollback() on failure paths, relying instead on returning early before Commit() is reached*.
  • Edit authorization (IsEditUser) is cached per-instance in the isUserAuthorizedToEditNotes nullable field after the first check, so subsequent calls on the same service instance reuse the cached result*.
  • The optimistic-concurrency check compares noteEdit.UpdateDate to the stored Note.UpdateDate and rejects the write with "Error: Another user updated this note." on mismatch.
  • EditNote/AppendNote/AddNote all route note text through .ReplaceUnicodeCharactersWithAscii() before persisting, normalizing non-ASCII characters.
  • DeleteExpiredNotes is unimplemented (throw new NotImplementedException()), so callers must not invoke it in current builds.
  • A sibling type, MoreReadableNoteService, implements the same agency-note operations using thrown NoteServiceExceptions instead of an IMessageContainer result pattern*.

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/Agencies/Notes/NoteService.cs