示例#1
0
        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();
        }
示例#3
0
        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");
        }
示例#4
0
        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());
        }
示例#5
0
        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));
        }
示例#6
0
 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
     });
 }
示例#7
0
        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);
        }
示例#8
0
        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");
        }
示例#9
0
        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();
        }
示例#13
0
 private void GivenTheCalculation(string calculationId,
                                  Calculation calculation)
 => _calculations.Setup(_ => _.GetCalculationById(calculationId))
 .ReturnsAsync(calculation);
示例#14
0
        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);
        }