public async Task GetFundingStructure_GivenNoSpecificationFoundForPublishedProviderVersion_ReturnsNotFound() { string publishedProviderVersionId = NewRandomString(); string specificationId = NewRandomString(); string fundingPeriodId = NewRandomString(); string providerId = NewRandomString(); string fundingStreamId = NewRandomString(); int templateVersion = NewRandomNumber(); PublishedProviderVersion publishedProviderVersion = NewPublishedProviderVersion(_ => _ .WithFundingStreamId(fundingStreamId) .WithFundingPeriodId(fundingPeriodId) .WithProviderId(providerId) .WithSpecificationId(specificationId)); _publishedFundingRepository.GetPublishedProviderVersionById(publishedProviderVersionId) .Returns(publishedProviderVersion); _specificationService.GetSpecificationSummaryById(specificationId) .Returns((SpecificationSummary)null); var result = await _service.GetPublishedProviderFundingStructure(publishedProviderVersionId); NotFoundObjectResult notFoundObjectResult = result.Should() .BeAssignableTo <NotFoundObjectResult>() .Which .As <NotFoundObjectResult>(); notFoundObjectResult.Value .Should() .Be($"Specification not found for SpecificationId - {specificationId}"); }
public async Task <IEnumerable <PublishedProvider> > GetPublishedProvidersForApproval(string specificationId, string[] publishedProviderIds = null) { Guard.IsNullOrWhiteSpace(specificationId, nameof(specificationId)); SpecificationSummary specificationSummary = await _specificationsRepositoryPolicy.ExecuteAsync( () => _specificationService.GetSpecificationSummaryById(specificationId)); ConcurrentBag <PublishedProvider> results = new ConcurrentBag <PublishedProvider>(); string fundingPeriodId = specificationSummary?.FundingPeriod?.Id; if (fundingPeriodId.IsNullOrWhitespace()) { string error = "Could not locate a funding period from the supplied funding period id on the specification summary"; throw new InvalidOperationException(error); } List <KeyValuePair <string, string> > allPublishedProviderIds = new List <KeyValuePair <string, string> >(); foreach (Common.Models.Reference fundingStream in specificationSummary.FundingStreams) { IEnumerable <KeyValuePair <string, string> > publishedProviders = await _publishedFundingRepositoryPolicy.ExecuteAsync( () => _publishedFundingRepository.GetPublishedProviderIdsForApproval(fundingStream.Id, fundingPeriodId, publishedProviderIds)); allPublishedProviderIds.AddRange(publishedProviders); } return(await _publishedFundingBulkRepository.GetPublishedProviders(allPublishedProviderIds)); }
private void AndTheSpecificationSummaryIsRetrieved(SpecificationSummary specificationSummary) { _specificationSummary = specificationSummary; _specificationService .GetSpecificationSummaryById(Arg.Is(_specificationId)) .Returns(_specificationSummary); }
public async Task <IActionResult> GetLatestPublishedProvidersForSpecificationId(string specificationId) { ValidationResult validationResults = _validator.Validate(specificationId); if (!validationResults.IsValid) { return(validationResults.AsBadRequest()); } SpecificationSummary specificationSummary = await _specificationService.GetSpecificationSummaryById(specificationId); List <PublishedProviderVersion> results = new List <PublishedProviderVersion>(); foreach (var fundingStream in specificationSummary.FundingStreams) { IEnumerable <PublishedProvider> publishedProviders = await _resiliencePolicy.ExecuteAsync(() => _publishedFunding.GetCurrentPublishedProviders(fundingStream.Id, specificationSummary.FundingPeriod.Id)); if (publishedProviders.AnyWithNullCheck()) { results.AddRange(publishedProviders.Select(_ => _.Current)); } } return(new OkObjectResult(results)); }
public async Task CheckChooseForFundingStatus_GivenNoSpecSummariesFoundForFundingPeriodId_ReturnsCanChoose() { //Arrange SpecificationSummary specificationSummary = new SpecificationSummary { FundingPeriod = new Reference { Id = fundingPeriodId } }; ISpecificationService specificationService = CreateSpecificationService(); specificationService .GetSpecificationSummaryById(Arg.Is(specificationId)) .Returns(specificationSummary); specificationService .GetSpecificationsSelectedForFundingByPeriod(Arg.Is(fundingPeriodId)) .Returns((IEnumerable <SpecificationSummary>)null); SpecificationFundingStatusService specificationFundingStatusService = CreateSpecificationFundingStatusService(specificationService: specificationService); //Act SpecificationFundingStatus status = await specificationFundingStatusService.CheckChooseForFundingStatus(specificationId); //Assert status .Should() .Be(SpecificationFundingStatus.CanChoose); }
public void CheckChooseForFundingStatus_GivenSpecificationSummaryNotFound_ThrowsEntityNotFoundException() { //Arrange SpecificationSummary specificationSummary = null; string errorMessage = $"Failed to find specification with for specification Id '{specificationId}'"; ILogger logger = CreateLogger(); ISpecificationService specificationService = CreateSpecificationService(); specificationService .GetSpecificationSummaryById(Arg.Is(specificationId)) .Returns(specificationSummary); SpecificationFundingStatusService specificationFundingStatusService = CreateSpecificationFundingStatusService(logger, specificationService); //Act Func <Task> test = async() => await specificationFundingStatusService.CheckChooseForFundingStatus(specificationId); //Assert test .Should() .ThrowExactly <EntityNotFoundException>() .Which .Message .Should() .Be(errorMessage); logger .Received(1) .Error(Arg.Is(errorMessage)); }
public async Task CheckChooseForFundingStatus_GivenSpecWIthMultipleFundingStreamsAndSpecsReturnedForFundingPeriodWithSameFundingStream_ReturnsSharesAlreadyChoseFundingStream() { //Arrange SpecificationSummary specificationSummary = new SpecificationSummary { FundingPeriod = new Reference { Id = fundingPeriodId }, FundingStreams = new[] { new Reference("fs-2", "fs2"), new Reference("fs-4", "fs4") } }; IEnumerable <SpecificationSummary> specificationSummaries = new[] { new SpecificationSummary { FundingStreams = new[] { new Reference("fs-1", "fs1"), new Reference("fs-5", "fs5"), } }, new SpecificationSummary { FundingStreams = new[] { new Reference("fs-3", "fs3"), new Reference("fs-4", "fs4"), } } }; ISpecificationService specificationService = CreateSpecificationService(); specificationService .GetSpecificationSummaryById(Arg.Is(specificationId)) .Returns(specificationSummary); specificationService .GetSpecificationsSelectedForFundingByPeriod(Arg.Is(fundingPeriodId)) .Returns(specificationSummaries); SpecificationFundingStatusService specificationFundingStatusService = CreateSpecificationFundingStatusService(specificationService: specificationService); //Act SpecificationFundingStatus status = await specificationFundingStatusService.CheckChooseForFundingStatus(specificationId); //Assert status .Should() .Be(SpecificationFundingStatus.SharesAlreadyChosenFundingStream); }
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)); }
public async Task <SpecificationFundingStatus> CheckChooseForFundingStatus(string specificationId) { Guard.IsNullOrWhiteSpace(specificationId, nameof(specificationId)); SpecificationSummary specificationSummary = await _specificationService.GetSpecificationSummaryById(specificationId); if (specificationSummary == null) { string errorMessage = $"Failed to find specification with for specification Id '{specificationId}'"; _logger.Error(errorMessage); throw new EntityNotFoundException(errorMessage, nameof(SpecificationSummary)); } return(await CheckChooseForFundingStatus(specificationSummary)); }
public async Task PublishProviderFundingResults(Message message, bool batched = false) { Guard.ArgumentNotNull(message, nameof(message)); string logMessage = batched ? "Batch" : "All"; _logger.Information($"Starting Publish{logMessage}ProviderFundingResults job"); Reference author = message.GetUserDetails(); string specificationId = message.UserProperties["specification-id"] as string; SpecificationSummary specification = await _specificationService.GetSpecificationSummaryById(specificationId); if (specification == null) { throw new NonRetriableException($"Could not find specification with id '{specificationId}'"); } string correlationId = message.GetUserProperty <string>(SfaCorrelationId); PublishedProviderIdsRequest publishedProviderIdsRequest = null; if (batched) { publishedProviderIdsRequest = message.GetPayloadAsInstanceOf <PublishedProviderIdsRequest>(); } foreach (Reference fundingStream in specification.FundingStreams) { await PublishFundingStream(fundingStream, specification, Job.Id, author, correlationId, batched?PrerequisiteCheckerType.ReleaseBatchProviders : PrerequisiteCheckerType.ReleaseAllProviders, publishedProviderIdsRequest?.PublishedProviderIds?.ToArray()); } _logger.Information($"Running search reindexer for published funding"); await _publishedIndexSearchResiliencePolicy.ExecuteAsync(() => _publishedFundingSearchRepository.RunIndexer()); await GenerateCsvJobs(specificationId, correlationId, specification, author); }
public async Task <IActionResult> GetProviderStatusCounts(string specificationId, string providerType, string localAuthority, string status) { ValidationResult validationResults = _validator.Validate(specificationId); if (!validationResults.IsValid) { return(validationResults.AsBadRequest()); } SpecificationSummary specificationSummary = await _specificationsRepositoryPolicy.ExecuteAsync(() => _specificationService.GetSpecificationSummaryById(specificationId)); IEnumerable <PublishedProviderFundingStreamStatus> publishedProviderFundingStreamStatuses = await _publishedFundingRepositoryResilience.ExecuteAsync(() => _publishedFundingRepository.GetPublishedProviderStatusCounts(specificationId, providerType, localAuthority, status)); List <ProviderFundingStreamStatusResponse> response = new List <ProviderFundingStreamStatusResponse>(); foreach (IGrouping <string, PublishedProviderFundingStreamStatus> publishedProviderFundingStreamGroup in publishedProviderFundingStreamStatuses.GroupBy(x => x.FundingStreamId)) { if (!specificationSummary.FundingStreams.Select(x => x.Id).Contains(publishedProviderFundingStreamGroup.Key)) { continue; } response.Add(new ProviderFundingStreamStatusResponse { FundingStreamId = publishedProviderFundingStreamGroup.Key, ProviderApprovedCount = GetCountValueOrDefault(publishedProviderFundingStreamGroup, "Approved"), ProviderDraftCount = GetCountValueOrDefault(publishedProviderFundingStreamGroup, "Draft"), ProviderReleasedCount = GetCountValueOrDefault(publishedProviderFundingStreamGroup, "Released"), ProviderUpdatedCount = GetCountValueOrDefault(publishedProviderFundingStreamGroup, "Updated"), TotalFunding = publishedProviderFundingStreamGroup.Sum(x => x.TotalFunding) }); } return(new OkObjectResult(response)); }
public async Task CheckChooseForFundingStatus_GivenSpecificationSummaryButAlreadyChosen_ReturnsAlreadyChosen() { //Arrange SpecificationSummary specificationSummary = new SpecificationSummary { IsSelectedForFunding = true }; ISpecificationService specificationService = CreateSpecificationService(); specificationService .GetSpecificationSummaryById(Arg.Is(specificationId)) .Returns(specificationSummary); SpecificationFundingStatusService specificationFundingStatusService = CreateSpecificationFundingStatusService(specificationService: specificationService); //Act SpecificationFundingStatus status = await specificationFundingStatusService.CheckChooseForFundingStatus(specificationId); //Assert status .Should() .Be(SpecificationFundingStatus.AlreadyChosen); }
public override async Task Process(Message message) { Guard.ArgumentNotNull(message, nameof(message)); Reference author = message.GetUserDetails(); string specificationId = message.UserProperties["specification-id"] as string; bool publishAll = false; if (message.UserProperties.ContainsKey("publish-all")) { publishAll = bool.Parse(message.UserProperties["publish-all"].ToString()); } IEnumerable <string> batchProviders = null; if (message.UserProperties.ContainsKey("providers-batch")) { batchProviders = JsonExtensions.AsPoco <IEnumerable <string> >(message.UserProperties["providers-batch"].ToString()); } SpecificationSummary specification = await _specificationService.GetSpecificationSummaryById(specificationId); if (specification == null) { throw new NonRetriableException($"Could not find specification with id '{specificationId}'"); } foreach (Reference fundingStream in specification.FundingStreams) { (IDictionary <string, PublishedProvider> publishedProvidersForFundingStream, IDictionary <string, PublishedProvider> scopedPublishedProviders) = await _providerService.GetPublishedProviders(fundingStream, specification); IDictionary <string, PublishedProvider> publishedProvidersByPublishedProviderId = publishedProvidersForFundingStream.Values.ToDictionary(_ => _.PublishedProviderId); IEnumerable <PublishedProvider> selectedPublishedProviders = batchProviders.IsNullOrEmpty() ? publishedProvidersForFundingStream.Values : batchProviders.Where(_ => publishedProvidersByPublishedProviderId.ContainsKey(_)).Select(_ => publishedProvidersByPublishedProviderId[_]); TemplateMapping templateMapping = await GetTemplateMapping(fundingStream, specification.Id); IEnumerable <PublishedFundingVersion> publishedFundingVersions = publishAll ? await _publishedFundingVersionDataService.GetPublishedFundingVersion(fundingStream.Id, specification.FundingPeriod.Id) : (await _publishingResiliencePolicy.ExecuteAsync(() => _publishedFundingDataService.GetCurrentPublishedFunding(fundingStream.Id, specification.FundingPeriod.Id))).Select(_ => _.Current); 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}'"); } // Save contents to blob storage and search for the feed _logger.Information($"Saving published funding contents"); await _publishedFundingContentsPersistanceService.SavePublishedFundingContents(publishedFundingVersions, templateMetadataContents); _logger.Information($"Finished saving published funding contents"); // Generate contents JSON for provider and save to blob storage IPublishedProviderContentsGenerator generator = _publishedProviderContentsGeneratorResolver.GetService(templateMetadataContents.SchemaVersion); await _publishedProviderContentsPersistanceService.SavePublishedProviderContents(templateMetadataContents, templateMapping, selectedPublishedProviders, generator, publishAll); } }
public override async Task Process(Message message) { Guard.ArgumentNotNull(message, nameof(message)); Reference author = message.GetUserDetails(); string specificationId = message.UserProperties["specification-id"] as string; SpecificationSummary specification = await _specificationService.GetSpecificationSummaryById(specificationId); if (specification == null) { throw new NonRetriableException($"Could not find specification with id '{specificationId}'"); } // Get scoped providers for this specification IDictionary <string, Provider> scopedProviders = await _providerService.GetScopedProvidersForSpecification(specification.Id, specification.ProviderVersionId); if (!scopedProviders.IsNullOrEmpty()) { _logger.Information($"Found {scopedProviders.Count} scoped providers for refresh"); } else { _logger.Information("No scoped providers found for refresh"); } // Get existing published providers for this specification _logger.Information("Looking up existing published providers from cosmos for refresh job"); IDictionary <string, List <PublishedProvider> > existingPublishedProvidersByFundingStream = new Dictionary <string, List <PublishedProvider> >(); foreach (Reference fundingStream in specification.FundingStreams) { List <PublishedProvider> publishedProviders = (await _publishingResiliencePolicy.ExecuteAsync(() => _publishedFundingDataService.GetCurrentPublishedProviders(fundingStream.Id, specification.FundingPeriod.Id))).ToList(); existingPublishedProvidersByFundingStream.Add(fundingStream.Id, publishedProviders); _logger.Information($"Found {publishedProviders.Count} existing published providers for funding stream {fundingStream.Id} from cosmos for refresh job"); } _logger.Information("Verifying prerequisites for funding refresh"); // Check prerequisites for this specification to be chosen/refreshed IPrerequisiteChecker prerequisiteChecker = _prerequisiteCheckerLocator.GetPreReqChecker(PrerequisiteCheckerType.Refresh); try { await prerequisiteChecker.PerformChecks(specification, Job.Id, existingPublishedProvidersByFundingStream.SelectMany(x => x.Value), scopedProviders?.Values); } catch (JobPrereqFailedException ex) { throw new NonRetriableException(ex.Message, ex); } _logger.Information("Prerequisites for refresh passed"); // Get calculation results for specification _logger.Information("Looking up calculation results"); IDictionary <string, ProviderCalculationResult> allCalculationResults; try { allCalculationResults = await _calculationResultsService.GetCalculationResultsBySpecificationId(specificationId, scopedProviders.Keys); } catch (Exception ex) { _logger.Error(ex, "Exception during calculation result lookup"); throw; } _logger.Information($"Found calculation results for {allCalculationResults?.Count} providers from cosmos for refresh job"); string correlationId = message.GetUserProperty <string>(SfaCorrelationId); try { foreach (Reference fundingStream in specification.FundingStreams) { _logger.Information($"Starting to refresh funding for '{fundingStream.Id}'"); await RefreshFundingStream(fundingStream, specification, scopedProviders, allCalculationResults, Job.Id, author, correlationId, existingPublishedProvidersByFundingStream[fundingStream.Id], specification.FundingPeriod.Id); _logger.Information($"Finished processing refresh funding for '{fundingStream.Id}'"); } } finally { _logger.Information("Starting to clear variation snapshots"); _variationService.ClearSnapshots(); _logger.Information("Finished clearing variation snapshots"); } }