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 TestInputs { get; set; } private List 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().ToList(); LoadData(conn, TestInputs); } private void LoadData(StrataSnowflakeConnection conn, List 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(); readmitJob.ProcessReadmissionsForAllEncounters(_DatabaseGuid, "GM Working Small", null, CancellationToken.None).GetAwaiter().GetResult(); TestOutputs = conn.Query($"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 GetTestCases() { using StreamReader reader = File.OpenText("./Standards/IntegrationTests/TestData/Readmit Test Data.csv"); using var csvReader = new CsvReader(reader, CultureInfo.InvariantCulture); return csvReader.GetRecords().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() { 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(); readmitJob.ProcessReadmissions(_DatabaseGuid, TransactionalTableName, null, CancellationToken.None).GetAwaiter().GetResult(); var outputs = _dbSnowflakeConnection.Query($"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; } } } }