=== 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
@@ -17,6 +17,7 @@ namespace adas_core.Application.Customizations.HPAZ;
/// <remarks>
/// This class implements the <see cref="ICalculatedObservations"/> contract, exposing the behavior defined by that interface while relying on constructor-injected services for its operations.
/// </remarks>
/// <!-- aidoc:v1 sig=c3598e8 -->
public class CalculatedObservations(IServiceProvider serviceProvider) : ICalculatedObservations
{
private readonly Lazy<IAlarmService> _alarmService = serviceProvider.GetRequiredService<Lazy<IAlarmService>>();
@@ -42,6 +43,8 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// Asynchronously calculates the active bolus for the specified patient.
/// </summary>
/// <param name="patientId">The unique identifier of the patient whose active bolus is to be calculated.</param>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "The summary states the method 'calculates the active bolus', but the body only returns Task.CompletedTask without performing any calculation." -->
public Task CalculateActiveBolus(ObjectId patientId)
{
return Task.CompletedTask;
@@ -52,6 +55,8 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// </summary>
/// <param name="activeMedicines">The list of medicines currently active for the patient.</param>
/// <param name="patientId">The unique identifier of the patient whose medicine observations are being calculated.</param>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "The summary states the method calculates medicine observations based on active medicines, but the body only returns Task.CompletedTask and performs no calculation." -->
public Task CalculateMedicineObservation(List<Medicine> activeMedicines, ObjectId patientId)
{
return Task.CompletedTask;
@@ -63,6 +68,8 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// </summary>
/// <param name="id">The unique identifier of the patient whose active treatments are being retrieved.</param>
/// <returns>A task that represents the asynchronous operation, containing a collection of active <see cref="PatientTreatment"/> records for the patient, or an empty collection if none exist.</returns>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "The summary states the method 'Retrieves the active treatments associated with the specified patient identifier,' but the implementation unconditionally returns an empty collection without performing any retrieval or checking the id parameter." -->
public Task<IEnumerable<PatientTreatment?>> GetActiveTreatmentsByPatient(ObjectId id)
{
return Task.FromResult<IEnumerable<PatientTreatment?>>(new List<PatientTreatment?>());
@@ -75,6 +82,10 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// <param name="source">Observation</param>
/// <param name="onlyByName">True if the observation needs to generate an alert</param>
/// <returns>Mapped observation</returns>
/// <!-- aidoc-review:v1 severity=high kind=mentions_removed_behavior
/// "Summary states 'inserts it if needed', but the method body contains no insertion logic — it only maps/processes the observation and returns it." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_param_role
/// "onlyByName is documented as 'True if the observation needs to generate an alert', but the in-code comment states 'No generamos alertas si viene onlyByName' (alerts are NOT generated when onlyByName is true), and the parameter is never actually used in the method body." -->
public async Task<T?> Map<T>(T source, bool onlyByName) where T : BasePatientObservation
{
_logger.LogDebug("Mapping {obsName} mode observation {obs}", source.Name, source);
@@ -113,6 +124,8 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// </summary>
/// <param name="pumpObservation">The source <see cref="PumpObservation"/> to map.</param>
/// <returns>A task that represents the asynchronous mapping operation. The task result contains the mapped <see cref="PumpObservation"/>.</returns>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "The summary states the method maps to a 'new PumpObservation instance', but the code returns the same pumpObservation instance unchanged." -->
public async Task<PumpObservation> Map(PumpObservation pumpObservation)
{
try
@@ -212,6 +225,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// <param name="treatment">The <see cref="PatientTreatment"/> to be mapped.</param>
/// <returns>A task representing the asynchronous operation, containing the mapped <see cref="PatientTreatment"/>.</returns>
/// <exception cref="NotImplementedException">Thrown in all cases because the method has not yet been implemented.</exception>
/// <!-- aidoc:v1 sig=adce250 body=bfa6f2f -->
public Task<PatientTreatment> Map(PatientTreatment treatment)
{
throw new NotImplementedException();
@@ -223,6 +237,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// <param name="diagnosis">The <see cref="PatientDiagnosis"/> to be mapped.</param>
/// <returns>A task that represents the asynchronous operation, containing the mapped <see cref="PatientDiagnosis"/>.</returns>
/// <exception cref="NotImplementedException">Thrown to indicate that the mapping logic has not been implemented.</exception>
/// <!-- aidoc:v1 sig=8ddf601 body=bfa6f2f -->
public Task<PatientDiagnosis> Map(PatientDiagnosis diagnosis)
{
throw new NotImplementedException();
@@ -234,6 +249,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// </summary>
/// <param name="newObservation">The new patient observation to validate and potentially adjust for time consistency.</param>
/// <returns>The patient observation with its time corrected if a time inconsistency was detected, otherwise the original observation.</returns>
/// <!-- aidoc:v1 sig=2b42b30 body=3a31920 -->
public async Task<PatientObservation?> FixTimeInconsistencyWithLast(PatientObservation newObservation)
{
if (string.IsNullOrEmpty(newObservation.Name))
@@ -267,6 +283,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// </summary>
/// <param name="listToMap">The list of patient observations to process for mapping and blue code calculation.</param>
/// <returns>The original list of patient observations passed to the method.</returns>
/// <!-- aidoc:v1 sig=655d2ec body=afe534e -->
public Task<List<PatientObservation>> PreMapList(List<PatientObservation> listToMap)
{
var mappedObsList = listToMap
@@ -290,6 +307,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// <param name="obs">The target <see cref="PatientObservation"/> instance that will be updated with values from the alarm.</param>
/// <param name="alarmToInsert">The source <see cref="PatientObservationAlarm"/> whose values are applied to <paramref name="obs"/>.</param>
/// <returns>A completed <see cref="Task{PatientObservation}"/> containing the updated <paramref name="obs"/>.</returns>
/// <!-- aidoc:v1 sig=405db8e body=9a22777 -->
public Task<PatientObservation> MapSourceAlarm(PatientObservation obs, PatientObservationAlarm alarmToInsert)
{
if (!string.IsNullOrEmpty(alarmToInsert.EventId))
@@ -310,6 +328,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// <param name="name">The name of the alarm to be sent.</param>
/// <param name="code">The optional alarm code identifying the type of alarm.</param>
/// <exception cref="System.NotImplementedException">Thrown because the method is not yet implemented.</exception>
/// <!-- aidoc:v1 sig=9d68c3e body=bfa6f2f -->
Task ICalculatedObservations.SendAlarm(PatientObservation obs, string name, AlarmEnum.Name? code)
{
throw new NotImplementedException();
@@ -323,6 +342,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// <param name="name">The name of the alarm.</param>
/// <param name="code">The optional alarm code identifier.</param>
/// <param name="type">The type of alarm to send.</param>
/// <!-- aidoc:v1 sig=cd9926e body=38786f6 -->
private async Task SendAlarm(PatientObservation obs, string name, AlarmEnum.Name? code, AlarmEnum.Type type)
{
await _alarmService.Value.SendAlarm(obs, name, code, AlarmEnum.Severity.None, type);
@@ -334,6 +354,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// </summary>
/// <param name="obs">Observation</param>
/// <returns>True if it needs to be ignored</returns>
/// <!-- aidoc:v1 sig=9343b34 body=bfb9ed9 -->
private bool CheckIfObservationIsOlderAndShouldBeIgnored(PatientObservation obs)
{
if (obs.Time.ToUniversalTime().AddMinutes(_apiSettings.IgnoreCalcObservationsOlderInMinutesThan) <
@@ -354,6 +375,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// </summary>
/// <param name="pobs">The patient observation whose alarm configuration should be resolved; its <c>Name</c> and <c>PatientId</c> are used to locate the configuration.</param>
/// <returns>The same <see cref="PatientObservation"/> instance with its <c>Alarm</c> property populated from the matching configuration, or <c>null</c> when no configuration is found.</returns>
/// <!-- aidoc:v1 sig=4d79a28 body=efca777 -->
private async Task<PatientObservation> CheckAlarmConfig(PatientObservation pobs)
{
var configObs = await _configObservationService.Get(new PatientObservation
@@ -373,6 +395,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// <param name="name">The alarm code used to identify the type of alarm; it is set as the <c>Code</c> and used to compose the <c>Name</c>.</param>
/// <param name="pobs">The source patient observation whose value, patient identifier, time, and alarm flag are copied into the new alarm observation.</param>
/// <returns>A new <see cref="PatientObservation"/> configured as an ADAS alarm observation based on the provided source.</returns>
/// <!-- aidoc:v1 sig=235b1d9 body=27fc0a4 -->
private static PatientObservation CreateAlarmObservation(string name, PatientObservation pobs)
{
return new PatientObservation
@@ -391,6 +414,10 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// Checks if a blue code observation Lists needs to be generated and inserts it.
/// </summary>
/// <param name="obsList"></param>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "The method does not 'generate' or 'insert' a blue code observation list; it evaluates clinical conditions (FC, SpO2, TAm) and calls SendBlueCode to trigger a notification. The summary misrepresents both the action and the outcome." -->
/// <!-- aidoc-review:v1 severity=high kind=missing_param
/// "The <param name='obsList'> tag has no description." -->
public async Task CalculateBlueCodeList(List<PatientObservation?>? obsList)
{
//Las 3 observaciones vienen siempre juntas en el mismo mensaje
@@ -461,6 +488,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// Sends a Blue Code alarm for the given patient observation. If the observation is null, the method returns without taking any action; otherwise it creates the corresponding alarm observation, validates it against the alarm configuration, persists it, and dispatches the alarm as an automatically triggered Blue alarm.
/// </summary>
/// <param name="pobs">The patient observation that triggers the Blue Code alarm; when null, the method short-circuits without processing.</param>
/// <!-- aidoc:v1 sig=5b6ce3f body=c8aa765 -->
private async Task SendBlueCode(PatientObservation? pobs)
{
if (pobs == null)
@@ -486,6 +514,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// </summary>
/// <param name="obs">The base patient observation value whose ventilation mode will be calculated and normalized.</param>
/// <returns>The patient observation with the normalized ventilation mode value.</returns>
/// <!-- aidoc:v1 sig=0a38ecd body=8d45d84 -->
private BasePatientObservationValue CalculateVentilationMode(BasePatientObservationValue obs)
{
var value = obs is PatientObservationAlarm oAlarm ? oAlarm.Value
@@ -508,6 +537,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// </summary>
/// <param name="obs">The patient observation to evaluate; non-<see cref="PatientObservation"/> instances are returned unchanged.</param>
/// <returns>The original observation, with its <c>Time</c> adjusted by one second when a matching observation is found.</returns>
/// <!-- aidoc:v1 sig=a546fa4 body=b8e5fa3 -->
private async Task<BasePatientObservationValue> CheckObsWithSameTimeExistsAndIncrementTime(
BasePatientObservationValue obs)
{
@@ -529,6 +559,8 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// </summary>
/// <param name="obs">The newly received patient observation that triggered the calculation; its Name must be either "FiO2" or "Sattc".</param>
/// <param name="name">The name of the observation, used to determine whether <paramref name="obs"/> is the FiO2 or the Sattc value.</param>
/// <!-- aidoc-review:v1 severity=low kind=wrong_summary
/// "The summary states the calculation is 'logged and skipped' when the insertion conditions are not met, but only the FiO2 == 0 case triggers a log message; other skip conditions (expired observations, unparseable values, null complementary observation, sat > 97) silently skip without logging." -->
private async Task CalculateSf(BasePatientObservationValue obs, string name)
{
try
@@ -590,6 +622,8 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// calculation if they are not
/// in database then does nothing.
/// </summary>
/// <!-- aidoc-review:v1 severity=medium kind=missing_param
/// "The parameters 'obs' (BasePatientObservationValue containing the triggering observation) and 'name' (the name of the observation being processed, used to switch on which value was provided) are not documented." -->
public async Task CalculateOxygenationIndex(BasePatientObservationValue obs, string name)
{
var toSearchList = new List<string>();
@@ -665,6 +699,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// </summary>
/// <param name="obs">The current patient observation that initiated the calculation; provides the patient identifier and timestamp used for the resulting observation.</param>
/// <param name="name">The name of the observation in <paramref name="obs"/>, expected to be either <c>FiO2</c> or <c>PaO2_Tidal</c>, which determines how the counterpart value is resolved.</param>
/// <!-- aidoc:v1 sig=1b41d79 body=5e03ddd -->
private async Task CalculatePf(BasePatientObservationValue obs, string name)
{
try
@@ -729,6 +764,7 @@ public class CalculatedObservations(IServiceProvider serviceProvider) : ICalcula
/// <param name="name">The alarm identifier used to build the observation <c>Code</c> and <c>Name</c>.</param>
/// <param name="pumpObservation">The pump data source providing rack/auxiliary info, drug name, time, and optional patient id.</param>
/// <returns>A <see cref="Task{PatientObservation}"/> that yields the resulting observation, or <c>null</c> when the alarm configuration check rejects it.</returns>
/// <!-- aidoc:v1 sig=adcd93c body=8ef1fe1 -->
private async Task<PatientObservation?> CreatePumpAlarmObservation(string name,
PumpObservation pumpObservation)
{