public void GuardsAgainstNoTemplateMappingItemForTheCalculation() { string calculationId = NewRandomString(); string specificationId = NewRandomString(); string fundingStreamId = NewRandomString(); string fundingPeriodId = NewRandomString(); string templateVersion = NewRandomString(); Calculation calculation = NewCalculation(_ => _.WithId(calculationId) .WithSpecificationId(specificationId) .WithFundingStreamId(fundingStreamId)); GivenTheCalculation(calculationId, calculation); AndTheSpecificationSummary(specificationId, NewSpecificationSummary(_ => _.WithTemplateVersions((fundingStreamId, templateVersion)) .WithFundingPeriodId(fundingPeriodId))); AndTheTemplate(fundingStreamId, fundingPeriodId, templateVersion, NewTemplate()); AndTheTemplateMapping(fundingStreamId, specificationId, NewTemplateMapping()); Func <Task <IActionResult> > invocation = () => WhenTheCalculationFundingLinesAreQueried(calculationId); invocation .Should() .Throw <InvalidOperationException>() .Which .Message .Should() .Be($"Did not locate a template mapping item for CalculationId {calculationId}"); }
public async Task ValidateAsync_WhenCalculationNameAlreadyExistsButItsTheSameCalc_EnsuresValidIsTrue() { //Arrange CalculationEditModel model = CreateModel(); Calculation calculationWithSameName = new Calculation { Id = model.CalculationId }; ICalculationsRepository calculationsRepository = CreateCalculationRepository(); calculationsRepository .GetCalculationsBySpecificationIdAndCalculationName(Arg.Is(model.SpecificationId), Arg.Is(model.Name)) .Returns(calculationWithSameName); CalculationEditModelValidator validator = CreateValidator(calculationRepository: calculationsRepository); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeTrue(); }
public void GuardsAgainstNoTemplateMappingForSpecificationAndFundingStream() { string calculationId = NewRandomString(); string specificationId = NewRandomString(); string fundingStreamId = NewRandomString(); string fundingPeriodId = NewRandomString(); string templateVersion = NewRandomString(); Calculation calculation = NewCalculation(_ => _.WithId(calculationId) .WithSpecificationId(specificationId) .WithFundingStreamId(fundingStreamId)); GivenTheCalculation(calculationId, calculation); AndTheSpecificationSummary(specificationId, NewSpecificationSummary(_ => _.WithTemplateVersions((fundingStreamId, templateVersion)) .WithFundingPeriodId(fundingPeriodId))); AndTheTemplate(fundingStreamId, fundingPeriodId, templateVersion, NewTemplate()); Func <Task <IActionResult> > invocation = () => WhenTheCalculationFundingLinesAreQueried(calculationId); invocation .Should() .Throw <ArgumentNullException>() .Which .ParamName .Should() .Be("templateMapping"); }
private StatementSyntax CreateCalculationVariables(Calculation calc) { if (string.IsNullOrWhiteSpace(calc.SourceCodeName)) { throw new InvalidOperationException($"Calculation source code name is not populated for calc {calc.Id }"); } StringBuilder builder = new StringBuilder(); // Add attributes to describe calculation and calculation specification builder.AppendLine($"<Calculation(Id := \"{calc.Id}\", Name := \"{calc.Name}\")>"); if (calc.CalculationSpecification != null) { builder.AppendLine($"<CalculationSpecification(Id := \"{calc.CalculationSpecification.Id}\", Name := \"{calc.CalculationSpecification.Name}\")>"); } if (calc.AllocationLine != null) { // Add attribute for allocation line builder.AppendLine($"<AllocationLine(Id := \"{calc.AllocationLine.Id}\", Name := \"{calc.AllocationLine.Name}\")>"); } if (calc.Policies != null) { // Add attributes for policies foreach (Common.Models.Reference policySpecification in calc.Policies) { builder.AppendLine($"<PolicySpecification(Id := \"{policySpecification.Id}\", Name := \"{policySpecification.Name}\")>"); } } // Add attribute for calculation description if (!string.IsNullOrWhiteSpace(calc.Description)) { builder.AppendLine($"<Description(Description := \"{calc.Description?.Replace("\"", "\"\"")}\")>"); } if (!string.IsNullOrWhiteSpace(calc.Current?.SourceCode)) { calc.Current.SourceCode = QuoteAggregateFunctionCalls(calc.Current.SourceCode); } builder.AppendLine($"Dim {calc.SourceCodeName} As Func(Of decimal?) = nothing"); builder.AppendLine(); SyntaxTree tree = SyntaxFactory.ParseSyntaxTree(builder.ToString()); return(tree .GetRoot() .DescendantNodes() .OfType <StatementSyntax>() .FirstOrDefault()); }
public async Task <IActionResult> GetCalculationFundingLines(string calculationId) { Guard.IsNullOrWhiteSpace(calculationId, nameof(calculationId)); Calculation calculation = await GetCalculation(calculationId); if (calculation == null) { return(new NotFoundResult()); } string specificationId = calculation.SpecificationId; string cacheKey = GetCacheKey(calculationId, specificationId); if (await CacheContains(cacheKey)) { return(new OkObjectResult(await GetCachedCalculationFundingLines(cacheKey))); } SpecificationSummary specificationSummary = await GetSpecificationSummary(specificationId); Guard.ArgumentNotNull(specificationSummary, nameof(specificationSummary)); string fundingStreamId = calculation.FundingStreamId; if (specificationSummary.TemplateIds == null || !specificationSummary.TemplateIds.TryGetValue(fundingStreamId, out string templateVersion)) { throw new ArgumentOutOfRangeException(nameof(fundingStreamId), $"Specification {specificationId} does not contain a template version for the funding stream {fundingStreamId}"); } TemplateMetadataContents template = await GetTemplate(fundingStreamId, specificationSummary.FundingPeriod?.Id, templateVersion); Guard.ArgumentNotNull(template, nameof(template)); TemplateMapping templateMapping = await GetTemplateMapping(fundingStreamId, specificationId); Guard.ArgumentNotNull(templateMapping, nameof(templateMapping)); uint?templateId = templateMapping.TemplateMappingItems?.SingleOrDefault(_ => _.CalculationId == calculationId)?.TemplateId; Guard.Ensure(templateId.HasValue, $"Did not locate a template mapping item for CalculationId {calculationId}"); IEnumerable <CalculationFundingLine> calculationFundingLines = GetCalculationFundingLines(template, templateId.GetValueOrDefault()); await CacheCalculationFundingLines(cacheKey, calculationFundingLines.ToArray()); return(new OkObjectResult(calculationFundingLines)); }
private CalculationIndex CreateCalculationIndexItem(Calculation calculation, SpecModel.SpecificationSummary specificationSummary) { return(new CalculationIndex { Id = calculation.Id, SpecificationId = calculation.SpecificationId, SpecificationName = specificationSummary.Name, Name = calculation.Current.Name, ValueType = calculation.Current.ValueType.ToString(), FundingStreamId = calculation.FundingStreamId ?? "N/A", FundingStreamName = specificationSummary.FundingStreams.FirstOrDefault(_ => _.Id == calculation.FundingStreamId)?.Name ?? "N/A", Namespace = calculation.Current.Namespace.ToString(), CalculationType = calculation.Current.CalculationType.ToString(), Description = calculation.Current.Description, WasTemplateCalculation = calculation.Current.WasTemplateCalculation, Status = calculation.Current.PublishStatus.ToString(), LastUpdatedDate = DateTimeOffset.Now }); }
public async Task ReturnsCacheContentsIfAvailable() { string calculationId = NewRandomString(); string specificationId = NewRandomString(); Calculation calculation = NewCalculation(_ => _.WithId(calculationId) .WithSpecificationId(specificationId)); CalculationFundingLine[] cachedCalculationFundingLines = new CalculationFundingLine[0]; GivenTheCalculation(calculationId, calculation); AndTheCacheContents(GetCacheKey(specificationId, calculationId), cachedCalculationFundingLines); OkObjectResult result = await WhenTheCalculationFundingLinesAreQueried(calculationId) as OkObjectResult; result? .Value .Should() .BeSameAs(cachedCalculationFundingLines); }
public void GuardsAgainstNoSpecificationForCalculation() { string calculationId = NewRandomString(); string specificationId = NewRandomString(); Calculation calculation = NewCalculation(_ => _.WithId(calculationId) .WithSpecificationId(specificationId)); GivenTheCalculation(calculationId, calculation); Func <Task <IActionResult> > invocation = () => WhenTheCalculationFundingLinesAreQueried(calculationId); invocation .Should() .Throw <ArgumentNullException>() .Which .ParamName .Should() .Be("specificationSummary"); }
public void GuardsAgainstNoTemplateVersionSetupForTheCalculationFundingStream() { string calculationId = NewRandomString(); string specificationId = NewRandomString(); Calculation calculation = NewCalculation(_ => _.WithId(calculationId) .WithSpecificationId(specificationId)); GivenTheCalculation(calculationId, calculation); AndTheSpecificationSummary(specificationId, NewSpecificationSummary()); Func <Task <IActionResult> > invocation = () => WhenTheCalculationFundingLinesAreQueried(calculationId); invocation .Should() .Throw <ArgumentOutOfRangeException>() .Which .ParamName .Should() .Be("fundingStreamId"); }
private void AndMissingCalculation(string calculationId, Calculation calculation) { _calculationsRepository.GetCalculationById(calculationId) .Returns(calculation); }
private void AndTheCalculationIsCreatedForRequestMatching(Expression <Predicate <CalculationCreateModel> > createModelMatching, Calculation calculation) { _createCalculationService.CreateCalculation(Arg.Is(_specificationId), Arg.Is(createModelMatching), Arg.Is(CalculationNamespace.Template), Arg.Is(Models.Calcs.CalculationType.Template), Arg.Is <Reference>(_ => _.Id == _userId && _.Name == _userName), Arg.Is(_correlationId), Arg.Any <CalculationDataType>(), Arg.Is(false), Arg.Any <IEnumerable <string> >()) .Returns(new CreateCalculationResponse { Succeeded = true, Calculation = calculation }); }
public async Task ModifiesCalculationsIfOnTemplateExists() { uint templateCalculationId1 = (uint)new RandomNumberBetween(1, int.MaxValue); uint templateCalculationId2 = (uint)new RandomNumberBetween(1, int.MaxValue); string calculationId1 = "calculationId1"; string calculationId2 = "calculationId2"; string calculationId3 = "calculationId3"; string calculationName1 = "calculationName1"; string calculationName2 = "calculationName2"; string calculationName3 = "calculationName3"; string newCalculationName1 = "newCalculationName1"; string newCalculationName2 = "newCalculationName2"; string newCalculationId4 = "newCalculationId4"; string newCalculationId5 = "newCalculationId5"; CalculationValueFormat calculationValueFormat1 = CalculationValueFormat.Currency; CalculationValueFormat calculationValueFormat2 = CalculationValueFormat.Number; CalculationValueType calculationValueType3 = CalculationValueType.Percentage; TemplateMappingItem mappingWithMissingCalculation1 = NewTemplateMappingItem(); TemplateMappingItem mappingWithMissingCalculation2 = NewTemplateMappingItem(); TemplateMappingItem mappingWithMissingCalculation3 = NewTemplateMappingItem(_ => { _.WithCalculationId(calculationId3); _.WithName(calculationName3); }); TemplateMapping templateMapping = NewTemplateMapping(_ => _.WithItems(mappingWithMissingCalculation1, NewTemplateMappingItem(mi => mi.WithCalculationId(calculationId1).WithTemplateId(templateCalculationId1)), mappingWithMissingCalculation2, NewTemplateMappingItem(mi => mi.WithCalculationId(calculationId2).WithTemplateId(templateCalculationId2)), mappingWithMissingCalculation3)); TemplateMetadataContents templateMetadataContents = NewTemplateMetadataContents(_ => _.WithFundingLines(NewFundingLine(fl => fl.WithCalculations( NewTemplateMappingCalculation(), NewTemplateMappingCalculation(), NewTemplateMappingCalculation(x => x.WithTemplateCalculationId(templateCalculationId1).WithName(newCalculationName1).WithValueFormat(calculationValueFormat1)), NewTemplateMappingCalculation(x => x.WithTemplateCalculationId(templateCalculationId2).WithName(newCalculationName2).WithValueFormat(calculationValueFormat2)))))); TemplateCalculation templateCalculationOne = NewTemplateMappingCalculation(_ => _.WithName("template calculation 1")); TemplateCalculation templateCalculationTwo = NewTemplateMappingCalculation(_ => _.WithName("template calculation 2")); List <Calculation> calculations = new List <Calculation> { NewCalculation(_ => _.WithId(calculationId1) .WithCurrentVersion( NewCalculationVersion(x => x.WithCalculationId(calculationId1).WithName(calculationName1)))), NewCalculation(_ => _.WithId(calculationId2) .WithCurrentVersion( NewCalculationVersion(x => x.WithCalculationId(calculationId2).WithName(calculationName2)))), }; Calculation missingCalculation = NewCalculation(_ => _.WithId(calculationId3) .WithCurrentVersion( NewCalculationVersion(x => { x.WithName(calculationName3); x.WithValueType(calculationValueType3); }))); GivenAValidMessage(); AndTheJobCanBeRun(); AndTheTemplateMapping(templateMapping); AndTheTemplateMetaDataContents(templateMetadataContents); CalculationValueType calculationValueTypeOne = templateCalculationOne.ValueFormat.AsMatchingEnum <CalculationValueType>(); CalculationValueType calculationValueTypeTwo = templateCalculationTwo.ValueFormat.AsMatchingEnum <CalculationValueType>(); AndTheCalculationIsCreatedForRequestMatching(_ => _.Name == templateCalculationOne.Name && _.SourceCode == calculationValueTypeOne.GetDefaultSourceCode() && _.SpecificationId == _specificationId && _.FundingStreamId == _fundingStreamId && _.ValueType.GetValueOrDefault() == calculationValueTypeOne, NewCalculation(_ => _.WithId(newCalculationId4))); AndTheCalculationIsEditedForRequestMatching(_ => _.Name == newCalculationName1 && _.ValueType.GetValueOrDefault() == calculationValueFormat1.AsMatchingEnum <CalculationValueType>() && _.Description == null && _.SourceCode == null, calculationId1); AndTheCalculationIsCreatedForRequestMatching(_ => _.Name == templateCalculationTwo.Name && _.SourceCode == calculationValueTypeTwo.GetDefaultSourceCode() && _.SpecificationId == _specificationId && _.FundingStreamId == _fundingStreamId && _.ValueType.GetValueOrDefault() == calculationValueTypeTwo, NewCalculation(_ => _.WithId(newCalculationId5))); AndTheCalculationIsEditedForRequestMatching(_ => _.Name == newCalculationName2 && _.ValueType.GetValueOrDefault() == calculationValueFormat2.AsMatchingEnum <CalculationValueType>() && _.Description == null && _.SourceCode == null, calculationId2); AndTheTemplateContentsCalculation(mappingWithMissingCalculation1, templateMetadataContents, templateCalculationOne); AndTheTemplateContentsCalculation(mappingWithMissingCalculation2, templateMetadataContents, templateCalculationTwo); AndMissingCalculation(calculationId3, missingCalculation); AndTheCalculations(calculations); AndTheSpecificationIsReturned(); AndTheCalculationCodeOnCalculationChangeReturned(calculationId1, newCalculationName1, calculationName1, _specificationId, calculations.Where(_ => _.Id == calculationId1)); await WhenTheTemplateCalculationsAreApplied(); mappingWithMissingCalculation1 .CalculationId .Should().Be(newCalculationId4); mappingWithMissingCalculation2 .CalculationId .Should().Be(newCalculationId5); AndTheCalculationCodeOnCalculationChangeUpdated(calculationId1, newCalculationName1, calculationName1, _specificationId, 1); AndTheCalculationCodeOnCalculationChangeUpdated(calculationId2, newCalculationName2, calculationName2, _specificationId, 1); AndUpdateBuildProjectCalled(_specificationId, 2); AndTheTemplateMappingWasUpdated(templateMapping, 1); AndTheJobsStartWasLogged(); AndTheJobCompletionWasLogged(); AndACalculationRunWasInitialised(); AndACodeContextUpdateJobWasQueued(); }
private void GivenTheCalculation(string calculationId, Calculation calculation) => _calculations.Setup(_ => _.GetCalculationById(calculationId)) .ReturnsAsync(calculation);
public async Task LocatesRootFundingLinesContainingTheCalculation() { string calculationId = NewRandomString(); string specificationId = NewRandomString(); string fundingStreamId = NewRandomString(); string fundingPeriodId = NewRandomString(); string templateVersion = NewRandomString(); uint templateCalculationId = NewRandomNumber(); uint rootFundingLineOneId = NewRandomNumber(); string rootFundingLineOneName = NewRandomString(); uint rootFundingLineTwoId = NewRandomNumber(); string rootFundingLineTwoName = NewRandomString(); Calculation calculation = NewCalculation(_ => _.WithId(calculationId) .WithSpecificationId(specificationId) .WithFundingStreamId(fundingStreamId)); GivenTheCalculation(calculationId, calculation); AndTheSpecificationSummary(specificationId, NewSpecificationSummary(_ => _.WithTemplateVersions((fundingStreamId, templateVersion)) .WithFundingPeriodId(fundingPeriodId))); AndTheTemplateMapping(fundingStreamId, specificationId, NewTemplateMapping(_ => _.WithItems( NewTemplateMappingItem(ti => ti.WithCalculationId(calculationId) .WithTemplateId(templateCalculationId)), NewTemplateMappingItem(), NewTemplateMappingItem()))); AndTheTemplate(fundingStreamId, fundingPeriodId, templateVersion, NewTemplate(_ => _.WithFundingLines( NewTemplateFundingLine(fl => fl.WithTemplateId(rootFundingLineOneId) .WithName(rootFundingLineOneName) .WithCalculations(NewTemplateCalculation(cal => cal.WithTemplateCalculationId(templateCalculationId))) .WithFundingLines(NewTemplateFundingLine())), NewTemplateFundingLine(fl => fl.WithFundingLines(NewTemplateFundingLine(fl1 => fl1.WithCalculations( NewTemplateCalculation(cal => cal.WithCalculations(NewTemplateCalculation())))))), NewTemplateFundingLine(fl => fl.WithTemplateId(rootFundingLineTwoId) .WithName(rootFundingLineTwoName) .WithFundingLines(NewTemplateFundingLine(fl1 => fl1.WithCalculations( NewTemplateCalculation(cal => cal.WithCalculations(NewTemplateCalculation(cal1 => cal1.WithTemplateCalculationId(templateCalculationId))))))))))); OkObjectResult result = await WhenTheCalculationFundingLinesAreQueried(calculationId) as OkObjectResult; CalculationFundingLine[] expectedCalculationFundingLines = new[] { new CalculationFundingLine { TemplateId = rootFundingLineOneId, Name = rootFundingLineOneName }, new CalculationFundingLine { TemplateId = rootFundingLineTwoId, Name = rootFundingLineTwoName } }; result? .Value .Should() .BeEquivalentTo(expectedCalculationFundingLines); AndTheCalculationFundingLinesWereCached(GetCacheKey(specificationId, calculationId), expectedCalculationFundingLines); }