using FluentAssertions; using Hangfire; using Microsoft.EntityFrameworkCore; using Moq; using Strata.ContinuousImprovement.Biz.Generics; using Strata.ContinuousImprovement.Biz.InitiativeRollupColumns; using Strata.ContinuousImprovement.Biz.OpportunityRoleAssignment; using Strata.ContinuousImprovement.Biz.OpportunityWorkbooks; using Strata.ContinuousImprovement.Biz.Security; using Strata.ContinuousImprovement.Biz.StrategicOpportunities; using Strata.ContinuousImprovement.Biz.StrategicOpportunities.DistributionProcess; using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Dtos; using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Enums; using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities; using Strata.CoreLib.Claims.Extensions; using Strata.DataSchema.Client; using Strata.DataSchema.Models.Query; using Strata.DataSchema.Models.Schema; using Strata.Id.Client; using Strata.Schema.Client; using Strata.Schema.Client.Dtos; using System.Diagnostics.CodeAnalysis; namespace Strata.ContinuousImprovement.Biz.Test.Integration.SnowflakeIntegrationTests { [ExcludeFromCodeCoverage] [Ignore("temporarily ignoring because schema is out of sync")] [TestFixture, Category("Integration"), Category("CCI")] public class StrategicOpportunityServiceTests : IntegrationTestBase { private const string POPULATION_NAME = "Mocked Population Name"; private IStrategicOpportunityService _strategicOpportunityService; private IOpportunityRoleAssignmentService _opportunityRoleAssignmentService; [OneTimeSetUp] public void Setup() { // Arrange mocks var mockSchemaServiceClient = new Mock(); var mockDataSchemaService = new Mock(); var mockIdServiceClient = new Mock(); var mockIdRollupColumn = new Mock(); var mockOpportunityWorkbookService = new Mock(); var mockStrategicOpportunityDetailService = new Mock(); var mockStrategicGLOpportunityDetailService = new Mock(); var mockSimpleSecurityServiceClient = new Mock(); var mockOpportunityRoleAssignmentServiceClient = new Mock(); var mockBackgroundJobClient = new Mock(); var mockDistributionProcessFactory = new Mock(); // Add mock responses mockDataSchemaService.Setup(x => x.GetDataTableBySqlFullNameAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new DataTable()); mockDataSchemaService.Setup(x => x.GetDataColumnsBySqlColumnNameAsync(It.IsAny(), It.IsAny())) .ReturnsAsync([]); mockDataSchemaService.Setup(x => x.BuildSqlQuery(It.IsAny(), It.IsAny())) .ReturnsAsync(new SqlResponse { SqlQuery = DataSchemaServiceSelectSql, Parameters = new List> { new(":dischargedatetime_Start_0", new DateTime(2024, 1, 1)), new(":dischargedatetime_End_1", new DateTime(2024, 12, 31)), new(":chargecodeid_2", 3541) } }); mockSchemaServiceClient.Setup(x => x.GetDimensionByGlobalIdAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new Schema.Client.Dtos.Info.ScoreDimensionInfoDto()); var list = new List(); list.Add(new HierarchyNodeDto { Path = "CLINICALINDICATOR|CLINICALINDI|188", Name = POPULATION_NAME }); mockSchemaServiceClient.Setup(x => x.GetHierarchyNodesFromHierarchyPathsAsync(It.IsAny(), It.IsAny>(), It.IsAny())) .ReturnsAsync(list); mockSchemaServiceClient.Setup(x => x.GetDimensionMembersFromHierarchyPathsAsync(It.IsAny(), It.IsAny>(), It.IsAny())) .ReturnsAsync(new List { new MemberDto { Id = "188", Name = "All Readmissions" }}); var claimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor(); _opportunityRoleAssignmentService = new OpportunityRoleAssignmentService( (DbContexts.CentralDbContext)CentralDbContext, mockIdServiceClient.Object, mockSimpleSecurityServiceClient.Object, claimsPrincipalAccessor ); _strategicOpportunityService = new StrategicOpportunityService( JazzConnBuilderFactory, (DbContexts.CentralDbContext)CentralDbContext, claimsPrincipalAccessor, mockSchemaServiceClient.Object, SnowflakeDatabaseContext, mockIdServiceClient.Object, _opportunityRoleAssignmentService, mockIdRollupColumn.Object, mockOpportunityWorkbookService.Object, mockBackgroundJobClient.Object, mockStrategicOpportunityDetailService.Object, new StrategicItemDimensionSyncService(JazzConnBuilderFactory, (DbContexts.CentralDbContext)CentralDbContext, SnowflakeDatabaseContext), mockStrategicGLOpportunityDetailService.Object, (Microsoft.Extensions.Logging.ILogger)logger); } [Test, Ignore("temporarily ignoring because schema is out of sync")] public async Task CreatingOpportunityShouldAlsoCreateDetails() { //arrange var opportunity = CreateOpportunityDto(); //act var result = await _strategicOpportunityService.CreateOpportunityChargeCodeAsync(opportunity, CancellationToken.None); //assert result.Should().Be(1, "On success should return opportunity id."); } private static StrategicOpportunityChargeCodeDto CreateOpportunityDto() { var opportunity = new StrategicOpportunityChargeCodeDto() { Name = "Integration-StrategicOpportunityChargeCode", OpportunityType = StrategicOpportunityTypes.ChargeCode, OpportunityFiltersJSON = "[]", Rollup1Id = 0, Rollup2Id = 0, Rollup3Id = 0, BaselineType = BaselineType.MonthRange, BaselineDistribution = DistributionMethod.Average, BaselineStartDate = new DateOnly(2024, 1, 1), BaselineEndDate = new DateOnly(2024, 12, 31), EstimatedTrackingDuration = 12, // Assume empty or test collections for these Measures = Enumerable.Empty(), WorkbookIds = Enumerable.Empty(), // ChargeCode-specific properties PatientPopulationHPath = "CLINICALINDICATOR|CLINICALINDI|188", ExplorationPopulationId = 0, ChargeCodeHPath = "CC|CCRU|Blood" }; return opportunity; } [Test] public async Task UpdateStrategicOpportunityRampUpsAsync_ShouldUpdateRampUps() { // Arrange var opportunity = CreateOpportunityDto(); var opportunityId = await _strategicOpportunityService.CreateOpportunityChargeCodeAsync(opportunity, CancellationToken.None); var rampUps = new List { new() { OpportunityId = opportunityId, MonthNumber = 1, Percentage = 0.1 }, new() { OpportunityId = opportunityId, MonthNumber = 2, Percentage = 0.2 } }; // Act var updateResult = await _strategicOpportunityService.UpdateStrategicOpportunityRampUpsAsync(opportunityId, rampUps, CancellationToken.None); // Assert updateResult.Should().BeTrue(); // Verify persisted values var retrieved = await _strategicOpportunityService.GetStrategicOpportunityRampUpsAsync(opportunityId, CancellationToken.None); retrieved.Should().HaveCount(rampUps.Count); retrieved[0].MonthNumber.Should().Be(rampUps[0].MonthNumber); retrieved[0].Percentage.Should().Be(rampUps[0].Percentage); retrieved[1].MonthNumber.Should().Be(rampUps[1].MonthNumber); retrieved[1].Percentage.Should().Be(rampUps[1].Percentage); } [Test] public async Task ResetStrategicOpportunityRampUps_ShouldResetRampUps() { // Arrange var opportunity = CreateOpportunityDto(); var opportunityId = await _strategicOpportunityService.CreateOpportunityChargeCodeAsync(opportunity, CancellationToken.None); var rampUps = new List { new() { OpportunityId = opportunityId, MonthNumber = 1, Percentage = 0.1 }, new() { OpportunityId = opportunityId, MonthNumber = 2, Percentage = 0.2 } }; await _strategicOpportunityService.UpdateStrategicOpportunityRampUpsAsync(opportunityId, rampUps, CancellationToken.None); // Act var resetResult = await _strategicOpportunityService.ResetStrategicOpportunityRampUps(opportunityId, CancellationToken.None); // Assert resetResult.Should().BeTrue(); var retrieved = await _strategicOpportunityService.GetStrategicOpportunityRampUpsAsync(opportunityId, CancellationToken.None); // Verify persisted values retrieved.Should().HaveCount(rampUps.Count); retrieved[0].Percentage.Should().Be(1); retrieved[1].Percentage.Should().Be(1); } [Test] public async Task ResetStrategicOpportunityRampUps_ShouldNotResetRampUps() { // Arrange var opportunity = CreateOpportunityDto(); var opportunityId = await _strategicOpportunityService.CreateOpportunityChargeCodeAsync(opportunity, CancellationToken.None); // Act var resetResult = await _strategicOpportunityService.ResetStrategicOpportunityRampUps(opportunityId, CancellationToken.None); // Assert resetResult.Should().BeFalse(); } [Test] public async Task UpdateStrategicOpportunityRoleAssignment_ShouldUpdateRoleAssignments() { // Arrange var opportunity = CreateOpportunityDto(); var opportunityId = await _strategicOpportunityService.CreateOpportunityChargeCodeAsync(opportunity, CancellationToken.None); var roleAssignments = new List() { new OpportunityRoleAssignmentView() { LootId = opportunityId, IdentityGuid = Guid.NewGuid(), IdentityName = "Test", CanRead = true, CanWrite = true, CanSecure = false } }; // Act var saveResult = await _opportunityRoleAssignmentService.SaveRoleAssignmentsAsync(opportunityId, roleAssignments, CancellationToken.None); // Assert saveResult.Should().BeTrue(); // Verify persisted values var retrieved = await _opportunityRoleAssignmentService.GetRoleAssignmentsAsync(opportunityId, CancellationToken.None); var userPermission = await _opportunityRoleAssignmentService.GetUserRoleAssignmentsAsync(opportunityId, CancellationToken.None); retrieved.Should().HaveCount(roleAssignments.Count); var item = retrieved.FirstOrDefault(); item.LootId.Should().Be(opportunityId); item.IdentityGuid.Should().Be(roleAssignments[0].IdentityGuid); item.IdentityName.Should().Be(roleAssignments[0].IdentityName); item.CanRead.Should().Be(roleAssignments[0].CanRead); item.CanWrite.Should().Be(roleAssignments[0].CanWrite); item.CanSecure.Should().Be(roleAssignments[0].CanSecure); } [Test] public async Task GetStrategicOpportunityRampUpsAsync_ShouldReturnEmptyListIfNoneExist() { // Arrange var nonExistentOpportunityId = long.MaxValue; // Act var rampUps = await _strategicOpportunityService.GetStrategicOpportunityRampUpsAsync(nonExistentOpportunityId, CancellationToken.None); // Assert rampUps.Should().NotBeNull(); rampUps.Should().BeEmpty(); } [Test] public async Task GetStrategicOpportunitiesAsync_ShouldReturnOpportunitiesWithRollupsAndPopulation() { // Arrange var opportunity = CreateOpportunityDto(); var opportunityId = await _strategicOpportunityService.CreateOpportunityChargeCodeAsync(opportunity, CancellationToken.None); // Act var results = await _strategicOpportunityService.GetStrategicOpportunitiesAsync(CancellationToken.None); // Assert results.Should().NotBeEmpty("At least one opportunity should be returned"); var createdOpportunity = results.FirstOrDefault(o => o.OpportunityId == opportunityId); createdOpportunity.Should().NotBeNull("Created opportunity should be found in results"); createdOpportunity.OpportunityId.Should().Be(opportunityId); createdOpportunity.Name.Should().Be(opportunity.Name); createdOpportunity.OpportunityTypeName.Should().Be("Charge Code"); createdOpportunity.EncounterGroupName.Should().Be("Patient Population", "When PatientPopulationHPath is set, it should be Patient Population"); createdOpportunity.AdditionalFilters.Should().Be("No"); createdOpportunity.BaselinePeriod.Should() .Be($"{opportunity.BaselineStartDate:MMM d, yyyy} - {opportunity.BaselineEndDate:MMM d, yyyy}"); createdOpportunity.EstimatedTrackDurationMonths.Should().Be(opportunity.EstimatedTrackingDuration); createdOpportunity.Rollup1.Should().BeEmpty("When rollup1Id is 0, rollup should be empty"); createdOpportunity.Rollup2.Should().BeEmpty("When rollup2Id is 0, rollup should be empty"); createdOpportunity.Rollup3.Should().BeEmpty("When rollup3Id is 0, rollup should be empty"); createdOpportunity.PatientPopulationHPath.Should().Be(opportunity.PatientPopulationHPath); createdOpportunity.ExplorationPopulationId.Should().Be(opportunity.ExplorationPopulationId); createdOpportunity.Population.Should().Be(POPULATION_NAME); } [Test] public async Task UpdateStrategicOpportunityStatus_WhenNewInitiative_ShouldUpdateStatusAndDates() { // Arrange var opportunity = CreateOpportunityDto(); var opportunityId = await _strategicOpportunityService.CreateOpportunityChargeCodeAsync(opportunity, CancellationToken.None); var updateStatusDto = new StrategicOpportunityUpdateStatusDto { Status = (byte)StrategicOpportunityStatus.NewInitiative, TrackingStartDate = new DateOnly(2024, 1, 1), TrackingEndDate = new DateOnly(2024, 12, 31) }; // Act var updateResult = await _strategicOpportunityService.UpdateStrategicOpportunityStatus(opportunityId, updateStatusDto, CancellationToken.None); // Assert updateResult.Should().BeTrue("Update should be successful"); var strataId = TestUtilities.GetClaimsPrincipalAccessor()?.GetCurrentClaimsPrincipal().GetStrataId(); var opportunityAfterUpdate = await CentralDbContext.StrategicOpportunities .FirstOrDefaultAsync(x => x.OpportunityId == opportunityId && x.StrataId == strataId, CancellationToken.None); opportunityAfterUpdate.Should().NotBeNull("Updated opportunity should exist"); opportunityAfterUpdate.Status.Should().Be(updateStatusDto.Status, "Status should be updated to NewInitiative"); opportunityAfterUpdate.TrackingStartDate.Should().Be(updateStatusDto.TrackingStartDate, "TrackingStartDate should be updated"); opportunityAfterUpdate.TrackingEndDate.Should().Be(updateStatusDto.TrackingEndDate, "TrackingEndDate should be updated"); } [Test] public async Task UpdateStrategicOpportunityStatus_WhenNewOpportunity_ShouldResetTrackingData() { // Arrange var opportunity = CreateOpportunityDto(); var opportunityId = await _strategicOpportunityService.CreateOpportunityChargeCodeAsync(opportunity, CancellationToken.None); var toInitiativeDto = new StrategicOpportunityUpdateStatusDto { Status = (byte)StrategicOpportunityStatus.NewInitiative, TrackingStartDate = new DateOnly(2024, 1, 1), TrackingEndDate = new DateOnly(2024, 12, 31) }; await _strategicOpportunityService.UpdateStrategicOpportunityStatus(opportunityId, toInitiativeDto, CancellationToken.None); var toOpportunityDto = new StrategicOpportunityUpdateStatusDto { Status = (byte)StrategicOpportunityStatus.NewOpportunity }; // Act var updateResult = await _strategicOpportunityService.UpdateStrategicOpportunityStatus(opportunityId, toOpportunityDto, CancellationToken.None); // Assert updateResult.Should().BeTrue("Update should be successful"); var strataId = TestUtilities.GetClaimsPrincipalAccessor()?.GetCurrentClaimsPrincipal().GetStrataId(); var opportunityAfterUpdate = await CentralDbContext.StrategicOpportunityChargeCodes .FirstOrDefaultAsync(x => x.OpportunityId == opportunityId && x.StrataId == strataId, CancellationToken.None); opportunityAfterUpdate.Should().NotBeNull("Updated opportunity should exist"); opportunityAfterUpdate.Status.Should().Be((byte)StrategicOpportunityStatus.NewOpportunity, "Status should be reset to NewOpportunity"); opportunityAfterUpdate.TrackingStartDate.Should().Be(default(DateOnly), "TrackingStartDate should be reset to default"); opportunityAfterUpdate.TrackingEndDate.Should().Be(default(DateOnly), "TrackingEndDate should be reset to default"); opportunityAfterUpdate.LastRunTrackingDate.Should().BeNull("LastRunTrackingDate should be cleared"); opportunityAfterUpdate.LastRunTrackingStatus.Should().Be(RunTrackingStatus.None, "LastRunTrackingStatus should be reset to None"); opportunityAfterUpdate.ProgressToDateActual.Should().Be(0, "ProgressToDateActual should be reset to 0"); opportunityAfterUpdate.ProgressToDateCommitted.Should().Be(0, "ProgressToDateCommitted should be reset to 0"); } [Test] public async Task UpdateStrategicOpportunityStatus_WhenOtherStatus_ShouldOnlyUpdateStatus() { // Arrange var opportunity = CreateOpportunityDto(); var opportunityId = await _strategicOpportunityService.CreateOpportunityChargeCodeAsync(opportunity, CancellationToken.None); var toInitiativeDto = new StrategicOpportunityUpdateStatusDto { Status = (byte)StrategicOpportunityStatus.NewInitiative, TrackingStartDate = new DateOnly(2024, 1, 1), TrackingEndDate = new DateOnly(2024, 12, 31) }; await _strategicOpportunityService.UpdateStrategicOpportunityStatus(opportunityId, toInitiativeDto, CancellationToken.None); var toInValidationDto = new StrategicOpportunityUpdateStatusDto { Status = (byte)StrategicOpportunityStatus.InValidation }; // Act var updateResult = await _strategicOpportunityService.UpdateStrategicOpportunityStatus(opportunityId, toInValidationDto, CancellationToken.None); // Assert updateResult.Should().BeTrue("Update should be successful"); var strataId = TestUtilities.GetClaimsPrincipalAccessor()?.GetCurrentClaimsPrincipal().GetStrataId(); var opportunityAfterUpdate = await CentralDbContext.StrategicOpportunityChargeCodes .FirstOrDefaultAsync(x => x.OpportunityId == opportunityId && x.StrataId == strataId, CancellationToken.None); opportunityAfterUpdate.Should().NotBeNull("Updated opportunity should exist"); opportunityAfterUpdate.Status.Should().Be((byte)StrategicOpportunityStatus.InValidation, "Status should be updated to InValidation"); opportunityAfterUpdate.TrackingStartDate.Should().Be(toInitiativeDto.TrackingStartDate, "TrackingStartDate should be unchanged"); opportunityAfterUpdate.TrackingEndDate.Should().Be(toInitiativeDto.TrackingEndDate, "TrackingEndDate should be unchanged"); } [Test] public async Task UpdateStrategicOpportunityStatus_WhenOpportunityNotFound_ShouldReturnFalse() { // Arrange var nonExistentOpportunityId = long.MaxValue; var updateStatusDto = new StrategicOpportunityUpdateStatusDto { Status = (byte)StrategicOpportunityStatus.NewOpportunity }; // Act var result = await _strategicOpportunityService.UpdateStrategicOpportunityStatus(nonExistentOpportunityId, updateStatusDto, CancellationToken.None); // Assert result.Should().BeFalse("Update should return false when the opportunity does not exist"); } [Test] public async Task CopyStrategicOpportunityRoleAssignments_ShouldReturnEmptyList() { // Arrange var opportunity = CreateOpportunityDto(); var opportunityId = await _strategicOpportunityService.CreateOpportunityChargeCodeAsync(opportunity, CancellationToken.None); // Act var newOpportunityId = opportunityId + 1; await _opportunityRoleAssignmentService.CopyTo(opportunityId, newOpportunityId, CancellationToken.None); // Assert var newRoles = await _opportunityRoleAssignmentService.GetRoleAssignmentsAsync(newOpportunityId, CancellationToken.None); newRoles.Should().BeEmpty(); } [Test] public async Task CopyStrategicOpportunityRoleAssignments_ShouldReturnRoleAssignments() { // Arrange var opportunity = CreateOpportunityDto(); var opportunityId = await _strategicOpportunityService.CreateOpportunityChargeCodeAsync(opportunity, CancellationToken.None); var roleAssignments = new List() { new() { LootId = opportunityId, IdentityGuid = Guid.NewGuid(), IdentityName = "Test1", CanRead = true, CanWrite = false, CanSecure = true }, new() { LootId = opportunityId, IdentityGuid = Guid.NewGuid(), IdentityName = "Test2", CanRead = false, CanWrite = true, CanSecure = false }, }; await _opportunityRoleAssignmentService.SaveRoleAssignmentsAsync(opportunityId, roleAssignments, CancellationToken.None); // Act var newOpportunityId = opportunityId + 1; await _opportunityRoleAssignmentService.CopyTo(opportunityId, newOpportunityId, CancellationToken.None); // Assert var newRoles = await _opportunityRoleAssignmentService.GetRoleAssignmentsAsync(newOpportunityId, CancellationToken.None); // Verify persisted values var retrieved = newRoles.ToList(); retrieved.Should().HaveCount(roleAssignments.Count); CompareRoleAssignments(retrieved[0], roleAssignments[0]); CompareRoleAssignments(retrieved[1], roleAssignments[1]); } private static void CompareRoleAssignments(OpportunityRoleAssignmentView item1, OpportunityRoleAssignmentView item2) { item1.IdentityGuid.Should().Be(item2.IdentityGuid); item1.IdentityName.Should().Be(item2.IdentityName); item1.CanRead.Should().Be(item2.CanRead); item1.CanWrite.Should().Be(item2.CanWrite); item1.CanSecure.Should().Be(item2.CanSecure); } public string DataSchemaServiceSelectSql = @"SELECT ""EncounterId"", ""DischargeDateTime"", ""EntityID"", ""PhysicianId"", ""PrimaryServiceLineId"", ""CPTCodeCaseTypeFamilyId"", ""MSDRGCaseTypeFamilyId"", ""APRDRGCaseTypeFamilyId"", ""DepartmentId"", ""PhysicianSpecialtyId"", ""ChargeCodeID"", ""CostDriver"", ""PatientTypeRollup"", ZEROIFNULL(""Units"") AS ""Units"", ZEROIFNULL(""Cost"") AS ""Cost"" FROM ( SELECT ""EncounterId"", ""DischargeDateTime"", ""EntityID"", ""PhysicianId"", ""PrimaryServiceLineId"", ""CPTCodeCaseTypeFamilyId"", ""MSDRGCaseTypeFamilyId"", ""APRDRGCaseTypeFamilyId"", ""DepartmentId"", ""PhysicianSpecialtyId"", ""ChargeCodeID"", ""CostDriver"", ""PatientTypeRollup"", SUM(""Units"") AS ""Units"", SUM(""Cost"") AS ""Cost"" FROM ( SELECT DSSPES.encounterid AS ""EncounterId"", DSSPES.dischargedatetime AS ""DischargeDateTime"", DSSPES.entityid AS ""EntityID"", DSSPES.primaryphysicianid AS ""PhysicianId"", DSSPES.servicelineid AS ""PrimaryServiceLineId"", DSSPES.cptcodecasetypefamilyid AS ""CPTCodeCaseTypeFamilyId"", DSSPES.msdrgcasetypefamilyid AS ""MSDRGCaseTypeFamilyId"", DSSPES.aprdrgcasetypefamilyid AS ""APRDRGCaseTypeFamilyId"", PBLID.departmentid AS ""DepartmentId"", PHYSPRIMARY.physicianspecialtyid AS ""PhysicianSpecialtyId"", CC.chargecodeid AS ""ChargeCodeID"", IFNULL(CC.costdriver::TEXT, '') AS ""CostDriver"", IFNULL(EncounterPatientTypeRollup.patienttyperollup::TEXT, '') AS ""PatientTypeRollup"", NULL AS ""Cost"", SUM(PBLID.unitsofservice) AS ""Units"" FROM dss.FactPatientBillingLineItemDetail AS PBLID INNER JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterrecordnumber = PBLID.encounterrecordnumber 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 CC.chargecodeid IN (:chargecodeid_2)) GROUP BY ""EncounterId"", ""DischargeDateTime"", ""EntityID"", ""PhysicianId"", ""PrimaryServiceLineId"", ""CPTCodeCaseTypeFamilyId"", ""MSDRGCaseTypeFamilyId"", ""APRDRGCaseTypeFamilyId"", ""DepartmentId"", ""PhysicianSpecialtyId"", ""ChargeCodeID"", ""CostDriver"", ""PatientTypeRollup"" UNION ALL SELECT DSSPES.encounterid AS ""EncounterId"", DSSPES.dischargedatetime AS ""DischargeDateTime"", DSSPES.entityid AS ""EntityID"", DSSPES.primaryphysicianid AS ""PhysicianId"", DSSPES.servicelineid AS ""PrimaryServiceLineId"", DSSPES.cptcodecasetypefamilyid AS ""CPTCodeCaseTypeFamilyId"", DSSPES.msdrgcasetypefamilyid AS ""MSDRGCaseTypeFamilyId"", DSSPES.aprdrgcasetypefamilyid AS ""APRDRGCaseTypeFamilyId"", PBLID.departmentid AS ""DepartmentId"", PHYSPRIMARY.physicianspecialtyid AS ""PhysicianSpecialtyId"", CC.chargecodeid AS ""ChargeCodeID"", IFNULL(CC.costdriver::TEXT, '') AS ""CostDriver"", IFNULL(EncounterPatientTypeRollup.patienttyperollup::TEXT, '') AS ""PatientTypeRollup"", SUM(COSTDETAIL.variabledirectcost) AS ""Cost"", NULL AS ""Units"" FROM dss.FactPatientCostDetail AS COSTDETAIL RIGHT JOIN dss.FactPatientBillingLineItemDetail AS PBLID ON PBLID.rowid = COSTDETAIL.pblidrowid INNER JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterrecordnumber = PBLID.encounterrecordnumber 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 CC.chargecodeid IN (:chargecodeid_2)) GROUP BY ""EncounterId"", ""DischargeDateTime"", ""EntityID"", ""PhysicianId"", ""PrimaryServiceLineId"", ""CPTCodeCaseTypeFamilyId"", ""MSDRGCaseTypeFamilyId"", ""APRDRGCaseTypeFamilyId"", ""DepartmentId"", ""PhysicianSpecialtyId"", ""ChargeCodeID"", ""CostDriver"", ""PatientTypeRollup"" ) GROUP BY ""EncounterId"", ""DischargeDateTime"", ""EntityID"", ""PhysicianId"", ""PrimaryServiceLineId"", ""CPTCodeCaseTypeFamilyId"", ""MSDRGCaseTypeFamilyId"", ""APRDRGCaseTypeFamilyId"", ""DepartmentId"", ""PhysicianSpecialtyId"", ""ChargeCodeID"", ""CostDriver"", ""PatientTypeRollup"" ) ORDER BY ""EncounterId"" ASC NULLS FIRST, ""DischargeDateTime"" ASC NULLS FIRST, ""EntityID"" ASC NULLS FIRST, ""PhysicianId"" ASC NULLS FIRST, ""PrimaryServiceLineId"" ASC NULLS FIRST, ""CPTCodeCaseTypeFamilyId"" ASC NULLS FIRST, ""MSDRGCaseTypeFamilyId"" ASC NULLS FIRST, ""APRDRGCaseTypeFamilyId"" ASC NULLS FIRST, ""DepartmentId"" ASC NULLS FIRST, ""PhysicianSpecialtyId"" ASC NULLS FIRST, ""ChargeCodeID"" ASC NULLS FIRST, ""CostDriver"" ASC NULLS FIRST, ""PatientTypeRollup"" ASC NULLS FIRST "; } }