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));
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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));
        }
Beispiel #7
0
        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));
        }
Beispiel #9
0
        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);
        }
Beispiel #11
0
        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));
        }
Beispiel #12
0
        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);
            }
        }
Beispiel #14
0
        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");
            }
        }