2401 lines
86 KiB
C#
2401 lines
86 KiB
C#
using adas_core.Application.Customizations.HUVH.UCIN;
|
|
using adas_core.Application.Services.Interfaces;
|
|
using adas_core.Domain.Enums;
|
|
using adas_core.Domain.Models;
|
|
using adas_core.Domain.Models.AppSettings;
|
|
using adas_core.Domain.Utils;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using MongoDB.Bson;
|
|
using Moq;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace adas_core.Test.Customizations.HUVH.UCIN;
|
|
|
|
[TestFixture]
|
|
public class CalculatedObservationsTest
|
|
{
|
|
[SetUp]
|
|
public void Setup()
|
|
{
|
|
_mockObservationService = new Mock<IObservationService>();
|
|
_medicineServiceMock = new Mock<IMedicineService>();
|
|
_treatmentServiceMock = new Mock<ITreatmentService>();
|
|
_logger = new Mock<ILogger<CalculatedObservations>>();
|
|
|
|
//JSON data
|
|
const string mappingInterventionsJson = @"[
|
|
{
|
|
""Type"": ""Respiratory_Device"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Oxigeno (O2)/Alto flujo"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 204.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Respiratory_Device"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""CPAP "",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 202.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Respiratory_Device"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Ventilaci\u00f3n mec\u00e1nica Invasiva"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 3.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 201.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Respiratory_Device"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""VAFO Ventilaci\u00f3n Oscilatoria de alta frecuencia"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 4.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 200.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Intravenous_Routes"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""VV perfif\u00e9rica"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 103.1,
|
|
""FinalValue"": 103.5
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Intravenous_Routes"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""VV epicut\u00e1neo cava"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 102.1,
|
|
""FinalValue"": 102.5
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Intravenous_Routes"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""VV umbilical"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 101.1,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Intravenous_Routes"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""VV central"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 104.1,
|
|
""FinalValue"": 104.3
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Intravenous_Routes"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""VV PICC"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 108.1,
|
|
""FinalValue"": 108.2
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Intravenous_Routes"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""VA umbilical"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 3.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 101.2,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Intravenous_Routes"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""VA"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 3.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 106.1,
|
|
""FinalValue"": 106.3
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Antiarr\u00edtmicos"",
|
|
""Name"": ""Digoxina ev"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 118.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Antiarr\u00edtmicos"",
|
|
""Name"": ""Digoxina vo"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 1753.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Antiarr\u00edtmicos"",
|
|
""Name"": ""Amiodarona ev"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 169.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Antiarr\u00edtmicos"",
|
|
""Name"": ""Amiodarona vo"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 16323.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Antiarr\u00edtmicos"",
|
|
""Name"": ""Atropina"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 186.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Antiarr\u00edtmicos"",
|
|
""Name"": ""Esmolol"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 853.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Antiarr\u00edtmicos"",
|
|
""Name"": ""Propranolol"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 7122.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Antiarr\u00edtmicos"",
|
|
""Name"": ""Isoprenalina"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 283.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Antiarr\u00edtmicos"",
|
|
""Name"": ""Flecainida ev"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 1247.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Antiarr\u00edtmicos"",
|
|
""Name"": ""Flecainida vo"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 7055.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Drogas vasoactivas"",
|
|
""Name"": ""Adrenalina"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 281.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Drogas vasoactivas"",
|
|
""Name"": ""Noradrenalina"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 100000.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Drogas vasoactivas"",
|
|
""Name"": ""Milrinona"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 618.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Drogas vasoactivas"",
|
|
""Name"": ""Levosimendan"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 2073.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Drogas vasoactivas"",
|
|
""Name"": ""Dopamina"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 149.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Drogas vasoactivas"",
|
|
""Name"": ""Debutamina"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 1968.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Drogas vasoactivas"",
|
|
""Name"": ""Fenilefrina"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 12319.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Sedaci\u00f3n"",
|
|
""Name"": ""Morfina ev"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 472.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Sedaci\u00f3n"",
|
|
""Name"": ""Morfina ov"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 7081.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Sedaci\u00f3n"",
|
|
""Name"": ""Fentanil"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 434.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Sedaci\u00f3n"",
|
|
""Name"": ""Midazolam"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 756.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Sedaci\u00f3n"",
|
|
""Name"": ""Dexmedetomidina"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 15910.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Sedaci\u00f3n"",
|
|
""Name"": ""Cisatraculi"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 15066.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Sedaci\u00f3n"",
|
|
""Name"": ""Propofol"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 314.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Medication"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Sedaci\u00f3n"",
|
|
""Name"": ""Ketamina"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 374.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""System"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Hipotermia"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 100001.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""System"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""aEEG"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 100002.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""System"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Drenaje ventricular (DVE)"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 315.1,
|
|
""FinalValue"": null
|
|
},
|
|
{
|
|
""InitialValue"": 315.2,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""System"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Drenaje toracico"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 311.0,
|
|
""FinalValue"": 314.0
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""System"",
|
|
""Category"": ""Intervention"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Dialisis peritoneal - abdominal"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 306.0,
|
|
""FinalValue"": 310.0
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Newborn_Weight"",
|
|
""Category"": ""Observation"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Newborn_Weight"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0.0,
|
|
""FinalValue"": 500.0,
|
|
""valueContributed"": 5
|
|
},
|
|
{
|
|
""InitialValue"": 501.0,
|
|
""FinalValue"": 1000.0,
|
|
""valueContributed"": 4
|
|
},
|
|
{
|
|
""InitialValue"": 1001.0,
|
|
""FinalValue"": 1500.0,
|
|
""valueContributed"": 3
|
|
},
|
|
{
|
|
""InitialValue"": 1501.0,
|
|
""FinalValue"": 2000.0,
|
|
""valueContributed"": 2
|
|
},
|
|
{
|
|
""InitialValue"": 2000.0,
|
|
""FinalValue"": 2500.0,
|
|
""valueContributed"": 1
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 10000465.0,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""surgery"",
|
|
""Category"": ""Observation"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Cardiaca"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 4.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 14000070.1,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""surgery"",
|
|
""Category"": ""Observation"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Digestiva"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 3.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 14000070.2,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""surgery"",
|
|
""Category"": ""Observation"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Neurologica "",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 3.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 14000070.3,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""surgery"",
|
|
""Category"": ""Observation"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Toracica"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 3.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 14000070.4,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""surgery"",
|
|
""Category"": ""Observation"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""ORL/Maxil\u00b7lo"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 2.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 14000070.5,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""surgery"",
|
|
""Category"": ""Observation"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Oftalmo"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 14000070.6,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""surgery"",
|
|
""Category"": ""Observation"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Ortopedia"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 14000070.7,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""surgery"",
|
|
""Category"": ""Observation"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""Altres"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 1.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 14000070.8,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""surgery"",
|
|
""Category"": ""Observation"",
|
|
""Group"": ""not defined"",
|
|
""Name"": ""No"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0.0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": 14000070.9,
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LM"",
|
|
""Name"": ""Llet materna"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIB586"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LM"",
|
|
""Name"": ""Llet materna de banc"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIB000589"",
|
|
""FinalValue"": null
|
|
},
|
|
{
|
|
""InitialValue"": ""BIB000587"",
|
|
""FinalValue"": null
|
|
},
|
|
{
|
|
""InitialValue"": ""BIB000588"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LM"",
|
|
""Name"": ""Llet materna a demanda"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""NO_EST2"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LM descremada"",
|
|
""Name"": ""LM descremada"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""NO_EST3"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Formula de soja"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIBCOM003"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Formula hidrolizada (Alfare)"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIBCOM002"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Formula inici"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIBNOR003"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Formula prematurs 14,4%"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIBCOM017"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Formula prematurs 15,9%"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIBCOM018"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Formula sense lactosa"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIBCOM01"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Monogen"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIBCOM009"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Infatrini"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIBNOR001"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Infatini Peptisorb"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIBNOR0013"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Neocate 13,8%"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIBBAS019"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Neocate Advance 25%"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""NO_EST4"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Energivit"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""BIBBAS021"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""LA"",
|
|
""Name"": ""Bibero especial"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""ALTESP001"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
},
|
|
{
|
|
""Type"": ""Nutrition"",
|
|
""Category"": ""Treatment"",
|
|
""Group"": ""Absoluta"",
|
|
""Name"": ""Absoluta"",
|
|
""Value"": [
|
|
{
|
|
""InitialValue"": 0,
|
|
""FinalValue"": null
|
|
}
|
|
],
|
|
""Codes"": [
|
|
{
|
|
""InitialValue"": ""15002284"",
|
|
""FinalValue"": null
|
|
}
|
|
]
|
|
}
|
|
]";
|
|
|
|
const string complexityValuesJson = @"{
|
|
""Oxigeno (O2)/Alto flujo"": 1,
|
|
""CPAP "": 2,
|
|
""Ventilación mecánica Invasiva"": 3,
|
|
""VAFO Ventilación Oscilatoria de alta frecuencia"": 4,
|
|
""VV perfiférica"": 1,
|
|
""VV epicutáneo cava"": 2,
|
|
""VV umbilical"": 2,
|
|
""VV central"": 2,
|
|
""VV PICC"": 2,
|
|
""VA umbilical"": 3,
|
|
""VA"": 3,
|
|
""Digoxina ev"": 1,
|
|
""Digoxina vo"": 1,
|
|
""Amiodarona ev"": 1,
|
|
""Amiodarona vo"": 1,
|
|
""Atropina"": 1,
|
|
""Esmolol"": 1,
|
|
""Propranolol"": 1,
|
|
""Isoprenalina"": 1,
|
|
""Flecainida ev"": 1,
|
|
""Flecainida vo"": 1,
|
|
""Adrenalina"": 2,
|
|
""Noradrenalina"": 2,
|
|
""Milrinona"": 2,
|
|
""Levosimendan"": 2,
|
|
""Dopamina"": 2,
|
|
""Debutamina"": 2,
|
|
""Fenilefrina"": 2,
|
|
""Hipotermia"": 2,
|
|
""aEEG"": 2,
|
|
""Drenaje ventricular (DVE)"": 2,
|
|
""Drenaje toracico"": 2,
|
|
""Dialisis peritoneal - abdominal"": 2,
|
|
""Cardiaca"": 4,
|
|
""Digestiva"": 3,
|
|
""Neurologica "": 3,
|
|
""Toracica"": 3,
|
|
""ORL/Maxil·lo"": 2,
|
|
""Oftalmo"": 1,
|
|
""Ortopedia"": 1,
|
|
""Altres"": 1,
|
|
""No"": 0
|
|
}";
|
|
|
|
// Deserialize the JSON
|
|
var apiSettings = JsonConvert.DeserializeObject<ApiSettings>(
|
|
$$"""
|
|
{
|
|
"MappingInterventions": {{mappingInterventionsJson}},
|
|
"ComplexityMappingObservation": {{complexityValuesJson}}
|
|
}
|
|
"""
|
|
);
|
|
|
|
if (apiSettings == null) return;
|
|
|
|
// Mock IOptions<ApiSettings> to return our populated ApiSettings
|
|
_mockApiSettings = new Mock<IOptions<ApiSettings>>();
|
|
_mockApiSettings.Setup(s => s.Value).Returns(apiSettings);
|
|
|
|
// Create an instance of MappingUtils with the mocked IOptions
|
|
_mappingUtils = new MappingUtils(_mockApiSettings.Object);
|
|
|
|
var serviceCollection = new ServiceCollection();
|
|
serviceCollection.AddSingleton(new Lazy<IObservationService>(() => _mockObservationService.Object));
|
|
serviceCollection.AddSingleton(new Lazy<IMedicineService>(() => _medicineServiceMock.Object));
|
|
serviceCollection.AddSingleton(new Lazy<ITreatmentService>(() => _treatmentServiceMock.Object));
|
|
serviceCollection.AddSingleton(_mockApiSettings.Object);
|
|
serviceCollection.AddSingleton(_logger.Object);
|
|
serviceCollection.AddSingleton(_mappingUtils); // Register the real instance
|
|
|
|
var serviceProvider = serviceCollection.BuildServiceProvider();
|
|
|
|
_calculatedObservations = new CalculatedObservations(serviceProvider);
|
|
}
|
|
|
|
private Mock<IObservationService> _mockObservationService;
|
|
private Mock<IMedicineService> _medicineServiceMock;
|
|
private Mock<ITreatmentService> _treatmentServiceMock;
|
|
private Mock<ILogger<CalculatedObservations>> _logger;
|
|
private Mock<IOptions<ApiSettings>> _mockApiSettings;
|
|
private MappingUtils _mappingUtils;
|
|
private CalculatedObservations _calculatedObservations;
|
|
|
|
[Test]
|
|
public async Task Map_WithInterventionCodeInObservationValue_CallsCalculateInterventionMultiValueObservation()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
var observation = new PatientObservation
|
|
{
|
|
Name = "Intervention_In", PatientId = patientId, Value = "204 Oxigeno (O2)/Alto flujo"
|
|
}; // Code 204 exists in data
|
|
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
|
|
.ReturnsAsync([]); // Simulate no existing multivalue observation
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(observation);
|
|
|
|
// Assert
|
|
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals("Respiratory_Device_Multivalue") &&
|
|
o.Value.GetType() == typeof(string[]) &&
|
|
((string[])o.Value).Count() == 1 &&
|
|
((string[])o.Value)[0].ToString() == "Oxigeno (O2)/Alto flujo"), true, true),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithInterventionOut_UpdatesExistingMultiValueObservation()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
var interventionCode = "204";
|
|
var interventionDescription = "Oxigeno (O2)/Alto flujo";
|
|
var observationOutValue = $"{interventionCode} {interventionDescription}";
|
|
var observationOut = new PatientObservation
|
|
{ Name = "Intervention_Out", PatientId = patientId, Value = observationOutValue };
|
|
|
|
// Simulate an existing multi-value observation that is active
|
|
var existingMultiValueObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = "Respiratory_Device_Multivalue",
|
|
Value = new[] { interventionDescription },
|
|
Time = DateTime.UtcNow.AddMinutes(-30) // Simulate it started 30 minutes ago
|
|
};
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Respiratory_Device_Multivalue")))) // Find the active multi-value observation
|
|
.ReturnsAsync([existingMultiValueObservation]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(observationOut);
|
|
|
|
// Assert
|
|
// Verify that the existing multi-value observation was updated to set an EndTime
|
|
_mockObservationService.Verify(
|
|
x => x.UpdateObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals("Respiratory_Device_Multivalue")
|
|
)),
|
|
Times.Once);
|
|
|
|
// Optionally, verify that a new observation was NOT inserted
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.IsAny<PatientObservation>(), It.IsAny<bool>(), It.IsAny<bool>()),
|
|
Times.Never);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithNewInterventionNoExistingLastIntervention_NewMultiValueObservation()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
|
|
// Simular una intervención activa existente
|
|
//var existingInterventionCode = "204";
|
|
const string existingInterventionDescription = "Oxigeno (O2)/Alto flujo";
|
|
var existingMultiValueObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = "Respiratory_Device_Multivalue",
|
|
Value = new[] { existingInterventionDescription },
|
|
Time = DateTime.UtcNow.AddMinutes(-30),
|
|
Expired = true
|
|
};
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Respiratory_Device_Multivalue"))))
|
|
.ReturnsAsync([existingMultiValueObservation]);
|
|
|
|
// Nuevo evento de "Intervention_In" con una intervención diferente
|
|
const string newInterventionCode = "202";
|
|
const string newInterventionDescription = "CPAP";
|
|
const string newObservationInValue = $"{newInterventionCode} {newInterventionDescription}";
|
|
var newObservationIn = new PatientObservation
|
|
{ Name = "Intervention_In", PatientId = patientId, Value = newObservationInValue };
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(newObservationIn);
|
|
|
|
// Assert
|
|
|
|
// Verificar que NO se insertó una nueva observación (se actualizó la existente)
|
|
_mockObservationService.Verify(
|
|
x => x.UpdateObservation(It.IsAny<PatientObservation>()),
|
|
Times.Never);
|
|
|
|
// Verificar que la observación multi-valor existente se actualizó añadiendo la nueva intervención
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals("Respiratory_Device_Multivalue") &&
|
|
o.Value.GetType() == typeof(string[]) &&
|
|
((string[])o.Value).Length == 1 &&
|
|
((string[])o.Value)[0] != existingInterventionDescription &&
|
|
((string[])o.Value)[0] != newInterventionDescription), true, true),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithNewInterventionAddsToExistingMultiValueObservation()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
|
|
// Simular una intervención activa existente
|
|
//var existingInterventionCode = "204";
|
|
const string existingInterventionDescription = "Oxigeno (O2)/Alto flujo";
|
|
var existingMultiValueObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = "Respiratory_Device_Multivalue",
|
|
Value = new[] { existingInterventionDescription },
|
|
Time = DateTime.UtcNow.AddMinutes(-30)
|
|
};
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Respiratory_Device_Multivalue"))))
|
|
.ReturnsAsync([existingMultiValueObservation]);
|
|
|
|
// Nuevo evento de "Intervention_In" con una intervención diferente
|
|
const string newInterventionCode = "202";
|
|
const string newInterventionDescription = "CPAP";
|
|
const string newObservationInValue = $"{newInterventionCode} {newInterventionDescription}";
|
|
var newObservationIn = new PatientObservation
|
|
{ Name = "Intervention_In", PatientId = patientId, Value = newObservationInValue };
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(newObservationIn);
|
|
|
|
// Assert
|
|
// Verificar que la observación multi-valor existente se actualizó añadiendo la nueva intervención
|
|
_mockObservationService.Verify(
|
|
x => x.UpdateObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals("Respiratory_Device_Multivalue") &&
|
|
o.Value.GetType() == typeof(string[]) &&
|
|
((string[])o.Value).Length == 1 &&
|
|
((string[])o.Value)[0] == existingInterventionDescription &&
|
|
o.Expired)),
|
|
Times.Once);
|
|
|
|
// Verificar que NO se insertó una nueva observación (se actualizó la existente)
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals("Respiratory_Device_Multivalue") &&
|
|
o.Value.GetType() == typeof(string[]) &&
|
|
((string[])o.Value).Length == 2 &&
|
|
((string[])o.Value)[0] == existingInterventionDescription &&
|
|
((string[])o.Value)[1] == newInterventionDescription
|
|
), It.IsAny<bool>(), It.IsAny<bool>()),
|
|
Times.Never);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithSurgeryObservation_InsertsNewSurgeryMultiValueObservation()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string surgeryName = "Surgery";
|
|
const string surgeryValue = "Appendectomy";
|
|
var surgeryObservation = new PatientObservation
|
|
{ Name = surgeryName, PatientId = patientId, Value = surgeryValue };
|
|
const string expectedMultiValueObservationName = $"{surgeryName}_Multivalue";
|
|
|
|
// Simulate no existing Surgery_Multivalue observation
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(expectedMultiValueObservationName))))
|
|
.ReturnsAsync([]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(surgeryObservation);
|
|
|
|
// Assert
|
|
// Verify that a new Surgery_Multivalue observation was inserted with the correct value
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals(expectedMultiValueObservationName) &&
|
|
o.Value.GetType() == typeof(string[]) &&
|
|
((string[])o.Value).Length == 1 &&
|
|
((string[])o.Value)[0].ToString() == surgeryValue),
|
|
true, true),
|
|
Times.Once);
|
|
|
|
// Verify that UpdateObservation was not called
|
|
_mockObservationService.Verify(
|
|
x => x.UpdateObservation(It.IsAny<PatientObservation>()),
|
|
Times.Never);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithSurgeryObservation_UpdatesExistingSurgeryMultiValueObservation()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string surgeryName = "Surgery";
|
|
const string newSurgeryValue = "Cholecystectomy";
|
|
var surgeryObservation = new PatientObservation
|
|
{ Name = surgeryName, PatientId = patientId, Value = newSurgeryValue };
|
|
const string expectedMultiValueObservationName = $"{surgeryName}_Multivalue";
|
|
const string existingSurgeryValue = "Appendectomy";
|
|
var existingMultiValueObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = expectedMultiValueObservationName,
|
|
Value = new[] { existingSurgeryValue },
|
|
Time = DateTime.UtcNow.AddMinutes(-30),
|
|
Expired = false
|
|
};
|
|
|
|
// Simulate an existing Surgery_Multivalue observation
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(expectedMultiValueObservationName))))
|
|
.ReturnsAsync([existingMultiValueObservation]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(surgeryObservation);
|
|
|
|
// Assert
|
|
// Verify that the existing Surgery_Multivalue observation was expired
|
|
_mockObservationService.Verify(
|
|
x => x.UpdateObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals(expectedMultiValueObservationName) &&
|
|
o.Expired)),
|
|
Times.Once);
|
|
|
|
// Verify that a new Surgery_Multivalue observation was inserted with the new value
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals(expectedMultiValueObservationName) &&
|
|
o.Value.GetType() == typeof(string[]) &&
|
|
((string[])o.Value).Length == 2 &&
|
|
((string[])o.Value)[0].ToString() == existingSurgeryValue &&
|
|
((string[])o.Value)[1].ToString() == newSurgeryValue),
|
|
true, true),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithSurgeryObservation_UpdatesExistingSurgeryMultiValueObservation_RemovesDuplicate()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string surgeryName = "Surgery";
|
|
const string duplicateSurgeryValue = "Appendectomy";
|
|
var surgeryObservation = new PatientObservation
|
|
{ Name = surgeryName, PatientId = patientId, Value = duplicateSurgeryValue };
|
|
const string expectedMultiValueObservationName = $"{surgeryName}_Multivalue";
|
|
var existingMultiValueObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = expectedMultiValueObservationName,
|
|
Value = new[] { "Appendectomy", "Tonsillectomy" },
|
|
Time = DateTime.UtcNow.AddMinutes(-30),
|
|
Expired = false
|
|
};
|
|
|
|
// Simulate an existing Surgery_Multivalue observation with a duplicate value
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(expectedMultiValueObservationName))))
|
|
.ReturnsAsync([existingMultiValueObservation]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(surgeryObservation);
|
|
|
|
// Assert
|
|
// Verify that the existing Surgery_Multivalue observation was expired
|
|
_mockObservationService.Verify(
|
|
x => x.UpdateObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals(expectedMultiValueObservationName) &&
|
|
o.Expired)),
|
|
Times.Once);
|
|
|
|
// Verify that a new Surgery_Multivalue observation was inserted with the duplicate removed
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals(expectedMultiValueObservationName) &&
|
|
o.Value.GetType() == typeof(string[]) &&
|
|
((string[])o.Value).Length == 2 &&
|
|
((string[])o.Value)[1].ToString() == "Appendectomy" &&
|
|
((string[])o.Value)[0].ToString() == "Tonsillectomy"),
|
|
true, true),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithSurgeryObservation_HandlesNonStringValue()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string surgeryName = "Surgery";
|
|
var surgeryObservation = new PatientObservation
|
|
{ Name = surgeryName, PatientId = patientId, Value = 123 }; // Non-string value
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(surgeryObservation);
|
|
|
|
// Assert
|
|
// Verify that no new observation was inserted
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.IsAny<PatientObservation>(), It.IsAny<bool>(), It.IsAny<bool>()),
|
|
Times.Never);
|
|
|
|
// Verify that no existing observation was updated
|
|
_mockObservationService.Verify(
|
|
x => x.UpdateObservation(It.IsAny<PatientObservation>()),
|
|
Times.Never);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithRespiratoryDeviceMultiValueObservation_CallsCalculateComplexity_Return1()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string observationName = "Respiratory_Device_Multivalue";
|
|
var observationValue = new[] { "Oxigeno (O2)/Alto flujo" };
|
|
var observation = new PatientObservation
|
|
{ Name = observationName, PatientId = patientId, Value = observationValue }; //value 1
|
|
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(observationName))))
|
|
.ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Intravenous_Routes_Multivalue"))))
|
|
.ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Medication_Multivalue"))))
|
|
.ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("System_Multivalue"))))
|
|
.ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Newborn_Weight"))))
|
|
.ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Surgery_Multivalue"))))
|
|
.ReturnsAsync([]);
|
|
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(observation);
|
|
|
|
// Assert
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals("Complexity") &&
|
|
o.Value is int &&
|
|
(int)o.Value == 1),
|
|
true, false),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithIntravenousRoutesAndRespiratoryDeviceMultiValueObservation_CalculatesComplexity_Return5()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string observationName = "Intravenous_Routes_Multivalue";
|
|
var observationValue = new[] { "VV central" };
|
|
var observation = new PatientObservation
|
|
{ Name = observationName, PatientId = patientId, Value = observationValue }; // value 2
|
|
|
|
var ventilationObs = new PatientObservation
|
|
{
|
|
Name = "Respiratory_Device_Multivalue", PatientId = patientId,
|
|
Value = new[] { "Ventilación mecánica Invasiva" }
|
|
}; //value 3
|
|
|
|
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(observationName)))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Respiratory_Device_Multivalue")))).ReturnsAsync([ventilationObs]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Medication_Multivalue")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("System_Multivalue")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Newborn_Weight")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Surgery_Multivalue")))).ReturnsAsync([]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(observation);
|
|
|
|
// Assert
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals("Complexity") &&
|
|
o.Value is int &&
|
|
(int)o.Value ==
|
|
5), // Esperamos 2 para "VV central" y 3 de "Ventilación mecánica Invasiva" según ComplexityValuesJson
|
|
true, false),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithTwoMedicationMultiValueObservation_CalculatesComplexity_Return4()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string observationName = "Medication_Multivalue";
|
|
var observationValue = new[] { "Adrenalina", "Dopamina" };
|
|
var observation = new PatientObservation
|
|
{ Name = observationName, PatientId = patientId, Value = observationValue };
|
|
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(observationName)))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Respiratory_Device_Multivalue")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Intravenous_Routes_Multivalue")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("System_Multivalue")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Newborn_Weight")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Surgery_Multivalue")))).ReturnsAsync([]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(observation);
|
|
|
|
// Assert
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals("Complexity") &&
|
|
o.Value is int &&
|
|
(int)o.Value == 4), // Esperamos 2 para "Adrenalina" y 2 para Dopamina
|
|
true, false),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithSystemMedicationAndNewbornWeightMultiValueObservation_CalculatesComplexity_Return9()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string observationName = "System_Multivalue";
|
|
var observationValue = new[] { "Hipotermia" };
|
|
var observation = new PatientObservation
|
|
{ Name = observationName, PatientId = patientId, Value = observationValue }; //value 2
|
|
var medicationObs = new PatientObservation
|
|
{
|
|
Name = "Medication_Multivalue", PatientId = patientId, Value = new[] { "Isoprenalina", "Milrinona" }
|
|
}; //value 1 + 2
|
|
var newbornWeight = new PatientObservation
|
|
{ Name = "Newborn_Weight", PatientId = patientId, Value = 800 }; //value 4
|
|
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(observationName)))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Respiratory_Device_Multivalue")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Intravenous_Routes_Multivalue")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Medication_Multivalue")))).ReturnsAsync([medicationObs]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Newborn_Weight")))).ReturnsAsync([newbornWeight]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Surgery_Multivalue")))).ReturnsAsync([]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(observation);
|
|
|
|
// Assert
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals("Complexity") &&
|
|
o.Value is int &&
|
|
(int)o.Value == 9), // Esperamos 9
|
|
true, false),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithNewbornWeightObservation_CalculatesComplexity_Return4()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string observationName = "Newborn_Weight";
|
|
const string observationValue = "600"; // Ejemplo de peso
|
|
var observation = new PatientObservation
|
|
{ Name = observationName, PatientId = patientId, Value = observationValue };
|
|
|
|
_mockObservationService.Setup(x =>
|
|
x.FindLastObservations(patientId, 1, It.Is<List<string>>(list => list.Contains(observationName))))
|
|
.ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1,
|
|
It.Is<List<string>>(list => list.Contains("Respiratory_Device_Multivalue")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1,
|
|
It.Is<List<string>>(list => list.Contains("Intravenous_Routes_Multivalue")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x =>
|
|
x.FindLastObservations(patientId, 1,
|
|
It.Is<List<string>>(list => list.Contains("Medication_Multivalue"))))
|
|
.ReturnsAsync([]);
|
|
_mockObservationService.Setup(x =>
|
|
x.FindLastObservations(patientId, 1, It.Is<List<string>>(list => list.Contains("System_Multivalue"))))
|
|
.ReturnsAsync([]);
|
|
_mockObservationService.Setup(x =>
|
|
x.FindLastObservations(patientId, 1, It.Is<List<string>>(list => list.Contains("Surgery_Multivalue"))))
|
|
.ReturnsAsync([]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(observation);
|
|
|
|
// Assert
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals("Complexity") &&
|
|
o.Value is int &&
|
|
(int)o.Value == 4), // Esperamos 4 para un peso entre 501 y 1000 según ComplexityValuesJson
|
|
true, false),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_WithSurgeryMedicationMewbornWeightMultiValueObservation_CalculatesComplexity_Returns13()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string observationName = "Surgery_Multivalue";
|
|
var observationValue = new[] { "Cardiaca", "Toracica", "Ortopedia" };
|
|
var observation = new PatientObservation
|
|
{ Name = observationName, PatientId = patientId, Value = observationValue }; //value 4 + 3 + 1
|
|
var medicationObs = new PatientObservation
|
|
{
|
|
Name = "Medication_Multivalue", PatientId = patientId, Value = new[] { "Isoprenalina", "Milrinona" }
|
|
}; //value 1 + 2
|
|
var newbornWeight = new PatientObservation
|
|
{ Name = "Newborn_Weight", PatientId = patientId, Value = 1800 }; //value 2
|
|
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(observationName)))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Respiratory_Device_Multivalue")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Intravenous_Routes_Multivalue")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Medication_Multivalue")))).ReturnsAsync([medicationObs]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("System_Multivalue")))).ReturnsAsync([]);
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains("Newborn_Weight")))).ReturnsAsync([newbornWeight]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(observation);
|
|
|
|
// Assert
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals("Complexity") &&
|
|
o.Value is int &&
|
|
(int)o.Value == 13), // Esperamos 13
|
|
true, false),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task CalculateSaturation_DiffObservation_WhenPreObservationExistsAndPostIsFound_InsertsDiffAndPrePost()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string preObservationName = "SpO2";
|
|
const string postObservationName = "SpO2_Post";
|
|
var currentTime = DateTime.UtcNow;
|
|
|
|
var preObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = preObservationName,
|
|
Value = 98,
|
|
Time = currentTime.AddMinutes(-5)
|
|
};
|
|
|
|
var postObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = postObservationName,
|
|
Value = 95,
|
|
Time = currentTime
|
|
};
|
|
|
|
// Simula que FindLastObservations devuelve la observación post
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(preObservationName) && list.Contains(postObservationName))))
|
|
.ReturnsAsync([postObservation]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(preObservation);
|
|
|
|
// Assert
|
|
// Verifica que se insertaron dos observaciones
|
|
_mockObservationService.Verify(x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name == "SpO2_Diff" &&
|
|
o.Value.Equals(Math.Round(98.0 - 95.0, 2))), // Verifica la diferencia calculada
|
|
true, true), Times.Once);
|
|
|
|
_mockObservationService.Verify(x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name == "SpO2_Pre_Post" &&
|
|
o.Value.Equals("98/95")), true, true),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task CalculateSaturation_DiffObservation_WhenPostObservationExistsAndPreIsFound_InsertsDiffAndPrePost()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string preObservationName = "SpO2";
|
|
const string postObservationName = "SpO2_Post";
|
|
var currentTime = DateTime.UtcNow;
|
|
|
|
var preObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = preObservationName,
|
|
Value = 98,
|
|
Time = currentTime.AddMinutes(-5)
|
|
};
|
|
|
|
var postObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = postObservationName,
|
|
Value = 95,
|
|
Time = currentTime
|
|
};
|
|
|
|
// Simula que FindLastObservations devuelve la observación pre
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(preObservationName) && list.Contains(postObservationName))))
|
|
.ReturnsAsync([preObservation]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(postObservation);
|
|
|
|
// Assert
|
|
// Verifica que se insertaron dos observaciones
|
|
_mockObservationService.Verify(x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name == "SpO2_Diff" &&
|
|
o.Value.Equals(Math.Round(98.0 - 95.0, 2))),
|
|
true, true), Times.Once);
|
|
|
|
_mockObservationService.Verify(x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name == "SpO2_Pre_Post" &&
|
|
o.Value.Equals("98/95")), true, true),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task CalculateSaturation_DiffObservation_WhenOnlyPreObservationExists_DoesNotInsertNewObservations()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string preObservationName = "SpO2_Pre";
|
|
const string postObservationName = "SpO2_Post";
|
|
var currentTime = DateTime.UtcNow;
|
|
|
|
var preObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = preObservationName,
|
|
Value = 98,
|
|
Time = currentTime.AddMinutes(-5)
|
|
};
|
|
|
|
// Simula que FindLastObservations devuelve solo la observación pre
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(preObservationName) && list.Contains(postObservationName))))
|
|
.ReturnsAsync([preObservation]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(preObservation);
|
|
|
|
// Assert
|
|
// Verifica que no se insertaron nuevas observaciones
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.IsAny<PatientObservation>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never);
|
|
}
|
|
|
|
[Test]
|
|
public async Task CalculateSaturation_DiffObservation_WhenOnlyPostObservationExists_DoesNotInsertNewObservations()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string preObservationName = "SpO2_Pre";
|
|
const string postObservationName = "SpO2_Post";
|
|
var currentTime = DateTime.UtcNow;
|
|
|
|
var postObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = postObservationName,
|
|
Value = 95,
|
|
Time = currentTime
|
|
};
|
|
|
|
// Simula que FindLastObservations devuelve solo la observación post
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(preObservationName) && list.Contains(postObservationName))))
|
|
.ReturnsAsync([postObservation]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(postObservation);
|
|
|
|
// Assert
|
|
// Verifica que no se insertaron nuevas observaciones
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.IsAny<PatientObservation>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never);
|
|
}
|
|
|
|
[Test]
|
|
public async Task CalculateSaturation_DiffObservation_WithDifferentPrePostValues_CalculatesCorrectDifference()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string preObservationName = "SpO2";
|
|
const string postObservationName = "SpO2_Post";
|
|
var currentTime = DateTime.UtcNow;
|
|
|
|
var preObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = preObservationName,
|
|
Value = 99.5,
|
|
Time = currentTime.AddMinutes(-5)
|
|
};
|
|
|
|
var postObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = postObservationName,
|
|
Value = 92.1,
|
|
Time = currentTime
|
|
};
|
|
|
|
// Simula que FindLastObservations devuelve la observación post
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(preObservationName) && list.Contains(postObservationName))))
|
|
.ReturnsAsync([postObservation]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(preObservation);
|
|
|
|
// Assert
|
|
// Verifica la diferencia calculada correctamente
|
|
_mockObservationService.Verify(x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name == "SpO2_Diff" &&
|
|
o.Value.Equals(7.4)),
|
|
true, true), Times.Once);
|
|
|
|
_mockObservationService.Verify(x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name == "SpO2_Pre_Post" &&
|
|
o.Value.Equals("99,5/92,1")), true, true),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task CalculateSaturation_DiffObservation_WithNonNumericPreValue_TreatsAsZero()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string preObservationName = "SpO2";
|
|
const string postObservationName = "SpO2_Post";
|
|
var currentTime = DateTime.UtcNow;
|
|
|
|
var preObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = preObservationName,
|
|
Value = "TextoNoNumerico",
|
|
Time = currentTime.AddMinutes(-5)
|
|
};
|
|
|
|
var postObservation = new PatientObservation
|
|
{
|
|
PatientId = patientId,
|
|
Name = postObservationName,
|
|
Value = "95",
|
|
Time = currentTime
|
|
};
|
|
|
|
// Simula que FindLastObservations devuelve la observación post
|
|
_mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is<List<string>>(list =>
|
|
list.Contains(preObservationName) && list.Contains(postObservationName))))
|
|
.ReturnsAsync([postObservation]);
|
|
|
|
// Act
|
|
await _calculatedObservations.Map(preObservation);
|
|
|
|
// Assert
|
|
// Verifica que la diferencia se calcula como 0 - 95 = -95
|
|
_mockObservationService.Verify(x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name == "SpO2_Diff" &&
|
|
o.Value.Equals(Math.Round(0 - 95.0, 2))),
|
|
true, true), Times.Once);
|
|
|
|
_mockObservationService.Verify(x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name == "SpO2_Pre_Post" &&
|
|
o.Value.Equals("TextoNoNumerico/95")), true, true),
|
|
Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_TreatmentWithNoPlacerOrder_ReturnsOriginalTreatment()
|
|
{
|
|
// Arrange
|
|
var treatment = new PatientTreatment { PlacerOrder = null };
|
|
|
|
// Act
|
|
var result = await _calculatedObservations.Map(treatment);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.SameAs(treatment));
|
|
Assert.That(treatment.PlacerOrder, Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_TreatmentWithActiveOlderTreatments_SetsOrderControlToXO()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string orderIdentifier = "ORD123";
|
|
var treatment = new PatientTreatment
|
|
{ PatientId = patientId, PlacerOrder = new Entity { EntityIdentifier = orderIdentifier } };
|
|
var oldTreatments = new List<PatientTreatment> { new() };
|
|
|
|
_treatmentServiceMock.Setup(x => x.GetActiveTreatmentsByPatient(patientId)).ReturnsAsync(oldTreatments);
|
|
|
|
// Act
|
|
var result = await _calculatedObservations.Map(treatment);
|
|
|
|
// Assert
|
|
Assert.That(result.OrderControl, Is.EqualTo(OrderControlType.Xo));
|
|
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.IsAny<PatientObservation>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_TreatmentWithNoActiveOlderTreatments_SetsOrderControlToNW()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string orderIdentifier = "ORD123";
|
|
var treatment = new PatientTreatment
|
|
{ PatientId = patientId, PlacerOrder = new Entity { EntityIdentifier = orderIdentifier } };
|
|
|
|
_treatmentServiceMock.Setup(x => x.GetActiveTreatmentsByPatient(patientId)).ReturnsAsync([]);
|
|
|
|
// Act
|
|
var result = await _calculatedObservations.Map(treatment);
|
|
|
|
// Assert
|
|
Assert.That(result.OrderControl, Is.EqualTo(OrderControlType.Nw));
|
|
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.IsAny<PatientObservation>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_TreatmentWithEndTimeSet_SetsOrderControlToDC()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string orderIdentifier = "ORD123";
|
|
var treatment = new PatientTreatment
|
|
{
|
|
PatientId = patientId,
|
|
PlacerOrder = new Entity { EntityIdentifier = orderIdentifier },
|
|
EndTime = DateTime.UtcNow.AddHours(1)
|
|
};
|
|
|
|
_treatmentServiceMock.Setup(x => x.GetActiveTreatmentsByPatient(patientId)).ReturnsAsync([]);
|
|
|
|
// Act
|
|
var result = await _calculatedObservations.Map(treatment);
|
|
|
|
// Assert
|
|
Assert.That(result.OrderControl, Is.EqualTo(OrderControlType.Dc));
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.IsAny<PatientObservation>(), It.IsAny<bool>(), It.IsAny<bool>()), Times.Never);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_TreatmentWithEndTimeSet_OverridesOrderControlFromOldTreatments()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string orderIdentifier = "ORD123";
|
|
var treatment = new PatientTreatment
|
|
{
|
|
PatientId = patientId,
|
|
PlacerOrder = new Entity { EntityIdentifier = orderIdentifier },
|
|
EndTime = DateTime.UtcNow.AddHours(1)
|
|
};
|
|
var oldTreatments = new List<PatientTreatment> { new() };
|
|
|
|
_treatmentServiceMock.Setup(x => x.GetActiveTreatmentsByPatient(patientId)).ReturnsAsync(oldTreatments);
|
|
|
|
// Act
|
|
var result = await _calculatedObservations.Map(treatment);
|
|
|
|
// Assert
|
|
// Aunque había tratamientos antiguos, EndTime debería priorizar OrderControlType.DC
|
|
Assert.That(result.OrderControl, Is.EqualTo(OrderControlType.Dc));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Map_TreatmentWithMedication_InsertObservation()
|
|
{
|
|
// Arrange
|
|
var patientId = ObjectId.GenerateNewId();
|
|
const string orderIdentifier = "ORD123";
|
|
var code = new Code { Identifier = "16323", CodingSystem = "CCC", Text = "Amiodarona vo" };
|
|
var medication = new Medicine
|
|
{
|
|
Name = code.Text,
|
|
Codes = [code.Identifier],
|
|
Type = ["Medication"],
|
|
Group = ["Antiarrítmicos"]
|
|
};
|
|
var treatment = new PatientTreatment
|
|
{
|
|
PatientId = patientId,
|
|
PlacerOrder = new Entity { EntityIdentifier = orderIdentifier },
|
|
RequestedGiveCodes = [code]
|
|
};
|
|
var oldTreatments = new List<PatientTreatment> { new() };
|
|
|
|
_treatmentServiceMock.Setup(x => x.GetActiveTreatmentsByPatient(patientId)).ReturnsAsync(oldTreatments);
|
|
|
|
_medicineServiceMock.Setup(m => m.GetByCode(code.Identifier)).ReturnsAsync(medication);
|
|
|
|
_mockObservationService.Setup(s => s.FindLastObservations(It.IsAny<ObjectId>(), 1, It.IsAny<List<string>>()))
|
|
.ReturnsAsync([]);
|
|
// Act
|
|
var result = await _calculatedObservations.Map(treatment);
|
|
|
|
// Assert
|
|
//Assert.That(result,Is.Null);
|
|
Assert.That(result.OrderControl, Is.EqualTo(OrderControlType.Xo));
|
|
|
|
_mockObservationService.Verify(
|
|
x => x.InsertObservation(It.Is<PatientObservation>(o =>
|
|
o.PatientId == patientId &&
|
|
o.Name != null &&
|
|
o.Name.Equals("Medication_Multivalue") &&
|
|
o.Value.GetType() == typeof(string[]) &&
|
|
((string[])o.Value).Length == 1 &&
|
|
((string[])o.Value)[0].ToString() == "Amiodarona vo"
|
|
),
|
|
true, true),
|
|
Times.Once);
|
|
}
|
|
} |