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
@@ -23,6 +23,13 @@ public class AdmissionRepository : MongoRepository<Admission>, IAdmissionReposit
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="AdmissionRepository"/> class, passing the MongoDB database to the base repository and storing the API configuration values used by the repository.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> providing the <see cref="ApiSettings"/> values required by the repository.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> passed to the base repository constructor.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="apiSettings"/> is null.</exception>
/// <!-- aidoc:v1 sig=b1a21dd body=d2b18a3 -->
public AdmissionRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
@@ -13,6 +13,12 @@ public class PoCMappingRepository : MongoRepository<PoCMapping>, IPoCMappingRepo
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="PoCMappingRepository"/> class, storing the resolved <see cref="ApiSettings"/> and forwarding the supplied <see cref="IMongoDatabase"/> to the base repository to support persistence of PoC mappings.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> wrapper that exposes the application's <see cref="ApiSettings"/>.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> instance passed to the base class to establish the MongoDB connection.</param>
/// <!-- aidoc:v1 sig=443b0db body=12fddac -->
public PoCMappingRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
_apiSettings = apiSettings.Value;
@@ -39,6 +39,12 @@ public class PatientCarePlanRepository : MongoRepository<PatientCarePlan>, IPati
/// <summary>
/// Initializes a new instance of the <see cref="PatientCarePlanRepository"/> class with the supplied API configuration and MongoDB database connection, forwarding the database to the base repository.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> providing the <see cref="ApiSettings"/> assigned to the repository.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> connection passed to the base class for data access.</param>
/// <!-- aidoc:v1 sig=ab4ee14 body=12fddac -->
public PatientCarePlanRepository(
IOptions<ApiSettings> apiSettings,
IMongoDatabase database
@@ -22,6 +22,13 @@ public class PatientRepository : MongoRepository<Patient>, IPatientRepository
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of <see cref="PatientRepository"/>, a MongoDB-backed data repository, capturing API configuration from <see cref="IOptions{ApiSettings}"/> and forwarding the <see cref="IMongoDatabase"/> to the base repository constructor.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> whose value supplies the repository's API configuration.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> connection passed to the base class constructor.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="apiSettings"/> is null.</exception>
/// <!-- aidoc:v1 sig=113519f body=d2b18a3 -->
public PatientRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
@@ -279,6 +286,12 @@ public class PatientRepository : MongoRepository<Patient>, IPatientRepository
}
/// <summary>
/// Finds a <see cref="Patient"/> by <paramref name="patientNumber"/>, preferring the most recently admitted active patient (one whose <see cref="Patient.DisTime"/> is null) and falling back to the <see cref="Patient"/> record with the most recent non-null <see cref="Patient.DisTime"/> when no active admission exists. Returns null when <paramref name="patientNumber"/> is null, empty, or whitespace, or when no matching record is found.
/// </summary>
/// <param name="patientNumber">The patient number used to locate the <see cref="Patient"/> record.</param>
/// <returns>A <see cref="Task{Patient}"/> that resolves to the matching <see cref="Patient"/>, or null when no record is found.</returns>
/// <!-- aidoc:v1 sig=09c89ab body=91862bd -->
public async Task<Patient?> FindByPatientNumber(string patientNumber)
{
if (string.IsNullOrWhiteSpace(patientNumber)) return null;
@@ -305,6 +318,13 @@ public class PatientRepository : MongoRepository<Patient>, IPatientRepository
return patient;
}
/// <summary>
/// Searches for a <see cref="Patient"/> by <paramref name="patientNumber"/> whose <see cref="Patient.UnitId"/> differs from <paramref name="unitId"/>, intended to locate a patient identified at a Point of Care but registered in another unit. Returns <c>null</c> when the patient number is blank, when multiple matches are found (since the patient number may be incomplete), or when no match exists; exceptions are logged and also surface as <c>null</c>.
/// </summary>
/// <param name="patientNumber">The patient number used to look up the <see cref="Patient"/>.</param>
/// <param name="unitId">The <see cref="ObjectId"/> of the unit that must be excluded from the match.</param>
/// <returns>A <see cref="Task{Patient}"/> resolving to the matching <see cref="Patient"/>, or <c>null</c> when there is no unique match.</returns>
/// <!-- aidoc:v1 sig=382b7c8 body=f2b7752 -->
public async Task<Patient?> SearchByPatientNumberAndDistinctUnit(string patientNumber, ObjectId unitId)
{
try
@@ -328,6 +348,12 @@ public class PatientRepository : MongoRepository<Patient>, IPatientRepository
}
}
/// <summary>
/// Retrieves all <see cref="Patient"/> documents that contain at least one procedure considered finished and eligible for archival. A procedure qualifies when its <c>EndDate</c> is not null and the time elapsed since that <c>EndDate</c> exceeds the supplied grace period of <paramref name="archiveProcedureEndDateAfterMinutes"/> minutes relative to the current UTC time.
/// </summary>
/// <param name="archiveProcedureEndDateAfterMinutes">The grace period, in minutes, added to a procedure's <c>EndDate</c>; the procedure is treated as finished only when the resulting timestamp is earlier than <see cref="DateTime.UtcNow"/>.</param>
/// <returns>A <see cref="Task{List{Patient}}"/> containing the patients matching the finished-procedure criteria, or an empty list when no patient has a procedure whose archival grace period has elapsed.</returns>
/// <!-- aidoc:v1 sig=8527a2e body=acd9bfe -->
public async Task<List<Patient>> FindAllPatientWithFinishedProcedures(int archiveProcedureEndDateAfterMinutes)
{
var currentDateTime = DateTime.UtcNow;
@@ -359,6 +385,13 @@ public class PatientRepository : MongoRepository<Patient>, IPatientRepository
return patientsWithFinishedProcedures;
}
/// <summary>
/// Retrieves all <see cref="Patient"/> records whose tests have finished and whose end date, offset by the specified archive threshold, is earlier than the current UTC time.
/// The initial MongoDB filter keeps tests with a non-null EndDate, and the in-memory filter then retains only those whose EndDate plus <paramref name="archiveTestEndDateAfterMinutes"/> minutes is before <see cref="DateTime.UtcNow"/>.
/// </summary>
/// <param name="archiveTestEndDateAfterMinutes">The number of minutes added to each test's EndDate to determine whether the test is eligible for archival.</param>
/// <returns>A <see cref="Task{List{Patient}}"/> containing the patients whose tests meet the finished and archive criteria.</returns>
/// <!-- aidoc:v1 sig=c7d3a85 body=8559f5d -->
public async Task<List<Patient>> FindAllPatientWithFinishedTests(int archiveTestEndDateAfterMinutes)
{
var currentDateTime = DateTime.UtcNow;
@@ -389,6 +422,12 @@ public class PatientRepository : MongoRepository<Patient>, IPatientRepository
return patientsWithFinishedTests;
}
/// <summary>
/// Asynchronously retrieves all patients that have at least one finished <see cref="Patient.Treatment"/> whose <see cref="Treatment.EndDate"/> is older than <paramref name="archiveTreatmentEndDateAfterMinutes"/> minutes relative to the current UTC time, using a MongoDB query combined with an in-memory time threshold filter.
/// </summary>
/// <param name="archiveTreatmentEndDateAfterMinutes">The grace period in minutes that must elapse after a treatment's <see cref="Treatment.EndDate"/> before the patient qualifies for retrieval.</param>
/// <returns>A <see cref="Task{List{Patient}}"/> that resolves to the list of <see cref="Patient"/> records whose treatments satisfy the finished-treatment time threshold.</returns>
/// <!-- aidoc:v1 sig=6b43cdf body=429c102 -->
public async Task<List<Patient>> FindAllPatientWithFinishedTreatment(int archiveTreatmentEndDateAfterMinutes)
{
var currentDateTime = DateTime.UtcNow;
@@ -414,6 +453,19 @@ public class PatientRepository : MongoRepository<Patient>, IPatientRepository
return patientsWithFinishedTreatments;
}
/// <summary>
/// Updates a master list option for all patients belonging to the specified <paramref name="unitIds"/>,
/// handling <see cref="MasterListType.DiagnosisList"/>, <see cref="MasterListType.DoctorList"/>,
/// and <see cref="MasterListType.OriginList"/> cases by updating the relevant fields and auxiliary fields,
/// and returning the updated <see cref="Patient"/> documents. If <paramref name="typeName"/> cannot be parsed
/// as a <see cref="MasterListType"/> or the type is not implemented, an empty list is returned.
/// </summary>
/// <param name="unitIds">The collection of unit identifiers used to scope the update to the affected patients.</param>
/// <param name="opt">The DTO containing the existing option and the replacement option values to apply.</param>
/// <param name="typeName">The textual name of the <see cref="MasterListType"/> that determines which update path is executed.</param>
/// <returns>A <see cref="Task{TResult}"/> containing the updated <see cref="List{Patient}"/> documents,
/// or an empty list when no update was performed.</returns>
/// <!-- aidoc:v1 sig=afe83cc body=25f24cf -->
public async Task<List<Patient>> UpdateMasterListOption(List<ObjectId> unitIds, UpdateOptionMasterListDto opt,
string typeName)
{
@@ -593,6 +645,14 @@ public class PatientRepository : MongoRepository<Patient>, IPatientRepository
}
/// <summary>
/// Deletes a master list option from <see cref="Patient"/> documents belonging to the specified units, applying the appropriate update logic based on the resolved <see cref="MasterListType"/>. Returns the affected patients for the supported types (<see cref="MasterListType.DiagnosisList"/>, <see cref="MasterListType.DoctorList"/>, and <see cref="MasterListType.OriginList"/>), or an empty collection when <paramref name="typeName"/> cannot be parsed or the type has no handling logic.
/// </summary>
/// <param name="unitIds">The collection of <see cref="ObjectId"/> values identifying the units whose patients will be affected by the deletion.</param>
/// <param name="opt">The <see cref="OptionList"/> option to remove, matched by its <see cref="OptionList.Name"/> (for diagnosis and origin lists) or its <see cref="OptionList.Id"/> (for the doctor list).</param>
/// <param name="typeName">The textual name of the master list type, parsed via <see cref="Enum.TryParse{T}"/> with <typeparamref name="T"/> = <see cref="MasterListType"/> to select the update strategy.</param>
/// <returns>A <see cref="Task"/> that yields the <see cref="Patient"/> documents modified for the supported <see cref="MasterListType"/> values, or an empty <see cref="List{Patient}"/> when no updates are performed.</returns>
/// <!-- aidoc:v1 sig=800d406 body=d26e8f1 -->
public async Task<IEnumerable<Patient>> DeleteMasterListOption(List<ObjectId> unitIds, OptionList opt,
string typeName)
{
@@ -714,6 +774,12 @@ public class PatientRepository : MongoRepository<Patient>, IPatientRepository
return new List<Patient>();
}
/// <summary>
/// Finds the <see cref="Patient"/> associated with the specified <see cref="Patient.PatientId"/>, preferring an active admission (no <see cref="Patient.DisTime"/>) sorted by most recent <see cref="Patient.AdmTime"/>, and falling back to the most recently discharged record when no active admission exists.
/// </summary>
/// <param name="patientId">The identifier of the patient to locate.</param>
/// <returns>A <see cref="Patient"/> instance if found; otherwise, <see langword="null"/> when <paramref name="patientId"/> is null, empty, or whitespace, or when no matching record exists.</returns>
/// <!-- aidoc:v1 sig=fca9190 body=71f3c84 -->
public async Task<Patient?> FindByPatientId(string patientId)
{
if (string.IsNullOrWhiteSpace(patientId)) return null;
@@ -729,6 +795,12 @@ public class PatientRepository : MongoRepository<Patient>, IPatientRepository
return patient;
}
/// <summary>
/// Retrieves the most relevant <see cref="Patient"/> record for the specified identifier, prioritizing an active admission (no discharge time) ordered by the latest <see cref="Patient.AdmTime"/>, and falling back to the most recently discharged patient ordered by <see cref="Patient.DisTime"/> when no active admission exists.
/// </summary>
/// <param name="patientId">The <see cref="ObjectId"/> of the <see cref="Patient"/> to look up.</param>
/// <returns>The matching <see cref="Patient"/> if one is found; otherwise, <see langword="null"/>.</returns>
/// <!-- aidoc:v1 sig=b9e9549 body=8f9c8ea -->
public async Task<Patient?> FindByPatientId(ObjectId patientId)
{
//Último paciente admitido
@@ -782,6 +854,11 @@ public class PatientRepository : MongoRepository<Patient>, IPatientRepository
return await result.ToListAsync();
}
/// <summary>
/// Asynchronously retrieves all <see cref="Patient"/> records whose associated point of care is not a virtual <see cref="VirtualPointOfCare"/>, by performing a lookup against the <c>pointOfCares</c> collection and excluding any bed whose value matches a virtual point of care.
/// </summary>
/// <returns>A <see cref="Task"/> that resolves to a <see cref="List{Patient}"/> containing the patients located in active (non-virtual) points of care.</returns>
/// <!-- aidoc:v1 sig=2479e43 body=f5b7981 -->
public async Task<List<Patient>> FindInActivePoC()
{
var virtualPointOfCareValues = Enum.GetValues(typeof(VirtualPointOfCare)).Cast<VirtualPointOfCare>()
@@ -812,6 +889,12 @@ public class PatientRepository : MongoRepository<Patient>, IPatientRepository
}
/// <summary>
/// Asynchronously retrieves the <see cref="Patient"/> records whose associated point of care has a bed value matching one of the <see cref="VirtualPointOfCare"/> enum values.
/// The lookup is performed through a MongoDB aggregation pipeline that joins the patients collection with the point of care collection and filters by the <c>pointOfCareInfo.bed</c> field.
/// </summary>
/// <returns>A <see cref="Task"/> that yields a <see cref="List{Patient}"/> containing the patients linked to a point of care whose bed matches any <see cref="VirtualPointOfCare"/> value.</returns>
/// <!-- aidoc:v1 sig=1a67064 body=3dc3451 -->
public async Task<List<Patient>> FindInInactivePoC()
{
var virtualPointOfCareValues = Enum.GetValues(typeof(VirtualPointOfCare)).Cast<VirtualPointOfCare>()
@@ -18,6 +18,13 @@ public class PoCSettingsRepository : MongoRepository<PoCSettings>, IPoCSettingsR
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of <see cref="PoCSettingsRepository"/>, capturing the API configuration from <paramref name="apiSettings"/> and forwarding the MongoDB database to the base repository.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> wrapping the <see cref="ApiSettings"/> configuration values.</param>
/// <param name="database">The <see cref="MongoDB.Driver.IMongoDatabase"/> passed to the base repository for data access.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="apiSettings"/> is <see langword="null"/>.</exception>
/// <!-- aidoc:v1 sig=6bccd95 body=d2b18a3 -->
public PoCSettingsRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
@@ -20,6 +20,13 @@ public class PointOfCareRepository : MongoRepository<PointOfCare>, IPointOfCareR
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="PointOfCareRepository"/> repository, capturing the configured <see cref="ApiSettings"/> and delegating the <see cref="IMongoDatabase"/> to the base class.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> providing access to the configured <see cref="ApiSettings"/>.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> forwarded to the base constructor.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="apiSettings"/> is <c>null</c>.</exception>
/// <!-- aidoc:v1 sig=5b54ed9 body=99d85d9 -->
public PointOfCareRepository(IOptions<ApiSettings>? apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings != null)
@@ -242,6 +249,14 @@ public class PointOfCareRepository : MongoRepository<PointOfCare>, IPointOfCareR
}
}
/// <summary>
/// Asynchronously finds a <see cref="PointOfCare"/> matching the specified <paramref name="bed"/> and <paramref name="unitId"/>.
/// Returns <see langword="null"/> when the bed is null or empty, when no matching document is found, or when an error occurs.
/// </summary>
/// <param name="bed">The bed identifier to search for. If null or empty, the method returns <see langword="null"/> without querying.</param>
/// <param name="unitId">The unit identifier used to filter the <see cref="PointOfCare"/> documents.</param>
/// <returns>A task containing the first matching <see cref="PointOfCare"/>, or <see langword="null"/> if no match is found.</returns>
/// <!-- aidoc:v1 sig=03d5e9a body=92ba139 -->
public async Task<PointOfCare?> FindByBedAndUnitId(string? bed, ObjectId unitId)
{
try
@@ -386,6 +401,12 @@ public class PointOfCareRepository : MongoRepository<PointOfCare>, IPointOfCareR
throw;
}
}
/// <summary>
/// Asynchronously counts the <see cref="PointOfCare"/> records associated with the supplied <paramref name="unitId"/>, applying a filter that targets documents whose Bed value corresponds to one of the inactive <see cref="VirtualPointOfCare"/> states such as Pushed, Unknown, Deleted, NoBed, Cancelled, Recovered, UnitData, or Moved.
/// </summary>
/// <param name="unitId">The identifier of the unit whose associated <see cref="PointOfCare"/> documents are filtered and counted.</param>
/// <returns>A <see cref="Task{Int64}"/> representing the asynchronous operation, with the result being the number of matching <see cref="PointOfCare"/> documents.</returns>
/// <!-- aidoc:v1 sig=040b525 body=8d8d306 -->
public async Task<long> CountVirtualsByUnitId(ObjectId unitId)
{
try
@@ -680,6 +701,12 @@ public class PointOfCareRepository : MongoRepository<PointOfCare>, IPointOfCareR
}
//Deprecated PatientLocation by UnitName
/// <summary>
/// Asynchronously searches for the first <see cref="PointOfCare"/> matching the supplied <paramref name="patientLocation"/> criteria, combining equality filters for <see cref="PatientLocation.UnitName"/>, <see cref="PatientLocation.Bed"/> and <see cref="PatientLocation.Room"/> when their values are provided; if no criteria are provided an empty filter is used.
/// </summary>
/// <param name="patientLocation">The <see cref="PatientLocation"/> whose non-empty fields (<see cref="PatientLocation.UnitName"/>, <see cref="PatientLocation.Bed"/>, <see cref="PatientLocation.Room"/>) are used to build the search filters.</param>
/// <returns>A <see cref="Task{PointOfCare}"/> that yields the first matching <see cref="PointOfCare"/>, or <see langword="null"/> when no document matches or when an error is caught and logged.</returns>
/// <!-- aidoc:v1 sig=ee884e8 body=c1e5afa -->
public async Task<PointOfCare?> FindByPatientLocation(PatientLocation patientLocation)
{
try
@@ -17,6 +17,12 @@ public class PumpAlarmEventRepository : MongoRepository<PumpAlarmEvent>, IPumpAl
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="PumpAlarmEventRepository"/> repository, capturing the configured <see cref="ApiSettings"/> from <paramref name="apiSettings"/> and forwarding <paramref name="database"/> to the base repository for persistence operations.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> wrapper that exposes the application's <see cref="ApiSettings"/>.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> passed to the base constructor and used to perform MongoDB operations.</param>
/// <!-- aidoc:v1 sig=cfddddb body=12fddac -->
public PumpAlarmEventRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database)
: base(database)
{
@@ -25,11 +31,20 @@ public class PumpAlarmEventRepository : MongoRepository<PumpAlarmEvent>, IPumpAl
/// <summary>
/// Retrieves the collection name used for pump alarm events, returning the configured value from _apiSettings.PumpAlarmEvent when set, or falling back to the default "pump_alarm_event".
/// </summary>
/// <returns>The configured pump alarm event collection name, or the default "pump_alarm_event" when no configuration value is available.</returns>
/// <!-- aidoc:v1 sig=94e22ff body=9e4a133 -->
public override string GetCollectionName()
{
return _apiSettings.PumpAlarmEvent ?? "pump_alarm_event";
}
/// <summary>
/// Creates the MongoDB indexes for the PumpAlarmEvent collection, optimizing the most common query patterns: device lookup with reverse-chronological time ordering, time-only range queries, patient lookup, and device queries filtered by alarm type.
/// </summary>
/// <!-- aidoc:v1 sig=4955da2 body=fae571b -->
public override async Task CreateIndexes()
{
var indexModels = new List<CreateIndexModel<PumpAlarmEvent>>
@@ -63,6 +78,11 @@ public class PumpAlarmEventRepository : MongoRepository<PumpAlarmEvent>, IPumpAl
}
/// <summary>
/// Asynchronously inserts a new <see cref="PumpAlarmEvent"/> document into the underlying MongoDB collection.
/// </summary>
/// <param name="alarmEvent">The <see cref="PumpAlarmEvent"/> record to persist.</param>
/// <!-- aidoc:v1 sig=5de5fec body=d69d42c -->
public async Task InsertAsync(PumpAlarmEvent alarmEvent)
{
await Collection.InsertOneAsync(alarmEvent);
@@ -85,6 +105,12 @@ public class PumpAlarmEventRepository : MongoRepository<PumpAlarmEvent>, IPumpAl
return await find.ToListAsync();
}
/// <summary>
/// Asynchronously retrieves the most recent <see cref="PumpAlarmEvent"/> for the device identified by <paramref name="deviceId"/>, returning the entry with the latest time stamp, or <c>null</c> if no event exists.
/// </summary>
/// <param name="deviceId">The identifier of the device whose latest alarm event is being retrieved.</param>
/// <returns>A <see cref="Task{PumpAlarmEvent}"/> that yields the latest <see cref="PumpAlarmEvent"/> associated with <paramref name="deviceId"/>, or <c>null</c> if no matching event is found.</returns>
/// <!-- aidoc:v1 sig=f0fbfb3 body=088b34a -->
public async Task<PumpAlarmEvent?> FindLastByDeviceIdAsync(string deviceId)
{
return await Collection
@@ -93,12 +119,25 @@ public class PumpAlarmEventRepository : MongoRepository<PumpAlarmEvent>, IPumpAl
.FirstOrDefaultAsync();
}
/// <summary>
/// Asynchronously removes all documents linked to the specified patient by deleting every record whose PatientId matches the supplied <paramref name="patientId"/>.
/// </summary>
/// <param name="patientId">The <see cref="ObjectId"/> of the patient whose associated documents should be deleted.</param>
/// <!-- aidoc:v1 sig=4776e51 body=395df12 -->
public async Task DeleteByPatientId(ObjectId patientId)
{
await Collection.DeleteManyAsync(x => x.PatientId == patientId);
}
/// <summary>
/// Asynchronously updates the value of the specified field across multiple <see cref="PumpAlarmEvent"/> documents, replacing occurrences of <paramref name="oldId"/> with <paramref name="newId"/>, and returns the number of documents that were modified.
/// </summary>
/// <param name="fieldName">The name of the <see cref="MongoDB.Bson.ObjectId"/> field on <see cref="PumpAlarmEvent"/> whose value should be replaced.</param>
/// <param name="newId">The new <see cref="MongoDB.Bson.ObjectId"/> value to assign to the field in matching documents.</param>
/// <param name="oldId">The existing <see cref="MongoDB.Bson.ObjectId"/> value used to identify documents to be updated.</param>
/// <returns>The number of <see cref="PumpAlarmEvent"/> documents modified by the bulk update.</returns>
/// <!-- aidoc:v1 sig=207e960 body=64489e6 -->
public async Task<long> UpdateManyObjectIdByFiledNameAsync(string fieldName, ObjectId newId, ObjectId oldId)
{
var filter = Builders<PumpAlarmEvent>.Filter.Eq(fieldName, oldId);
@@ -15,6 +15,12 @@ public class PumpAlarmStateRepository : MongoRepository<PumpAlarmState>, IPumpAl
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="PumpAlarmStateRepository"/> class, which persists pump alarm state data, by storing the resolved <see cref="ApiSettings"/> and delegating MongoDB initialization to the base repository.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> instance whose <see cref="IOptions{TOptions}.Value"/> supplies the <see cref="ApiSettings"/> used by the repository.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> passed to the base constructor to provide the underlying MongoDB connection.</param>
/// <!-- aidoc:v1 sig=df28b3e body=12fddac -->
public PumpAlarmStateRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database)
: base(database)
{
@@ -32,6 +38,10 @@ public class PumpAlarmStateRepository : MongoRepository<PumpAlarmState>, IPumpAl
return _apiSettings.PumpAlarmState ?? "pump_alarm_state";
}
/// <summary>
/// Creates the MongoDB indexes required by the <see cref="PumpAlarmState"/> collection: a unique compound index on <see cref="PumpAlarmState.DeviceId"/>, <see cref="PumpAlarmState.AlarmType"/>, and <see cref="PumpAlarmState.AlarmCodeMdc"/> (named <c>ux_device_alarm</c>), plus supporting indexes on <see cref="PumpAlarmState.DeviceId"/> and <see cref="PumpAlarmState.PatientId"/>.
/// </summary>
/// <!-- aidoc:v1 sig=4955da2 body=cfe5f4a -->
public override async Task CreateIndexes()
{
var indexModels = new List<CreateIndexModel<PumpAlarmState>>
@@ -80,6 +90,15 @@ public class PumpAlarmStateRepository : MongoRepository<PumpAlarmState>, IPumpAl
return await Collection.Find(filter).FirstOrDefaultAsync();
}
/// <summary>
/// Inserts or updates an active <see cref="PumpAlarmState"/> document, reusing the identifier of an
/// existing record that already matches the same <see cref="PumpAlarmState.DeviceId"/>, <see cref="PumpAlarmState.AlarmType"/>
/// and <see cref="PumpAlarmState.AlarmCodeMdc"/> combination, or generating a new <see cref="ObjectId"/> when
/// <paramref name="state"/> does not yet carry one.
/// </summary>
/// <param name="state">The <see cref="PumpAlarmState"/> to persist; its <see cref="PumpAlarmState.Id"/> is
/// populated from the matching document when one is found, or newly generated when it is currently <see cref="ObjectId.Empty"/>.</param>
/// <!-- aidoc:v1 sig=9119854 body=4bd6c92 -->
public async Task UpsertActiveAsync(PumpAlarmState state)
{
var filter =
@@ -19,6 +19,12 @@ namespace adas_core.Infrastructure.Repositories
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="PumpArchiveRepository"/> class, forwarding <paramref name="database"/> to the base repository and storing the resolved <see cref="ApiSettings"/> configuration for subsequent operations.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> wrapper whose <see cref="IOptions{T}.Value"/> supplies the current <see cref="ApiSettings"/>.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> connection passed to the base class constructor.</param>
/// <!-- aidoc:v1 sig=875c7ca body=12fddac -->
public PumpArchiveRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database)
: base(database)
{
@@ -26,12 +32,21 @@ namespace adas_core.Infrastructure.Repositories
}
/// <summary>
/// Returns the agreed MongoDB collection name used to store archived pump observations for patients, falling back to the default value when the corresponding setting is not configured.
/// </summary>
/// <returns>The collection name to use, either the value configured in <c>ArchivePatientsPumpobservations</c> or the default <c>archive_pumpobservations</c>.</returns>
/// <!-- aidoc:v1 sig=94e22ff body=09ed313 -->
public override string GetCollectionName()
{
// Nombre de colección pactado: "archive_pumpobservations"
return _apiSettings.ArchivePatientsPumpobservations ?? "archive_pumpobservations";
}
/// <summary>
/// Creates the MongoDB indexes required by the <see cref="PumpObservation"/> collection: an ascending index on <see cref="PumpObservation.PatientId"/> for patient-based lookups and audits, a compound index on <see cref="PumpObservation.DeviceId"/> (ascending) and <see cref="PumpObservation.Time"/> (descending) for per-device timelines, and a descending index on <see cref="PumpObservation.Time"/> for chronological ordering.
/// </summary>
/// <!-- aidoc:v1 sig=4955da2 body=2c1d18d -->
public override async Task CreateIndexes()
{
var indexModels = new List<CreateIndexModel<PumpObservation>>
@@ -23,6 +23,12 @@ namespace adas_core.Infrastructure.Repositories
/// <summary>
/// Initializes a new instance of the <see cref="PumpObservationRepository"/> class, capturing the <see cref="ApiSettings"/> configuration and forwarding the <see cref="IMongoDatabase"/> to the base repository to back pump observation data.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> providing API configuration values assigned to the repository.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> passed to the base class to supply the MongoDB connection.</param>
/// <!-- aidoc:v1 sig=8a1d3fa body=12fddac -->
public PumpObservationRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
_apiSettings = apiSettings.Value;
@@ -37,6 +43,10 @@ namespace adas_core.Infrastructure.Repositories
return _apiSettings.PumpObservations ?? "pump_observations";
}
/// <summary>
/// Creates the MongoDB indexes for the <see cref="PumpObservation"/> collection, defining a compound index on <see cref="PumpObservation.DeviceId"/> (ascending) and <see cref="PumpObservation.Time"/> (descending) to optimize per-pump timeline queries and a single-field index on <see cref="PumpObservation.PatientId"/> for patient-scoped lookups. A commented TTL index on <see cref="PumpObservation.Time"/> is included as a reference for enabling direct MongoDB retention when needed.
/// </summary>
/// <!-- aidoc:v1 sig=4955da2 body=e820feb -->
public override async Task CreateIndexes()
{
var indexModels = new List<CreateIndexModel<PumpObservation>>
@@ -149,6 +159,12 @@ namespace adas_core.Infrastructure.Repositories
return await query.ToListAsync();
}
/// <summary>
/// Asynchronously retrieves the most recent observation time for every patient that has at least one observation with a non-null patient identifier, by running a MongoDB aggregation that groups observations by patient and selects the maximum time per group.
/// Documents whose grouped identifier is not an <see cref="ObjectId"/> or whose maximum time is not a valid <see cref="DateTime"/> are skipped from the result, and the remaining timestamps are normalized to UTC.
/// </summary>
/// <returns>A <see cref="Task{Dictionary}"/> that yields a dictionary keyed by the patient's <see cref="ObjectId"/> with the latest observation <see cref="DateTime"/> as the value.</returns>
/// <!-- aidoc:v1 sig=9cf32b6 body=db998dd -->
public async Task<Dictionary<ObjectId, DateTime>> FindAllLastPatientObservationTimeAsync()
{
// Pipeline:
@@ -321,6 +337,14 @@ namespace adas_core.Infrastructure.Repositories
}
/// <summary>
/// Deletes older <see cref="PumpObservation"/> entries for the specified <paramref name="name"/>, keeping only the <paramref name="maxCount"/> most recent records ordered by <see cref="PumpObservation.Time"/>.
/// Returns <c>0</c> when <paramref name="name"/> is null or whitespace, when the existing count does not exceed <paramref name="maxCount"/>, or when there is nothing left to delete after skipping the most recent items.
/// </summary>
/// <param name="name">Name used to filter the <see cref="PumpObservation"/> documents to be considered for deletion.</param>
/// <param name="maxCount">Maximum number of most recent <see cref="PumpObservation"/> entries to retain; any additional older entries will be removed.</param>
/// <returns>The number of <see cref="PumpObservation"/> documents deleted, or <c>0</c> when no deletion was required.</returns>
/// <!-- aidoc:v1 sig=ae5008a body=6960e61 -->
public async Task<long> DeleteOlderNumberAsync(string name, int maxCount)
{
if (string.IsNullOrWhiteSpace(name))
@@ -15,6 +15,12 @@ namespace adas_core.Infrastructure.Repositories
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of <see cref="PumpStateRepository"/>, storing the resolved <see cref="ApiSettings"/> from <paramref name="apiSettings"/> and passing the <see cref="IMongoDatabase"/> to the base class constructor.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> providing the <see cref="ApiSettings"/> configuration values used by the repository.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> forwarded to the base class to establish the underlying data connection.</param>
/// <!-- aidoc:v1 sig=48961b9 body=12fddac -->
public PumpStateRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database)
: base(database)
{
@@ -31,6 +37,10 @@ namespace adas_core.Infrastructure.Repositories
return _apiSettings.PumpStates ?? "pump_states";
}
/// <summary>
/// Creates the MongoDB indexes required by the <see cref="PumpState"/> collection, including a unique index on <see cref="PumpState.DeviceId"/>, a compound index on <see cref="PumpState.DeviceId"/> and <see cref="PumpState.LastUpdated"/> for time-based queries, and an index on <see cref="PumpState.PatientId"/> for patient-scoped lookups.
/// </summary>
/// <!-- aidoc:v1 sig=4955da2 body=fd5fa60 -->
public override async Task CreateIndexes()
{
var indexModels = new List<CreateIndexModel<PumpState>>
@@ -14,6 +14,13 @@ public class RecordingAlertArchiveRepository : MongoRepository<PatientRecordingA
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="RecordingAlertArchiveRepository"/> class, which provides repository access to recording alert archive data, by storing the resolved <see cref="ApiSettings"/> configuration and forwarding the supplied <see cref="IMongoDatabase"/> to the base repository.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> containing the API configuration values assigned to the repository.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> passed to the base class for persistence operations.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="apiSettings"/> is null.</exception>
/// <!-- aidoc:v1 sig=63386fa body=d2b18a3 -->
public RecordingAlertArchiveRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
@@ -18,6 +18,13 @@ public class RecordingAlertRepository : MongoRepository<PatientRecordingAlert>,
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="RecordingAlertRepository"/> class, capturing the API configuration and forwarding the MongoDB database to the base repository to support recording-alert persistence operations.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> providing access to the <see cref="ApiSettings"/> values.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> passed to the base class constructor.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="apiSettings"/> is <see langword="null"/>.</exception>
/// <!-- aidoc:v1 sig=a457f4a body=d2b18a3 -->
public RecordingAlertRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
@@ -23,6 +23,12 @@ public class RelayRepository : MongoRepository<Relay>, IRelayRepository
/// <summary>
/// Initializes a new instance of the <see cref="RelayRepository"/> class, a MongoDB-backed repository that depends on <see cref="ApiSettings"/>. It forwards the <paramref name="database"/> to the base constructor and stores the configuration obtained from <paramref name="apiSettings"/>.
/// </summary>
/// <param name="database">The <see cref="IMongoDatabase"/> instance passed to the base class.</param>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> wrapper supplying the active <see cref="ApiSettings"/> configuration.</param>
/// <!-- aidoc:v1 sig=f9dbbda body=12fddac -->
public RelayRepository(IMongoDatabase database, IOptions<ApiSettings> apiSettings) : base(database)
{
_apiSettings = apiSettings.Value;
@@ -18,6 +18,13 @@ public class SectionRepository : MongoRepository<Section>, ISectionRepository
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="SectionRepository"/> class, capturing the configured <see cref="ApiSettings"/> and forwarding the <see cref="IMongoDatabase"/> to the base repository.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> providing the resolved <see cref="ApiSettings"/> used by the repository.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> passed to the base constructor to enable MongoDB data access.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="apiSettings"/> is null.</exception>
/// <!-- aidoc:v1 sig=02bfd10 body=d2b18a3 -->
public SectionRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
@@ -14,6 +14,13 @@ public class ServiceConfigRepository : MongoRepository<ServiceConfig>, IServiceC
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="ServiceConfigRepository"/> class, capturing the <see cref="ApiSettings"/> from the supplied <see cref="IOptions{ApiSettings}"/> and forwarding the <paramref name="database"/> to the base repository for MongoDB-backed operations.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> providing access to the API configuration.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> passed to the base class.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="apiSettings"/> is <c>null</c>.</exception>
/// <!-- aidoc:v1 sig=e674d73 body=d2b18a3 -->
public ServiceConfigRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
@@ -15,6 +15,13 @@ public class TreatmentArchiveRepository : MongoRepository<PatientTreatment>, ITr
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="TreatmentArchiveRepository"/> class, which manages treatment archive records persisted in MongoDB. The constructor stores the API settings and forwards the <see cref="IMongoDatabase"/> connection to the base repository.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> wrapper exposing the application API settings required by the repository.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> instance passed to the base constructor to provide the storage context.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="apiSettings"/> is <see langword="null"/>.</exception>
/// <!-- aidoc:v1 sig=cb353ae body=d2b18a3 -->
public TreatmentArchiveRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
@@ -19,6 +19,13 @@ public class TreatmentRepository : MongoRepository<PatientTreatment>, ITreatment
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="TreatmentRepository"/> class by forwarding the <paramref name="database"/> to the base constructor and caching the <see cref="ApiSettings"/> resolved from <paramref name="apiSettings"/>.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> providing the <see cref="ApiSettings"/> instance stored by the repository.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> passed to the base class for MongoDB access.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="apiSettings"/> is null.</exception>
/// <!-- aidoc:v1 sig=3b30d15 body=d2b18a3 -->
public TreatmentRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
@@ -203,6 +210,12 @@ public class TreatmentRepository : MongoRepository<PatientTreatment>, ITreatment
return result.ToEnumerable();
}
/// <summary>
/// Retrieves a paginated, filterable query of <see cref="PatientTreatment"/> records sorted by <see cref="PatientTreatment.OrderTime"/> in descending order. When <paramref name="filter"/> carries a <c>FilteredRequest</c>, the query is narrowed by <see cref="PatientTreatment.PatientId"/>, an optional date range, and the active-treatments flag; otherwise default time-based filters are applied.
/// </summary>
/// <param name="filter">The pagination and search criteria used to build the MongoDB filter pipeline.</param>
/// <returns>An <see cref="IFindFluent{TSource, TDocument}"/> of <see cref="PatientTreatment"/> that can be paged or iterated.</returns>
/// <!-- aidoc:v1 sig=4a06ded body=ea0fa2f -->
public IFindFluent<PatientTreatment, PatientTreatment> GetPaginatedTreatments(PaginationFilter filter)
{
var filterBuilder = Builders<PatientTreatment>.Filter;
@@ -28,6 +28,12 @@ public class UnitRepository : MongoRepository<Unit>, IUnitRepository
/// <summary>
/// Initializes a new instance of the <see cref="UnitRepository"/> class by forwarding the <see cref="IMongoDatabase"/> to the base constructor and storing the <see cref="ApiSettings"/> obtained from <paramref name="apiSettings"/>.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> wrapper whose <see cref="IOptions{T}.Value"/> provides the <see cref="ApiSettings"/> configuration used by the repository.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> connection passed to the base class constructor.</param>
/// <!-- aidoc:v1 sig=303625e body=12fddac -->
public UnitRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
_apiSettings = apiSettings.Value;
@@ -105,6 +111,13 @@ public class UnitRepository : MongoRepository<Unit>, IUnitRepository
throw new NotImplementedException();
}
/// <summary>
/// Finds all <see cref="Unit"/> records linked to the supplied master list identifier, dynamically resolving the property to filter on based on <paramref name="masterListType"/>. Any failure encountered while querying is logged and rethrown.
/// </summary>
/// <param name="id">The <see cref="ObjectId"/> of the master list whose related units should be retrieved.</param>
/// <param name="masterListType">The <see cref="MasterListType"/> that selects which property of <see cref="Unit"/> is matched against <paramref name="id"/>.</param>
/// <returns>A task yielding an <see cref="IEnumerable{Unit}"/> with the units that satisfy the resolved filter.</returns>
/// <!-- aidoc:v1 sig=ec8caf6 body=2a1b3b7 -->
public async Task<IEnumerable<Unit>> FindByMasterListId(ObjectId id, MasterListType masterListType)
{
try
@@ -20,6 +20,13 @@ public class UserRepository : MongoRepository<User>, IUserRepository
{
private readonly ApiSettings _apiSettings;
/// <summary>
/// Initializes a new instance of the <see cref="UserRepository"/> class, passing the MongoDB database to the base constructor and storing the API settings required by the repository.
/// </summary>
/// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> containing the API settings used by the repository.</param>
/// <param name="database">The <see cref="IMongoDatabase"/> supplied to the base constructor for MongoDB data access.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="apiSettings"/> is <see langword="null"/>.</exception>
/// <!-- aidoc:v1 sig=4f76e46 body=d2b18a3 -->
public UserRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));