Files
strataspheredatamanagement/tests/Strata.Stratasphere.Biz.IntegrationTests/Standards/IntegrationTests/ReadmissionTests.cs
T
2026-06-23 11:26:55 -05:00

229 lines
11 KiB
C#

using CsvHelper;
using Dapper;
using NUnit.Framework;
using Strata.Stratasphere.Biz.Standards;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using Strata.SnowflakeLib;
namespace Strata.Stratasphere.Biz.IntegrationTests.Standards.IntegrationTests
{
[TestFixture]
public class ReadmissionTests : IntegrationTestBase
{
public List<TestInput> TestInputs { get; set; }
private List<TestOutput> TestOutputs { get; set; }
private readonly string TransactionalTableName;
public ReadmissionTests() : base()
{
#if (DEBUG)
TransactionalTableName = "SPH.MEL_TEST123";
#else
TransactionalTableName = $"SPH.MEL_TEST123_{Guid.NewGuid():N}";
#endif
}
[OneTimeSetUp]
public void SetupFixture()
{
DeleteData(_dbSnowflakeConnection);
LoadInitialData(_dbSnowflakeConnection);
RunFullReadmit(_dbSnowflakeConnection);
CreateEncounterTable(_dbSnowflakeConnection);
}
[OneTimeTearDown]
public void TearDownFixture()
{
DeleteData(_dbSnowflakeConnection);
}
private void CreateEncounterTable(StrataSnowflakeConnection conn)
{
var ctable = $@"CREATE OR REPLACE TABLE {TransactionalTableName} (ENCOUNTERID BIGINT, ROWID BIGINT IDENTITY(1,1));";
conn.Execute(ctable);
}
private void LoadInitialData(StrataSnowflakeConnection conn)
{
using StreamReader reader = File.OpenText("./Standards/IntegrationTests/TestData/Readmit Test Data.csv");
using var csvReader = new CsvReader(reader, CultureInfo.InvariantCulture);
TestInputs = csvReader.GetRecords<TestInput>().ToList();
LoadData(conn, TestInputs);
}
private void LoadData(StrataSnowflakeConnection conn, List<TestInput> testInputs)
{
var encLoops = string.Join("\nUNION ALL ", testInputs.Select(a => $"SELECT {a.EncounterID} ENCOUNTERID, {a.PatientID} PATIENTID, '{a.AdmitDateTime:u}' ADMITDATETIME, '{a.DischargeDateTime:u}' DISCHARGEDATETIME,'{a.Diag1}' DIAG1"));
var ptLoops = string.Join("\nUNION ALL ", testInputs.Select(a => $"SELECT {a.EncounterID} ENCOUNTERID, '{a.IsInpatient}' ISINPATIENT, '{a.IsOutpatient}' ISOUTPATIENT"));
var diagLoops = string.Join("\nUNION ALL ", testInputs.Select(a => $"SELECT {a.EncounterID} ENCOUNTERID, '{a.Diag1}' DIAGCODE, 1 SEQUENCENUMBER\nUNION ALL SELECT {a.EncounterID} ENCOUNTERID, '{a.Diag2}' DIAGCODE, 2 SEQUENCENUMBER"));
var procLoops = string.Join("\nUNION ALL ", testInputs.Select(a => $"SELECT {a.EncounterID} ENCOUNTERID, '{a.Proc1}' PROCCODE, 1 SEQUENCENUMBER\nUNION ALL SELECT {a.EncounterID} ENCOUNTERID, '{a.Proc2}' PROCCODE, 2 SEQUENCENUMBER"));
var encInput = $@"
INSERT INTO CLIENTDSS.FACTPATIENTENCOUNTERSUMMARY (ENCOUNTERID, ENCOUNTERRECORDNUMBER, PATIENTID, ADMITDATETIME, DISCHARGEDATETIME, ICD10DXPRIMARYDIAGID, DISCHARGEDATEID, ADMITDATEID)
SELECT a.EncounterID, a.EncounterID, a.PatientID, a.AdmitDateTime, a.DischargeDateTime, DX.ICD10DXID, DISDATE.DATEID, ADDATE.DATEID FROM
(
{encLoops}
) a
INNER JOIN DSS.DIMICD10DX DX ON DX.ICD10DXCODENODECIMAL = a.Diag1
INNER JOIN FW.DIMDATE DISDATE ON DISDATE.CALENDARDATETIME = a.DISCHARGEDATETIME
INNER JOIN FW.DIMDATE ADDATE ON ADDATE.CALENDARDATETIME = a.ADMITDATETIME;";
var ptInput = $@"
INSERT INTO SPH.ENCOUNTERPATIENTTYPE (ENCOUNTERID, ISINPATIENT, ISOUTPATIENT)
SELECT ENCOUNTERID, ISINPATIENT, ISOUTPATIENT FROM
(
{ptLoops}
);
";
var diagInput = $@"
INSERT INTO DSS.FACTPATIENTICD10DIAGNOSTICDETAIL (ENCOUNTERID, ENCOUNTERRECORDNUMBER, ICD10DXID, SEQUENCENUMBERID)
SELECT ENCOUNTERID, ENCOUNTERID, DX.ICD10DXID, SEQUENCENUMBER
FROM (
{diagLoops}
) a
INNER JOIN DSS.DIMICD10DX DX ON DX.ICD10DXCODENODECIMAL = a.DIAGCODE;
";
var procInput = $@"
INSERT INTO DSS.FACTPATIENTICD10PROCEDURALDETAIL (ENCOUNTERID, ENCOUNTERRECORDNUMBER, ICD10PXID, SEQUENCENUMBERID)
SELECT ENCOUNTERID, ENCOUNTERID, PX.ICD10PXID, SEQUENCENUMBER
FROM (
{procLoops}
) a
INNER JOIN DSS.DIMICD10PX PX ON PX.ICD10PXCODENODECIMAL = a.PROCCODE;
";
conn.Execute(encInput);
conn.Execute(ptInput);
conn.Execute(diagInput);
conn.Execute(procInput);
}
private void RunFullReadmit(StrataSnowflakeConnection conn)
{
var readmitJob = _serviceProvider.GetRequiredService<ReadmissionJob>();
readmitJob.ProcessReadmissionsForAllEncounters(_DatabaseGuid, "GM Working Small", null, CancellationToken.None).GetAwaiter().GetResult();
TestOutputs = conn.Query<TestOutput>($"SELECT * FROM {StandardsConstants.READMISSION_TABLENAME} WHERE ENCOUNTERID < 0").ToList();
}
private void DeleteData(StrataSnowflakeConnection conn)
{
conn.Execute("DELETE FROM CLIENTDSS.FACTPATIENTENCOUNTERSUMMARY where EncounterID < 0;");
conn.Execute("DELETE FROM dss.FACTPATIENTICD10DIAGNOSTICDETAIL where encounterid < 0; ");
conn.Execute("DELETE FROM DSS.FACTPATIENTICD10PROCEDURALDETAIL where encounterid < 0; ");
conn.Execute("DELETE FROM SPH.ENCOUNTERPATIENTTYPE where encounterid < 0; ");
conn.Execute($"DROP TABLE IF EXISTS {TransactionalTableName};");
}
private static IEnumerable<TestCaseData> GetTestCases()
{
using StreamReader reader = File.OpenText("./Standards/IntegrationTests/TestData/Readmit Test Data.csv");
using var csvReader = new CsvReader(reader, CultureInfo.InvariantCulture);
return csvReader.GetRecords<TestResult>().Select(a => new TestCaseData(a).SetName($"Encounter: {a.EncounterID} - 30Day-90Day: {a.Is30DayReadmit}/{a.Is30DayIndex} - {a.Is90DayReadmit}/{a.Is90DayIndex}").SetDescription(a.Description)).ToList();
}
[Test, TestCaseSource("GetTestCases")]
public void Test(TestResult test)
{
var output = TestOutputs.FirstOrDefault(a => a.EncounterID == test.EncounterID);
AssertReadmit(output, test);
}
private void AssertReadmit(TestOutput output, TestResult expected)
{
if (output != null)
{
Assert.AreEqual(expected.EncounterID, output.EncounterID);
Assert.AreEqual(expected.IsEligibleIndex, output.IsEligibleIndex);
Assert.AreEqual(expected.IsEligibleReadmit, output.IsEligibleReadmit);
Assert.AreEqual(expected.Is30DayReadmit, output.Is30DayReadmit);
Assert.AreEqual(expected.Is30DayIndex, output.Is30DayReadmitIndex);
Assert.AreEqual(expected.Is90DayReadmit, output.Is90DayReadmit);
Assert.AreEqual(expected.Is90DayIndex, output.Is90DayReadmitIndex);
}
else
{
Assert.AreEqual(!expected.IsEligibleIndex && !expected.IsEligibleReadmit, output == null);
}
}
[Test]
[TestCase(-101, Description = "Test Transactional Readmission Based on Index Encounter")]
[TestCase(-102, Description = "Test Transactional Readmission Based on Readmit Encounter")]
public void TestReadmit_Transactional(int changedEncounter)
{
var input = new List<TestInput>()
{
new TestInput() { PatientID = -150, EncounterID = -101, IsInpatient = true,IsOutpatient = false, AdmitDateTime = new DateTime(2030, 1, 10), DischargeDateTime = new DateTime(2030, 1, 11), Diag1 = "E03", Diag2 = "E030", Proc1 = "0SW5X8Z", Proc2 = "04734FZ" },
new TestInput() {PatientID = -150, EncounterID = -102, IsInpatient = true,IsOutpatient = false, AdmitDateTime = new DateTime(2030, 1, 20), DischargeDateTime = new DateTime(2030, 1, 21), Diag1 = "E03", Diag2 = "E030", Proc1 = "0SW5X8Z", Proc2 = "04734FZ" }
};
var expectedIndex = new TestResult() { EncounterID = -101, Is30DayReadmit = false, Is30DayIndex = true, Is90DayReadmit = false, Is90DayIndex = true, IsEligibleIndex = true, IsEligibleReadmit = true };
var expectedReadmit = new TestResult() { EncounterID = -102, Is30DayReadmit = true, Is30DayIndex = false, Is90DayReadmit = true, Is90DayIndex = false, IsEligibleIndex = true, IsEligibleReadmit = true };
_dbSnowflakeConnection.Execute($"DELETE FROM {TransactionalTableName};");
_dbSnowflakeConnection.Execute($"INSERT INTO {TransactionalTableName} (ENCOUNTERID) VALUES ({changedEncounter});");
LoadData(_dbSnowflakeConnection, input);
var readmitJob = _serviceProvider.GetRequiredService<ReadmissionJob>();
readmitJob.ProcessReadmissions(_DatabaseGuid, TransactionalTableName, null, CancellationToken.None).GetAwaiter().GetResult();
var outputs = _dbSnowflakeConnection.Query<TestOutput>($"SELECT * FROM {StandardsConstants.READMISSION_TABLENAME} WHERE ENCOUNTERID < 0").ToList();
var index = outputs.FirstOrDefault(a => a.EncounterID == -101);
var readmit = outputs.FirstOrDefault(a => a.EncounterID == -102);
AssertReadmit(index, expectedIndex);
AssertReadmit(readmit, expectedReadmit);
}
public class TestResult
{
public long EncounterID { get; set; }
public bool IsEligibleIndex { get; set; }
public bool IsEligibleReadmit { get; set; }
public bool Is30DayReadmit { get; set; }
public bool Is30DayIndex { get; set; }
public bool Is90DayReadmit { get; set; }
public bool Is90DayIndex { get; set; }
public string Description { get; set; }
}
public class TestInput
{
public long EncounterID { get; set; }
public long PatientID { get; set; }
public bool IsInpatient { get; set; }
public bool IsOutpatient { get; set; }
public DateTime AdmitDateTime { get; set; }
public DateTime DischargeDateTime { get; set; }
public string Diag1 { get; set; }
public string Diag2 { get; set; }
public string Proc1 { get; set; }
public string Proc2 { get; set; }
}
public class TestOutput
{
public long EncounterID { get; set; }
public bool IsEligibleIndex { get; set; }
public bool IsEligibleReadmit { get; set; }
public bool Is30DayReadmit { get; set; }
public bool Is30DayReadmitIndex { get; set; }
public bool Is90DayReadmit { get; set; }
public bool Is90DayReadmitIndex { get; set; }
}
}
}