229 lines
11 KiB
C#
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; }
|
|
}
|
|
}
|
|
}
|