=== Summary: 675 files | 7 generated | 484 fresh | 4605 untracked | 4268 adopted | 355 marked | 466 validated-ok | 2+0 stale (sig+body) | 0 skipped | 0 failed | elapsed 11:08:11.442 (40091.44s) ===

This commit is contained in:
julian
2026-06-28 02:50:05 -07:00
parent a19fb90902
commit 586f02a2ca
654 changed files with 5260 additions and 0 deletions
@@ -57,6 +57,7 @@ public class DisplayService(
/// <param name="display">The display to insert. Its <c>DisplayConfigId</c> is assigned from the resolved default configuration.</param>
/// <returns>The inserted <see cref="Display"/> with its <c>DisplayConfigId</c> populated.</returns>
/// <exception cref="NotFoundException">Thrown when no default configuration is found for the specified display type.</exception>
/// <!-- aidoc:v1 sig=9e0b693 body=032ec82 -->
public async Task<Display> InsertOne(Display display)
{
var defaultConfig = await displayConfigService.GetDefaultConfig(display.Type) ??
@@ -71,6 +72,7 @@ public class DisplayService(
/// Inserts a test Display record into the repository and records a corresponding audit log entry using the current HTTP context user.
/// </summary>
/// <returns>The newly created <see cref="Display"/> entity.</returns>
/// <!-- aidoc:v1 sig=4ec9793 body=0fdb428 -->
public async Task<Display> InsertOneTest()
{
var d = new Display
@@ -92,6 +94,7 @@ public class DisplayService(
/// Retrieves all displays from the repository and maps them to a compact representation.
/// </summary>
/// <returns>A task that represents the asynchronous operation, containing a list of <see cref="DisplayMinimalDto"/> with the mapped display data.</returns>
/// <!-- aidoc:v1 sig=d065c6f body=4d0461d -->
public async Task<List<DisplayMinimalDto>> GetAllCompact()
{
var result = await displayRepository.GetAll();
@@ -106,6 +109,7 @@ public class DisplayService(
/// <param name="userName">The user name used to filter the display items, or <see langword="null"/> to retrieve all items.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains a list of <see cref="Display"/> items.</returns>
/// <exception cref="NotImplementedException">The method has not been implemented yet.</exception>
/// <!-- aidoc:v1 sig=7a39576 body=bfa6f2f -->
public Task<List<Display>> GetAll(string? userName)
{
throw new NotImplementedException();
@@ -116,6 +120,7 @@ public class DisplayService(
/// </summary>
/// <param name="filter">The pagination filter containing the page number and page size used to determine the slice of results to return.</param>
/// <returns>A <see cref="Task{PaginationResponse{Display}}"/> containing the requested page of displays, the current page number, the page size, and the total number of documents.</returns>
/// <!-- aidoc:v1 sig=5ace491 body=5778d73 -->
public async Task<PaginationResponse<Display>> GetPaginatedDisplays(PaginationFilter filter)
{
var result = displayRepository.GetPaginatedDisplays(filter);
@@ -138,6 +143,7 @@ public class DisplayService(
/// <param name="userName">The username whose displays should be retrieved; when null, the method returns an empty list.</param>
/// <returns>A task that yields a list of <see cref="DisplayWithPermissionsDto"/> containing the displays the user can access along with their permissions.</returns>
/// <exception cref="ForbbidenException">Thrown when permissions for a unit-scoped display cannot be obtained for the user.</exception>
/// <!-- aidoc:v1 sig=3460ae9 body=04cbe7e -->
public async Task<List<DisplayWithPermissionsDto>> GetAllByUser(string? userName)
{
var start = DateTime.Now;
@@ -208,6 +214,7 @@ public class DisplayService(
/// <param name="displayId">The identifier of the display to look up, compared as a string.</param>
/// <param name="perms">The collection of display-with-permissions entries to search through.</param>
/// <returns><c>true</c> if a non-null display with a matching identifier is found; otherwise, <c>false</c>.</returns>
/// <!-- aidoc:v1 sig=3e72746 body=367999b -->
private static bool FindDisplayInPerms(string displayId, List<DisplayWithPermissionsDto> perms)
{
return perms.Any(p => p.Display != null && p.Display.Id.ToString() == displayId);
@@ -219,6 +226,7 @@ public class DisplayService(
/// </summary>
/// <param name="type">The display type used to filter the display configurations.</param>
/// <returns>A list of displays matching the specified type, each with its related configuration assigned; an empty list is returned when no displays are found.</returns>
/// <!-- aidoc:v1 sig=37f36bb body=aac9b72 -->
public async Task<List<Display>> GetByType(DisplayConfigEnums.DisplayType type)
{
var configs = await displayConfigService.GetByType(type);
@@ -238,6 +246,7 @@ public class DisplayService(
/// </summary>
/// <param name="pointOfCare">The point of care used to filter the displays.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the list of displays matching the specified point of care.</returns>
/// <!-- aidoc:v1 sig=ad8af85 body=9447333 -->
public async Task<List<Display>> GetByPointOfCare(PointOfCare pointOfCare)
{
return await displayRepository.GetByPointOfCare(pointOfCare);
@@ -248,6 +257,7 @@ public class DisplayService(
/// </summary>
/// <param name="configId">The configuration identifier used to look up the associated displays.</param>
/// <returns>A task that returns the list of <see cref="Display"/> objects matching the given configuration identifier.</returns>
/// <!-- aidoc:v1 sig=1ceff79 body=c343dde -->
public Task<List<Display>> GetByConfigId(ObjectId configId)
{
return displayRepository.GetByConfigId(configId);
@@ -258,6 +268,7 @@ public class DisplayService(
/// </summary>
/// <param name="configId">The unique identifier of the card configuration used to look up the associated displays.</param>
/// <returns>A task that represents the asynchronous operation, containing a list of <see cref="Display"/> objects matching the provided card configuration identifier.</returns>
/// <!-- aidoc:v1 sig=c38a1bb body=4696c61 -->
public Task<List<Display>> GetByCardConfigId(ObjectId configId)
{
return displayRepository.GetByCardConfigId(configId);
@@ -269,6 +280,7 @@ public class DisplayService(
/// <param name="name">The name of the display to look up.</param>
/// <returns>The <see cref="Display"/> that matches the specified name.</returns>
/// <exception cref="NotFoundException">Thrown when no display is found for the given name.</exception>
/// <!-- aidoc:v1 sig=58df1bb body=33a5e00 -->
public async Task<Display?> GetByName(string name)
{
return await displayRepository.GetByName(name) ??
@@ -280,6 +292,7 @@ public class DisplayService(
/// </summary>
/// <param name="id">The unique identifier of the display to retrieve.</param>
/// <returns>The matching <see cref="Display"/> if found; otherwise, <c>null</c>.</returns>
/// <!-- aidoc:v1 sig=06fe2a7 body=bf712b4 -->
public async Task<Display?> GetById(ObjectId id)
{
return await displayRepository.GetById(id);
@@ -292,6 +305,7 @@ public class DisplayService(
/// <param name="localeEnum">The locale used to localize the related point-of-care information.</param>
/// <returns>A <see cref="DisplayWithPermissionsDto"/> containing the display and its associated permissions.</returns>
/// <exception cref="NotFoundException">Thrown when the current user cannot be identified from the JWT or when no display is found for the specified <paramref name="id"/>.</exception>
/// <!-- aidoc:v1 sig=4aa342c body=756b4f9 -->
public async Task<DisplayWithPermissionsDto> GetByIdWithPermissions(ObjectId id, LocaleEnum localeEnum)
{
var username = JwtHelper.GetUsernameFromPrincipal(httpContextAccessor.HttpContext?.User!) ??
@@ -333,6 +347,7 @@ public class DisplayService(
/// </summary>
/// <param name="unitId">The unique identifier of the unit whose displays should be counted.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the total number of displays for the given unit.</returns>
/// <!-- aidoc:v1 sig=db66b12 body=1dd1fbe -->
public async Task<long> CountDisplaysByUnitId(ObjectId unitId)
{
return await displayRepository.CountByUnitId(unitId);
@@ -353,6 +368,7 @@ public class DisplayService(
/// <param name="fillDisplayConfig">If true, retrieves the full display including its configuration (cached); otherwise retrieves the base display.</param>
/// <param name="ct">Cancellation token to cancel the operation.</param>
/// <returns>The requested <see cref="Display"/>, or <c>null</c> if no display is found for the given id.</returns>
/// <!-- aidoc:v1 sig=7a4d82f body=f266015 -->
public async Task<Display?> GetInfo(ObjectId id,
string? userName,
List<Authorization>? authorizations,
@@ -429,6 +445,8 @@ public class DisplayService(
/// <param name="id">The identifier of the display to load.</param>
/// <param name="ct">The cancellation token used to cancel the asynchronous operation.</param>
/// <returns>The <see cref="Display"/> with its configuration populated, or <c>null</c> if no display exists for the given <paramref name="id"/>.</returns>
/// <!-- aidoc-review:v1 severity=medium kind=wrong_param_role
/// "The ct parameter is documented as 'used to cancel the asynchronous operation', but the method never passes ct to displayRepository.GetById, displayConfigService.GetById, or displayConfigService.GetCardConfigById, so the token has no effect on cancellation." -->
private async Task<Display?> BuildDisplayWithConfig(ObjectId id, CancellationToken ct)
{
var display = await displayRepository.GetById(id);
@@ -465,6 +483,7 @@ public class DisplayService(
/// <param name="userName">The username used to look up the user and their authorities; if null, an empty list is returned.</param>
/// <param name="authorizations">Optional pre-fetched list of user authorities; when null, authorities are retrieved from the authority service.</param>
/// <returns>A task that resolves to a list of <see cref="MinimalDisplaySection"/> items accessible to the user and matching the specified display type.</returns>
/// <!-- aidoc:v1 sig=64d7b66 body=cc129cf -->
public async Task<List<MinimalDisplaySection>> GetDisplaySectionByUser(
DisplayConfigEnums.DisplayType type,
ObjectId? currentDisplay,
@@ -539,6 +558,7 @@ public class DisplayService(
/// Asynchronously retrieves all display configurations of type DisplayNurse and SmartDisplay, mapping them into minimal display sections and grouping them within a display list DTO.
/// </summary>
/// <returns>A task that represents the asynchronous operation. The task result contains a MinimalDisplayListDto with the populated DisplayNurse and SmartDisplay collections.</returns>
/// <!-- aidoc:v1 sig=208d6c6 body=b473ad8 -->
public async Task<MinimalDisplayListDto> GetAllDisplaySection()
{
var minimalDisplayListDto = new MinimalDisplayListDto();
@@ -572,6 +592,7 @@ public class DisplayService(
/// </summary>
/// <param name="unitId">The identifier of the unit whose displays should be returned.</param>
/// <returns>A task that represents the asynchronous operation, containing the list of <see cref="Display"/> objects for the given unit.</returns>
/// <!-- aidoc:v1 sig=61f7d68 body=08a2310 -->
public async Task<List<Display>> GetByUnitId(ObjectId unitId)
{
return await displayRepository.GetByUnitId(unitId);
@@ -584,6 +605,8 @@ public class DisplayService(
/// <param name="excludeVirtual">When set to <c>true</c>, virtual points of care are excluded from the result; otherwise, they are included.</param>
/// <returns>A <see cref="PocAndUnitDto"/> containing the available points of care and their associated unit details.</returns>
/// <exception cref="NotFoundException">Thrown when a unit associated with one of the resolved display identifiers cannot be found.</exception>
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
/// "NotFoundException is thrown inside the try block but immediately caught by the generic catch(Exception) handler, which logs the error and returns an empty PocAndUnitDto. The exception never propagates to the caller, so documenting it as thrown is misleading." -->
public async Task<PocAndUnitDto> GetAllAvailablePoc(List<string> displayIds, bool excludeVirtual = false)
{
try
@@ -635,6 +658,7 @@ public class DisplayService(
/// </summary>
/// <param name="id">The ObjectId of the display whose points of care should be retrieved.</param>
/// <returns>A list of points of care linked to the display, or an empty list if the display cannot be found or if an error is encountered.</returns>
/// <!-- aidoc:v1 sig=9215df7 body=d5eaca6 -->
public async Task<List<PointOfCare>> GetAllPocsByDisplayId(ObjectId id)
{
try
@@ -664,6 +688,7 @@ public class DisplayService(
/// </summary>
/// <param name="displayConfigId">The identifier of the display configuration whose locations are being retrieved.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains a list of <see cref="DisplayConfigLocationDto"/> objects with display and unit information.</returns>
/// <!-- aidoc:v1 sig=0895dcd body=e5b010a -->
public async Task<List<DisplayConfigLocationDto>> GetDisplayConfigLocations(ObjectId displayConfigId)
{
var displays = await GetByConfigId(displayConfigId);
@@ -687,6 +712,7 @@ public class DisplayService(
/// </summary>
/// <param name="displayConfigId">The unique identifier of the display configuration to check.</param>
/// <returns><c>true</c> if the display configuration is referenced by at least one entity; otherwise, <c>false</c>.</returns>
/// <!-- aidoc:v1 sig=685c5f5 body=f4b630c -->
public async Task<bool> IsDisplayConfigInUse(ObjectId displayConfigId)
{
return await displayRepository.IsDisplayConfigInUse(displayConfigId) > 0;
@@ -708,6 +734,7 @@ public class DisplayService(
/// <returns>The updated <see cref="Display"/> instance after the point of care list change.</returns>
/// <exception cref="NotFoundException">Thrown when no display exists for the specified <paramref name="objectId"/>.</exception>
/// <exception cref="ConflictException">Thrown when the point of care list update cannot be persisted.</exception>
/// <!-- aidoc:v1 sig=68b108f body=41d1e6a -->
public async Task<Display?> UpdatePointOfCareList(ObjectId objectId, List<ObjectId> listPocObId)
{
var oldDisplay = await displayRepository.GetById(objectId) ??
@@ -729,6 +756,10 @@ public class DisplayService(
/// <param name="oldDisplay">The existing display whose configuration will be updated.</param>
/// <param name="newDisplayConfig">The new configuration to apply, or <c>null</c> if no update is provided.</param>
/// <returns>The updated <see cref="Display"/> if the configuration was successfully applied; otherwise, <c>null</c>.</returns>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "The summary states the method returns null 'if the provided configuration type is not supported,' but newDisplayConfigCast is initialized to a non-null default and the code proceeds to the repository call for any non-null cast result, including unsupported types." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "The summary groups broadcast, audit log creation, and cache invalidation together as happening 'on a successful update,' but cache invalidation occurs whenever a valid config type is provided, even if the repository update returns null." -->
public async Task<Display?> UpdateConfig(Display oldDisplay, DisplayConfig? newDisplayConfig)
{
var newDisplayConfigCast = new DisplayConfig();
@@ -766,6 +797,7 @@ public class DisplayService(
/// <param name="oldDisplay">The display whose configuration ID is being updated.</param>
/// <param name="configId">The new configuration ID to assign to the display.</param>
/// <returns>The updated display, or <c>null</c> if the display was not found.</returns>
/// <!-- aidoc:v1 sig=a4c5a08 body=1c84331 -->
public async Task<Display?> UpdateConfigId(Display oldDisplay, ObjectId configId)
{
var displayToReturn = await displayRepository.UpdateConfigId(oldDisplay.Id, configId);
@@ -787,6 +819,8 @@ public class DisplayService(
/// <returns>The updated <see cref="Display"/> entity, or <c>null</c> if the update could not be completed.</returns>
/// <exception cref="NotFoundException">Thrown when the update result or the resolved configuration is <c>null</c>.</exception>
/// <exception cref="InvalidFormatException">Thrown when the configuration type is not one of the handled display types.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=wrong_returns
/// "Documentation states the method returns 'null if the update could not be completed', but the code throws NotFoundException when result is null, never actually returning null to the caller." -->
public async Task<Display?> UpdateConfigPreset(ObjectId objectIdDisplay, ObjectId objectIdConfigDisplay)
{
var oldConfig = await displayConfigService.GetById(objectIdConfigDisplay);
@@ -824,6 +858,7 @@ public class DisplayService(
/// <param name="name">The new name to assign to the display.</param>
/// <returns>The updated <see cref="Display"/> instance, or <c>null</c> if the update could not be performed.</returns>
/// <exception cref="NotFoundException">Thrown when no display is found for the specified <paramref name="id"/>.</exception>
/// <!-- aidoc:v1 sig=18e4a50 body=b0ad3f7 -->
public async Task<Display?> UpdateName(ObjectId id, string name)
{
var display = await displayRepository.GetById(id) ??
@@ -846,6 +881,7 @@ public class DisplayService(
/// <param name="id">The unique identifier of the display to delete.</param>
/// <returns>A task that resolves to <c>true</c> when the display has been successfully deleted.</returns>
/// <exception cref="NotFoundException">Thrown when no display is found for the specified <paramref name="id"/>.</exception>
/// <!-- aidoc:v1 sig=328e872 body=46f2b0a -->
public async Task<bool> DeleteDisplay(ObjectId id)
{
var display = await displayRepository.GetById(id) ??
@@ -865,6 +901,7 @@ public class DisplayService(
/// Deletes all displays associated with the specified unit identifier, invalidates the displays cache, and removes related authority data for the unit.
/// </summary>
/// <param name="unitId">The unique identifier of the unit whose displays and related authority data will be removed.</param>
/// <!-- aidoc:v1 sig=bd663aa body=28edafe -->
public async Task DeleteDisplaysByUnitId(ObjectId unitId)
{
await displayRepository.DeleteManyByUnitId(unitId);
@@ -883,6 +920,7 @@ public class DisplayService(
/// </summary>
/// <param name="subscribers">The list of WebSocket subscribers that will receive the smart display configuration update.</param>
/// <param name="config">The smart display configuration to broadcast. May be <c>null</c> if no configuration is provided.</param>
/// <!-- aidoc:v1 sig=57faa95 body=71328cd -->
private void SendSmartDisplayBroadcast(List<WsSubscriber> subscribers, SmartDisplay? config)
{
foreach (var subscriber in subscribers)
@@ -894,6 +932,7 @@ public class DisplayService(
/// </summary>
/// <param name="subscribers">The list of WebSocket subscribers that will receive the nurse display configuration update.</param>
/// <param name="config">The nurse display configuration to broadcast, which may be <c>null</c>.</param>
/// <!-- aidoc:v1 sig=6730073 body=809b5d8 -->
private void SendNurseDisplayBroadcast(List<WsSubscriber> subscribers, DisplayNurse? config)
{
foreach (var subscriber in subscribers)
@@ -906,6 +945,7 @@ public class DisplayService(
/// </summary>
/// <param name="display">The display whose subscribers will receive the broadcast; used to filter the subscriber list by its identifier.</param>
/// <param name="operation">The type of operation being broadcast, which determines the action taken on matching subscribers.</param>
/// <!-- aidoc:v1 sig=30dad01 body=bbd0711 -->
private void SendDisplayBroadcast(Display display, OperationType operation)
{
var subscribers = subscribersService.GetSubscribers().Where(s =>