chore: deploy initial code base

This commit is contained in:
Thom Lamb
2026-05-12 10:34:30 -05:00
parent cce2961782
commit a81300a571
1829 changed files with 248331 additions and 1 deletions
@@ -0,0 +1,114 @@
using NUnit.Framework;
using Strata.ContinuousImprovement.Biz.Shared;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.DistributionProcess.ChargeCode;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Enums;
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using VerifyNUnit;
using VerifyTests;
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities.DistributionProcess
{
public class DistributionProcessChargeCodeSqlBuilderTests : StrategicOpportunityTestsBase
{
private readonly long _testOpportunityId = 0;
private readonly Period<DateOnly> _baselinePeriod;
private readonly Period<DateOnly> _goalPeriod;
private readonly Period<DateOnly> _trackingPeriod;
private readonly double[] _rampUps;
public DistributionProcessChargeCodeSqlBuilderTests()
{
_baselinePeriod = new Period<DateOnly>(new DateOnly(2024, 1, 1), new DateOnly(2024, 12, 31));
_goalPeriod = new Period<DateOnly>(new DateOnly(2025, 1, 1), new DateOnly(2025, 12, 31));
_trackingPeriod = new Period<DateOnly>(new DateOnly(2026, 1, 1), new DateOnly(2026, 12, 31));
_rampUps = [0.1, 0.2, 0.3, 0.4];
}
[TestCaseSource(nameof(BuildInsertDistributedSqlTestCases))]
public async Task BuildInsertDistributedSqlTest(DistributionMethod methodType, DistributionStage stage)
{
// Arrange
var builder = new DistributionProcessChargeCodeSqlBuilder(
_testOpportunityId,
_baselinePeriod,
_goalPeriod,
_trackingPeriod,
_rampUps);
// Act
var result = builder.BuildInsertDistributedSql(methodType, stage);
// Assert
await Verifier.Verify(result.Sql, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
[TestCase(true)]
[TestCase(false)]
public async Task BuildDistributionSummarySqlTest(bool isInitiative)
{
// Arrange
var builder = new DistributionProcessChargeCodeSqlBuilder(
_testOpportunityId,
_baselinePeriod,
_goalPeriod,
_trackingPeriod,
_rampUps);
// Act
var result = builder.BuildDistributionSummarySql(isInitiative);
// Assert
await Verifier.Verify(result.Sql, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
[Test]
public async Task BuildUpdateDetailCommittedByRampUpSqlTest()
{
// Arrange
var builder = new DistributionProcessChargeCodeSqlBuilder(
_testOpportunityId,
_baselinePeriod,
_goalPeriod,
_trackingPeriod,
_rampUps);
// Act
var result = builder.BuildUpdateDetailCommittedByRampUpSql(_rampUps.Reverse().ToArray());
// Assert
await Verifier.Verify(result.Sql, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
public static IEnumerable<TestCaseData> BuildInsertDistributedSqlTestCases()
{
var distributionMethods = new[]
{
DistributionMethod.Average,
DistributionMethod.Monthly
};
var distributionStages = new[]
{
DistributionStage.FromSourceToOpportunity,
DistributionStage.OpportunityChangeGoalPeriod,
DistributionStage.FromInitiativeToOpportunity,
DistributionStage.FromOpportunityToInitiative,
DistributionStage.InitiativeChangeTrackingPeriod
};
foreach (var method in distributionMethods)
{
foreach (var stage in distributionStages)
{
yield return new TestCaseData(method, stage);
}
}
}
}
}
@@ -0,0 +1,115 @@
using NUnit.Framework;
using Strata.ContinuousImprovement.Biz.Shared;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.DistributionProcess.GL;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Enums;
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
using VerifyNUnit;
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities.DistributionProcess
{
[ExcludeFromCodeCoverage]
[TestFixture, Category("Unit"), Category("CCI")]
public class DistributionProcessGLSqlBuilderTests : StrategicOpportunityTestsBase
{
private readonly long _testOpportunityId = 0;
private readonly Period<DateOnly> _baselinePeriod;
private readonly Period<DateOnly> _goalPeriod;
private readonly Period<DateOnly> _trackingPeriod;
private readonly double[] _rampUps;
public DistributionProcessGLSqlBuilderTests()
{
_baselinePeriod = new Period<DateOnly>(new DateOnly(2024, 1, 1), new DateOnly(2024, 12, 31));
_goalPeriod = new Period<DateOnly>(new DateOnly(2025, 1, 1), new DateOnly(2025, 12, 31));
_trackingPeriod = new Period<DateOnly>(new DateOnly(2026, 1, 1), new DateOnly(2026, 12, 31));
_rampUps = [0.1, 0.2, 0.3, 0.4];
}
[TestCaseSource(nameof(BuildInsertDistributedSqlTestCases))]
public async Task BuildInsertDistributedSqlTest(DistributionMethod methodType, DistributionStage stage)
{
// Arrange
var builder = new DistributionProcessGLSqlBuilder(
_testOpportunityId,
_baselinePeriod,
_goalPeriod,
_trackingPeriod,
_rampUps);
// Act
var result = builder.BuildInsertDistributedSql(methodType, stage);
// Assert
await Verifier.Verify(result.Sql, VerifySettings)
.UseFileName("GL " + TestContext.CurrentContext.TestName());
}
[TestCase(true)]
[TestCase(false)]
public async Task BuildDistributionSummarySqlTest(bool isInitiative)
{
// Arrange
var builder = new DistributionProcessGLSqlBuilder(
_testOpportunityId,
_baselinePeriod,
_goalPeriod,
_trackingPeriod,
_rampUps);
// Act
var result = builder.BuildDistributionSummarySql(isInitiative);
// Assert
await Verifier.Verify(result.Sql, VerifySettings)
.UseFileName("GL " + TestContext.CurrentContext.TestName());
}
[Test]
public async Task BuildUpdateDetailCommittedByRampUpSqlTest()
{
// Arrange
var builder = new DistributionProcessGLSqlBuilder(
_testOpportunityId,
_baselinePeriod,
_goalPeriod,
_trackingPeriod,
_rampUps);
// Act
var result = builder.BuildUpdateDetailCommittedByRampUpSql(_rampUps.Reverse().ToArray());
// Assert
await Verifier.Verify(result.Sql, VerifySettings)
.UseFileName("GL " + TestContext.CurrentContext.TestName());
}
public static IEnumerable<TestCaseData> BuildInsertDistributedSqlTestCases()
{
var distributionMethods = new[]
{
DistributionMethod.Average,
DistributionMethod.Monthly
};
var distributionStages = new[]
{
DistributionStage.FromSourceToOpportunity,
DistributionStage.OpportunityChangeGoalPeriod,
DistributionStage.FromInitiativeToOpportunity,
DistributionStage.FromOpportunityToInitiative,
DistributionStage.InitiativeChangeTrackingPeriod
};
foreach (var method in distributionMethods)
{
foreach (var stage in distributionStages)
{
yield return new TestCaseData(method, stage);
}
}
}
}
}
@@ -0,0 +1,295 @@
using NUnit.Framework;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Dtos;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Enums;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Queries;
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
using Strata.DataSchema.Models.Query;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using VerifyNUnit;
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities.Queries
{
[TestFixture]
public class StrategicOpportunityDetailQueryBuilderTests : StrategicOpportunityTestsBase
{
private IStrategicOpportunityDetailQueryBuilder _builder;
private const long TestOpportunityId = 123;
private const long TestMeasureId = 456;
private const string TestStartDate = "2024-01-01";
private const int TestTrackingMonths = 12;
private const string SelectQuery = "SELECT * FROM TestTable";
private const string InvalidSelectQuery = "UPDATE TestTable SET Column1 = 'Value'";
private const string ComplexSelectQuery = @"
SELECT
*
FROM dss.FactPatientCostDetail AS COSTDETAIL
RIGHT JOIN dss.FactPatientBillingLineItemDetail AS PBLID ON PBLID.rowid = COSTDETAIL.pblidrowid
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
LEFT JOIN CCI.FACTEXPLORATIONPOPULATIONENCOUNTER AS EXPLORATIONPOPULATIONENCOUNTER ON EXPLORATIONPOPULATIONENCOUNTER.encounterid = PBLID.encounterid
LEFT JOIN CCI.VIEWENCOUNTERPATIENTTYPEROLLUP AS ENCOUNTERPATIENTTYPEROLLUP ON ENCOUNTERPATIENTTYPEROLLUP.encounterid = PBLID.encounterid
INNER JOIN FW.DIMCHARGECODE AS CC ON CC.chargecodeid = PBLID.chargecodeid
INNER JOIN DSS.DIMPHYSICIAN AS PHYSPRIMARY ON PHYSPRIMARY.physicianid = DSSPES.primaryphysicianid
";
[SetUp]
public void Setup()
{
_builder = new StrategicOpportunityDetailQueryBuilder();
}
#region BuildInsertQuery Tests
[TestCase(true, TestName = "BuildInsertQuery with APRDRG")]
[TestCase(false, TestName = "BuildInsertQuery without APRDRG")]
public async Task BuildInsertQuery_ShouldGenerateValidSql(bool isUsingAprdrg)
{
// Arrange
var opportunity = new StrategicOpportunityChargeCode { OpportunityId = TestOpportunityId };
// Act
var result = _builder.BuildInsertQuery(opportunity, SelectQuery, isUsingAprdrg);
// Assert
await Verifier.Verify(result, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
[Test]
public void BuildInsertQuery_WithInvalidSelectQuery_ShouldThrowException()
{
// Arrange
var opportunity = new StrategicOpportunityChargeCode { OpportunityId = TestOpportunityId };
// Act & Assert
var ex = Assert.Throws<InvalidOperationException>(() =>
_builder.BuildInsertQuery(opportunity, InvalidSelectQuery, true));
Assert.That(ex.Message, Does.Contain("Unexpected SQL syntax. SELECT should be first word."));
}
#endregion
#region BuildDeleteQuery Tests
[Test]
public async Task BuildDeleteQuery_WithOpportunityId_ShouldGenerateValidSql()
{
// Act
var result = _builder.BuildDeleteQuery(TestOpportunityId);
// Assert
await Verifier.Verify(result, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
[Test]
public async Task BuildDeleteQuery_WithoutOpportunityId_ShouldGenerateParameterizedSql()
{
// Act
var result = _builder.BuildDeleteQuery();
// Assert
await Verifier.Verify(result, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
#endregion
#region BuildMergeQuery Tests
[TestCase(true, TestName = "BuildMergeQuery with APRDRG")]
[TestCase(false, TestName = "BuildMergeQuery without APRDRG")]
public async Task BuildMergeQuery_ShouldGenerateValidSql(bool isUsingAprdrg)
{
// Act
var result = _builder.BuildMergeQuery(TestOpportunityId, SelectQuery, isUsingAprdrg);
// Assert
await Verifier.Verify(result, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
[Test]
public void BuildMergeQuery_WithInvalidSelectQuery_ShouldThrowException()
{
// Act & Assert
var ex = Assert.Throws<InvalidOperationException>(() =>
_builder.BuildMergeQuery(TestOpportunityId, InvalidSelectQuery, true));
Assert.That(ex.Message, Does.Contain("Unexpected SQL syntax. SELECT should be first word."));
}
#endregion
#region BuildGetDistinctEncounterCountQuery Tests
[TestCase(true, TestName = "BuildGetDistinctEncounterCountQuery with APRDRG")]
[TestCase(false, TestName = "BuildGetDistinctEncounterCountQuery without APRDRG")]
public async Task BuildGetDistinctEncounterCountQuery_ShouldGenerateValidSql(bool isUsingAprdrg)
{
// Arrange
var getData = new StrategicOpportunityGetDetailData
{
Dimensions = new[] { "entity", "chargeCode", "costDriver" }
};
// Act
var result = _builder.BuildGetDistinctEncounterCountQuery(TestOpportunityId, SelectQuery, isUsingAprdrg, getData);
// Assert
await Verifier.Verify(result, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
[Test]
public void BuildGetDistinctEncounterCountQuery_ShouldThrowException()
{
// Arrange
var getData = new StrategicOpportunityGetDetailData
{
Dimensions = new[] { "entity", "chargeCode", "costDriver" }
};
// Act & Assert
var ex = Assert.Throws<InvalidOperationException>(() =>
_builder.BuildGetDistinctEncounterCountQuery(TestOpportunityId, InvalidSelectQuery, true, getData));
Assert.That(ex.Message, Does.Contain("Unexpected SQL syntax. SELECT should be first word."));
}
#endregion
#region BuildMergeSystemMeasureMergeQuery Tests
[TestCaseSource(nameof(GetMeasureTypeTestCases))]
public async Task BuildMergeSystemMeasureMergeQuery_WithDifferentMeasureTypes_ShouldGenerateValidSql(MeasureType measureType)
{
// Act
var result = _builder.BuildMergeSystemMeasureMergeQuery(TestOpportunityId, TestMeasureId, measureType, TestStartDate, TestTrackingMonths);
// Assert
await Verifier.Verify(result, VerifySettings)
.UseFileName($"{TestContext.CurrentContext.Test.Name}_{measureType}");
}
private static IEnumerable<TestCaseData> GetMeasureTypeTestCases()
{
yield return new TestCaseData(MeasureType.CommittedCost).SetName("BuildMergeSystemMeasureMergeQuery with CommittedCost");
yield return new TestCaseData(MeasureType.ActualCost).SetName("BuildMergeSystemMeasureMergeQuery with ActualCost");
}
#endregion
#region GetSelectMeasureSql Tests
[TestCaseSource(nameof(GetSelectMeasureSql_TestCases))]
public async Task GetSelectMeasureSql_ShouldGenerateValidSql(MeasureType measureType)
{
// Arrange
var marginFilters = new Dictionary<string, FilterCondition>
{
{ "DepartmentId", new FilterCondition { Operator = FilterOperator.In, Values = new List<string> { "1", "2", "3", "4", "5" } } },
{ "ChargeCodeId", new FilterCondition { Operator = FilterOperator.NotIn, Values = new List<string> { "100", "200", "300" } } },
{ "EntityId", new FilterCondition { Operator = FilterOperator.In, Values = new List<string> { "999" } } }
};
// Act
var result = _builder.GetSelectMeasureSql(TestOpportunityId, measureType, ComplexSelectQuery, marginFilters);
// Assert
await Verifier.Verify(result, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
[Test]
public async Task GetSelectMeasureSql_EncountersCases()
{
// Arrange
var marginFilters = new Dictionary<string, FilterCondition>();
var complexSelectQuery = ComplexSelectQuery.Replace(
"RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid",
"INNER JOIN (SELECT * FROM clientdss.FactPatientEncounterSummary AS DSSPES) AS DSSPES ON DSSPES.encounterid = PBLID.encounterid"
);
// Act
var result = _builder.GetSelectMeasureSql(TestOpportunityId, MeasureType.EncountersCases, complexSelectQuery, marginFilters);
// Assert
await Verifier.Verify(result, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
private static IEnumerable<TestCaseData> GetSelectMeasureSql_TestCases()
{
foreach (var x in Enum.GetValues<MeasureType>().Where(x => x < MeasureType.CommittedCost))
{
yield return new TestCaseData(x)
.SetName($"GetSelectMeasureSql with {x}");
}
}
#endregion
#region WrapIntoMeasureMergeQuery Tests
[Test]
public async Task WrapIntoMeasureMergeQuery_ShouldWrapSelectQueryCorrectly()
{
// Act
var result = _builder.WrapIntoMeasureMergeQuery(SelectQuery);
// Assert
await Verifier.Verify(result, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
#endregion
#region WrapIntoMeasureAverageQuery Tests
[Test]
public async Task WrapIntoMeasureAverageQuery_ShouldWrapSelectQueryCorrectly()
{
// Act
var result = _builder.WrapIntoMeasureAverageQuery(SelectQuery);
// Assert
await Verifier.Verify(result, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
#endregion
#region GetDeleteAllMeasuresSql Tests
[TestCaseSource(nameof(GetDeleteAllMeasuresSql_TestCases))]
public async Task GetDeleteAllMeasuresSql_ShouldGenerateValidSql(long[] measureIds)
{
// Act
var result = _builder.GetDeleteAllMeasuresSql(measureIds);
// Assert
if (measureIds == null || measureIds.Length == 0)
{
Assert.That(result, Is.Empty);
}
else
{
await Verifier.Verify(result, VerifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
}
private static IEnumerable<TestCaseData> GetDeleteAllMeasuresSql_TestCases()
{
yield return new TestCaseData(new long[] { 1, 2, 3, 4, 5 })
.SetName("GetDeleteAllMeasuresSql with MeasureIds");
yield return new TestCaseData(new long[] { })
.SetName("GetDeleteAllMeasuresSql with empty MeasureIds");
yield return new TestCaseData(null)
.SetName("GetDeleteAllMeasuresSql with null MeasureIds");
}
#endregion
}
}
@@ -0,0 +1,703 @@
using Hangfire;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Biz.DbContexts;
using Strata.ContinuousImprovement.Biz.DbContexts.Snowflake;
using Strata.ContinuousImprovement.Biz.Exploration;
using Strata.ContinuousImprovement.Biz.Exploration.Filters;
using Strata.ContinuousImprovement.Biz.Notification;
using Strata.ContinuousImprovement.Biz.Population;
using Strata.ContinuousImprovement.Biz.Shared;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.DistributionProcess;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Enums;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Queries;
using Strata.ContinuousImprovement.Biz.Test.Unit.DbContexts;
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
using Strata.DataSchema.Client;
using Strata.DataSchema.Models.Query;
using Strata.DataSchema.Models.Schema;
using Strata.Schema.Client;
using Strata.Schema.Client.Dtos;
using Strata.Schema.Client.Dtos.Info;
using Strata.SqlTools.Configuration.Common.AsyncFactory;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using VerifyNUnit;
using static Strata.ContinuousImprovement.Biz.Exploration.ExplorationService;
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities
{
[ExcludeFromCodeCoverage]
[TestFixture, Category("Unit"), Category("CCI")]
public class StrategicChargeCodeOpportunityDetailServiceTests : StrategicOpportunityTestsBase
{
private IStrategicChargeCodeOpportunityDetailService _strategicOpportunityDetailService;
private Mock<IDataSchemaService> _mockDataSchemaService;
private Mock<ISchemaServiceClient> _mockSchemaServiceClient;
private Mock<ISnowflakeDatabaseContext> _mockSnowflakeContext;
private Mock<IAsyncDbContextFactory<JazzDbContext>> _mockJazzDbContext;
private Mock<IExplorationFilterService> _mockExplorationService;
private Mock<IDistributionProcessFactory> _mockDistributionProcessFactory;
private Mock<IStrategicOpportunityDetailQueryBuilder> _mockStrategicOpportunityDetailQueryBuilder;
private Mock<IHubContext<NotificationHub, INotificationHub>> _mockNotificationHubClient;
private Mock<ILogger<StrategicChargeCodeOpportunityDetailService>> _mockLogger;
private Mock<IStrategicItemDimensionSyncService> _mockDimensionSyncService;
private CentralDbContext _centralDbContext;
[OneTimeSetUp]
public void Setup()
{
// Create in-memory database
var options = new DbContextOptionsBuilder<CentralDbContext>()
.UseInMemoryDatabase(databaseName: "TestCentralDb_" + Guid.NewGuid())
.Options;
_centralDbContext = new CentralDbContext(options);
// Arrange mocks
_mockSchemaServiceClient = new Mock<ISchemaServiceClient>();
_mockJazzDbContext = new Mock<IAsyncDbContextFactory<JazzDbContext>>();
_mockSnowflakeContext = new Mock<ISnowflakeDatabaseContext>();
_mockDataSchemaService = new Mock<IDataSchemaService>();
_mockExplorationService = new Mock<IExplorationFilterService>();
_mockNotificationHubClient = new Mock<IHubContext<NotificationHub, INotificationHub>>();
_mockLogger = new Mock<ILogger<StrategicChargeCodeOpportunityDetailService>>();
_mockDistributionProcessFactory = new Mock<IDistributionProcessFactory>();
_mockStrategicOpportunityDetailQueryBuilder = new Mock<IStrategicOpportunityDetailQueryBuilder>();
_mockDimensionSyncService = new Mock<IStrategicItemDimensionSyncService>();
_mockDimensionSyncService.Setup(x => x.UpsertAsync(It.IsAny<StrategicOpportunity>(), It.IsAny<CancellationToken>())).Returns(Task.CompletedTask);
_mockDimensionSyncService.Setup(x => x.DeleteAsync(It.IsAny<long>())).Returns(Task.CompletedTask);
// Seed ExplorationPopulation data for exploration test cases
_centralDbContext.ExplorationPopulations.Add(new ExplorationPopulation
{
ExplorationPopulationId = 100,
Name = "Test Exploration Population",
CaseTypeFamilyId = 123,
StrataId = 1,
FiltersJSON = @"[{""ChipType"":4,""Key"":1,""DateRange"":[""2024-01-01T00:00:00"",""2024-12-31T00:00:00""]}]"
});
_centralDbContext.SaveChanges();
// Create in-memory JazzDbContext options that will be reused
var jazzOptions = new DbContextOptionsBuilder<JazzDbContext>()
.UseInMemoryDatabase(databaseName: "TestJazzDb_" + Guid.NewGuid())
.Options;
// Seed the JazzDb with initial data
using (var jazzDbContext = new JazzDbContext(jazzOptions))
{
jazzDbContext.SystemSettings.Add(new SystemSetting
{
SystemSettingId = 1,
Name = "Flexible Exploration Inpatient Case Type Family",
Value = "0"
});
jazzDbContext.SaveChanges();
}
// Mock JazzDbContext factory to return a NEW context instance each time
_mockJazzDbContext.Setup(x => x.CreateDbContextAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(() => new JazzDbContext(jazzOptions));
// Mock ExplorationFilterService
_mockExplorationService.Setup(x =>
x.GetFilterStringsAsync(It.IsAny<IEnumerable<FilterChipItem>>(), It.IsAny<IQueryParamBase>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(("WHERE DSSPES.dischargedatetime >= :DischargeDateStart AND DSSPES.dischargedatetime < :DischargeDateEnd\r\n",
"AND fpes.EntityId = 1\r\n"));
// Mock DataSchemaService
var dataTableId = 12345;
var dataColumnId = 67890;
var testDataSourceId = 999;
_mockDataSchemaService.Setup(x =>
x.GetDataSourcesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(new List<Strata.DataSchema.Models.DataSourceManagement.DataSource>
{
new Strata.DataSchema.Models.DataSourceManagement.DataSource
{
DataSourceId = testDataSourceId,
Name = "DS Strata Encounter Cost Detail"
}
});
_mockDataSchemaService.Setup(x =>
x.GetDataTablesByDataSourceId(It.Is<int>(dataSourceId => dataSourceId == testDataSourceId), It.IsAny<bool>(), It.IsAny<DataTableType?>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((int dsId, bool includeChildren, DataTableType? tableType, CancellationToken ct) =>
{
var tableAliases = new[] { "dsspes", "pblid", "costdetail", "cc", "PATIENTTYPE", "physPrimary", "dsspeci", "explorationPopulationEncounter", "msdrg" };
return tableAliases.Select(alias => new DataTable
{
DataTableId = dataTableId,
SqlAlias = alias
}).ToList();
});
_mockDataSchemaService.Setup(x =>
x.GetDataColumnsBySqlColumnNameAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((string columnName, CancellationToken ct) => new List<DataColumn>
{
new DataColumn
{
DataColumnId = dataColumnId,
DataTableId = dataTableId
}
});
_mockDataSchemaService.Setup(x =>
x.BuildSqlQuery(It.IsAny<QueryConfig>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new SqlResponse
{
SqlQuery = _unitsOfServicePatPopQuery,
Parameters = new List<KeyValuePair<string, object>>
{
new(":dischargedatetime_Start_0", new DateTime(2024, 1, 1)),
new(":dischargedatetime_End_1", new DateTime(2024, 12, 31)),
new(":chargecodeid_2", 3541)
}
});
// Mock SchemaServiceClient
_mockSchemaServiceClient.Setup(x =>
x.GetDimensionByGlobalIdAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new ScoreDimensionInfoDto { DimensionGuid = Guid.NewGuid() });
_mockSchemaServiceClient.Setup(x =>
x.GetDimensionMembersFromHierarchyPathsAsync(It.IsAny<Guid>(), It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new List<MemberDto>
{
new MemberDto
{
Id = "777",
Name = "Charge Code Stub"
}
});
_mockSchemaServiceClient.Setup(x =>
x.GetHierarchyNodesFromHierarchyPathsAsync(It.IsAny<Guid>(), It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new List<HierarchyNodeDto>());
// Mock Snowflake context
_mockSnowflakeContext.Setup(x =>
x.QueryAsync<StrategicOpportunityDetail>(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<object>(), It.IsAny<TimeSpan>()))
.ReturnsAsync(new List<StrategicOpportunityDetail>());
_mockSnowflakeContext.Setup(x =>
x.ExecuteScalarAsync<double>(It.IsAny<string>(), It.IsAny<object>()))
.ReturnsAsync(123.45);
_mockSnowflakeContext.Setup(x =>
x.ExecuteCommandAsync(It.IsAny<string>(), It.IsAny<object>(), It.IsAny<TimeSpan>()))
.ReturnsAsync(1);
var claimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor();
_strategicOpportunityDetailService = new StrategicChargeCodeOpportunityDetailService(
_mockJazzDbContext.Object,
_centralDbContext,
claimsPrincipalAccessor,
_mockDataSchemaService.Object,
_mockSchemaServiceClient.Object,
_mockSnowflakeContext.Object,
_mockExplorationService.Object,
_mockDistributionProcessFactory.Object,
_mockStrategicOpportunityDetailQueryBuilder.Object,
_mockNotificationHubClient.Object,
_mockDimensionSyncService.Object,
_mockLogger.Object);
}
[SetUp]
public void TestSetup()
{
_centralDbContext.StrategicOpportunityMeasures.RemoveRange(_centralDbContext.StrategicOpportunityMeasures);
_centralDbContext.StrategicOpportunityChargeCodes.RemoveRange(_centralDbContext.StrategicOpportunityChargeCodes);
_centralDbContext.SaveChanges();
}
private const string _unitsOfServicePatPopQuery = @"SELECT
""DischargeDateTime"",
ZEROIFNULL(""Value"") AS ""Value""
FROM (
SELECT
""DischargeDateTime"",
SUM(""Value"") AS ""Value""
FROM (
SELECT
DSSPES.dischargedatetime AS ""DischargeDateTime"",
SUM(PBLID.unitsofservice) AS ""Value""
FROM dss.FactPatientBillingLineItemDetail AS PBLID
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
WHERE
(((DSSPES.dischargedatetime >= :dischargedatetime_Start_0 AND DSSPES.dischargedatetime <= :dischargedatetime_End_1) AND PBLID.departmentid = :departmentid_2) AND DSSPES.primaryphysicianid = :primaryphysicianid_3)
GROUP BY
""DischargeDateTime""
)
GROUP BY
""DischargeDateTime""
)
ORDER BY
""DischargeDateTime"" ASC NULLS FIRST";
private const string _unitsOfServiceFlexPopQuery = @"SELECT
""DischargeDateTime"",
ZEROIFNULL(""Value"") AS ""Value""
FROM (
SELECT
""DischargeDateTime"",
SUM(""Value"") AS ""Value""
FROM (
SELECT
DSSPES.dischargedatetime AS ""DischargeDateTime"",
SUM(PBLID.unitsofservice) AS ""Value""
FROM dss.FactPatientBillingLineItemDetail AS PBLID
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
LEFT JOIN CCI.FACTEXPLORATIONPOPULATIONENCOUNTER AS EXPLORATIONPOPULATIONENCOUNTER ON EXPLORATIONPOPULATIONENCOUNTER.encounterid = PBLID.encounterid
WHERE
((DSSPES.dischargedatetime >= :dischargedatetime_Start_0 AND DSSPES.dischargedatetime <= :dischargedatetime_End_1) AND EXPLORATIONPOPULATIONENCOUNTER.explorationpopulationid = :explorationpopulationid_2)
GROUP BY
""DischargeDateTime""
)
GROUP BY
""DischargeDateTime""
)
ORDER BY
""DischargeDateTime"" ASC NULLS FIRST";
private const string _contributionMarginPatPopQuery = @"SELECT
""DischargeDateTime"",
""dsspesNetRevenue"",
ZEROIFNULL(""Value"") AS ""Value""
FROM (
SELECT
""DischargeDateTime"",
""dsspesNetRevenue"",
SUM(""Value"") AS ""Value""
FROM (
SELECT
DSSPES.dischargedatetime AS ""DischargeDateTime"",
DSSPES.netrevenue AS ""dsspesNetRevenue"",
SUM(COSTDETAIL.variabledirectcost) AS ""Value""
FROM dss.FactPatientCostDetail AS COSTDETAIL
RIGHT JOIN dss.FactPatientBillingLineItemDetail AS PBLID ON PBLID.rowid = COSTDETAIL.pblidrowid
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
WHERE
((DSSPES.dischargedatetime >= :dischargedatetime_Start_0 AND DSSPES.dischargedatetime <= :dischargedatetime_End_1))
GROUP BY
""DischargeDateTime"",
""dsspesNetRevenue""
)
GROUP BY
""DischargeDateTime"",
""dsspesNetRevenue""
)
ORDER BY
""DischargeDateTime"" ASC NULLS FIRST,
""dsspesNetRevenue"" ASC NULLS FIRST";
private const string _contributionMarginFlexPopQuery = @"SELECT
""DischargeDateTime"",
""dsspesNetRevenue"",
ZEROIFNULL(""Value"") AS ""Value""
FROM (
SELECT
""DischargeDateTime"",
""dsspesNetRevenue"",
SUM(""Value"") AS ""Value""
FROM (
SELECT
DSSPES.dischargedatetime AS ""DischargeDateTime"",
DSSPES.netrevenue AS ""dsspesNetRevenue"",
SUM(COSTDETAIL.variabledirectcost) AS ""Value""
FROM dss.FactPatientCostDetail AS COSTDETAIL
RIGHT JOIN dss.FactPatientBillingLineItemDetail AS PBLID ON PBLID.rowid = COSTDETAIL.pblidrowid
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
LEFT JOIN CCI.FACTEXPLORATIONPOPULATIONENCOUNTER AS EXPLORATIONPOPULATIONENCOUNTER ON EXPLORATIONPOPULATIONENCOUNTER.encounterid = PBLID.encounterid
WHERE
((DSSPES.dischargedatetime >= :dischargedatetime_Start_0 AND DSSPES.dischargedatetime <= :dischargedatetime_End_1) AND EXPLORATIONPOPULATIONENCOUNTER.explorationpopulationid = :explorationpopulationid_2)
GROUP BY
""DischargeDateTime"",
""dsspesNetRevenue""
)
GROUP BY
""DischargeDateTime"",
""dsspesNetRevenue""
)
ORDER BY
""DischargeDateTime"" ASC NULLS FIRST,
""dsspesNetRevenue"" ASC NULLS FIRST";
// SQL returned by BuildSqlQuery for the tracking merge path with clinical indicator population
private const string _trackingPatPopQuery = @"SELECT
""dsspesEncounterId"",
""dsspesDischargeDateTime"",
""dsspesEntityID"",
""dsspesPhysicianId"",
""dsspesPrimaryServiceLineId"",
""dsspesCPTCodeCaseTypeFamilyId"",
""dsspesMSDRGCaseTypeFamilyId"",
""dsspesAPRDRGCaseTypeFamilyId"",
""pblidDepartmentId"",
""physPrimaryPhysicianSpecialtyId"",
""ccChargeCodeID"",
""ccCostDriver"",
""encounterPatientTypeRollupPatientTypeRollup"",
ZEROIFNULL(""Units"") AS ""Units"",
ZEROIFNULL(""Cost"") AS ""Cost""
FROM (
SELECT
""dsspesEncounterId"",
""dsspesDischargeDateTime"",
""dsspesEntityID"",
""dsspesPhysicianId"",
""dsspesPrimaryServiceLineId"",
""dsspesCPTCodeCaseTypeFamilyId"",
""dsspesMSDRGCaseTypeFamilyId"",
""dsspesAPRDRGCaseTypeFamilyId"",
""pblidDepartmentId"",
""physPrimaryPhysicianSpecialtyId"",
""ccChargeCodeID"",
""ccCostDriver"",
""encounterPatientTypeRollupPatientTypeRollup"",
SUM(""Units"") AS ""Units"",
SUM(""Cost"") AS ""Cost""
FROM (
SELECT
DSSPES.encounterid AS ""dsspesEncounterId"",
DSSPES.dischargedatetime AS ""dsspesDischargeDateTime"",
DSSPES.entityid AS ""dsspesEntityID"",
DSSPES.primaryphysicianid AS ""dsspesPhysicianId"",
DSSPES.servicelineid AS ""dsspesPrimaryServiceLineId"",
DSSPES.cptcodecasetypefamilyid AS ""dsspesCPTCodeCaseTypeFamilyId"",
DSSPES.msdrgcasetypefamilyid AS ""dsspesMSDRGCaseTypeFamilyId"",
DSSPES.aprdrgcasetypefamilyid AS ""dsspesAPRDRGCaseTypeFamilyId"",
PBLID.departmentid AS ""pblidDepartmentId"",
PHYSPRIMARY.physicianspecialtyid AS ""physPrimaryPhysicianSpecialtyId"",
CC.chargecodeid AS ""ccChargeCodeID"",
IFNULL(CC.costdriver::TEXT, '') AS ""ccCostDriver"",
IFNULL(ENCOUNTERPATIENTTYPEROLLUP.patienttyperollup::TEXT, '') AS ""encounterPatientTypeRollupPatientTypeRollup"",
NULL AS ""Cost"",
SUM(PBLID.unitsofservice) AS ""Units""
FROM dss.FactPatientBillingLineItemDetail AS PBLID
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
LEFT JOIN dss.FactPatientEncounterClinicalIndicator AS DSSPECI ON DSSPECI.encounterid = PBLID.encounterid
LEFT JOIN CCI.VIEWENCOUNTERPATIENTTYPEROLLUP AS ENCOUNTERPATIENTTYPEROLLUP ON ENCOUNTERPATIENTTYPEROLLUP.encounterid = PBLID.encounterid
INNER JOIN FW.DIMCHARGECODE AS CC ON CC.chargecodeid = PBLID.chargecodeid
INNER JOIN DSS.DIMPHYSICIAN AS PHYSPRIMARY ON PHYSPRIMARY.physicianid = DSSPES.primaryphysicianid
WHERE
((DSSPES.dischargedatetime >= :dischargedatetime_Start_0 AND DSSPES.dischargedatetime <= :dischargedatetime_End_1) AND DSSPECI.clinicalindicatorid = :clinicalindicatorid_2)
GROUP BY
""dsspesEncounterId"",
""dsspesDischargeDateTime"",
""dsspesEntityID"",
""dsspesPhysicianId"",
""dsspesPrimaryServiceLineId"",
""dsspesCPTCodeCaseTypeFamilyId"",
""dsspesMSDRGCaseTypeFamilyId"",
""dsspesAPRDRGCaseTypeFamilyId"",
""pblidDepartmentId"",
""physPrimaryPhysicianSpecialtyId"",
""ccChargeCodeID"",
""ccCostDriver"",
""encounterPatientTypeRollupPatientTypeRollup""
UNION ALL
SELECT
DSSPES.encounterid AS ""dsspesEncounterId"",
DSSPES.dischargedatetime AS ""dsspesDischargeDateTime"",
DSSPES.entityid AS ""dsspesEntityID"",
DSSPES.primaryphysicianid AS ""dsspesPhysicianId"",
DSSPES.servicelineid AS ""dsspesPrimaryServiceLineId"",
DSSPES.cptcodecasetypefamilyid AS ""dsspesCPTCodeCaseTypeFamilyId"",
DSSPES.msdrgcasetypefamilyid AS ""dsspesMSDRGCaseTypeFamilyId"",
DSSPES.aprdrgcasetypefamilyid AS ""dsspesAPRDRGCaseTypeFamilyId"",
PBLID.departmentid AS ""pblidDepartmentId"",
PHYSPRIMARY.physicianspecialtyid AS ""physPrimaryPhysicianSpecialtyId"",
CC.chargecodeid AS ""ccChargeCodeID"",
IFNULL(CC.costdriver::TEXT, '') AS ""ccCostDriver"",
IFNULL(ENCOUNTERPATIENTTYPEROLLUP.patienttyperollup::TEXT, '') AS ""encounterPatientTypeRollupPatientTypeRollup"",
SUM(COSTDETAIL.variabledirectcost) AS ""Cost"",
NULL AS ""Units""
FROM dss.FactPatientCostDetail AS COSTDETAIL
RIGHT JOIN dss.FactPatientBillingLineItemDetail AS PBLID ON PBLID.rowid = COSTDETAIL.pblidrowid
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
LEFT JOIN dss.FactPatientEncounterClinicalIndicator AS DSSPECI ON DSSPECI.encounterid = PBLID.encounterid
LEFT JOIN CCI.VIEWENCOUNTERPATIENTTYPEROLLUP AS ENCOUNTERPATIENTTYPEROLLUP ON ENCOUNTERPATIENTTYPEROLLUP.encounterid = PBLID.encounterid
INNER JOIN FW.DIMCHARGECODE AS CC ON CC.chargecodeid = PBLID.chargecodeid
INNER JOIN DSS.DIMPHYSICIAN AS PHYSPRIMARY ON PHYSPRIMARY.physicianid = DSSPES.primaryphysicianid
WHERE
((DSSPES.dischargedatetime >= :dischargedatetime_Start_3 AND DSSPES.dischargedatetime <= :dischargedatetime_End_4) AND DSSPECI.clinicalindicatorid = :clinicalindicatorid_5)
GROUP BY
""dsspesEncounterId"",
""dsspesDischargeDateTime"",
""dsspesEntityID"",
""dsspesPhysicianId"",
""dsspesPrimaryServiceLineId"",
""dsspesCPTCodeCaseTypeFamilyId"",
""dsspesMSDRGCaseTypeFamilyId"",
""dsspesAPRDRGCaseTypeFamilyId"",
""pblidDepartmentId"",
""physPrimaryPhysicianSpecialtyId"",
""ccChargeCodeID"",
""ccCostDriver"",
""encounterPatientTypeRollupPatientTypeRollup""
)
GROUP BY
""dsspesEncounterId"",
""dsspesDischargeDateTime"",
""dsspesEntityID"",
""dsspesPhysicianId"",
""dsspesPrimaryServiceLineId"",
""dsspesCPTCodeCaseTypeFamilyId"",
""dsspesMSDRGCaseTypeFamilyId"",
""dsspesAPRDRGCaseTypeFamilyId"",
""pblidDepartmentId"",
""physPrimaryPhysicianSpecialtyId"",
""ccChargeCodeID"",
""ccCostDriver"",
""encounterPatientTypeRollupPatientTypeRollup""
)
ORDER BY
""dsspesEncounterId"" ASC NULLS FIRST,
""dsspesDischargeDateTime"" ASC NULLS FIRST,
""dsspesEntityID"" ASC NULLS FIRST,
""dsspesPhysicianId"" ASC NULLS FIRST,
""dsspesPrimaryServiceLineId"" ASC NULLS FIRST,
""dsspesCPTCodeCaseTypeFamilyId"" ASC NULLS FIRST,
""dsspesMSDRGCaseTypeFamilyId"" ASC NULLS FIRST,
""dsspesAPRDRGCaseTypeFamilyId"" ASC NULLS FIRST,
""pblidDepartmentId"" ASC NULLS FIRST,
""physPrimaryPhysicianSpecialtyId"" ASC NULLS FIRST,
""ccChargeCodeID"" ASC NULLS FIRST,
""ccCostDriver"" ASC NULLS FIRST,
""encounterPatientTypeRollupPatientTypeRollup"" ASC NULLS FIRST";
// SQL returned by BuildSqlQuery for the tracking merge path with exploration population
private const string _trackingFlexPopQuery = @"SELECT
""dsspesEncounterId"",
""dsspesDischargeDateTime"",
""dsspesEntityID"",
""dsspesPhysicianId"",
""dsspesPrimaryServiceLineId"",
""dsspesCPTCodeCaseTypeFamilyId"",
""dsspesMSDRGCaseTypeFamilyId"",
""dsspesAPRDRGCaseTypeFamilyId"",
""pblidDepartmentId"",
""physPrimaryPhysicianSpecialtyId"",
""ccChargeCodeID"",
""ccCostDriver"",
""encounterPatientTypeRollupPatientTypeRollup"",
ZEROIFNULL(""Units"") AS ""Units"",
ZEROIFNULL(""Cost"") AS ""Cost""
FROM (
SELECT
""dsspesEncounterId"",
""dsspesDischargeDateTime"",
""dsspesEntityID"",
""dsspesPhysicianId"",
""dsspesPrimaryServiceLineId"",
""dsspesCPTCodeCaseTypeFamilyId"",
""dsspesMSDRGCaseTypeFamilyId"",
""dsspesAPRDRGCaseTypeFamilyId"",
""pblidDepartmentId"",
""physPrimaryPhysicianSpecialtyId"",
""ccChargeCodeID"",
""ccCostDriver"",
""encounterPatientTypeRollupPatientTypeRollup"",
SUM(""Units"") AS ""Units"",
SUM(""Cost"") AS ""Cost""
FROM (
SELECT
DSSPES.encounterid AS ""dsspesEncounterId"",
DSSPES.dischargedatetime AS ""dsspesDischargeDateTime"",
DSSPES.entityid AS ""dsspesEntityID"",
DSSPES.primaryphysicianid AS ""dsspesPhysicianId"",
DSSPES.servicelineid AS ""dsspesPrimaryServiceLineId"",
DSSPES.cptcodecasetypefamilyid AS ""dsspesCPTCodeCaseTypeFamilyId"",
DSSPES.msdrgcasetypefamilyid AS ""dsspesMSDRGCaseTypeFamilyId"",
DSSPES.aprdrgcasetypefamilyid AS ""dsspesAPRDRGCaseTypeFamilyId"",
PBLID.departmentid AS ""pblidDepartmentId"",
PHYSPRIMARY.physicianspecialtyid AS ""physPrimaryPhysicianSpecialtyId"",
CC.chargecodeid AS ""ccChargeCodeID"",
IFNULL(CC.costdriver::TEXT, '') AS ""ccCostDriver"",
IFNULL(ENCOUNTERPATIENTTYPEROLLUP.patienttyperollup::TEXT, '') AS ""encounterPatientTypeRollupPatientTypeRollup"",
NULL AS ""Cost"",
SUM(PBLID.unitsofservice) AS ""Units""
FROM dss.FactPatientBillingLineItemDetail AS PBLID
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
LEFT JOIN CCI.FACTEXPLORATIONPOPULATIONENCOUNTER AS EXPLORATIONPOPULATIONENCOUNTER ON EXPLORATIONPOPULATIONENCOUNTER.encounterid = PBLID.encounterid
LEFT JOIN CCI.VIEWENCOUNTERPATIENTTYPEROLLUP AS ENCOUNTERPATIENTTYPEROLLUP ON ENCOUNTERPATIENTTYPEROLLUP.encounterid = PBLID.encounterid
INNER JOIN FW.DIMCHARGECODE AS CC ON CC.chargecodeid = PBLID.chargecodeid
INNER JOIN DSS.DIMPHYSICIAN AS PHYSPRIMARY ON PHYSPRIMARY.physicianid = DSSPES.primaryphysicianid
WHERE
((DSSPES.dischargedatetime >= :dischargedatetime_Start_0 AND DSSPES.dischargedatetime <= :dischargedatetime_End_1) AND EXPLORATIONPOPULATIONENCOUNTER.explorationpopulationid = :explorationpopulationid_2)
GROUP BY
""dsspesEncounterId"",
""dsspesDischargeDateTime"",
""dsspesEntityID"",
""dsspesPhysicianId"",
""dsspesPrimaryServiceLineId"",
""dsspesCPTCodeCaseTypeFamilyId"",
""dsspesMSDRGCaseTypeFamilyId"",
""dsspesAPRDRGCaseTypeFamilyId"",
""pblidDepartmentId"",
""physPrimaryPhysicianSpecialtyId"",
""ccChargeCodeID"",
""ccCostDriver"",
""encounterPatientTypeRollupPatientTypeRollup""
UNION ALL
SELECT
DSSPES.encounterid AS ""dsspesEncounterId"",
DSSPES.dischargedatetime AS ""dsspesDischargeDateTime"",
DSSPES.entityid AS ""dsspesEntityID"",
DSSPES.primaryphysicianid AS ""dsspesPhysicianId"",
DSSPES.servicelineid AS ""dsspesPrimaryServiceLineId"",
DSSPES.cptcodecasetypefamilyid AS ""dsspesCPTCodeCaseTypeFamilyId"",
DSSPES.msdrgcasetypefamilyid AS ""dsspesMSDRGCaseTypeFamilyId"",
DSSPES.aprdrgcasetypefamilyid AS ""dsspesAPRDRGCaseTypeFamilyId"",
PBLID.departmentid AS ""pblidDepartmentId"",
PHYSPRIMARY.physicianspecialtyid AS ""physPrimaryPhysicianSpecialtyId"",
CC.chargecodeid AS ""ccChargeCodeID"",
IFNULL(CC.costdriver::TEXT, '') AS ""ccCostDriver"",
IFNULL(ENCOUNTERPATIENTTYPEROLLUP.patienttyperollup::TEXT, '') AS ""encounterPatientTypeRollupPatientTypeRollup"",
SUM(COSTDETAIL.variabledirectcost) AS ""Cost"",
NULL AS ""Units""
FROM dss.FactPatientCostDetail AS COSTDETAIL
RIGHT JOIN dss.FactPatientBillingLineItemDetail AS PBLID ON PBLID.rowid = COSTDETAIL.pblidrowid
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
LEFT JOIN CCI.FACTEXPLORATIONPOPULATIONENCOUNTER AS EXPLORATIONPOPULATIONENCOUNTER ON EXPLORATIONPOPULATIONENCOUNTER.encounterid = PBLID.encounterid
LEFT JOIN CCI.VIEWENCOUNTERPATIENTTYPEROLLUP AS ENCOUNTERPATIENTTYPEROLLUP ON ENCOUNTERPATIENTTYPEROLLUP.encounterid = PBLID.encounterid
INNER JOIN FW.DIMCHARGECODE AS CC ON CC.chargecodeid = PBLID.chargecodeid
INNER JOIN DSS.DIMPHYSICIAN AS PHYSPRIMARY ON PHYSPRIMARY.physicianid = DSSPES.primaryphysicianid
WHERE
((DSSPES.dischargedatetime >= :dischargedatetime_Start_3 AND DSSPES.dischargedatetime <= :dischargedatetime_End_4) AND EXPLORATIONPOPULATIONENCOUNTER.explorationpopulationid = :explorationpopulationid_5)
GROUP BY
""dsspesEncounterId"",
""dsspesDischargeDateTime"",
""dsspesEntityID"",
""dsspesPhysicianId"",
""dsspesPrimaryServiceLineId"",
""dsspesCPTCodeCaseTypeFamilyId"",
""dsspesMSDRGCaseTypeFamilyId"",
""dsspesAPRDRGCaseTypeFamilyId"",
""pblidDepartmentId"",
""physPrimaryPhysicianSpecialtyId"",
""ccChargeCodeID"",
""ccCostDriver"",
""encounterPatientTypeRollupPatientTypeRollup""
)
GROUP BY
""dsspesEncounterId"",
""dsspesDischargeDateTime"",
""dsspesEntityID"",
""dsspesPhysicianId"",
""dsspesPrimaryServiceLineId"",
""dsspesCPTCodeCaseTypeFamilyId"",
""dsspesMSDRGCaseTypeFamilyId"",
""dsspesAPRDRGCaseTypeFamilyId"",
""pblidDepartmentId"",
""physPrimaryPhysicianSpecialtyId"",
""ccChargeCodeID"",
""ccCostDriver"",
""encounterPatientTypeRollupPatientTypeRollup""
)
ORDER BY
""dsspesEncounterId"" ASC NULLS FIRST,
""dsspesDischargeDateTime"" ASC NULLS FIRST,
""dsspesEntityID"" ASC NULLS FIRST,
""dsspesPhysicianId"" ASC NULLS FIRST,
""dsspesPrimaryServiceLineId"" ASC NULLS FIRST,
""dsspesCPTCodeCaseTypeFamilyId"" ASC NULLS FIRST,
""dsspesMSDRGCaseTypeFamilyId"" ASC NULLS FIRST,
""dsspesAPRDRGCaseTypeFamilyId"" ASC NULLS FIRST,
""pblidDepartmentId"" ASC NULLS FIRST,
""physPrimaryPhysicianSpecialtyId"" ASC NULLS FIRST,
""ccChargeCodeID"" ASC NULLS FIRST,
""ccCostDriver"" ASC NULLS FIRST,
""encounterPatientTypeRollupPatientTypeRollup"" ASC NULLS FIRST";
}
}
@@ -0,0 +1,102 @@
using FluentAssertions;
using NUnit.Framework;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Queries;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities
{
[ExcludeFromCodeCoverage]
[TestFixture, Category("Unit"), Category("CCI")]
internal class StrategicOpportunityGLDetailQueryBuilderTest
{
private StrategicOpportunityGLDetailQueryBuilder _queryBuilder;
[SetUp]
public void Setup()
{
_queryBuilder = new StrategicOpportunityGLDetailQueryBuilder();
}
[Test]
public void BuildDeleteQuery_WithOpportunityId_EmbedsIdDirectly()
{
var result = _queryBuilder.BuildDeleteQuery(42);
result.Should().Contain("OpportunityId = 42");
result.Should().NotContain(":opportunityId");
}
[Test]
public void BuildDeleteQuery_WithoutOpportunityId_UsesParameterWithoutTrailingSemicolon()
{
var result = _queryBuilder.BuildDeleteQuery(null);
result.Should().Contain(":opportunityId");
result.Should().NotContain(":opportunityId;");
}
[Test]
public void BuildInsertQuery_WithTypedAccountIds_GeneratesAccountTypeMapCte()
{
var revenueIds = new List<int> { 100, 101 };
var expenseIds = new List<int> { 200 };
var statisticIds = new List<int> { 300 };
var result = _queryBuilder.BuildInsertQuery(
opportunityId: 42,
sourceTable: "fw.factglsampled",
departmentIds: new List<int> { 1, 2 },
revenueAccountIds: revenueIds,
expenseAccountIds: expenseIds,
statisticAccountIds: statisticIds,
baselineStart: new DateOnly(2024, 1, 1),
baselineEnd: new DateOnly(2024, 12, 31));
result.Should().Contain("(100, 0)");
result.Should().Contain("(101, 0)");
result.Should().Contain("(200, 1)");
result.Should().Contain("(300, 2)");
}
[Test]
public void BuildInsertQuery_WithTypedAccountIds_IncludesAccountTypeInInsertAndSelect()
{
var result = _queryBuilder.BuildInsertQuery(
opportunityId: 42,
sourceTable: "fw.factglsampled",
departmentIds: new List<int> { 1 },
revenueAccountIds: new List<int> { 100 },
expenseAccountIds: new List<int> { 200 },
statisticAccountIds: new List<int> { 300 },
baselineStart: new DateOnly(2024, 1, 1),
baselineEnd: new DateOnly(2024, 12, 31));
result.Should().Contain("AccountType,");
result.Should().Contain("at.AccountType,");
result.Should().Contain("at.AccountType;");
result.Should().Contain("JOIN (SELECT AccountId, AccountType FROM (VALUES");
}
[Test]
public void BuildMergeQuery_WithTypedAccountIds_IncludesAccountTypeInMergeConditionAndInsert()
{
var result = _queryBuilder.BuildMergeQuery(
opportunityId: 42,
sourceTable: "fw.factglsampled",
departmentIds: new List<int> { 1 },
revenueAccountIds: new List<int> { 100 },
expenseAccountIds: new List<int> { 200 },
statisticAccountIds: new List<int> { 300 },
trackingStart: new DateOnly(2025, 1, 1),
trackingEnd: new DateOnly(2025, 12, 31));
result.Should().Contain("AND t.AccountType = s.AccountType");
result.Should().Contain("AccountId, AccountType, Amount");
result.Should().Contain("s.AccountType, s.Amount");
result.Should().Contain("at.AccountType,");
result.Should().Contain("JOIN (SELECT AccountId, AccountType FROM (VALUES");
}
}
}
@@ -0,0 +1,121 @@
using FluentAssertions;
using NUnit.Framework;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Dtos;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Queries;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using VerifyNUnit;
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities
{
[ExcludeFromCodeCoverage]
[TestFixture, Category("Unit"), Category("CCI")]
internal class StrategicOpportunityGLUpdateQueryBuilderTest : StrategicOpportunityTestsBase
{
private StrategicOpportunityGLUpdateQueryBuilder _queryBuilder;
private static readonly IEnumerable<string> Rows =
[
StrategicOpportunityDetailDimension.System.Value,
StrategicOpportunityDetailDimension.Entity.Value,
StrategicOpportunityDetailDimension.Department.Value,
StrategicOpportunityDetailDimension.GLAccount.Value,
];
[SetUp]
public void Setup()
{
_queryBuilder = new StrategicOpportunityGLUpdateQueryBuilder();
}
[Test]
public async Task BuildUpdateQuery_WithFourAdjustments_GeneratesCorrectSql()
{
// Arrange
const long opportunityId = 42;
var adjustments = new List<StrategicOpportunityGLAdjustment>
{
// Root-level adjustment
new() { NodeKey = "root", GoalAmountValue = 50000 },
// Entity-level adjustment
new() { NodeKey = "101", GoalAmountValue = 20000 },
// Entity + Department level: null (passthrough)
new() { NodeKey = "101|201", GoalAmountValue = null },
// Entity + Department + GLAccount (lowest level)
new() { NodeKey = "101|201|3001", GoalAmountValue = 15000 },
};
// Act
var result = _queryBuilder.BuildUpdateQuery(adjustments, opportunityId, Rows).Query;
// Assert
await Verifier.Verify(result, VerifySettings);
}
[Test]
public void BuildUpdateQuery_WithAccountTypeOnSecondAdjustment_IncludesAccountTypeFilterInSubquery()
{
// AccountType filters are embedded in the inner SELECT WHERE for non-first adjustments
// (the first adjustment uses an outer WHERE clause that filters by hierarchy only)
const long opportunityId = 42;
var adjustments = new List<StrategicOpportunityGLAdjustment>
{
new() { NodeKey = "root", GoalAmountValue = 50000 },
new() { NodeKey = "101|201|3001", GoalAmountValue = 15000, AccountType = 0 },
};
var (query, parameters) = _queryBuilder.BuildUpdateQuery(adjustments, opportunityId, Rows);
query.Should().Contain("AccountType = :AccountType_1");
parameters.Should().ContainKey("AccountType_1");
parameters["AccountType_1"].Should().Be((byte)0);
}
[Test]
public void BuildUpdateQuery_WithNullAccountType_OmitsAccountTypeFilter()
{
const long opportunityId = 42;
var adjustments = new List<StrategicOpportunityGLAdjustment>
{
new() { NodeKey = "root", GoalAmountValue = 50000 },
new() { NodeKey = "101|201|3001", GoalAmountValue = 15000, AccountType = null },
};
var (query, parameters) = _queryBuilder.BuildUpdateQuery(adjustments, opportunityId, Rows);
query.Should().NotContain("AccountType = :");
parameters.Should().NotContainKey("AccountType_1");
}
[Test]
public void BuildUpdateQuery_WithInvalidOpportunityId_ThrowsArgumentException()
{
var adjustments = new List<StrategicOpportunityGLAdjustment>
{
new() { NodeKey = "101", GoalAmountValue = 1000 },
};
var act = () => _queryBuilder.BuildUpdateQuery(adjustments, opportunityId: 0, Rows);
act.Should().Throw<ArgumentException>().WithParameterName("opportunityId");
}
[Test]
public void BuildUpdateQuery_WithEmptyNodeKey_ThrowsArgumentException()
{
var adjustments = new List<StrategicOpportunityGLAdjustment>
{
new() { NodeKey = "", GoalAmountValue = 1000 },
};
var act = () => _queryBuilder.BuildUpdateQuery(adjustments, opportunityId: 42, Rows);
act.Should().Throw<ArgumentException>().WithParameterName("nodeKey");
}
}
}
@@ -0,0 +1,24 @@
using NUnit.Framework;
using System.Diagnostics.CodeAnalysis;
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using VerifyTests;
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities
{
[ExcludeFromCodeCoverage]
[TestFixture]
public class StrategicOpportunityTestsBase
{
protected VerifySettings VerifySettings { get; set; }
[OneTimeSetUp]
public void TestFixtureSetup()
{
VerifySettings = TestExtensions.TestSettings();
}
}
}
@@ -0,0 +1,56 @@
using NUnit.Framework;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Dtos;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Queries;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using VerifyNUnit;
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities
{
[ExcludeFromCodeCoverage]
[TestFixture, Category("Unit"), Category("CCI")]
internal class StrategicOpportunityUpdateQueryBuilderTest : StrategicOpportunityTestsBase
{
private StrategicOpportunityUpdateQueryBuilder _queryBuilder;
private static readonly IEnumerable<string> Rows =
[
StrategicOpportunityDetailDimension.System.Value,
StrategicOpportunityDetailDimension.Entity.Value,
StrategicOpportunityDetailDimension.Department.Value,
StrategicOpportunityDetailDimension.ChargeCode.Value,
];
[SetUp]
public void Setup()
{
_queryBuilder = new StrategicOpportunityUpdateQueryBuilder();
}
[Test]
public async Task BuildUpdateQuery_WithFourAdjustments_GeneratesCorrectSql()
{
// Arrange
const long opportunityId = 42;
var adjustments = new List<StrategicOpportunityChargeCodeAdjustment>
{
// Root-level adjustment: both units and costs
new() { NodeKey = "root", UnitsValue = 1000m, CostsValue = 50000m },
// Entity-level adjustment: costs only
new() { NodeKey = "101", UnitsValue = null, CostsValue = 20000m },
// Entity + Department level: units only
new() { NodeKey = "101|201", UnitsValue = 300m, CostsValue = null },
// Entity + Department + ChargeCode (lowest level): both units and costs
new() { NodeKey = "101|201|3001", UnitsValue = 75m, CostsValue = 5000m },
};
// Act
var result = _queryBuilder.BuildUpdateQuery(adjustments, opportunityId, Rows).Query;
// Assert
await Verifier.Verify(result, VerifySettings);
}
}
}