private async Task TryCachePupilNumberTemplateCalculationIds(string cacheKey, string fundingStreamId, string fundingPeriodId, string templateVersion) { ApiResponse <TemplateMetadataContents> templateContentsResponse = await _policiesResilience.ExecuteAsync( () => _policies.GetFundingTemplateContents(fundingStreamId, fundingPeriodId, templateVersion)); if (!templateContentsResponse.StatusCode.IsSuccess()) { throw new InvalidOperationException("Cannot move pupil numbers to successor.\n" + $" Did not locate Template MetaData Contents for funding stream id {fundingStreamId} and template version {templateVersion}"); } TemplateMetadataContents templateMetadataContents = templateContentsResponse.Content; IEnumerable <FundingLine> flattenedFundingLines = templateMetadataContents.RootFundingLines .Flatten(_ => _.FundingLines) ?? new FundingLine[0]; IEnumerable <uint> pupilNumberTemplateCalculationIds = flattenedFundingLines.SelectMany(_ => _.Calculations.Flatten(cal => cal.Calculations)) .Where(_ => _.Type == CalculationType.PupilNumber) .Select(_ => _.TemplateCalculationId) .Distinct() .ToArray(); await _cachingResilience.ExecuteAsync(() => _caching.SetAsync(cacheKey, pupilNumberTemplateCalculationIds, TimeSpan.FromHours(24), false)); }
private void AndTheFundingTemplateContentsForPeriodAndStream(string fundingPeriodId, string fundingStreamId, string templateVersionId, TemplateMetadataContents templateContents) { GivenTheFundingTemplateContentsForPeriodAndStream(fundingPeriodId, fundingStreamId, templateVersionId, templateContents); }
public async Task <ISqlImportContext> CreateImportContext(string specificationId, string fundingStreamId, SchemaContext schemaContext) { ICosmosDbFeedIterator <PublishedProvider> publishedProviderFeed = GetPublishedProviderFeed(specificationId, fundingStreamId); TemplateMetadataContents template = await GetTemplateMetadataContents(specificationId, fundingStreamId); IEnumerable <FundingLine> allFundingLines = template.RootFundingLines.Flatten(_ => _.FundingLines); IEnumerable <Calculation> allCalculations = allFundingLines.SelectMany(_ => _.Calculations.Flatten(cal => cal.Calculations)); IEnumerable <Calculation> uniqueCalculations = allCalculations.DistinctBy(_ => _.TemplateCalculationId); IDictionary <uint, string> calculationNames = GetCalculationNames(uniqueCalculations); return(new SqlImportContext { Documents = publishedProviderFeed, CalculationNames = calculationNames, Calculations = new CalculationDataTableBuilder(uniqueCalculations), Providers = new ProviderDataTableBuilder(), Funding = new PublishedProviderVersionDataTableBuilder(), InformationFundingLines = new InformationFundingLineDataTableBuilder(), PaymentFundingLines = new PaymentFundingLineDataTableBuilder(), SchemaContext = schemaContext }); }
public async Task GenerateTotals_GivenValidTemplateMetadataContentsAndProvidersButMissingCalculations_EmptyGeneratedProviderResultsReturned() { //Arrange ILogger logger = CreateLogger(); ITemplateMetadataGenerator templateMetaDataGenerator = CreateTemplateGenerator(logger); TemplateMetadataContents contents = templateMetaDataGenerator.GetMetadata(GetResourceString("CalculateFunding.Services.Publishing.UnitTests.Resources.exampleFundingLineTemplate1.json")); IMapper mapper = CreateMapper(); FundingLineTotalAggregator fundingLineTotalAggregator = new FundingLineTotalAggregator(new Mock <IFundingLineRoundingSettings>().Object); TemplateMapping mapping = CreateTemplateMappings(); PublishedProviderDataGenerator publishedProviderDataGenerator = new PublishedProviderDataGenerator(logger, fundingLineTotalAggregator, mapper); //Act Dictionary <string, ProviderCalculationResult> providerCalculationResults = new Dictionary <string, ProviderCalculationResult>(); IDictionary <string, GeneratedProviderResult> generatedProviderResult = publishedProviderDataGenerator.Generate(contents, mapping, GetProviders(), providerCalculationResults); generatedProviderResult.Any() .Should() .BeFalse(); }
private async Task <UniqueTemplateContents> GetTemplateData(SpecificationSummary specification, string fundingStreamId) { UniqueTemplateContents uniqueTemplateContents = new UniqueTemplateContents(); TemplateMetadataContents templateMetadata = await GetTemplateMetadataContents(specification, fundingStreamId); if (templateMetadata == null) { throw new NonRetriableException( $"Did not locate template information for specification {specification.Id} in {fundingStreamId}. Unable to complete Qa Schema Generation"); } IEnumerable <FundingLine> flattenedFundingLines = templateMetadata.RootFundingLines.Flatten(_ => _.FundingLines) ?? new FundingLine[0]; IEnumerable <FundingLine> uniqueFundingLines = flattenedFundingLines.GroupBy(x => x.TemplateLineId) .Select(f => f.First()); IEnumerable <Calculation> flattenedCalculations = flattenedFundingLines.SelectMany(_ => _.Calculations.Flatten(cal => cal.Calculations)) ?? new Calculation[0]; IEnumerable <Calculation> uniqueFlattenedCalculations = flattenedCalculations.GroupBy(x => x.TemplateCalculationId) .Select(x => x.FirstOrDefault()); uniqueTemplateContents.FundingLines = uniqueFundingLines; uniqueTemplateContents.Calculations = uniqueFlattenedCalculations; return(uniqueTemplateContents); }
public async Task Assemble_GivenSpecificationWithTwoFundingStreamsButTemplateContentsNotFoundForOneFundingStream_ReturnsCollectionWithOneItem() { //Arrange TemplateMetadataContents templateMetadataContents = new TemplateMetadataContents(); SpecificationSummary specificationSummary = CreateSpecificationSummary(); IPoliciesApiClient policiesApiClient = CreatePoliciesClient(); policiesApiClient .GetFundingTemplateContents(Arg.Is("fs-1"), Arg.Is("fp-1"), Arg.Is("1.0")) .Returns(new ApiResponse <TemplateMetadataContents>(HttpStatusCode.OK, templateMetadataContents)); policiesApiClient .GetFundingTemplateContents(Arg.Is("fs-2"), Arg.Is("fp-1"), Arg.Is("1.0")) .Returns((ApiResponse <TemplateMetadataContents>)null); TemplateMetadataContentsAssemblerService templateMetadataContentsAssemblerService = CreateService(policiesApiClient: policiesApiClient); //Act var templateMetadataContentsCollection = await templateMetadataContentsAssemblerService.Assemble(specificationSummary); //Assert templateMetadataContentsCollection .Should() .HaveCount(1); templateMetadataContentsCollection .First().Value .Should() .Be(templateMetadataContents); }
public async Task Assemble_GivenSpecificationWithTwoFundingStreamsAndTemplatesFound_ReturnsCollectionWithTwoItems() { //Arrange TemplateMetadataContents templateMetadataContentsFs1 = new TemplateMetadataContents(); TemplateMetadataContents templateMetadataContentsFs2 = new TemplateMetadataContents(); SpecificationSummary specificationSummary = CreateSpecificationSummary(); IPoliciesApiClient policiesApiClient = CreatePoliciesClient(); policiesApiClient .GetFundingTemplateContents(Arg.Is("fs-1"), Arg.Is("fp-1"), Arg.Is("1.0")) .Returns(new ApiResponse <TemplateMetadataContents>(HttpStatusCode.OK, templateMetadataContentsFs1)); policiesApiClient .GetFundingTemplateContents(Arg.Is("fs-2"), Arg.Is("fp-1"), Arg.Is("1.0")) .Returns(new ApiResponse <TemplateMetadataContents>(HttpStatusCode.OK, templateMetadataContentsFs2)); TemplateMetadataContentsAssemblerService templateMetadataContentsAssemblerService = CreateService(policiesApiClient: policiesApiClient); //Act var templateMetadataContentsCollection = await templateMetadataContentsAssemblerService.Assemble(specificationSummary); //Assert templateMetadataContentsCollection .Should() .HaveCount(2); }
public async Task CachesPupilNumberTemplateCalculationsIfNotCachedForContext() { uint calculationOneId = NewRandomUint(); uint calculationTwoId = NewRandomUint(); uint calculationThreeId = NewRandomUint(); TemplateMetadataContents templateMapping = NewTemplateMetadataContents(_ => _.WithFundingLines(NewTemplateFundingLine(fl => fl.WithCalculations(NewTemplateCalculation(cl => cl.WithTemplateCalculationId(calculationOneId) .WithType(TemplateCalculationType.PupilNumber)), NewTemplateCalculation(cl => cl.WithTemplateCalculationId(calculationTwoId) .WithType(NewCalculationTypeExcept(TemplateCalculationType.PupilNumber)))) .WithFundingLines(NewTemplateFundingLine(fl2 => fl2.WithCalculations(NewTemplateCalculation(cl => cl.WithTemplateCalculationId(calculationThreeId) .WithType(TemplateCalculationType.PupilNumber)))))))); GivenTheTemplateMetadataContents(templateMapping); AndTheFundingCalculations(NewFundingCalculation(_ => _.WithTemplateCalculationId(calculationOneId) .WithValue(calculationOneId)), NewFundingCalculation(), NewFundingCalculation(_ => _.WithTemplateCalculationId(calculationTwoId) .WithValue(calculationThreeId))); AndTheSuccessorFundingCalculations(NewFundingCalculation(_ => _.WithTemplateCalculationId(calculationOneId) .WithValue(calculationOneId)), NewFundingCalculation(), NewFundingCalculation(_ => _.WithTemplateCalculationId(calculationTwoId) .WithValue(calculationThreeId))); await WhenTheChangeIsApplied(); ThenTheTemplateCalculationIdsWereCached(calculationThreeId, calculationOneId); }
public void ThrowsExceptionWhenContentGeneratorReturnsNull() { // Arrange TemplateMetadataContents templateMetadataContents = Substitute.For <TemplateMetadataContents>(); TemplateMapping templateMapping = Substitute.For <TemplateMapping>(); IPublishedProviderContentsGenerator publishedProviderContentsGenerator = Substitute.For <IPublishedProviderContentsGenerator>(); Dictionary <string, GeneratedProviderResult> generatedPublishedProviderData = new Dictionary <string, GeneratedProviderResult>(); List <PublishedProvider> publishedProvidersToUpdate = new List <PublishedProvider>(); GeneratedProviderResult generatedProviderResult = new GeneratedProviderResult(); PublishedProviderVersion publishedProviderVersion = NewPublishedProviderVersion(providerVersion => providerVersion .WithProviderId(ProviderVersionProviderId) .WithFundingPeriodId(ProviderVersionFundingPeriodId) .WithFundingStreamId(ProviderVersionFundingStreamId) .WithVersion(ProviderVersionVersion)); PublishedProvider publishedProvider = NewPublishedProvider(provider => provider.WithCurrent(publishedProviderVersion)); generatedPublishedProviderData.Add(key, generatedProviderResult); publishedProvidersToUpdate.Add(publishedProvider); // Act Func <Task> invocation = async() => await _publishedProviderContentPersistanceService.SavePublishedProviderContents( templateMetadataContents, templateMapping, publishedProvidersToUpdate, publishedProviderContentsGenerator); // Assert ThenExceptionShouldBeThrown($"Generator failed to generate content for published provider version with id: '{publishedProviderVersion.Id}'", invocation); }
public string GenerateContents(PublishedFundingVersion publishedFundingVersion, TemplateMetadataContents templateMetadataContents) { Guard.ArgumentNotNull(publishedFundingVersion, nameof(publishedFundingVersion)); Guard.ArgumentNotNull(templateMetadataContents, nameof(templateMetadataContents)); SchemaJson contents = new SchemaJson { Schema = "https://fundingschemas.blob.core.windows.net/schemas/logicalmodel-1.0.json#schema", SchemaVersion = publishedFundingVersion.SchemaVersion, Funding = new { publishedFundingVersion.TemplateVersion, Id = publishedFundingVersion.FundingId, FundingVersion = $"{publishedFundingVersion.MajorVersion}_{publishedFundingVersion.MinorVersion}", Status = publishedFundingVersion.Status.ToString(), FundingStream = new { Code = publishedFundingVersion.FundingStreamId, Name = publishedFundingVersion.FundingStreamName }, FundingPeriod = new { publishedFundingVersion.FundingPeriod.Id, publishedFundingVersion.FundingPeriod.Period, publishedFundingVersion.FundingPeriod.Name, Type = publishedFundingVersion.FundingPeriod.Type.ToString(), publishedFundingVersion.FundingPeriod.StartDate, publishedFundingVersion.FundingPeriod.EndDate }, OrganisationGroup = new { GroupTypeCode = publishedFundingVersion.OrganisationGroupTypeCode, GroupTypeIdentifier = publishedFundingVersion.OrganisationGroupTypeIdentifier, IdentifierValue = publishedFundingVersion.OrganisationGroupIdentifierValue, GroupTypeClassification = publishedFundingVersion.OrganisationGroupTypeClassification, Name = publishedFundingVersion.OrganisationGroupName, SearchableName = publishedFundingVersion.OrganisationGroupSearchableName, Identifiers = publishedFundingVersion.OrganisationGroupIdentifiers?.Select(groupTypeIdentifier => new { groupTypeIdentifier.Type, groupTypeIdentifier.Value }).ToArray() }, FundingValue = new { TotalValue = publishedFundingVersion.TotalFunding, FundingLines = templateMetadataContents.RootFundingLines?.Select(_ => BuildSchemaJsonFundingLines(publishedFundingVersion.ReferenceData, publishedFundingVersion.Calculations, publishedFundingVersion.FundingLines, _, publishedFundingVersion.OrganisationGroupTypeIdentifier, publishedFundingVersion.OrganisationGroupIdentifierValue)) }, ProviderFundings = publishedFundingVersion.ProviderFundings?.ToArray(), publishedFundingVersion.GroupingReason, publishedFundingVersion.StatusChangedDate, publishedFundingVersion.ExternalPublicationDate, publishedFundingVersion.EarliestPaymentAvailableDate, VariationReasons = publishedFundingVersion.VariationReasons?.ToArray() } }; return(contents.AsJson()); }
private void GivenTheFundingTemplateContentsForPeriodAndStream(string fundingPeriodId, string fundingStreamId, string templateVersionId, TemplateMetadataContents templateContents) { _policies.GetFundingTemplateContents(fundingStreamId, fundingPeriodId, templateVersionId) .Returns(new ApiResponse <TemplateMetadataContents>(HttpStatusCode.OK, templateContents)); }
public void TemplateMetadataSchema10_GetInvalidMetaData_ReturnsEmptyContents() { TemplateMetadataContents contents = WhenTheMetadataContentsIsGenerated("CalculateFunding.TemplateMetadata.Schema10.UnitTests.Resources.dsg1.0.error.json"); logger .Received(1) .Error(Arg.Is <Exception>(x => x.GetType().Name == "JsonSerializationException"), Arg.Any <string>()); }
private IEnumerable <AggregateFundingLine> WhenTheSchema1_1FundingLinesAreAggregated() { ITemplateMetadataGenerator templateMetaDataGenerator = CreateSchema11TemplateGenerator(); _contents = templateMetaDataGenerator.GetMetadata(GetResourceString("CalculateFunding.Services.Publishing.UnitTests.Resources.exampleProviderTemplate1_Schema1_1.json")); return(_fundingValueAggregator.GetTotals(_contents, GetProviderVersions("_Schema1_1"))); }
public async Task <PublishedFundingInput> GeneratePublishedFundingInput(IDictionary <string, PublishedProvider> publishedProvidersForFundingStream, IEnumerable <Provider> scopedProviders, Reference fundingStream, SpecificationSummary specification, IEnumerable <PublishedProvider> publishedProvidersInScope) { Guard.ArgumentNotNull(publishedProvidersForFundingStream, nameof(publishedProvidersForFundingStream)); Guard.ArgumentNotNull(scopedProviders, nameof(scopedProviders)); Guard.ArgumentNotNull(fundingStream, nameof(fundingStream)); Guard.ArgumentNotNull(specification, nameof(specification)); _logger.Information($"Fetching existing published funding"); // Get latest version of existing published funding IEnumerable <PublishedFunding> publishedFunding = await _publishingResiliencePolicy.ExecuteAsync(() => _publishedFundingDataService.GetCurrentPublishedFunding(fundingStream.Id, specification.FundingPeriod.Id)); _logger.Information($"Fetched {publishedFunding.Count()} existing published funding items"); _logger.Information($"Generating organisation groups"); FundingConfiguration fundingConfiguration = await _policiesService.GetFundingConfiguration(fundingStream.Id, specification.FundingPeriod.Id); TemplateMetadataContents templateMetadataContents = await ReadTemplateMetadataContents(fundingStream, specification); // Foreach group, determine the provider versions required to be latest IEnumerable <OrganisationGroupResult> organisationGroups = await _organisationGroupGenerator.GenerateOrganisationGroup(fundingConfiguration, _mapper.Map <IEnumerable <ApiProvider> >(scopedProviders), specification.ProviderVersionId, specification.ProviderSnapshotId); // filter out organisation groups which don't contain a provider which is in scope if (!publishedProvidersInScope.IsNullOrEmpty()) { HashSet <string> publishedProviderIdsInScope = new HashSet <string>(publishedProvidersInScope.DistinctBy(_ => _.Current.ProviderId).Select(_ => _.Current.ProviderId)); organisationGroups = organisationGroups.Where(_ => _.Providers.Any(provider => publishedProviderIdsInScope.Contains(provider.ProviderId))); } _logger.Information($"A total of {organisationGroups.Count()} were generated"); _logger.Information($"Generating organisation groups to save"); // Compare existing published provider versions with existing current PublishedFundingVersion IEnumerable <(PublishedFunding PublishedFunding, OrganisationGroupResult OrganisationGroupResult)> organisationGroupsToSave = _publishedFundingChangeDetectorService.GenerateOrganisationGroupsToSave(organisationGroups, publishedFunding, publishedProvidersForFundingStream); _logger.Information($"A total of {organisationGroupsToSave.Count()} organisation groups returned to save"); // Generate PublishedFundingVersion for new and updated PublishedFundings return(new PublishedFundingInput() { OrganisationGroupsToSave = organisationGroupsToSave, TemplateMetadataContents = templateMetadataContents, TemplateVersion = specification.TemplateIds[fundingStream.Id], FundingStream = fundingStream, FundingPeriod = await _policiesService.GetFundingPeriodByConfigurationId(specification.FundingPeriod.Id), PublishingDates = await _publishedFundingDateService.GetDatesForSpecification(specification.Id), SpecificationId = specification.Id, }); }
public async Task SavePublishedProviderContents(TemplateMetadataContents templateMetadataContents, TemplateMapping templateMapping, IEnumerable <PublishedProvider> publishedProvidersToUpdate, IPublishedProviderContentsGenerator generator, bool publishAll = false) { _logger.Information("Saving published provider contents"); List <Task> allTasks = new List <Task>(); SemaphoreSlim throttler = new SemaphoreSlim(initialCount: _publishingEngineOptions.SavePublishedProviderContentsConcurrencyCount); foreach (PublishedProvider provider in publishedProvidersToUpdate) { await throttler.WaitAsync(); allTasks.Add( Task.Run(async() => { try { IEnumerable <PublishedProviderVersion> publishedProviderVersions = publishAll ? await _publishedProviderVersioningService.GetVersions(provider) : new[] { provider.Current }; foreach (PublishedProviderVersion publishedProviderVersion in publishedProviderVersions) { string contents = generator.GenerateContents(publishedProviderVersion, templateMetadataContents, templateMapping); if (string.IsNullOrWhiteSpace(contents)) { throw new RetriableException($"Generator failed to generate content for published provider version with id: '{publishedProviderVersion.Id}'"); } try { await _publishedProviderVersionService.SavePublishedProviderVersionBody( publishedProviderVersion.FundingId, contents, publishedProviderVersion.SpecificationId); } catch (Exception ex) { throw new RetriableException(ex.Message); } try { await _publishedProviderIndexerService.IndexPublishedProvider(publishedProviderVersion); } catch (Exception ex) { throw new RetriableException(ex.Message); } } } finally { throttler.Release(); } })); } await TaskHelper.WhenAllAndThrow(allTasks.ToArray()); }
public void GeneratesJsonConformingToThe11Schema() { TemplateMetadataContents templateMetadataContents = GetTemplateMetaDataContents("example-funding-template1.1.json"); PublishedFundingVersion publishedFundingVersion = GetPublishedFundingVersion("example-published-funding-version.json"); string funding = WhenThePublishedFundingVersionIsTransformed(publishedFundingVersion, templateMetadataContents); ThenTheJsonValidatesAgainstThe1_1FundingSchema(funding); }
protected void AndTheTemplateMetadataContents(string schemaVersion, string templateContents, TemplateMetadataContents templateMetadataContents) { TemplateMetadataResolver.Setup(_ => _.GetService(schemaVersion)) .Returns(TemplateMetadataGenerator.Object); TemplateMetadataGenerator.Setup(_ => _.GetMetadata(templateContents)) .Returns(templateMetadataContents); }
private void AndTheTemplate(string fundingStreamId, string fundingPeriodId, string templateVersion, TemplateMetadataContents template) => _templates.Setup(_ => _.GetFundingTemplateContents(fundingStreamId, fundingPeriodId, templateVersion, null)) .ReturnsAsync(new ApiResponse <TemplateMetadataContents>(HttpStatusCode.OK, template));
public void GenerateTotals_GivenValidTemplateMetadataContentsAndCalculations_ReturnsFundingLines() { //Arrange ILogger logger = CreateLogger(); ITemplateMetadataGenerator templateMetaDataGenerator = CreateTemplateGenerator(logger); TemplateMetadataContents contents = templateMetaDataGenerator.GetMetadata(GetResourceString("CalculateFunding.Services.Publishing.UnitTests.Resources.exampleFundingLineTemplate1.json")); Mock <IFundingLineRoundingSettings> rounding = new Mock <IFundingLineRoundingSettings>(); rounding.Setup(_ => _.DecimalPlaces) .Returns(2); FundingLineTotalAggregator fundingLineTotalAggregator = new FundingLineTotalAggregator(rounding.Object); TemplateMapping mapping = CreateTemplateMappings(); //Act GeneratorModels.FundingValue fundingValue = fundingLineTotalAggregator.GenerateTotals(contents, mapping.TemplateMappingItems.ToDictionary(_ => _.TemplateId), CreateCalculations(mapping).ToDictionary(_ => _.Id)); IEnumerable <GeneratorModels.FundingLine> fundingLines = fundingValue.FundingLines.Flatten(_ => _.FundingLines); //Assert fundingLines.Single(_ => _.TemplateLineId == 1).Value .Should() .Be(16200.64M); fundingLines.Single(_ => _.TemplateLineId == 2).Value .Should() .Be(8000M); fundingLines.Single(_ => _.TemplateLineId == 3).Value .Should() .Be(3200M); fundingLines.Single(_ => _.TemplateLineId == 4).Value .Should() .Be(5000.64M); fundingLines.Single(_ => _.TemplateLineId == 5).Value .Should() .Be(null); fundingLines.Single(_ => _.TemplateLineId == 6).Value .Should() .Be(8000M); fundingLines.Single(_ => _.TemplateLineId == 7).Value .Should() .Be(500M); fundingLines.Single(_ => _.TemplateLineId == 8).Value .Should() .Be(1200M); }
public IEnumerable <CalculationFundingLine> GetCalculationFundingLines(TemplateMetadataContents template, uint templateId) => template.RootFundingLines? .Where(_ => ContainsCalculation(_, templateId)) .Select(_ => new CalculationFundingLine { TemplateId = _.TemplateLineId, Name = _.Name }) .ToArray();
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 async Task <TemplateMetadataContents> ReadTemplateMetadataContents(Reference fundingStream, SpecificationSummary specification) { TemplateMetadataContents templateMetadataContents = await _policiesService.GetTemplateMetadataContents(fundingStream.Id, specification.FundingPeriod.Id, specification.TemplateIds[fundingStream.Id]); if (templateMetadataContents == null) { throw new NonRetriableException($"Unable to get template metadata contents for funding stream. '{fundingStream.Id}'"); } return(templateMetadataContents); }
private void AndTheTemplateContentsCalculation(TemplateMappingItem mappingItem, TemplateMetadataContents templateMetadataContents, TemplateCalculation calculation) { calculation.TemplateCalculationId = mappingItem.TemplateId; FundingLine fundingLine = templateMetadataContents.RootFundingLines.First(); fundingLine.Calculations = fundingLine.Calculations.Concat(new[] { calculation }); }
public async Task CreatesDDLMatchingSpecificationFundingAndReCreatesSchemaObjectsInQaRepository() { string specificationId = NewRandomString(); string fundingStreamId = NewRandomString(); string fundingPeriodId = NewRandomString(); string templateVersion = NewRandomString(); string schemaVersion = NewRandomString(); string fundingTemplateContents = NewRandomString(); Calculation calculationOne = NewCalculation(); Calculation calculationTwo = NewCalculation(); Calculation calculationThree = NewCalculation(); Calculation calculationFour = NewCalculation(_ => _.WithCalculations(calculationOne)); Calculation calculationFive = NewCalculation(_ => _.WithCalculations(calculationTwo)); string fundingLineOneCode = NewRandomString(); string fundingLineTwoCode = NewRandomString(); SpecificationSummary specificationSummary = NewSpecificationSummary(_ => _.WithId(specificationId) .WithFundingStreamIds(fundingStreamId) .WithFundingPeriodId(fundingPeriodId) .WithTemplateIds((fundingStreamId, templateVersion))); FundingTemplateContents fundingTemplate = NewFundingTemplateContents(_ => _.WithSchemaVersion(schemaVersion) .WithTemplateFileContents(fundingTemplateContents)); TemplateMetadataContents templateMetadataContents = NewTemplateMetadataContents(_ => _.WithFundingLines( NewFundingLine(fl => fl.WithCalculations(calculationFour, calculationFive) .WithFundingLineCode(fundingLineOneCode) .WithFundingLines(NewFundingLine(fl1 => fl1.WithCalculations(calculationThree) .WithFundingLineCode(fundingLineTwoCode))) ))); FundingStreamPeriodProfilePattern profilePatternOne = NewFundingStreamPeriodProfilePattern(_ => _.WithFundingPeriodId(fundingPeriodId) .WithFundingStreamId(fundingStreamId) .WithFundingLineId(fundingLineOneCode)); FundingStreamPeriodProfilePattern profilePatternTwo = NewFundingStreamPeriodProfilePattern(_ => _.WithFundingPeriodId(fundingPeriodId) .WithFundingStreamId(fundingStreamId) .WithFundingLineId(fundingLineTwoCode)); GivenTheSpecification(specificationId, specificationSummary); AndTheFundingTemplate(fundingStreamId, fundingPeriodId, templateVersion, fundingTemplate); AndTheTemplateMetadataContents(schemaVersion, fundingTemplateContents, templateMetadataContents); AndTheProfiling(fundingStreamId, fundingPeriodId, profilePatternOne, profilePatternTwo); await WhenTheSchemaIsRecreated(specificationId, fundingStreamId); ThenTheTotalNumberOfDDLScriptsExecutedWas(32); }
private async Task <IActionResult> GetPublishedProviderFundingStructure(PublishedProviderVersion publishedProviderVersion) { Guard.ArgumentNotNull(publishedProviderVersion, nameof(publishedProviderVersion)); string specificationId = publishedProviderVersion.SpecificationId; string fundingStreamId = publishedProviderVersion.FundingStreamId; string fundingPeriodId = publishedProviderVersion.FundingPeriodId; SpecificationSummary specificationSummary = await _specificationService.GetSpecificationSummaryById(specificationId); if (specificationSummary == null) { return(new NotFoundObjectResult($"Specification not found for SpecificationId - {specificationId}")); } string templateVersion = specificationSummary.TemplateIds.ContainsKey(fundingStreamId) ? specificationSummary.TemplateIds[fundingStreamId] : null; if (templateVersion == null) { return(new InternalServerErrorResult($"Specification contains no matching template version for funding stream '{fundingStreamId}'")); } TemplateMetadataContents fundingTemplateContents = await _policiesService.GetTemplateMetadataContents(fundingStreamId, fundingPeriodId, templateVersion); if (fundingTemplateContents == null) { return(new InternalServerErrorResult($"Unable to locate funding template contents for {fundingStreamId} {fundingPeriodId} {templateVersion}")); } TemplateMapping templateMapping = await _calculationsService.GetTemplateMapping(specificationId, fundingStreamId); List <PublishedProviderFundingStructureItem> fundingStructures = new List <PublishedProviderFundingStructureItem>(); RecursivelyAddFundingLineToFundingStructure( fundingStructures, fundingTemplateContents.RootFundingLines, templateMapping.TemplateMappingItems.ToList(), publishedProviderVersion); PublishedProviderFundingStructure fundingStructure = new PublishedProviderFundingStructure { Items = fundingStructures, PublishedProviderVersion = publishedProviderVersion.Version }; return(new OkObjectResult(fundingStructure)); }
private void AndTemplateMetadataContents() { _calculationTemplateIds = new[] { NewTemplateCalculation(), NewTemplateCalculation(), NewTemplateCalculation() }; _fundingLines = new[] { NewTemplateFundingLine(fl => fl.WithCalculations(_calculationTemplateIds)) }; _templateMetadataContents = NewTemplateMetadataContents(_ => _.WithFundingLines(_fundingLines)); _policiesService .GetTemplateMetadataContents(FundingStreamId, _specificationSummary.FundingPeriod.Id, _specificationSummary.TemplateIds[FundingStreamId]) .Returns(_templateMetadataContents); }
public void TemplateMetadataSchema10_GetValidMetaData_ReturnsValidContents() { TemplateMetadataContents contents = WhenTheMetadataContentsIsGenerated("CalculateFunding.TemplateMetadata.Schema10.UnitTests.Resources.dsg1.0.json"); contents.RootFundingLines.Count() .Should() .Be(2); contents.RootFundingLines.First().Name .Should() .Be("Prior To Recoupment"); contents.RootFundingLines.First().Type .Should() .Be(FundingLineType.Information); contents.RootFundingLines.Last().Name .Should() .Be("Post Deduction For Recoupment And High Needs"); contents.RootFundingLines.Last().FundingLineCode .Should() .Be("PostDeductionForRecoupmentAndHighNeeds"); contents.RootFundingLines.Last().Calculations.First().ValueFormat .Should() .Be(CalculationValueFormat.Number); contents.RootFundingLines.Last().Calculations.First().AggregationType .Should() .Be(AggregationType.Sum); contents.RootFundingLines.Last().Calculations.First().Type .Should() .Be(CalculationType.PupilNumber); contents.RootFundingLines.Last().Calculations.First().ReferenceData.First().AggregationType .Should() .Be(AggregationType.Sum); contents.RootFundingLines.Last().Calculations.First().ReferenceData.First().Format .Should() .Be(ReferenceDataValueFormat.Number); contents.SchemaVersion .Should() .Be("1.0"); }
public void ThrowsExceptionIfCreateCallFailsWhenCreatingMissingCalculations() { TemplateMappingItem mappingWithMissingCalculation1 = NewTemplateMappingItem(); TemplateMapping templateMapping = NewTemplateMapping(_ => _.WithItems(mappingWithMissingCalculation1)); TemplateMetadataContents templateMetadataContents = NewTemplateMetadataContents(_ => _.WithFundingLines(NewFundingLine(fl => fl.WithCalculations(NewTemplateMappingCalculation())))); TemplateCalculation templateCalculationOne = NewTemplateMappingCalculation(_ => _.WithName("template calculation 1")); GivenAValidMessage(); AndTheJobCanBeRun(); AndTheTemplateMapping(templateMapping); AndTheTemplateMetaDataContents(templateMetadataContents); AndTheTemplateContentsCalculation(mappingWithMissingCalculation1, templateMetadataContents, templateCalculationOne); AndTheSpecificationIsReturned(); ThenAnExceptionShouldBeThrownWithMessage("Unable to create new default template calculation for template mapping"); }
public async Task <ActionResult <TemplateMetadataFundingLineCashCalculationsContents> > GetCashCalcsForTemplateVersion(string fundingStreamId, string fundingPeriodId, string templateVersion) { ActionResult <TemplateMetadataContents> templateMetadata = await GetFundingTemplateContentMetadata(fundingStreamId, fundingPeriodId, templateVersion); if (templateMetadata.Result != null) { return(templateMetadata.Result); } TemplateMetadataContents templateMetadataContents = templateMetadata.Value; IEnumerable <FundingLine> flattenedFundingLines = templateMetadataContents.RootFundingLines.Flatten(x => x.FundingLines); IEnumerable <Calculation> flatternedCalculations = flattenedFundingLines.SelectMany(fl => fl.Calculations.Flatten(cal => cal.Calculations)); IEnumerable <FundingLine> uniqueFundingLines = flattenedFundingLines.DistinctBy(f => f.TemplateLineId); IOrderedEnumerable <FundingLine> paymentFundingLine = uniqueFundingLines.Where(f => f.Type == Common.TemplateMetadata.Enums.FundingLineType.Payment).OrderBy(f => f.FundingLineCode); Dictionary <string, IEnumerable <TemplateMetadataCalculation> > cashCalculations = new Dictionary <string, IEnumerable <TemplateMetadataCalculation> >(); List <TemplateMetadataFundingLine> fundingLineResults = new List <TemplateMetadataFundingLine>(paymentFundingLine.Count()); foreach (FundingLine fundingLine in paymentFundingLine) { fundingLineResults.Add(new TemplateMetadataFundingLine() { FundingLineCode = fundingLine.FundingLineCode, Name = fundingLine.Name, TemplateLineId = fundingLine.TemplateLineId, Type = Common.TemplateMetadata.Enums.FundingLineType.Payment, }); List <TemplateMetadataCalculation> cashCalculationsForFundingLines = FindCashCalculations(fundingLine); cashCalculations.Add(fundingLine.FundingLineCode, cashCalculationsForFundingLines.OrderBy(_ => _.Name)); } return(new TemplateMetadataFundingLineCashCalculationsContents() { FundingPeriodId = fundingPeriodId, FundingStreamId = fundingStreamId, SchemaVersion = templateMetadata.Value.SchemaVersion, TemplateVersion = templateMetadata.Value.TemplateVersion, FundingLines = fundingLineResults, CashCalculations = cashCalculations, }); }
private async Task <ActionResult <TemplateMetadataContents> > GetFundingTemplateContentMetadata(string fundingStreamId, string fundingPeriodId, string templateVersion) { TemplateMetadataContents fundingTemplateContentMetadata = await _cacheProvider.GetAsync <TemplateMetadataContents>($"{CacheKeys.FundingTemplateContentMetadata}{fundingStreamId}:{fundingPeriodId}:{templateVersion}"); if (fundingTemplateContentMetadata == null) { ActionResult <string> fundingTemplateContentSourceFileResult = await GetFundingTemplateSourceFile(fundingStreamId, fundingPeriodId, templateVersion); if (fundingTemplateContentSourceFileResult.Result != null) { return(fundingTemplateContentSourceFileResult.Result); } string fundingTemplateContentSourceFile = fundingTemplateContentSourceFileResult.Value; ActionResult <string> fundingTemplateValidationResult = GetFundingTemplateSchemaVersion(fundingTemplateContentSourceFile); if (fundingTemplateValidationResult.Result != null) { return(fundingTemplateValidationResult.Result); } string fundingTemplateSchemaVersion = fundingTemplateValidationResult.Value; bool templateMetadataGeneratorRetrieved = _templateMetadataResolver.TryGetService(fundingTemplateSchemaVersion, out ITemplateMetadataGenerator templateMetadataGenerator); if (!templateMetadataGeneratorRetrieved) { string message = $"Template metadata generator with given schema {fundingTemplateSchemaVersion} could not be retrieved."; _logger.Error(message); return(new PreconditionFailedResult(message)); } string blobName = GetBlobNameFor(fundingStreamId, fundingPeriodId, templateVersion); fundingTemplateContentMetadata = templateMetadataGenerator.GetMetadata(fundingTemplateContentSourceFile); fundingTemplateContentMetadata.FundingStreamId = fundingStreamId; fundingTemplateContentMetadata.FundingPeriodId = fundingPeriodId; fundingTemplateContentMetadata.TemplateVersion = templateVersion; fundingTemplateContentMetadata.LastModified = await _fundingTemplateRepositoryPolicy.ExecuteAsync(() => _fundingTemplateRepository.GetLastModifiedDate(blobName)); await _cacheProvider.SetAsync($"{CacheKeys.FundingTemplateContentMetadata}{fundingStreamId}:{fundingPeriodId}:{templateVersion}", fundingTemplateContentMetadata); } return(fundingTemplateContentMetadata); }