Documentation modifications

This commit is contained in:
julian
2026-06-27 15:23:26 -07:00
parent a633fe6c06
commit a19fb90902
218 changed files with 2882 additions and 0 deletions
@@ -7,10 +7,22 @@ namespace adas_core.Domain.Exceptions;
/// </summary>
public class BusinessException : AggregateException
{
/// <summary>
/// Initializes a new instance of the <see cref="BusinessException"/> class with the supplied <see cref="HttpStatusCode"/> and message, forwarding their combined textual representation to the base exception constructor. <see cref="BusinessException"/> represents errors raised by business logic that are associated with an HTTP status.
/// </summary>
/// <param name="status">The <see cref="HttpStatusCode"/> that identifies the nature of the business error.</param>
/// <param name="message">The descriptive message that provides additional context for the error.</param>
/// <!-- aidoc:v1 sig=0825145 body=4448e1d -->
public BusinessException(HttpStatusCode status, string message) : base($"{status}: {message}")
{
}
/// <summary>
/// Initializes a new instance of the <see cref="BusinessException"/> class, which represents errors in business logic, by passing the specified error message and inner <see cref="Exception"/> to the base class constructor.
/// </summary>
/// <param name="message">The error message that describes the reason for the exception.</param>
/// <param name="exception">The inner <see cref="Exception"/> that is the cause of the current exception, or <see langword="null"/> if no inner exception is specified.</param>
/// <!-- aidoc:v1 sig=cd57c0c body=4448e1d -->
public BusinessException(string message, Exception exception) : base(message, exception)
{
}
@@ -11,11 +11,22 @@ namespace adas_core.Domain.Exceptions;
/// </remarks>
public class LoginServicesException : BusinessException
{
/// <summary>
/// Initializes a new instance of the <see cref="LoginServicesException"/> class with a descriptive error message, forwarding it to the base exception together with an HTTP <see cref="HttpStatusCode.BadRequest"/> status code.
/// </summary>
/// <param name="message">The error message that describes the login service failure.</param>
/// <!-- aidoc:v1 sig=16739ff body=4448e1d -->
public LoginServicesException(string message) :
base(HttpStatusCode.BadRequest, $"Login service error: {message}")
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LoginServicesException"/> class, which represents errors that occur in the login service. The supplied <paramref name="message"/> is prefixed with a service-context note and the underlying <paramref name="exception"/> is preserved as the inner exception.
/// </summary>
/// <param name="message">The error message describing the login service failure.</param>
/// <param name="exception">The inner <see cref="System.Exception"/> that caused the current exception.</param>
/// <!-- aidoc:v1 sig=83e8d73 body=4448e1d -->
public LoginServicesException(string message, Exception exception) : base($"Login service error: {message}",
exception)
{
@@ -2,5 +2,12 @@
namespace adas_core.Domain.Exceptions;
/// <summary>
/// Represents the exception that is thrown when no login services are available to handle authentication requests.
/// </summary>
/// <remarks>
/// This exception derives from <see cref="BusinessException"/> and is raised with the <see cref="HttpStatusCode.Forbidden"/> status code and the message "No login services available".
/// </remarks>
/// <!-- aidoc:v1 sig=e23ced3 -->
public class LoginServicesNotFoundException()
: BusinessException(HttpStatusCode.Forbidden, "No login services available");
@@ -10,11 +10,22 @@ namespace adas_core.Domain.Exceptions;
/// </remarks>
public class UserNotFoundException : BusinessException
{
/// <summary>
/// Initializes a new instance of the <see cref="UserNotFoundException"/> class with a <see cref="HttpStatusCode.NotFound"/> status code and a message identifying the missing <paramref name="username"/>.
/// </summary>
/// <param name="username">The username of the user that could not be found.</param>
/// <!-- aidoc:v1 sig=3e9ae01 body=4448e1d -->
public UserNotFoundException(string username) :
base(HttpStatusCode.NotFound, $"USER with username {username} not found")
{
}
/// <summary>
/// Initializes a new instance of the <see cref="UserNotFoundException"/> class with the username that could not be found and a wrapped inner <see cref="Exception"/>.
/// </summary>
/// <param name="username">The username that was not found.</param>
/// <param name="exception">The inner <see cref="Exception"/> that caused this exception to be raised.</param>
/// <!-- aidoc:v1 sig=2ed5f9f body=4448e1d -->
public UserNotFoundException(string username, Exception exception) : base(
$"USER with username {username} not found", exception)
{
@@ -70,6 +70,10 @@ public class UsersWhiteListConfig : List<string>
/// <remarks>
/// This type serves as a container or marker for grouping validation logic within a broader validation framework.
/// </remarks>
/// <summary>
/// Represents a group that has been validated as meeting the required criteria.
/// </summary>
/// <!-- aidoc:v1 sig=1cee181 -->
public class ValidGroupsConfig : List<ValidGroup>
{
/// <summary>
@@ -272,6 +272,13 @@ public class PermissionSettings
);
}
/// <summary>
/// Represents a set of permissions for a source, grouping the unit-level and display-level <see cref="DisplayPermissionTypes"/> together with the corresponding <see cref="PanelPermissionTypes"/>.
/// </summary>
/// <remarks>
/// The primary constructor captures <paramref name="unit"/> and <paramref name="display"/> permissions as <see cref="DisplayPermissionTypes"/>, and <paramref name="panel"/> permissions as <see cref="PanelPermissionTypes"/>.
/// </remarks>
/// <!-- aidoc:v1 sig=74dcf70 -->
public class SourcePermissions(
DisplayPermissionTypes unit,
DisplayPermissionTypes display,
@@ -282,6 +289,13 @@ public class SourcePermissions(
public PanelPermissionTypes Panel { get; set; } = panel;
}
/// <summary>
/// Encapsulates a collection of <see cref="UserActions"/> that govern the display permissions for clinical and administrative areas such as admissions, discharges, observations, demographic data, box blocking, notices, and cell management.
/// </summary>
/// <remarks>
/// The <paramref name="useDemoMode"/> flag indicates whether the permission configuration should be evaluated in demonstration mode.
/// </remarks>
/// <!-- aidoc:v1 sig=5c32eb7 -->
public class DisplayPermissionTypes(
UserActions admissions,
UserActions discharges,
@@ -302,6 +316,13 @@ public class DisplayPermissionTypes(
public bool UseDemoMode { get; set; } = useDemoMode;
}
/// <summary>
/// Encapsulates the <see cref="UserActions"/> permissions available for each application panel, such as <paramref name="units"/>, <paramref name="patients"/>, and <paramref name="observations"/>, along with the <paramref name="useDemoMode"/> flag.
/// </summary>
/// <remarks>
/// A dedicated <see cref="UserActions"/> value is supplied for every panel — units, displays, display configurations, master lists, treatments, patients, medicines, pumps, users, configuration observations, observations, and audits — so that the access rights for each section can be evaluated independently. The <paramref name="useDemoMode"/> parameter indicates whether the system is operating in demo mode.
/// </remarks>
/// <!-- aidoc:v1 sig=3d15620 -->
public class PanelPermissionTypes(
UserActions units,
UserActions displays,
@@ -9,11 +9,21 @@ namespace adas_core.Domain.Models.DTO;
/// </summary>
public class UnitInfoDto
{
/// <summary>
/// Initializes a new instance of the <see cref="UnitInfoDto"/> data transfer object, enabling JSON deserialization via the <see cref="JsonConstructorAttribute"/>.
/// </summary>
/// <!-- aidoc:v1 sig=e9065d4 body=4448e1d -->
[JsonConstructor]
public UnitInfoDto()
{
}
/// <summary>
/// Initializes a new instance of <see cref="UnitInfoDto"/> from the supplied <paramref name="unit"/>,
/// projecting its identifier and name into the DTO with safe empty-string defaults for the display fields.
/// </summary>
/// <param name="unit">The optional <see cref="Unit"/> whose values populate the DTO; when null, the string properties default to <see cref="string.Empty"/>.</param>
/// <!-- aidoc:v1 sig=98aa992 body=1d6ed29 -->
public UnitInfoDto(Unit? unit)
{
Id = unit?.Id;
@@ -2,10 +2,21 @@
public record PaginationFilter
{
/// <summary>
/// Initializes a new instance of the <see cref="PaginationFilter"/> class, which encapsulates the parameters used to paginate query results.
/// </summary>
/// <!-- aidoc:v1 sig=2ec7383 body=4448e1d -->
public PaginationFilter()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PaginationFilter"/> class with sanitized pagination values and an optional <see cref="FilteredRequest"/>.
/// </summary>
/// <param name="pageNumber">The requested page number; values less than 1 are clamped to 1.</param>
/// <param name="pageSize">The requested page size; values less than or equal to 0 default to 100.</param>
/// <param name="filtered">The optional <see cref="FilteredRequest"/> providing additional filtering criteria.</param>
/// <!-- aidoc:v1 sig=9004f63 body=c312b00 -->
public PaginationFilter(int pageNumber, int pageSize, FilteredRequest? filtered)
{
PageNumber = pageNumber < 1 ? 1 : pageNumber;
@@ -10,10 +10,28 @@ namespace adas_core.Domain.Models.GroupedObservations;
/// </remarks>
public class GroupedField
{
/// <summary>
/// Initializes a new default instance of the <see cref="GroupedField"/> class, representing a field that aggregates related items into a single addressable group.
/// </summary>
/// <!-- aidoc:v1 sig=703c28d body=4448e1d -->
public GroupedField()
{
}
/// <summary>
/// Initializes a new instance of <see cref="GroupedField"/>, which represents a configurable field for grouped observations with identifiers, scheduling offsets, and result selection.
/// Null collection parameters are normalized to empty lists, and <paramref name="result"/> defaults to a list containing <see cref="GroupedObservationEnum.Result.First"/> when omitted.
/// </summary>
/// <param name="name">The primary identifier of the field, or null when only the <paramref name="names"/> collection is used.</param>
/// <param name="names">The alternative identifiers for the field; when null, an empty <see cref="List{String}"/> is stored.</param>
/// <param name="group">The grouping key that associates the field with a logical group, or null if unspecified.</param>
/// <param name="startTimeShift">The list of schedule offsets applied to the field; when null, an empty <see cref="List{String}"/> is stored.</param>
/// <param name="max">The maximum number of observations retained for the field.</param>
/// <param name="regularity">The optional <see cref="GroupedObservationEnum.Regularity"/> that governs how observations are spaced.</param>
/// <param name="since">The <see cref="GroupedObservationEnum.Since"/> value that defines the schedule's starting reference.</param>
/// <param name="result">The list of <see cref="GroupedObservationEnum.Result"/> values the field should produce; when null, a list containing <see cref="GroupedObservationEnum.Result.First"/> is stored.</param>
/// <param name="labelList">The labels associated with the field, or null when no labels are provided.</param>
/// <!-- aidoc:v1 sig=8ca95e4 body=4742386 -->
public GroupedField(
string? name,
List<string>? names,
@@ -19,6 +19,13 @@ public class HistoricalLocation : IEquatable<HistoricalLocation>
public HistoricalLocation() { }
// Tu constructor actual
/// <summary>
/// Initializes a new instance of <see cref="HistoricalLocation"/> with the specified admission time and <see cref="PatientLocation"/>, representing a historical record of a patient's location.
/// </summary>
/// <param name="admTime">The admission time assigned to <see cref="HistoricalLocation.AdmTime"/>.</param>
/// <param name="patientLocation">The <see cref="PatientLocation"/> assigned to <see cref="HistoricalLocation.PatientLocation"/>; cannot be <see langword="null"/>.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="patientLocation"/> is <see langword="null"/>.</exception>
/// <!-- aidoc:v1 sig=eaeda50 body=ebde455 -->
public HistoricalLocation(DateTime admTime, PatientLocation patientLocation)
{
AdmTime = admTime;
@@ -22,6 +22,12 @@ public class MasterList
public LocaleEnum? DefaultLocale { get; set; }
public List<OptionList> Options { get; set; } = [];
/// <summary>
/// Returns a copy of this <see cref="MasterList"/> with each option name in <see cref="MasterList.Options"/> localized to the requested <paramref name="localeToReturn"/>, falling back to the original name when no translation is found.
/// </summary>
/// <param name="localeToReturn">Target <see cref="LocaleEnum"/> used to look up a translated name via reflection on <see cref="OptionList.LocaleItems"/>. When <c>null</c>, the current instance is returned unchanged.</param>
/// <returns>A new <see cref="MasterList"/> with localized option names when <paramref name="localeToReturn"/> is provided; otherwise the current instance.</returns>
/// <!-- aidoc:v1 sig=803939c body=2054117 -->
public MasterList ReturnMasterListOptionsInLocaleIfExist(LocaleEnum? localeToReturn)
{
if (localeToReturn == null) return this;
@@ -184,6 +184,12 @@ public class SmartDisplay : DisplayConfig
}
// TO TEST
/// <summary>
/// Compares the values of the public properties of <see cref="SmartDisplay"/> between the current instance and <paramref name="other"/>, and returns the names of the properties that differ. The <see cref="SmartDisplay.ColorConfig"/> property is also included when it is not null and not equal to the one in <paramref name="other"/>.
/// </summary>
/// <param name="other">The <see cref="SmartDisplay"/> instance to compare against; may be null.</param>
/// <returns>A <see cref="List{String}"/> containing the names of the properties that have different values between the two instances.</returns>
/// <!-- aidoc:v1 sig=5d5d974 body=db6cf7c -->
public List<string> GetDifferentProperties(SmartDisplay? other)
{
// Obtiene las propiedades públicas de la clase SmartDisplay
@@ -858,6 +864,10 @@ public class AxisLabel
/// <summary>
/// Represents a line associated with an axis, typically used in charting or graphing scenarios to render or define axis-related visual elements.
/// </summary>
/// <summary>
/// Represents a line associated with an axis, typically used to render or define the visual structure of an axis in a chart or graph.
/// </summary>
/// <!-- aidoc:v1 sig=5e39639 -->
public class AxisLineStyle
{
public string? Color { get; set; }
@@ -1030,6 +1040,10 @@ public class Piece
// /// <summary>
// /// Represents a candle entity within the system.
// /// </summary>
// /// <summary>
// /// Represents a single <c>candlestick</c> data point, typically used in financial charting to encapsulate price information for a discrete time interval.
// /// </summary>
// /// <!-- aidoc:v1 sig=59009c7 -->
// public class CandlestickSeriesConfig : SeriesConfigBase
// {
// public List<Candle>? CandleKeyList { get; set; }
@@ -7,10 +7,20 @@ namespace adas_core.Domain.Models;
/// </summary>
public class ObservatitonRetentionResult
{
/// <summary>
/// Initializes a new instance of the <see cref="ObservatitonRetentionResult"/> class, which represents the outcome of an observation retention operation.
/// </summary>
/// <!-- aidoc:v1 sig=4f5f5d1 body=4448e1d -->
public ObservatitonRetentionResult()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ObservatitonRetentionResult"/> class, which represents the outcome of a retention evaluation, by storing the supplied <paramref name="retentionPolicy"/> and its associated <paramref name="retentionPolicyValue"/>.
/// </summary>
/// <param name="retentionPolicy">The <see cref="RetentionPolicy"/> that was evaluated to produce the result.</param>
/// <param name="retentionPolicyValue">The optional numeric value paired with the <paramref name="retentionPolicy"/>, or <see langword="null"/> when no value is required.</param>
/// <!-- aidoc:v1 sig=d280e78 body=d032d9b -->
public ObservatitonRetentionResult(RetentionPolicy retentionPolicy, int? retentionPolicyValue)
{
RetentionPolicy = retentionPolicy;
@@ -11,10 +11,20 @@ namespace adas_core.Domain.Models.Observations;
/// </remarks>
public class Medication : Observation
{
/// <summary>
/// Initializes a new instance of the <see cref="Medication"/> class with default values.
/// </summary>
/// <!-- aidoc:v1 sig=bb98407 body=4448e1d -->
public Medication()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Medication"/> class, which represents medication delivery state, by reading pump-related properties from <paramref name="obj"/> when their MDC codes are present and assigning <paramref name="id"/> to <see cref="Medication.Id"/>.
/// </summary>
/// <param name="id">The identifier stored in <see cref="Medication.Id"/>.</param>
/// <param name="obj">A <see cref="Dictionary{TKey,TValue}"/> of <see cref="PumpElement"/> entries keyed by MDC code, consulted via <see cref="Dictionary{TKey,TValue}.TryGetValue"/>.</param>
/// <!-- aidoc:v1 sig=b107edc body=3412539 -->
public Medication(string id, Dictionary<string, PumpElement> obj)
{
if (obj.TryGetValue("MDC_184504", out var mode)) PumpMode = new PumpMode(mode);
@@ -57,10 +67,20 @@ public class Medication : Observation
/// </summary>
public class DrugValue
{
/// <summary>
/// Initializes a new instance of the <see cref="DrugValue"/> class using default values. The <see cref="DrugValue"/> type represents the value associated with a drug.
/// </summary>
/// <!-- aidoc:v1 sig=b79012f body=4448e1d -->
public DrugValue()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="DrugValue"/> class by copying the medication-related values from the specified <see cref="PumpElement"/>.
/// This constructor populates the properties <see cref="DrugValue.Id"/>, <see cref="DrugValue.Text"/>, <see cref="DrugValue.Time"/>, <see cref="DrugValue.Units"/>, <see cref="DrugValue.CodingSystem"/>, and <see cref="DrugValue.Result"/> from the source element.
/// </summary>
/// <param name="pumpElement">The <see cref="PumpElement"/> from which to copy the medication data.</param>
/// <!-- aidoc:v1 sig=8c84a69 body=a72ec1a -->
public DrugValue(PumpElement pumpElement)
{
Id = pumpElement.Id;
@@ -101,6 +121,11 @@ public class DrugValue
/// </remarks>
public abstract class DrugDoubleValue : DrugValue
{
/// <summary>
/// Initializes a new instance of the <see cref="DrugDoubleValue"/> class by forwarding <paramref name="pumpElement"/> to the base constructor and parsing its textual value as a <see cref="double"/> to set the Value property when the conversion succeeds.
/// </summary>
/// <param name="pumpElement">The <see cref="PumpElement"/> whose string representation is parsed as a <see cref="double"/> to initialize the Value property.</param>
/// <!-- aidoc:v1 sig=d14bd75 body=29c2c0d -->
protected DrugDoubleValue(PumpElement pumpElement) : base(pumpElement)
{
if (double.TryParse(pumpElement.Value?.ToString(), out var valueParsed))
@@ -175,6 +200,11 @@ public class Drug(PumpElement pumpElement) : DrugStringValue(pumpElement);
/// </summary>
public class PumpMode : DrugStringValue
{
/// <summary>
/// Initializes a new instance of the <see cref="PumpMode"/> class by forwarding the supplied <see cref="PumpElement"/> to the base constructor and computing the normalized mode identifier from its raw value. The type represents a pump mode value extracted from a pump element.
/// </summary>
/// <param name="pumpElement">The source element providing the raw mode text that is normalized to produce the mode identifier.</param>
/// <!-- aidoc:v1 sig=97f7b03 body=bdf432f -->
public PumpMode(PumpElement pumpElement) : base(pumpElement)
{
Value = pumpElement.Value?.ToString()?.SubstringAfter("pump-mode-").Replace("-", "_");
@@ -186,6 +216,11 @@ public class PumpMode : DrugStringValue
/// </summary>
public class PumpStatus : DrugStringValue
{
/// <summary>
/// Initializes a new instance of the <see cref="PumpStatus"/> class from the specified <paramref name="pumpElement"/>, deriving the <see cref="PumpStatus.Value"/> by stripping the "pump-status-" prefix and normalizing dashes to underscores.
/// </summary>
/// <param name="pumpElement">The <see cref="PumpElement"/> whose value is parsed to populate the status.</param>
/// <!-- aidoc:v1 sig=526c2d6 body=d13ab1e -->
public PumpStatus(PumpElement pumpElement) : base(pumpElement)
{
Value = pumpElement.Value?.ToString()?.SubstringAfter("pump-status-").Replace("-", "_");
@@ -6,6 +6,13 @@
/// </summary>
public class PatientLocation : IEquatable<PatientLocation>
{
/// <summary>
/// Initializes a new instance of the <see cref="PatientLocation"/> class, which represents a patient's location within a care unit, using the specified unit name, bed, and room values.
/// </summary>
/// <param name="unitName">The name of the care unit assigned to <see cref="PatientLocation.UnitName"/>, or <see langword="null"/>.</param>
/// <param name="bed">The bed identifier assigned to <see cref="PatientLocation.Bed"/>, or <see langword="null"/>.</param>
/// <param name="room">The room identifier assigned to <see cref="PatientLocation.Room"/>, or <see langword="null"/>.</param>
/// <!-- aidoc:v1 sig=401fc97 body=2b1784e -->
public PatientLocation(string? unitName, string? bed, string? room)
{
UnitName = unitName;
@@ -13,6 +20,12 @@ public class PatientLocation : IEquatable<PatientLocation>
Room = room;
}
/// <summary>
/// Initializes a new instance of the <see cref="PatientLocation"/> class, storing the supplied unit name and bed, and using the bed value as the room identifier.
/// </summary>
/// <param name="unitName">The unit name to assign to <see cref="PatientLocation.UnitName"/>, or <see langword="null"/> if unspecified.</param>
/// <param name="bed">The bed identifier to assign to <see cref="PatientLocation.Bed"/> and <see cref="PatientLocation.Room"/>, or <see langword="null"/> if unspecified.</param>
/// <!-- aidoc:v1 sig=44a90e4 body=fbafeea -->
public PatientLocation(string? unitName, string? bed)
{
UnitName = unitName;
@@ -20,6 +33,11 @@ public class PatientLocation : IEquatable<PatientLocation>
Room = bed;
}
/// <summary>
/// Initializes a new instance of the <see cref="PatientLocation"/> class without performing explicit initialization of its members.
/// The <see cref="PatientLocation"/> type represents the location of a patient.
/// </summary>
/// <!-- aidoc:v1 sig=0911aca body=4448e1d -->
public PatientLocation()
{
// Constructor vacío
@@ -15,10 +15,21 @@ public class PatientObservation : BasePatientObservationValue
{
private string? _result;
/// <summary>
/// Initializes a new default instance of the <see cref="PatientObservation"/> class, which represents a clinical observation recorded for a patient.
/// </summary>
/// <!-- aidoc:v1 sig=5c55204 body=4448e1d -->
public PatientObservation()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PatientObservation"/> class, which represents an observation linked to a patient, with the specified identifier, value, and name.
/// </summary>
/// <param name="patientId">The <see cref="ObjectId"/> identifying the patient associated with the observation.</param>
/// <param name="value">The value recorded for the observation.</param>
/// <param name="name">The name of the observation, or <see langword="null"/>.</param>
/// <!-- aidoc:v1 sig=6b8c74d body=a32087f -->
public PatientObservation(ObjectId patientId, object value, string? name)
{
PatientId = patientId;
@@ -12,10 +12,20 @@ namespace adas_core.Domain.Models.Responses;
/// </remarks>
public class DisplayConfigMinimalResponse
{
/// <summary>
/// Initializes a new instance of the <see cref="DisplayConfigMinimalResponse"/> class, which represents a minimal response payload carrying display configuration data.
/// </summary>
/// <!-- aidoc:v1 sig=722895f body=4448e1d -->
public DisplayConfigMinimalResponse()
{
}
/// <summary>
/// Initializes a new <see cref="DisplayConfigMinimalResponse"/>, a minimal response view of a display configuration, from the supplied <paramref name="displayConfig"/> and optional <paramref name="isInUse"/> flag.
/// </summary>
/// <param name="displayConfig">The source <see cref="DisplayConfigSummary"/> whose <see cref="DisplayConfigSummary.Id"/>, <see cref="DisplayConfigSummary.Type"/>, and <see cref="DisplayConfigSummary.Name"/> populate the response.</param>
/// <param name="isInUse">The nullable boolean indicating whether the display configuration is in use, stored in <see cref="DisplayConfigMinimalResponse.IsInUse"/>.</param>
/// <!-- aidoc:v1 sig=017b17e body=422f274 -->
public DisplayConfigMinimalResponse(DisplayConfigSummary displayConfig, bool? isInUse = false)
{
Id = displayConfig.Id;
@@ -6,6 +6,14 @@
/// <typeparam name="T">The type of the items contained in the paginated response.</typeparam>
public class PaginationResponse<T>
{
/// <summary>
/// Initializes a new instance of <see cref="PaginationResponse{T}"/> with the supplied page items and pagination metadata, deriving the total page count from <paramref name="totalRecords"/> and <paramref name="pageSize"/>.
/// </summary>
/// <param name="data">The <see cref="List{T}"/> of items included in the current page.</param>
/// <param name="pageNumber">The number of the current page.</param>
/// <param name="pageSize">The maximum number of items per page.</param>
/// <param name="totalRecords">The total number of records available across all pages.</param>
/// <!-- aidoc:v1 sig=bbc53e5 body=c9e44a7 -->
public PaginationResponse(List<T> data, int pageNumber, int pageSize, long totalRecords)
{
PageNumber = pageNumber;
@@ -2,6 +2,10 @@ using adas_core.Domain.Models.MongoModels;
namespace adas_core.Domain.Models.Responses;
/// <summary>
/// Encapsulates the outcome of a <see cref="Patient"/> lookup, bundling the matched <see cref="Patient"/>, the corresponding archived <see cref="Patient"/>, the related <see cref="Admission"/>, and flags that indicate archive status and result availability.
/// </summary>
/// <!-- aidoc:v1 sig=461ed22 -->
public class PatientSearch(
Patient? patient,
Patient? archivePatient,
@@ -6,10 +6,19 @@
/// <typeparam name="T">The type of the payload contained within the response.</typeparam>
public class Response<T>
{
/// <summary>
/// Initializes a new instance of the <see cref="Response"/> class using default values.
/// </summary>
/// <!-- aidoc:v1 sig=c192431 body=4448e1d -->
public Response()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Response{T}"/> class representing a successful result, setting <see cref="Response{T}.Succeeded"/> to <c>true</c>, <see cref="Response{T}.Message"/> to an empty string, <see cref="Response{T}.Errors"/> to <c>null</c>, and storing the supplied payload in <see cref="Response{T}.Data"/>.
/// </summary>
/// <param name="data">The payload to expose through <see cref="Response{T}.Data"/>.</param>
/// <!-- aidoc:v1 sig=f4d0833 body=8db513f -->
public Response(T data)
{
Succeeded = true;
+8
View File
@@ -12,11 +12,19 @@ public sealed class AuthUtils
{
private LoginResponse _loginResponse = new();
/// <summary>
/// Static constructor that initializes the static <see cref="AuthUtils.InternalInstance"/> field of the <see cref="AuthUtils"/> class by assigning a new <see cref="AuthUtils"/> instance if it has not already been set.
/// </summary>
/// <!-- aidoc:v1 sig=b1904e8 body=05a5e0c -->
static AuthUtils()
{
InternalInstance ??= new AuthUtils();
}
/// <summary>
/// Initializes a new instance of the <see cref="AuthUtils"/> authentication utility class and stores a self-reference in <see cref="AuthUtils.InternalInstance"/>, allowing callers to retrieve the active instance through that property.
/// </summary>
/// <!-- aidoc:v1 sig=cfb2f97 body=ec96561 -->
public AuthUtils()
{
InternalInstance = this;
+7
View File
@@ -140,6 +140,13 @@ namespace adas_core.Domain.Utils
public static string ConfigObservationsAll()
=> "configObservations:all";
/// <summary>
/// Returns the cache key and its associated time-to-live (TTL) for caching the complete collection of configuration observations.
/// The TTL is resolved by <see cref="CacheKeyTtl.ResolveForEntity"/> using <paramref name="settings"/> and <see cref="CacheEnum.EntityType.ConfigObservations"/>.
/// </summary>
/// <param name="settings">Optional cache configuration used to resolve the TTL; may be <see langword="null"/>.</param>
/// <returns>A tuple containing the cache key and the resolved TTL as a <see cref="Nullable{TimeSpan}"/>.</returns>
/// <!-- aidoc:v1 sig=4708037 body=5108bf4 -->
public static (string Key, TimeSpan? Ttl) ConfigObservationsAllKeyWithTtl(
CacheSettings? settings)
{
@@ -11,6 +11,14 @@ namespace adas_core.Domain.Utils;
public static class CardConfigExtensions
{
// Método principal para extraer todos los nombres
/// <summary>
/// Retrieves all unique observation names defined within the rows and cells of the specified <see cref="CardConfig"/>.
/// Returns an empty list when <paramref name="config"/> has no <see cref="CardConfig.Rows"/>, and skips any row whose <c>Cells</c> collection is <see langword="null"/>.
/// Observation names are extracted recursively from each cell, with duplicates removed.
/// </summary>
/// <param name="config">The <see cref="CardConfig"/> whose cell observation names should be collected.</param>
/// <returns>A <see cref="List{T}"/> of distinct observation names found across all cells of <paramref name="config"/>, or an empty list if no rows are defined.</returns>
/// <!-- aidoc:v1 sig=2538759 body=b24f5d8 -->
public static List<string> GetAllObservationNames(this CardConfig config)
{
if (config.Rows == null) return [];
@@ -28,6 +36,12 @@ public static class CardConfigExtensions
}
// Método auxiliar RECURSIVO para extraer nombres de una Cell y sus SubObs
/// <summary>
/// Extracts observation names from the specified <paramref name="cell"/>, yielding the values in <see cref="Cell.ObservationName"/> when present and recursively collecting names from each <see cref="Cell.SubObs"/>.
/// </summary>
/// <param name="cell">The <see cref="Cell"/> whose observation names and nested sub-observations are traversed.</param>
/// <returns>An <see cref="IEnumerable{String}"/> of observation names from the <paramref name="cell"/> and its sub-observations.</returns>
/// <!-- aidoc:v1 sig=0831490 body=43bfafd -->
private static IEnumerable<string> ExtractObservationNames(Cell cell)
{
// 1. Si la Cell tiene ObservationName, devolver esos nombres.
@@ -26,6 +26,14 @@ public partial class ComplexObjectValueTypeSerializer : SerializerBase<object>
[GeneratedRegex("ObjectId\\((.[a-f0-9]{24}.)\\)")]
private static partial Regex ObjectIdRegex();
/// <summary>
/// Deserializes a BSON value into a .NET <see cref="object"/>, handling primitive <see cref="BsonType"/> values directly, marker types (Null, EndOfDocument, Undefined, MinKey, MaxKey) as <c>false</c>, embedded <see cref="BsonDocument"/> instances by resolving the <c>_t</c> type discriminator with legacy namespace normalization (mapping <c>adas-core.Models</c> to <c>adas-core.Domain.Models</c>), and <see cref="BsonArray"/> values as a <see cref="List{T}"/> of the inferred element type after cleaning <c>$oid</c> wrappers from the intermediate JSON.
/// </summary>
/// <param name="context">The <see cref="BsonDeserializationContext"/> whose <see cref="BsonDeserializationContext.Reader"/> supplies the BSON tokens to read.</param>
/// <param name="args">The <see cref="BsonDeserializationArgs"/> carrying additional deserialization configuration.</param>
/// <returns>An <see cref="object"/> representing the deserialized value: a primitive returned directly, <c>false</c> for marker types, an instance of the type indicated by the <c>_t</c> field for documents, or a typed <see cref="List{T}"/> for arrays.</returns>
/// <exception cref="Exception">Thrown when a <see cref="BsonDocument"/> lacks a <c>_t</c> discriminator or a <c>_v</c> array payload, the referenced <see cref="Type"/> cannot be resolved via <see cref="Type.GetType(string)"/>, the element type of a non-empty <see cref="BsonArray"/> cannot be determined, the current <see cref="BsonType"/> is unhandled, or any inner step via <see cref="JsonConvert.DeserializeObject(string, System.Type, JsonSerializerSettings)"/> fails.</exception>
/// <!-- aidoc:v1 sig=b805219 body=fc5d56f -->
public override object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
try
@@ -11,6 +11,13 @@ namespace adas_core.Domain.Utils;
public static class DetailConfigExtension
{
// Método principal para iniciar la extracción
/// <summary>
/// Retrieves all unique observation names defined in the nurse rows of the specified <paramref name="config"/>.
/// Returns an empty list when <see cref="CardDetailsConfig.NurseRows"/> is null.
/// </summary>
/// <param name="config">The <see cref="CardDetailsConfig"/> extension target whose nurse rows are inspected.</param>
/// <returns>A <see cref="List{String}"/> containing the distinct observation names extracted from the nurse rows; an empty list when no nurse rows are defined.</returns>
/// <!-- aidoc:v1 sig=1a41350 body=9520d6e -->
public static List<string> GetAllObservationNames(this CardDetailsConfig config)
{
if (config.NurseRows == null) return [];
@@ -24,6 +31,12 @@ public static class DetailConfigExtension
}
// --- Auxiliar 1: Recorre la anidación de Filas (RowDetailsConfig) ---
/// <summary>
/// Recursively extracts names from a collection of <see cref="RowDetailsConfig"/> entries, traversing both the <see cref="RowDetailsConfig.Cells"/> and nested <see cref="RowDetailsConfig.Rows"/> of each row.
/// </summary>
/// <param name="rows">The list of <see cref="RowDetailsConfig"/> instances to process.</param>
/// <returns>An <see cref="IEnumerable{T}"/> of <see cref="string"/> containing all names collected from the cells and nested rows.</returns>
/// <!-- aidoc:v1 sig=4148c6b body=c6277a5 -->
private static IEnumerable<string> ExtractNamesFromRows(List<RowDetailsConfig> rows)
{
foreach (var row in rows)
@@ -43,6 +56,12 @@ public static class DetailConfigExtension
}
// --- Auxiliar 2: Recorre la anidación de Celdas (CellDetails) ---
/// <summary>
/// Recursively extracts every observation name from a <see cref="CellDetails"/>, yielding names from the current cell as well as from all its nested <see cref="CellDetails.Cells"/>. Null <see cref="CellDetails.ObservationName"/> and null <see cref="CellDetails.Cells"/> collections are safely skipped without yielding any elements.
/// </summary>
/// <param name="cell">The <see cref="CellDetails"/> whose observation names, including those of its descendant cells, should be collected.</param>
/// <returns>A lazily evaluated <see cref="IEnumerable{T}"/> of <see cref="string"/> containing every observation name found in <paramref name="cell"/> and its nested cells.</returns>
/// <!-- aidoc:v1 sig=a01fdc1 body=25dff85 -->
private static IEnumerable<string> ExtractNamesFromCells(CellDetails cell)
{
// 1. EXTRAER nombres del nivel actual
@@ -1,5 +1,14 @@
namespace adas_core.Domain.Utils;
/// <summary>
/// Represents a sealed dictionary that inherits from <see cref="Dictionary{TKey,TValue}"/> and provides equality comparison with <see cref="ComparableDictionary{TKey,TValue}"/> instances through <see cref="IEquatable{T}"/>.
/// </summary>
/// <typeparam name="TKey">The type of the keys stored in the dictionary, constrained to be non-null.</typeparam>
/// <typeparam name="TValue">The type of the values stored in the dictionary, constrained to be non-null.</typeparam>
/// <remarks>
/// The <see cref="IEquatable{T}"/> implementation targets <see cref="ComparableDictionary{TKey,TValue}"/> rather than the declaring <see cref="EquatableDictionary{TKey,TValue}"/> type, enabling cross-type equality semantics between the two dictionary variants.
/// </remarks>
/// <!-- aidoc:v1 sig=c2a0a45 -->
public sealed class EquatableDictionary<TKey, TValue>
: Dictionary<TKey, TValue>, IEquatable<ComparableDictionary<TKey, TValue>>
where TKey : notnull where TValue : notnull
+12
View File
@@ -3,12 +3,24 @@ using System.Reflection;
namespace adas_core.Domain.Utils;
/// <summary>
/// Provides a static mapping utility for instances of the reference type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The reference type that this mapper operates on, constrained to reference types via the <c>class</c> constraint.</typeparam>
/// <remarks>
/// As indicated by the <c>where T : class</c> constraint, only reference types can be supplied as the generic argument for <typeparamref name="T"/>.
/// </remarks>
/// <!-- aidoc:v1 sig=4a87291 -->
public static class Mapper<T>
// We can only use reference types
where T : class
{
private static readonly Dictionary<string, PropertyInfo> PropertyMap;
/// <summary>
/// Initializes the static <see cref="Mapper{T}.PropertyMap"/> cache used by the mapper to look up <see cref="System.Reflection.PropertyInfo"/> entries for the type parameter T by their lowercased property name.
/// </summary>
/// <!-- aidoc:v1 sig=ed9693b body=3dc0e55 -->
static Mapper()
{
// At this point we can convert each
+12
View File
@@ -13,6 +13,11 @@ public sealed class MappingUtils : IMappingUtils
private readonly List<MappingInterventions>? _cccData;
private bool _isTransformedValue;
/// <summary>
/// Initializes a new instance of the <see cref="MappingUtils"/> class by loading the CCC mapping interventions from the supplied <see cref="ApiSettings"/> and resetting the transformed-value flag.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{TOptions}"/> wrapper whose <see cref="IOptions{TOptions}.Value"/> provides the <see cref="ApiSettings"/> whose <see cref="ApiSettings.MappingInterventions"/> data is stored in this instance.</param>
/// <!-- aidoc:v1 sig=396ced4 body=2be44b9 -->
public MappingUtils(IOptions<ApiSettings> apiSettings)
{
var cccMappingData = apiSettings.Value.MappingInterventions;
@@ -46,6 +51,13 @@ public sealed class MappingUtils : IMappingUtils
return null; // No se encontro el code
}*/
/// <summary>
/// Searches for an entry matching the supplied <paramref name="code"/> within the given <paramref name="category"/> and returns its associated type, name, and group. The <paramref name="code"/> may be a <see cref="double"/> (matched as an exact value or within a numeric range) or a <see cref="string"/> (parsed as a <see cref="double"/> when possible, otherwise compared as text). Returns <see langword="null"/> when no matching entry is found.
/// </summary>
/// <param name="code">The code to look up. Accepts a <see cref="double"/> for numeric matching and a <see cref="string"/> for text matching or numeric parsing.</param>
/// <param name="category">The category used to filter the entries; only entries whose category matches this value are considered.</param>
/// <returns>A tuple containing the <c>type</c>, <c>name</c>, and <c>group</c> of the matching entry, or <see langword="null"/> when no match is found.</returns>
/// <!-- aidoc:v1 sig=b69e7ef body=e42117e -->
public (string type, string name, string group)? SearchByCode(object code, string category)
{
// esta funcion conviete a double los string que permitan conversion si no se puede los deja como string
+12
View File
@@ -10,6 +10,12 @@ namespace adas_core.Domain.Utils;
/// </summary>
public class RelayHelper
{
/// <summary>
/// Retrieves the current status of a <see cref="Relay"/> by calling a local REST API endpoint built from its connection parameters, returning <see langword="true"/> when the relay is reported as active and <see langword="false"/> when the response is not <see cref="HttpStatusCode.OK"/>, the payload cannot be converted to a boolean, or any exception is raised during the request.
/// </summary>
/// <param name="relay">The <see cref="Relay"/> whose status is queried; its <see cref="Relay.RelayNumber"/> is used in the URL path while <see cref="Relay.Driver"/>, <see cref="Relay.Ip"/>, and <see cref="Relay.Port"/> are passed as query parameters.</param>
/// <returns><see langword="true"/> if the API responds with <see cref="HttpStatusCode.OK"/> and the response body converts to a boolean value of <see langword="true"/>; otherwise, <see langword="false"/>.</returns>
/// <!-- aidoc:v1 sig=0240829 body=a1db00d -->
public static bool GetRelayStatusFromApiRest(Relay relay)
{
UriBuilder builder = new()
@@ -94,6 +100,12 @@ public class RelayHelper
PowerRelay(relay, builder);
}
/// <summary>
/// Sends an HTTP POST request to power a <see cref="Relay"/> through the endpoint described by <paramref name="builder"/>, enriching the query string with the relay's driver, IP address, port, and a fixed channel count of 8. Logs an information message when the response status is not <see cref="HttpStatusCode.OK"/> and logs any exception raised during the call at debug level instead of propagating it.
/// </summary>
/// <param name="relay">The relay to power, whose <see cref="Relay.Driver"/>, <see cref="Relay.Ip"/> and <see cref="Relay.Port"/> values are written into the request query string.</param>
/// <param name="builder">The <see cref="UriBuilder"/> whose query string is populated and whose <see cref="UriBuilder.Uri"/> identifies the target endpoint of the POST request.</param>
/// <!-- aidoc:v1 sig=01d6944 body=089ce17 -->
private static void PowerRelay(Relay relay, UriBuilder builder)
{
var query = HttpUtility.ParseQueryString(builder.Query);