=== 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
@@ -16,6 +16,7 @@ namespace adas_core.Application.Customizations.HUVH.UCIN;
/// Represents a concrete implementation of the <see cref="ICalculatedObservations"/> interface,
/// providing a collection of calculated observation data.
/// </summary>
/// <!-- aidoc:v1 sig=1b16cfc -->
public class CalculatedObservations : ICalculatedObservations
{
private const string Spo2PreObservationName = "SpO2";
@@ -61,6 +62,7 @@ public class CalculatedObservations : ICalculatedObservations
/// </summary>
/// <param name="patientId">The unique identifier of the patient for whom the active bolus is calculated.</param>
/// <exception cref="NotImplementedException">Thrown because the method has not been implemented yet.</exception>
/// <!-- aidoc:v1 sig=7d38721 body=bfa6f2f -->
public Task CalculateActiveBolus(ObjectId patientId)
{
throw new NotImplementedException();
@@ -73,6 +75,8 @@ public class CalculatedObservations : ICalculatedObservations
/// <param name="obs">The patient observation to be mapped, which may be transformed depending on its name.</param>
/// <param name="onlyByName">Indicates whether the mapping should be performed using only the observation name.</param>
/// <returns>The mapped patient observation, potentially enriched with computed values, wrapped in a task.</returns>
/// <!-- aidoc-review:v1 severity=medium kind=wrong_param_role
/// "The 'onlyByName' parameter is documented as controlling whether 'the mapping should be performed using only the observation name,' but the parameter is never referenced in the method body, so passing a value for it has no effect on the mapping behavior." -->
public async Task<T?> Map<T>(T obs, bool onlyByName = false) where T : BasePatientObservation
{
if (obs.Name is "Intervention_In" or "Intervention_Out") await CalculateInterventionMultiValueObservation(obs);
@@ -105,6 +109,7 @@ public class CalculatedObservations : ICalculatedObservations
/// </summary>
/// <param name="treatment">The patient treatment to map, including its placer order, end time, and medicines.</param>
/// <returns>The mapped <see cref="PatientTreatment"/> with its order control type and medicines updated.</returns>
/// <!-- aidoc:v1 sig=442a6e8 body=e1bed22 -->
public async Task<PatientTreatment> Map(PatientTreatment treatment)
{
var order = treatment.PlacerOrder?.EntityIdentifier; //aquí almacenamos el número de orden
@@ -129,6 +134,7 @@ public class CalculatedObservations : ICalculatedObservations
/// </summary>
/// <param name="pumpObservation">The pump observation to map.</param>
/// <returns>A completed <see cref="Task{TResult}"/> containing the provided <see cref="PumpObservation"/>.</returns>
/// <!-- aidoc:v1 sig=50be4c1 body=e481734 -->
public async Task<PumpObservation> Map(PumpObservation pumpObservation)
{
return await Task.FromResult(pumpObservation);
@@ -140,6 +146,7 @@ public class CalculatedObservations : ICalculatedObservations
/// </summary>
/// <param name="activeMedicines">The list of active medicines from which distinct medication names are extracted to build the observation value.</param>
/// <param name="patientId">The identifier of the patient for whom the medication observation is calculated and stored.</param>
/// <!-- aidoc:v1 sig=299c0fe body=8145436 -->
public async Task CalculateMedicineObservation(List<Medicine> activeMedicines, ObjectId patientId)
{
var medicineObs = new PatientObservation
@@ -171,6 +178,7 @@ public class CalculatedObservations : ICalculatedObservations
/// </summary>
/// <param name="id">The unique <see cref="ObjectId"/> of the patient whose active treatments should be fetched.</param>
/// <returns>A task that represents the asynchronous operation, containing an <see cref="IEnumerable{T}"/> of nullable <see cref="PatientTreatment"/> instances for the patient.</returns>
/// <!-- aidoc:v1 sig=1c9e799 body=2a62eb7 -->
public async Task<IEnumerable<PatientTreatment?>> GetActiveTreatmentsByPatient(ObjectId id)
{
var activeTreatments = await _treatmentService.Value.GetActiveTreatmentsByPatient(id);
@@ -184,6 +192,7 @@ public class CalculatedObservations : ICalculatedObservations
/// <param name="diagnosis">The source <see cref="PatientDiagnosis"/> instance to be mapped.</param>
/// <returns>A <see cref="Task{PatientDiagnosis}"/> that represents the asynchronous mapping operation, containing the mapped <see cref="PatientDiagnosis"/>.</returns>
/// <exception cref="T:System.NotImplementedException">Thrown when the method is invoked, as the mapping logic has not yet been implemented.</exception>
/// <!-- aidoc:v1 sig=8ddf601 body=bfa6f2f -->
public Task<PatientDiagnosis> Map(PatientDiagnosis diagnosis)
{
throw new NotImplementedException();
@@ -195,6 +204,7 @@ public class CalculatedObservations : ICalculatedObservations
/// </summary>
/// <param name="newObservation">The new patient observation whose time may be adjusted to follow the most recent observation for the same patient and measurement.</param>
/// <returns>The patient observation with a corrected time if a time conflict was detected, or the original observation if no adjustment was needed or the name was invalid.</returns>
/// <!-- aidoc:v1 sig=2b42b30 body=04118be -->
public async Task<PatientObservation?> FixTimeInconsistencyWithLast(PatientObservation newObservation)
{
if (string.IsNullOrEmpty(newObservation.Name))
@@ -227,6 +237,7 @@ public class CalculatedObservations : ICalculatedObservations
/// </summary>
/// <param name="listToInsert">The list of patient observations to pre-map.</param>
/// <returns>A task that represents the asynchronous operation, containing the provided list of patient observations.</returns>
/// <!-- aidoc:v1 sig=5a37e9b body=0791af0 -->
public Task<List<PatientObservation>> PreMapList(List<PatientObservation> listToInsert)
{
return Task.FromResult(listToInsert);
@@ -238,6 +249,7 @@ public class CalculatedObservations : ICalculatedObservations
/// <param name="obs">The patient observation that the alarm is to be associated with.</param>
/// <param name="alarmToInsert">The alarm intended to be inserted into the observation.</param>
/// <returns>A task containing the patient observation, returned as-is.</returns>
/// <!-- aidoc:v1 sig=405db8e body=ea790e4 -->
public Task<PatientObservation> MapSourceAlarm(PatientObservation obs, PatientObservationAlarm alarmToInsert)
{
return Task.FromResult(obs);
@@ -250,6 +262,7 @@ public class CalculatedObservations : ICalculatedObservations
/// <param name="name">The name associated with the alarm.</param>
/// <param name="code">The optional alarm code categorizing the type of alarm to be sent.</param>
/// <exception cref="NotImplementedException">Thrown because the method has not been implemented.</exception>
/// <!-- aidoc:v1 sig=90426a4 body=bfa6f2f -->
public Task SendAlarm(PatientObservation obs, string name, AlarmEnum.Name? code)
{
throw new NotImplementedException();
@@ -261,6 +274,7 @@ public class CalculatedObservations : ICalculatedObservations
/// Returns without creating a record when the observation is not a <see cref="PatientObservation"/> or when its name does not match any of the supported scales.
/// </summary>
/// <param name="obs">The source patient observation used to derive the pain scale; only instances of <see cref="PatientObservation"/> with a supported name (ALPS, NPASS_Sedation, NPASS_Analgesia) are processed.</param>
/// <!-- aidoc:v1 sig=f89cebc body=f5dfb0c -->
private async Task CalculatePainScale(BasePatientObservation obs)
{
if (obs is not PatientObservation pobs) return;
@@ -314,6 +328,7 @@ public class CalculatedObservations : ICalculatedObservations
/// </summary>
/// <param name="obs">The base patient observation to process.</param>
/// <returns>The original <see cref="BasePatientObservation"/> if it is not a <see cref="PatientObservation"/>; otherwise, the <see cref="PatientObservation"/> with its value set to the locally formatted observation time.</returns>
/// <!-- aidoc:v1 sig=479318b body=e536a62 -->
private static BasePatientObservation CalculateLastDefecationValue(BasePatientObservation obs)
{
if (obs is not PatientObservation pobs) return obs;
@@ -332,6 +347,7 @@ public class CalculatedObservations : ICalculatedObservations
/// Calculates and persists a multi-value observation by appending the current value to the existing list of values for the corresponding "Multivalue" observation. Expirates the previous multi-value observation before inserting the new one.
/// </summary>
/// <param name="obs">The base patient observation used to derive the multi-value observation; it must be a <see cref="PatientObservation"/> with a non-empty name and a string value.</param>
/// <!-- aidoc:v1 sig=d821a40 body=264c069 -->
private async Task CalculateMultiValueObservation(BasePatientObservation obs)
{
//El valor de la observación es un array de strings
@@ -388,6 +404,7 @@ public class CalculatedObservations : ICalculatedObservations
/// Calculates and persists a multi-value observation that aggregates the active intervention groups (e.g., devices, routes) for a patient based on incoming "<c>_In</c>" and "<c>_Out</c>" observations. Handles the insertion of new groups (with special duplicate prevention for respiratory devices) and the removal of groups when a corresponding "Out" event is received, expiring the previous multi-value observation and inserting a new one when the resulting set is not empty.
/// </summary>
/// <param name="obs">The base patient observation that triggered the calculation; expected to be a <see cref="PatientObservation"/> with a non-empty name and a string value representing the intervention group.</param>
/// <!-- aidoc:v1 sig=25ac55d body=191bd88 -->
private async Task CalculateInterventionMultiValueObservation(BasePatientObservation obs)
{
if (obs is not PatientObservation pobs || string.IsNullOrEmpty(obs.Name) ||
@@ -478,6 +495,7 @@ public class CalculatedObservations : ICalculatedObservations
/// <param name="valueObs">Observation text from which the leading token is taken as the candidate intervention code.</param>
/// <param name="r">When the method returns true, contains the resolved intervention's type, name, and group; otherwise null.</param>
/// <returns><c>true</c> if a matching intervention was found; <c>false</c> if the code is not numeric or the lookup yields no result.</returns>
/// <!-- aidoc:v1 sig=d3884cf body=1ea9ac7 -->
private bool GetInterventionValue(string valueObs, out (string type, string Name, string Group)? r)
{
var code = valueObs.Split(" ")[0]; //
@@ -506,6 +524,7 @@ public class CalculatedObservations : ICalculatedObservations
/// Calcula la complejidad del paciente en función de las observaciones registradas.
/// </summary>
/// <param name="obs">Observación del paciente que se va a evaluar para recalcular su complejidad.</param>
/// <!-- aidoc:v1 sig=4545d3a body=a6e9e71 -->
private async Task CalculateComplexity(BasePatientObservation obs)
{
var pobs = obs as PatientObservation;
@@ -575,6 +594,7 @@ public class CalculatedObservations : ICalculatedObservations
/// <param name="observationName">The name of the multivalue observation to look up and calculate complexity for.</param>
/// <param name="observation">An optional pre-loaded observation that overrides the database lookup when supplied.</param>
/// <returns>The aggregated complexity value for the observation, or 0 if no observation or values are found.</returns>
/// <!-- aidoc:v1 sig=cdba6ba body=3c7e7fd -->
private async Task<int> CalculateMultivalueObservationComplexityValue(ObjectId patientId, string observationName,
PatientObservation? observation = null)
{
@@ -602,6 +622,7 @@ public class CalculatedObservations : ICalculatedObservations
/// <param name="patientId">The identifier of the patient whose newborn weight complexity is being calculated.</param>
/// <param name="pobs">An optional patient observation to use instead of the latest stored one; if provided with "kg" units, its value is converted.</param>
/// <returns>The calculated newborn weight complexity value, or 0 when no valid value is available.</returns>
/// <!-- aidoc:v1 sig=85b6f46 body=c89d98c -->
private async Task<int> CalculateWeightNewBornValue(ObjectId patientId, PatientObservation? pobs = null)
{
var result =
@@ -644,6 +665,7 @@ public class CalculatedObservations : ICalculatedObservations
/// </summary>
/// <param name="obs">The patient observation containing the weight value to parse and convert.</param>
/// <returns>The patient observation with the value converted to grams, or the original observation if the value could not be parsed.</returns>
/// <!-- aidoc:v1 sig=2d84953 body=d947a19 -->
private PatientObservation ParseWeight(PatientObservation obs)
{
if (!double.TryParse(obs.Value.ToString(), out var dValue))
@@ -664,6 +686,7 @@ public class CalculatedObservations : ICalculatedObservations
/// </summary>
/// <param name="obs">The incoming patient observation (either a pre or post SpO2 measurement) used to drive the calculation and identify the counterpart observation.</param>
/// <returns>A task that represents the asynchronous insert of the derived observations.</returns>
/// <!-- aidoc:v1 sig=7f9be58 body=e3f6858 -->
private async Task CalculateSaturation_DiffObservation(BasePatientObservation obs)
{
var toSearchList = new List<string>();
@@ -726,6 +749,8 @@ public class CalculatedObservations : ICalculatedObservations
/// </summary>
/// <param name="treatment">The patient treatment being evaluated, used to locate the existing record by its placer order entity identifier and to persist the updated state.</param>
/// <returns>A task that yields the list of active patient treatments for the patient that are not the same placer order as the supplied treatment.</returns>
/// <!-- aidoc-review:v1 severity=medium kind=wrong_summary
/// "Summary claims to 'check for expired patient treatments' but the code calls GetActiveTreatmentsByPatient (active, not expired) and sets DC when t.EndTime > DateTime.UtcNow (future, not past), making the word 'expired' contradictory to the documented condition 'end time is in the future'." -->
private async Task<List<PatientTreatment>> CheckExpiredPatientTreatments(PatientTreatment treatment)
{
//si el tratamiento ha expirado actualizamos el OrderControl a DC y devolvemos las que siguen activas
@@ -763,6 +788,7 @@ public class CalculatedObservations : ICalculatedObservations
/// medicines remain after filtering.
/// </summary>
/// <param name="treatment">The patient treatment whose requested give codes are inspected for medicines, nutrition items, and vasoactive drugs.</param>
/// <!-- aidoc:v1 sig=e762e81 body=6f65d8e -->
private async Task CheckTreatmentMedicines(PatientTreatment treatment)
{
var newMedicines = new List<Medicine>();
@@ -825,6 +851,7 @@ public class CalculatedObservations : ICalculatedObservations
/// </summary>
/// <param name="value">The feeding type value to record; if it contains "parenteral" (case-insensitive), the observation is stored as a parenteral entry.</param>
/// <param name="patientId">The identifier of the patient to whom the observation belongs.</param>
/// <!-- aidoc:v1 sig=7b17fa3 body=af49d06 -->
private async Task CreateNutritionObservation(string value, ObjectId patientId)
{
var nutritionObs = new PatientObservation