Files

520 lines
26 KiB
C#

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Moq;
using MoreLinq;
using MoreLinq.Extensions;
using NUnit.Framework;
using Strata.ContinuousImprovement.Biz.All;
using Strata.ContinuousImprovement.Biz.All.Opportunities;
using Strata.ContinuousImprovement.Biz.ChargeCode.Opportunities;
using Strata.ContinuousImprovement.Biz.DbContexts;
using Strata.ContinuousImprovement.Biz.FiscalMonths;
using Strata.ContinuousImprovement.Biz.Generics;
using Strata.ContinuousImprovement.Biz.OpportunityComments;
using Strata.ContinuousImprovement.Biz.PeerGroups;
using Strata.ContinuousImprovement.Biz.PeerGroups.Enums;
using Strata.ContinuousImprovement.Biz.QualityVariation.Breakdowns;
using Strata.ContinuousImprovement.Biz.Shared;
using Strata.ContinuousImprovement.Biz.Utilities;
using Strata.ContinuousImprovement.Biz.UtilizationVariation;
using Strata.ContinuousImprovement.JazzEntityFrameworkStub.Generics;
using Strata.SqlTools.Configuration.Common.AsyncFactory;
using Strata.StrataSphereCompare.Client.Models.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.JazzEntityFrameworkStub
{
public partial class JazzEntityFrameworkFactory : IAsyncDbContextFactory<JazzDbContext>
{
public static List<Guid> OpportunityGuids = new List<Guid>
{
Guid.NewGuid(),
Guid.NewGuid(),
Guid.NewGuid(),
Guid.NewGuid()
};
public static Guid CurrentConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345");
public static Guid CaseTypeGuid = new Guid("c7838982-b2c6-4e93-a571-c1fd5cedc961");
public static Guid DatabaseGuid = new Guid("21E97CAF-F37D-4F22-9777-0C6A36210FF9");
public string TestName { get; set; } = TestContext.CurrentContext?.Test.FullName ??
throw new InvalidOperationException("TestContext.CurrentContext cannot be null");
public JazzDbContext JazzDbContext;
public CentralDbContext CentralDbContext;
public IFiscalMonthResolver FiscalMonthResolver = Mock.Of<IFiscalMonthResolver>();
public IDatabaseFunctionService DbFunctionService = Mock.Of<IDatabaseFunctionService>();
public async Task<JazzDbContext> CreateDbContextAsync(CancellationToken cancellationToken)
=> await CreateDbContextAsync(TestName, cancellationToken);
public async Task<JazzDbContext> CreateDbContextAsync(string dbName, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(dbName))
{
return await Task.FromResult((JazzDbContext)null);
}
var options = new DbContextOptionsBuilder<JazzDbContext>()
.UseInMemoryDatabase(dbName)
// don't raise the error warning us that the in memory db doesn't support transactions
.ConfigureWarnings(x => x.Ignore(InMemoryEventId.TransactionIgnoredWarning))
.Options;
JazzDbContext = new JazzDbContext(options);
Mock.Get(DbFunctionService)
.Setup(x => x.SplitString(It.IsAny<IEnumerable<string>>()))
.Returns<IEnumerable<string>>(x => (y => y.EntityId.Split(',', StringSplitOptions.TrimEntries).Intersect(x).Count() > 0));
await JazzDbContext.Database.EnsureCreatedAsync(cancellationToken);
JazzDbContext.DatabaseFunctionService = DbFunctionService;
if (FiscalMonthResolver != null)
{
Mock.Get(FiscalMonthResolver)
.Setup(s => s.AllFiscalMonths)
.Returns(new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
.Select(m => new FiscalMonth
{
MemberGuid = Guid.NewGuid(),
FiscalMonthId = (byte)m,
FiscalMonthCode = $"{m}",
SortOrder = (byte)m,
DaysInMonth = m switch
{
2 => 28,
4 => 30,
6 => 30,
9 => 30,
11 => 30,
_ => 31
},
MonthColumnName = $"Month{m:00}",
Abbreviation = new DateTime(2024, m, 1).ToString("MMM"),
IsReal = true
}).ToList().AsReadOnly());
Mock.Get(FiscalMonthResolver)
.Setup(s => s.FirstFiscalMonth())
.Returns(new FiscalMonth
{
MemberGuid = Guid.NewGuid(),
FiscalMonthId = 1,
FiscalMonthCode = "1",
SortOrder = 1,
DaysInMonth = 31,
MonthColumnName = "Month01",
Abbreviation = "Jan",
IsReal = true,
});
Mock.Get(FiscalMonthResolver)
.Setup(s => s.LastFiscalMonth())
.Returns(new FiscalMonth
{
MemberGuid = Guid.NewGuid(),
FiscalMonthId = 12,
FiscalMonthCode = "12",
SortOrder = 12,
DaysInMonth = 31,
MonthColumnName = "Month12",
Abbreviation = "Dec",
IsReal = true,
});
}
if (!JazzDbContext.SystemSettings.Any())
{
await JazzDbContext.SystemSettings.AddRangeAsync(SystemSettings, cancellationToken);
}
if (!JazzDbContext.Configurations.Any())
{
Configurations.ForEach(c =>
{
c.FiscalMonthResolver = FiscalMonthResolver;
});
await JazzDbContext.Configurations.AddRangeAsync(Configurations, cancellationToken);
}
if (!JazzDbContext.UserSettings.Any())
{
await JazzDbContext.UserSettings.AddRangeAsync(UserSettings, cancellationToken);
}
if (!JazzDbContext.CaseTypeFamilies.Any())
{
await JazzDbContext.CaseTypeFamilies.AddRangeAsync(CaseTypeFamilies, cancellationToken);
}
if (!JazzDbContext.FFOpportunities.Any())
{
FFOpportunities.First().ConfigurationGuid = Configurations.First().ConfigurationGuid;
await JazzDbContext.FFOpportunities.AddRangeAsync(FFOpportunities, cancellationToken);
}
if (!JazzDbContext.FreeFormOpportunities.Any())
{
var configuration = Configurations[0];
configuration.FiscalMonthResolver = FiscalMonthResolver;
FFOpportunitiesDataModel.ForEach(ff =>
{
ff.ConfigurationGuid = configuration.ConfigurationGuid;
ff.Configuration = configuration;
});
await JazzDbContext.FreeFormOpportunities.AddRangeAsync(FFOpportunitiesDataModel, cancellationToken);
}
if (!JazzDbContext.GeneralLedgerOpportunities.Any())
{
GLOpportunities.First().ConfigurationGuid = Configurations.First().ConfigurationGuid;
await JazzDbContext.GeneralLedgerOpportunities.AddRangeAsync(GLOpportunities, cancellationToken);
}
if (!JazzDbContext.PayrollOpportunities.Any())
{
PROpportunities.First().ConfigurationGuid = Configurations.First().ConfigurationGuid;
await JazzDbContext.PayrollOpportunities.AddRangeAsync(PROpportunities, cancellationToken);
}
if (!JazzDbContext.VariationOpportunities.Any())
{
UVOpportunities.First().ConfigurationGuid = Configurations.First().ConfigurationGuid;
await JazzDbContext.VariationOpportunities.AddRangeAsync(UVOpportunities, cancellationToken);
}
if (!JazzDbContext.UtilizationVariationOpportunitiesData.Any())
{
UtilizationVariationOpportunities.First().ConfigurationGuid = Configurations.First().ConfigurationGuid;
await JazzDbContext.UtilizationVariationOpportunitiesData.AddRangeAsync(UtilizationVariationOpportunities, cancellationToken);
}
if (!JazzDbContext.ExplorationVariationOpportunitiesData.Any())
{
ExplorationVariationOpportunities.First().ConfigurationGuid = Configurations.First().ConfigurationGuid;
await JazzDbContext.ExplorationVariationOpportunitiesData.AddRangeAsync(ExplorationVariationOpportunities, cancellationToken);
}
if (!JazzDbContext.ChargeCodeOpportunities.Any())
{
CCOpportunities.First().ConfigurationGuid = Configurations.First().ConfigurationGuid;
await JazzDbContext.ChargeCodeOpps.AddRangeAsync(CCOpportunities, cancellationToken);
var ccDataModels = CCOpportunities.Select(cc => cc.MapToDataModel()).ToList();
foreach (var cc in ccDataModels)
{
if (cc.ConfigurationGuid == Configurations.First().ConfigurationGuid)
{
cc.Configuration = Configurations.First();
}
cc.EncounterGroup = (int)EncounterGroup.CaseType;
cc.CaseTypes = new List<string>
{
"CaseType 1",
"CaseType 2",
"CaseType 3"
};
cc.ChargeCodes = new List<string>
{
"CC 1",
"CC 2",
"CC 3",
};
var details = new List<ChargeCodeOpportunityDetail>();
details.AddRange(
Enumerable.Range(1, 12).Select(month => new ChargeCodeOpportunityDetail
{
OpportunityGUID = cc.OpportunityGuid,
OpportunityLevelId = 0,
OpportunityLevelName = "Organization",
ChargeCodeId = 0,
ChargeCodeName = "",
ChargeCodeRollupName = "CC 1",
TotalCases = 10,
TotalCost = 10,
TotalUnitsOfService = 10,
GoalTotalUnitsOfService = 10,
IsBaseline = true,
Month = month,
GoalCostPerUnit = 10
}));
cc.Details = details;
}
ChargeCodeOpportunities.AddRange(ccDataModels);
ChargeCodeDetails.AddRange(ccDataModels.SelectMany(dm => dm.Details));
await JazzDbContext.ChargeCodeOpportunities.AddRangeAsync(ccDataModels, cancellationToken);
await JazzDbContext.ChargeCodeDetails.AddRangeAsync(ccDataModels.SelectMany(dm => dm.Details), cancellationToken);
}
if (!JazzDbContext.EncounterOpportunities.Any())
{
FFOpportunities.First().ConfigurationGuid = Configurations.First().ConfigurationGuid;
await JazzDbContext.EncounterOpportunities.AddRangeAsync(ENOpportunities, cancellationToken);
}
if (!JazzDbContext.DimEntities.Any())
{
await JazzDbContext.DimEntities.AddRangeAsync(DimEntities, cancellationToken);
}
if (!JazzDbContext.VariationCaseTypes.Any())
{
await JazzDbContext.VariationCaseTypes.AddRangeAsync(UVCaseTypes, cancellationToken);
}
if (!JazzDbContext.QualityVariationItemOpportunities.Any())
{
QVIOpportunities.First().ConfigurationGuid = Configurations.First().ConfigurationGuid;
await JazzDbContext.QualityVariationItemOpportunities.AddRangeAsync(QVIOpportunities, cancellationToken);
}
if (!JazzDbContext.QualityVariationItemEvents.Any())
{
QVIEvents.First().ConfigurationGuid = Configurations.First().ConfigurationGuid;
await JazzDbContext.QualityVariationItemEvents.AddRangeAsync(QVIEvents, cancellationToken);
}
if (!JazzDbContext.QualityVariationItemBreakdowns.Any())
{
qviBreakdowns.AddRange(
QVIOpportunities.GroupBy(
opp => new { opp.ConfigurationGuid, opp.BreakdownId },
(g, d) => new QVIBreakdown
{
BreakdownId = g.BreakdownId,
BreakdownName = d.First().BreakdownName,
IdentifiedSavingsTotal = d.Sum(b => b.IdentifiedSavings),
QVICasesTotal = d.Sum(b => b.QVICases),
CasesTotal = d.Sum(b => b.Cases),
OpportunitiesCount = d.Count(),
QVIRate = (decimal)d.Sum(b => b.QVICases).DivideBy(d.Sum(b => b.Cases)),
ConfigurationGuid = g.ConfigurationGuid
}));
await JazzDbContext.QualityVariationItemBreakdowns.AddRangeAsync(qviBreakdowns, cancellationToken);
}
if (!JazzDbContext.AllOpportunities.Any())
{
var configurationGuid = Configurations.First().ConfigurationGuid;
await JazzDbContext.AllOpportunities.AddRangeAsync(UVOpportunities
.ConvertAll(uv => new AllOpportunity
{
ConfigurationGuid = configurationGuid,
OpportunityGuid = uv.OpportunityGuid,
OpportunityKey = uv.OpportunityKey,
OpportunityType = (int)OpportunityTypes.Variation,
OpportunityTypeName = OpportunityTypes.Variation.OpportunityTypeName(),
Name = $"{uv.CaseTypeName} - {uv.EntityName}",
IdentifiedSavings = uv.IdentifiedSavings,
Initiative = uv.Initiative,
InitiativeGuid = uv.InitiativeGuid,
IsHidden = uv.IsHidden,
CostDriver = uv.CostDriver,
Note = uv.Note
}), cancellationToken);
await JazzDbContext.AllOpportunities.AddRangeAsync(CCOpportunities
.ConvertAll(opp => new AllOpportunity
{
ConfigurationGuid = configurationGuid,
OpportunityGuid = opp.OpportunityGuid,
OpportunityKey = opp.OpportunityKey,
OpportunityType = (int)OpportunityTypes.Encounter,
OpportunityTypeName = OpportunityTypes.Encounter.OpportunityTypeName(),
Name = opp.Name,
IdentifiedSavings = opp.IdentifiedSavings,
Initiative = opp.Initiative,
InitiativeGuid = opp.InitiativeGuid,
IsHidden = opp.IsHidden,
CostDriver = "Encounter",
Note = opp.Note
}), cancellationToken);
await JazzDbContext.AllOpportunities.AddRangeAsync(ENOpportunities
.ConvertAll(en => new AllOpportunity
{
ConfigurationGuid = configurationGuid,
OpportunityGuid = en.OpportunityGuid,
OpportunityKey = en.OpportunityKey,
OpportunityType = (int)OpportunityTypes.Encounter,
OpportunityTypeName = OpportunityTypes.Encounter.OpportunityTypeName(),
Name = en.Name,
IdentifiedSavings = en.IdentifiedSavings,
Initiative = en.Initiative,
InitiativeGuid = en.InitiativeGuid,
IsHidden = en.IsHidden,
CostDriver = "Encounter",
Note = en.Note
}), cancellationToken);
await JazzDbContext.AllOpportunities.AddRangeAsync(GLOpportunities
.ConvertAll(gl => new AllOpportunity
{
ConfigurationGuid = configurationGuid,
OpportunityGuid = gl.OpportunityGuid,
OpportunityKey = gl.OpportunityKey,
OpportunityType = (int)OpportunityTypes.FreeForm,
OpportunityTypeName = OpportunityTypes.FreeForm.OpportunityTypeName(),
Name = gl.Name,
IdentifiedSavings = gl.IdentifiedSavings,
Initiative = gl.Initiative,
InitiativeGuid = gl.InitiativeGuid,
IsHidden = gl.IsHidden,
CostDriver = "",
Note = gl.Note
}), cancellationToken);
await JazzDbContext.AllOpportunities.AddRangeAsync(PROpportunities
.ConvertAll(pr => new AllOpportunity
{
ConfigurationGuid = configurationGuid,
OpportunityGuid = pr.OpportunityGuid,
OpportunityKey = pr.OpportunityKey,
OpportunityType = (int)OpportunityTypes.Payroll,
OpportunityTypeName = OpportunityTypes.Payroll.OpportunityTypeName(),
Name = pr.Name,
IdentifiedSavings = pr.IdentifiedSavings,
Initiative = pr.Initiative,
InitiativeGuid = pr.InitiativeGuid,
IsHidden = pr.IsHidden,
CostDriver = "",
Note = pr.Note
}), cancellationToken);
await JazzDbContext.AllOpportunities.AddRangeAsync(QVIOpportunities
.ConvertAll(qv => new AllOpportunity
{
ConfigurationGuid = configurationGuid,
OpportunityGuid = qv.OpportunityGuid,
OpportunityKey = qv.OpportunityKey,
OpportunityType = (int)OpportunityTypes.QualityVariation,
OpportunityTypeName = OpportunityTypes.QualityVariation.OpportunityTypeName(),
Name = qv.BreakdownName,
IdentifiedSavings = qv.IdentifiedSavings,
Initiative = qv.Initiative,
InitiativeGuid = qv.InitiativeGuid,
IsHidden = qv.IsHidden,
CostDriver = "",
Note = qv.Note
}), cancellationToken);
await JazzDbContext.AllOpportunities.AddRangeAsync(FFOpportunities
.ConvertAll(ff => new AllOpportunity
{
ConfigurationGuid = configurationGuid,
OpportunityGuid = Guid.NewGuid(),
OpportunityKey = ff.OpportunityKey,
OpportunityType = (int)OpportunityTypes.FreeForm,
OpportunityTypeName = OpportunityTypes.FreeForm.OpportunityTypeName(),
Name = ff.Name,
IdentifiedSavings = ff.IdentifiedSavings,
Initiative = ff.Initiative,
InitiativeGuid = ff.InitiativeGuid,
IsHidden = ff.IsHidden,
CostDriver = ff.MetricType == ContinuousImprovement.Biz.FreeForm.Opportunities.MetricType.Financial
? "Financial Free Form" : "Free Form",
Note = ff.Note
}), cancellationToken);
if (!JazzDbContext.PeerGroups.Any())
{
await JazzDbContext.PeerGroups.AddAsync(new PeerGroup() { PeerGroupId = 1, Name = "Test Name" }, cancellationToken);
}
if (!JazzDbContext.PeerGroupCriteriaMappings.Any())
{
var mappings = new List<PeerGroupCriteriaMapping>()
{
new PeerGroupCriteriaMapping() { RowId = 1, PeerGroupId = 1, MappingType = (byte)PeerGroupCritetiaType.EntityTypes, MappingValue = (byte)HospitalType.RehabLTACOther },
new PeerGroupCriteriaMapping() { RowId = 2, PeerGroupId = 1, MappingType = (byte)PeerGroupCritetiaType.UrbanRural, MappingValue = (byte)UrbanRural.Urban },
new PeerGroupCriteriaMapping() { RowId = 3, PeerGroupId = 1, MappingType = (byte)PeerGroupCritetiaType.AMCTypes, MappingValue = (byte)IsAmc.AcademicMedicalCenters },
new PeerGroupCriteriaMapping() { RowId = 4, PeerGroupId = 1, MappingType = (byte)PeerGroupCritetiaType.CensusRegions, MappingValue = (byte)CensusRegion.Midwest },
new PeerGroupCriteriaMapping() { RowId = 5, PeerGroupId = 1, MappingType = (byte)PeerGroupCritetiaType.BedSize, MappingValue = (byte)BedSize._0_250 },
new PeerGroupCriteriaMapping() { RowId = 6, PeerGroupId = 1, MappingType = (byte)PeerGroupCritetiaType.OperatingExpenses, MappingValue = (byte)OperatingExpense._250MTo500M },
};
await JazzDbContext.PeerGroupCriteriaMappings.AddRangeAsync(mappings, cancellationToken);
}
}
await JazzDbContext.SaveChangesAsync(cancellationToken);
return await Task.FromResult(JazzDbContext);
}
public Task<JazzDbContext> CreateDbContextAsync(Guid databaseGuid, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public async Task<CentralDbContext> CreateCentralDbContextAsync(CancellationToken cancellationToken)
=> await CreateCentralDbContextAsync(TestName, cancellationToken);
public async Task<CentralDbContext> CreateCentralDbContextAsync(string dbName, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(dbName))
{
return await Task.FromResult((CentralDbContext)null);
}
var centralOptions = new DbContextOptionsBuilder<CentralDbContext>()
.UseInMemoryDatabase(dbName)
.Options;
CentralDbContext = new CentralDbContext(centralOptions);
await EnsureCreatedAsync(CentralDbContext, JazzDbContext, cancellationToken);
return await Task.FromResult(CentralDbContext);
}
public async Task EnsureCreatedAsync(ICentralDbContext dbContext, CancellationToken cancellationToken)
{
var centralDbContext = (CentralDbContext)dbContext;
await centralDbContext.Database.EnsureCreatedAsync(cancellationToken);
if (!(await centralDbContext.NetworkOpportunities.AnyAsync(cancellationToken)))
{
await centralDbContext.NetworkOpportunities.AddRangeAsync(NetworkOpportunities, cancellationToken);
}
if (!(await centralDbContext.ClientNetworkOpportunities.AnyAsync(cancellationToken)))
{
await centralDbContext.ClientNetworkOpportunities.AddRangeAsync(ClientNetworkOpportunities, cancellationToken);
}
await centralDbContext.SaveChangesAsync(cancellationToken);
}
public async Task EnsureCreatedAsync(ICentralDbContext dbContext, IJazzDbContext jazzDbContext, CancellationToken cancellationToken)
{
await EnsureCreatedAsync(dbContext, cancellationToken);
var centralDbContext = (CentralDbContext)dbContext;
if (await centralDbContext.Comments.AnyAsync(cancellationToken)) { return; }
await centralDbContext.Comments.AddRangeAsync(Comments, cancellationToken);
if (jazzDbContext != null)
{
var allOpportunities = await jazzDbContext.AllOpportunities.ToListAsync(cancellationToken);
if (!allOpportunities.Any()) { return; }
var dateTime = new DateTimeOffset(DateTime.UtcNow, TimeSpan.Zero).UtcDateTime;
var comments = allOpportunities
.Select((opp, idx) => new Comment
{
CommentDate = dateTime.AddHours(idx),
CommentId = idx + 2,
CommentText = $"Comment on {opp.Name}",
Author = "Name, Author",
SourceOfSavingsId = (int)opp.OpportunityType,
StrataId = 9,
OpportunityId = opp.OpportunityId
}).ToList();
await centralDbContext.Comments.AddRangeAsync(comments, cancellationToken);
}
try
{
await centralDbContext.SaveChangesAsync(cancellationToken);
}
catch (Exception ex)
{
// ILB
}
}
}
}