public void SaveFundingPeriod(FundingPeriod fundingPeriod) { Guard.ArgumentNotNull(fundingPeriod, nameof(fundingPeriod)); Guard.IsNullOrWhiteSpace(fundingPeriod.Id, nameof(fundingPeriod.Id)); _fundingPeriods[fundingPeriod.Id] = fundingPeriod; }
private void SetupMocks() { _validatorFactory = Substitute.For <IIoCValidatorFactory>(); _validatorFactory.Validate(Arg.Any <object>()).Returns(new ValidationResult()); _templateRepository = Substitute.For <ITemplateRepository>(); _templateRepository.CreateDraft(Arg.Any <Template>()).Returns(HttpStatusCode.OK); _versionRepository = Substitute.For <ITemplateVersionRepository>(); _versionRepository.SaveVersion(Arg.Any <TemplateVersion>()).Returns(HttpStatusCode.OK); _searchRepository = Substitute.For <ISearchRepository <TemplateIndex> >(); _searchRepository.Index(Arg.Any <IEnumerable <TemplateIndex> >()).Returns(Enumerable.Empty <IndexError>()); _fundingPeriod = new FundingPeriod { Id = _command.FundingPeriodId, Name = "Test Period", Type = FundingPeriodType.FY }; _fundingStream = new FundingStream { Id = _command.FundingStreamId, ShortName = "XX", Name = "FundingSteam" }; _policyRepository = Substitute.For <IPolicyRepository>(); _policyRepository.GetFundingPeriods().Returns(new [] { _fundingPeriod }); _policyRepository.GetFundingStreams().Returns(new [] { _fundingStream }); _policyRepository.GetFundingConfigurations().Returns(new [] { new FundingConfiguration { FundingStreamId = _fundingStream.Id, FundingPeriodId = _fundingPeriod.Id } }); }
private void AddDurationAndFundingToStandards(ICollection <LarsStandard> standards, ICollection <ApprenticeshipFundingMetaData> metaData) { foreach (var std in standards) { var fundingBands = metaData.Where(stdrd => stdrd.ApprenticeshipType.ToLower() == "std" && stdrd.ApprenticeshipCode == std.Id); if (!fundingBands.Any()) { continue; } std.Duration = fundingBands.First().ReservedValue1; std.FundingPeriods = new List <FundingPeriod>(); foreach (var apprenticeshipFundingMetaData in fundingBands) { var fundingPeriod = new FundingPeriod { FundingCap = apprenticeshipFundingMetaData.MaxEmployerLevyCap, EffectiveFrom = apprenticeshipFundingMetaData.EffectiveFrom, EffectiveTo = apprenticeshipFundingMetaData.EffectiveTo }; std.FundingPeriods.Add(fundingPeriod); } std.FundingCap = fundingBands.Last(x => x.EffectiveFrom <= DateTime.Today).MaxEmployerLevyCap; } }
public async Task GetFundingPeriodById__GivenFundingStreamnWasFound_ReturnsSuccess() { // Arrange const string fundingPeriodId = "fp-1"; FundingPeriod fundingPeriod = new FundingPeriod { Id = fundingPeriodId }; IPolicyRepository policyRepository = CreatePolicyRepository(); policyRepository .GetFundingPeriodById(Arg.Is(fundingPeriodId)) .Returns(fundingPeriod); FundingPeriodService fundingPeriodService = CreateFundingPeriodService(policyRepository: policyRepository); // Act IActionResult result = await fundingPeriodService.GetFundingPeriodById(fundingPeriodId); // Assert result .Should() .BeOfType <OkObjectResult>() .Which .Value .Should() .Be(fundingPeriod); }
public void Then_The_Fields_Are_Correctly_Mapped(FundingPeriod fundingPeriod, string frameworkId) { var actual = new FrameworkFundingImport().Map(fundingPeriod, frameworkId); actual.Should().BeEquivalentTo(fundingPeriod); actual.FrameworkId.Should().Be(frameworkId); }
public TemplateCreateCommandValidator( IPolicyRepository policyRepository, IPolicyResiliencePolicies policyResiliencePolicies) { Guard.ArgumentNotNull(policyRepository, nameof(policyRepository)); Guard.ArgumentNotNull(policyResiliencePolicies?.PolicyRepository, nameof(policyResiliencePolicies.PolicyRepository)); AsyncPolicy policyRepositoryPolicy = policyResiliencePolicies.PolicyRepository; RuleFor(x => x.Description).Length(0, 1000); RuleFor(x => x.FundingStreamId) .NotEmpty() .WithMessage("Missing funding stream id") .MustAsync(async(command, propertyValue, context, cancellationToken) => { FundingStream fundingStream = await policyRepositoryPolicy.ExecuteAsync(() => policyRepository.GetFundingStreamById(command.FundingStreamId)); return(fundingStream != null); }) .WithMessage("Funding stream id does not exist"); RuleFor(x => x.FundingPeriodId) .NotEmpty() .WithMessage("Missing funding period id") .MustAsync(async(command, propertyValue, context, cancellationToken) => { FundingPeriod fundingPeriod = await policyRepositoryPolicy.ExecuteAsync(() => policyRepository.GetFundingPeriodById(command.FundingPeriodId)); return(fundingPeriod != null); }) .WithMessage("Funding period id does not exist"); }
/// <summary> /// Get the provider funding ids to return for a feed entry. /// </summary> /// <param name="orgGroup"></param> /// <param name="period"></param> /// <param name="stream"></param> /// <param name="fundingVersion"></param> /// <returns>A list of provider funding ids.</returns> private static List <string> GetProviderFundingIds(OrgGroup orgGroup, FundingPeriod period, Stream stream, string fundingVersion, OrganisationType[] organisationTypes, VariationReason[] variationReasons, string[] ukprns) { var returnList = new List <string>(); // We don't have variation reasons yet if (variationReasons?.Any() == true) { return(returnList); } // If we are asking for anything but local authorities, there won't be any results if (organisationTypes?.Any() == true && organisationTypes?.Contains(OrganisationType.LocalAuthority) == false) { return(returnList); } foreach (var provider in orgGroup.Providers) { var ukprn = $"MOCKUKPRN{provider.LaEstablishmentNo}"; if (ukprns?.Any() == true && ukprns?.Contains(ukprn) == false) { continue; } returnList.Add($"{stream.Code}_{period.Code}_{ukprn}_{fundingVersion}"); } return(returnList); }
private void GivenTheFundingPeriod(Action <FundingPeriodBuilder> setUp = null) { FundingPeriodBuilder fundingPeriodBuilder = new FundingPeriodBuilder(); setUp?.Invoke(fundingPeriodBuilder); _fundingPeriod = fundingPeriodBuilder.Build(); }
public async Task GetFundingConfiguration__GivenFundingConfigurationWasFound_ReturnsSuccess(string fundingStreamId, string fundingPeriodId) { // Arrange FundingStream fundingStream = new FundingStream { Id = fundingStreamId }; FundingPeriod fundingPeriod = new FundingPeriod { Id = fundingPeriodId }; string configId = $"config-{fundingStreamId}-{fundingPeriodId}"; FundingConfiguration fundingConfiguration = new FundingConfiguration { Id = configId }; IPolicyRepository policyRepository = CreatePolicyRepository(); policyRepository .GetFundingStreamById(Arg.Is(fundingStreamId)) .Returns(fundingStream); policyRepository .GetFundingPeriodById(Arg.Is(fundingPeriodId)) .Returns(fundingPeriod); policyRepository .GetFundingConfiguration(Arg.Is(configId)) .Returns(fundingConfiguration); FundingConfigurationService fundingConfigurationsService = CreateFundingConfigurationService(policyRepository: policyRepository); // Act IActionResult result = await fundingConfigurationsService.GetFundingConfiguration(fundingStreamId, fundingPeriodId); // Assert result .Should() .BeOfType <OkObjectResult>() .Which .Value .Should() .Be(fundingConfiguration); FundingConfiguration fundingConfigurationResult = ((OkObjectResult)result).Value.As <FundingConfiguration>(); fundingConfigurationResult.ProviderSource.Should().Be(CalculateFunding.Models.Providers.ProviderSource.CFS); fundingConfigurationResult.PaymentOrganisationSource.Should().Be(PaymentOrganisationSource.PaymentOrganisationAsProvider); }
async public Task SaveFundingConfiguration_GivenValidConfigurationButFailedToSaveToDatabase_ReturnsStatusCode(string fundingStreamId, string fundingPeriodId) { //Arrange FundingStream fundingStream = new FundingStream { Id = fundingStreamId }; FundingPeriod fundingPeriod = new FundingPeriod { Id = fundingPeriodId }; ILogger logger = CreateLogger(); HttpStatusCode statusCode = HttpStatusCode.BadRequest; IPolicyRepository policyRepository = CreatePolicyRepository(); policyRepository .GetFundingStreamById(Arg.Is(fundingStreamId)) .Returns(fundingStream); policyRepository .GetFundingPeriodById(Arg.Is(fundingPeriodId)) .Returns(fundingPeriod); policyRepository .SaveFundingConfiguration(Arg.Is <FundingConfiguration>(x => x.FundingStreamId == fundingStreamId && x.FundingPeriodId == fundingPeriodId)) .Returns(statusCode); FundingConfigurationService fundingConfigurationsService = CreateFundingConfigurationService(logger: logger, policyRepository: policyRepository); FundingConfigurationViewModel fundingConfigurationViewModel = CreateConfigurationModel(); //Act IActionResult result = await fundingConfigurationsService.SaveFundingConfiguration("Action", "Controller", fundingConfigurationViewModel, fundingStreamId, fundingPeriodId); //Assert result .Should() .BeOfType <InternalServerErrorResult>(); InternalServerErrorResult statusCodeResult = (InternalServerErrorResult)result; statusCodeResult .StatusCode .Should() .Be(500); logger .Received(1) .Error(Arg.Is($"Failed to save configuration file for funding stream id: {fundingStreamId} and period id: {fundingPeriodId} to cosmos db with status 400")); }
public async Task GetFundingConfiguration__GivenFundingConfigurationAlreadyInCache_ReturnsSuccessWithConfigurationFromCache(string fundingStreamId, string fundingPeriodId) { // Arrange FundingStream fundingStream = new FundingStream { Id = fundingStreamId }; FundingPeriod fundingPeriod = new FundingPeriod { Id = fundingPeriodId }; string configId = $"config-{fundingStreamId}-{fundingPeriodId}"; FundingConfiguration fundingConfiguration = new FundingConfiguration { Id = configId }; IPolicyRepository policyRepository = CreatePolicyRepository(); policyRepository .GetFundingStreamById(Arg.Is(fundingStreamId)) .Returns(fundingStream); policyRepository .GetFundingPeriodById(Arg.Is(fundingPeriodId)) .Returns(fundingPeriod); string cacheKey = $"{CacheKeys.FundingConfig}{fundingStreamId}-{fundingPeriodId}"; ICacheProvider cacheProvider = CreateCacheProvider(); cacheProvider .GetAsync <FundingConfiguration>(Arg.Is(cacheKey)) .Returns(fundingConfiguration); FundingConfigurationService fundingConfigurationsService = CreateFundingConfigurationService(policyRepository: policyRepository, cacheProvider: cacheProvider); // Act IActionResult result = await fundingConfigurationsService.GetFundingConfiguration(fundingStreamId, fundingPeriodId); // Assert result .Should() .BeOfType <OkObjectResult>() .Which .Value .Should() .Be(fundingConfiguration); }
private async Task ValidateFundingPeriod(FundingTemplateValidationResult fundingTemplateValidationResult) { if (!string.IsNullOrWhiteSpace(fundingTemplateValidationResult.FundingPeriodId)) { FundingPeriod fundingPeriod = await _policyRepositoryPolicy.ExecuteAsync(() => _policyRepository.GetFundingPeriodById(fundingTemplateValidationResult.FundingPeriodId)); if (fundingPeriod == null) { fundingTemplateValidationResult.Errors .Add(new ValidationFailure("", $"A funding period could not be found for funding period id '{fundingTemplateValidationResult.FundingPeriodId}'")); } } }
public async Task <string> GetFundingPeriodId(string fundingPeriodId) { ApiResponse <FundingPeriod> fundingPeriodResponse = await _policiesApiClientPolicy.ExecuteAsync(() => _policiesApiClient.GetFundingPeriodById(fundingPeriodId)); if (fundingPeriodResponse?.Content == null) { return(null); } FundingPeriod fundingPeriod = fundingPeriodResponse.Content; return(string.Format(periodIdStringFormat, fundingPeriod.Type, fundingPeriod.Period)); }
public void ShouldReturnNoDetailsOfSingleInstanceIfItIsCurrent(DateTime?currentEffectiveFrom) { var numberOfMonths = 3; var expectedFundingCap = 1500; var expectedFundingPeriod = new FundingPeriod { EffectiveFrom = currentEffectiveFrom, FundingCap = expectedFundingCap }; var fundingBands = new List <FundingPeriod> { expectedFundingPeriod }; var res = _fundingBandService.GetNextFundingPeriodWithinTimePeriod(fundingBands, currentEffectiveFrom, numberOfMonths); res.Should().BeNull(); }
public void ShouldReturnNoDetailsOfSingleInstanceAt3MonthsAnd1Day(DateTime?currentEffectiveFrom) { var numberOfMonths = 3; var expectedFundingCap = 1500; var usedDateTime = DateTime.Today.AddMonths(numberOfMonths).AddDays(1); var expectedFundingPeriod = new FundingPeriod { EffectiveFrom = usedDateTime, FundingCap = expectedFundingCap }; var fundingBands = new List <FundingPeriod> { expectedFundingPeriod }; var res = _fundingBandService.GetNextFundingPeriodWithinTimePeriod(fundingBands, currentEffectiveFrom, numberOfMonths); res.Should().BeNull(); }
public async Task <IActionResult> GetFundingPeriodById(string fundingPeriodId) { if (string.IsNullOrWhiteSpace(fundingPeriodId)) { _logger.Error("No funding period id was provided to GetFundingPeriodById"); return(new BadRequestObjectResult("Null or empty funding period id provided")); } FundingPeriod fundingPeriod = await _policyRepositoryPolicy.ExecuteAsync(() => _policyRepository.GetFundingPeriodById(fundingPeriodId)); if (fundingPeriod == null) { _logger.Error($"No funding period was returned for funding period id: '{fundingPeriodId}'"); return(new NotFoundResult()); } return(new OkObjectResult(fundingPeriod)); }
public void ShouldReturnTheCorrectInstanceAt3MonthsForMixedListOf5(DateTime?currentEffectiveFrom) { var numberOfMonths = 3; var earliestFundingCap = 1501; var earliestDateTime = DateTime.Today.AddDays(1); var secondDateTime = DateTime.Today.AddDays(7); var secondFundingCap = 1507; var thirdDateTime = DateTime.Today.AddDays(28); var thirdFundingCap = 1528; var fourthDateTime = DateTime.Today.AddDays(50); var fourthFundingCap = 1550; var firstFundingPeriod = new FundingPeriod { EffectiveFrom = earliestDateTime, FundingCap = earliestFundingCap }; var secondFundingPeriod = new FundingPeriod { EffectiveFrom = secondDateTime, FundingCap = secondFundingCap }; var thirdFundingPeriod = new FundingPeriod { EffectiveFrom = thirdDateTime, FundingCap = thirdFundingCap }; var fourthFundingPeriod = new FundingPeriod { EffectiveFrom = fourthDateTime, FundingCap = fourthFundingCap }; var currentFundingPeriod = new FundingPeriod { EffectiveFrom = currentEffectiveFrom, FundingCap = 1200 }; var fundingBands = new List <FundingPeriod> { thirdFundingPeriod, currentFundingPeriod, secondFundingPeriod, fourthFundingPeriod, firstFundingPeriod }; var res = _fundingBandService.GetNextFundingPeriodWithinTimePeriod(fundingBands, currentEffectiveFrom, numberOfMonths); res.Should().Be(firstFundingPeriod); }
public void ShouldReturnTheCorrectInstanceAt3MonthsForListContainingCurrent(DateTime?currentEffectiveFrom) { var numberOfMonths = 3; var expectedFundingCap = 1500; var usedDateTime = DateTime.Today.AddMonths(numberOfMonths); var expectedFundingPeriod = new FundingPeriod { EffectiveFrom = usedDateTime, FundingCap = expectedFundingCap }; var currentFundingPeriod = new FundingPeriod { EffectiveFrom = currentEffectiveFrom, FundingCap = 1200 }; var fundingBands = new List <FundingPeriod> { currentFundingPeriod, expectedFundingPeriod }; var res = _fundingBandService.GetNextFundingPeriodWithinTimePeriod(fundingBands, currentEffectiveFrom, numberOfMonths); res.Should().Be(expectedFundingPeriod); }
public async Task <IEnumerable <FundingPeriod> > GetAllFundingPeriods() { IEnumerable <FundingPeriod> fundingPeriods = await _cacheProviderPolicy.ExecuteAsync(() => _cacheProvider.GetAsync <FundingPeriod[]>(CacheKeys.FundingPeriods)); if (fundingPeriods.IsNullOrEmpty()) { fundingPeriods = await _policyRepositoryPolicy.ExecuteAsync(() => _policyRepository.GetFundingPeriods()); if (fundingPeriods.IsNullOrEmpty()) { _logger.Error("No funding periods were returned"); fundingPeriods = new FundingPeriod[0]; } else { await _cacheProviderPolicy.ExecuteAsync(() => _cacheProvider.SetAsync(CacheKeys.FundingPeriods, fundingPeriods.ToArraySafe())); } } return(fundingPeriods); }
private void ThenFundingPeriodResultMatches(IActionResult result) { result .Should() .BeOfType <OkObjectResult>() .Which .Value .Should() .BeOfType <List <FundingPeriod> >(); IEnumerable <FundingPeriod> fundingPeriods = (result as OkObjectResult).Value as IEnumerable <FundingPeriod>; fundingPeriods .Count() .Should() .Be(1); fundingPeriods .FirstOrDefault() .Should() .NotBeNull(); FundingPeriod fundingPeriod = fundingPeriods.FirstOrDefault(); fundingPeriod .Id .Should() .Be(_fundingPeriodId); fundingPeriod .Name .Should() .Be(_fundingPeriodName); fundingPeriod .DefaultTemplateVersion .Should() .Be(_fundingPeriodDefaultTemplateVersion); }
private void AddDurationAndFundingToFrameworks(ICollection <FrameworkMetaData> frameworks, ICollection <ApprenticeshipFundingMetaData> metaData) { foreach (var framework in frameworks) { var fw = metaData.Where(fwk => fwk.ApprenticeshipType.ToLower() == "fwk" && fwk.ApprenticeshipCode == framework.FworkCode && fwk.ProgType == framework.ProgType && fwk.PwayCode == framework.PwayCode && fwk.EffectiveFrom.HasValue && fwk.EffectiveFrom.Value.Date != DateTime.MinValue.Date) .ToList(); if (!fw.Any()) { continue; } framework.Duration = fw.OrderByDescending(x => x.EffectiveFrom).First().ReservedValue1; framework.FundingPeriods = new List <FundingPeriod>(); foreach (var apprenticeshipFundingMetaData in fw) { var fundingPeriod = new FundingPeriod { FundingCap = apprenticeshipFundingMetaData.MaxEmployerLevyCap, EffectiveFrom = apprenticeshipFundingMetaData.EffectiveFrom, EffectiveTo = apprenticeshipFundingMetaData.EffectiveTo }; framework.FundingPeriods.Add(fundingPeriod); } framework.FundingCap = fw.Last(x => x.EffectiveFrom <= DateTime.Today).MaxEmployerLevyCap; } }
public SaveFundingConfigurationValidator(IPolicyRepository policyRepository, IPolicyResiliencePolicies policyResiliencePolicies, IFundingTemplateService fundingTemplateService) { Guard.ArgumentNotNull(policyRepository, nameof(policyRepository)); Guard.ArgumentNotNull(fundingTemplateService, nameof(fundingTemplateService)); Guard.ArgumentNotNull(policyResiliencePolicies?.PolicyRepository, nameof(policyResiliencePolicies.PolicyRepository)); ResiliencePolicy policyRepositoryPolicy = policyResiliencePolicies.PolicyRepository; RuleFor(_ => _.ApprovalMode) .Must(_ => _ != ApprovalMode.Undefined) .WithMessage("No valid approval mode was selected"); RuleFor(model => model.FundingStreamId) .NotEmpty() .WithMessage("No funding stream id was provided to SaveFundingConfiguration") .CustomAsync(async(name, context, cancellationToken) => { FundingConfiguration model = context.ParentContext.InstanceToValidate as FundingConfiguration; if (!string.IsNullOrWhiteSpace(model.FundingStreamId)) { FundingStream fundingStream = await policyRepositoryPolicy.ExecuteAsync(() => policyRepository.GetFundingStreamById(model.FundingStreamId)); if (fundingStream == null) { context.AddFailure("Funding stream not found"); } } }); RuleFor(model => model.FundingPeriodId) .NotEmpty() .WithMessage("No funding period id was provided to SaveFundingConfiguration") .CustomAsync(async(name, context, cancellationToken) => { FundingConfiguration model = context.ParentContext.InstanceToValidate as FundingConfiguration; if (!string.IsNullOrWhiteSpace(model.FundingPeriodId)) { FundingPeriod fundingPeriod = await policyRepositoryPolicy.ExecuteAsync(() => policyRepository.GetFundingPeriodById(model.FundingPeriodId)); if (fundingPeriod == null) { context.AddFailure("Funding period not found"); } } }); RuleFor(model => model.DefaultTemplateVersion) .CustomAsync(async(name, context, cancellationToken) => { FundingConfiguration model = context.ParentContext.InstanceToValidate as FundingConfiguration; string fundingStreamId = model.FundingStreamId; string defaultTemplateVersion = model.DefaultTemplateVersion; string fundingPeriodId = model.FundingPeriodId; if (!string.IsNullOrWhiteSpace(fundingStreamId) && !string.IsNullOrWhiteSpace(fundingPeriodId) && !string.IsNullOrWhiteSpace(defaultTemplateVersion)) { if (!await fundingTemplateService.TemplateExists(fundingStreamId, fundingPeriodId, defaultTemplateVersion)) { context.AddFailure("Default template not found"); } } }); RuleFor(_ => _.UpdateCoreProviderVersion) .Must(v => v == UpdateCoreProviderVersion.Manual) .When(_ => _.ProviderSource != CalculateFunding.Models.Providers.ProviderSource.FDZ, ApplyConditionTo.CurrentValidator) .WithMessage(x => $"UpdateCoreProviderVersion - {x.UpdateCoreProviderVersion.ToString()} is not valid for provider source - {x.ProviderSource}"); }
/// <summary> /// Generate instances of the PublishedFundingVersion to save into cosmos for the Organisation Group Results /// </summary> /// <param name="publishedFundingInput"></param> /// <param name="publishedProviders"></param> /// <returns></returns> public IEnumerable <(PublishedFunding, PublishedFundingVersion)> GeneratePublishedFunding(PublishedFundingInput publishedFundingInput, IEnumerable <PublishedProvider> publishedProviders) { Guard.ArgumentNotNull(publishedFundingInput, nameof(publishedFundingInput)); Guard.ArgumentNotNull(publishedFundingInput.FundingPeriod, nameof(publishedFundingInput.FundingPeriod)); Guard.ArgumentNotNull(publishedFundingInput.FundingStream, nameof(publishedFundingInput.FundingStream)); Guard.ArgumentNotNull(publishedFundingInput.OrganisationGroupsToSave, nameof(publishedFundingInput.OrganisationGroupsToSave)); Guard.ArgumentNotNull(publishedProviders, nameof(publishedProviders)); Guard.ArgumentNotNull(publishedFundingInput.PublishingDates, nameof(publishedFundingInput.PublishingDates)); Guard.ArgumentNotNull(publishedFundingInput.TemplateMetadataContents, nameof(publishedFundingInput.TemplateMetadataContents)); Guard.IsNullOrWhiteSpace(publishedFundingInput.TemplateVersion, nameof(publishedFundingInput.TemplateVersion)); Guard.IsNullOrWhiteSpace(publishedFundingInput.SpecificationId, nameof(publishedFundingInput.SpecificationId)); IEnumerable <(PublishedFunding PublishedFunding, OrganisationGroupResult OrganisationGroupResult)> organisationGroupsToSave = publishedFundingInput.OrganisationGroupsToSave; TemplateMetadataContents templateMetadataContents = publishedFundingInput.TemplateMetadataContents; string templateVersion = publishedFundingInput.TemplateVersion; FundingPeriod fundingPeriod = publishedFundingInput.FundingPeriod; FundingValueAggregator fundingValueAggregator = new FundingValueAggregator(); foreach ((PublishedFunding PublishedFunding, OrganisationGroupResult OrganisationGroupResult)organisationGroup in organisationGroupsToSave) { // TODO: extract interface IEnumerable <string> providerIds = organisationGroup.OrganisationGroupResult.Providers.Select(p => p.ProviderId); IEnumerable <string> publishedProvidersIds = publishedProviders.Select(p => p.Current.ProviderId); List <PublishedProvider> publishedProvidersForOrganisationGroup = new List <PublishedProvider>(publishedProviders.Where(p => providerIds.Contains(p.Current.ProviderId))); List <PublishedProviderVersion> publishedProviderVersionsForOrganisationGroup = new List <PublishedProviderVersion>( publishedProvidersForOrganisationGroup.Select(p => p.Current)); IEnumerable <string> missingProviders = providerIds.Except(publishedProvidersIds); if (missingProviders.AnyWithNullCheck()) { string providerIdsString = string.Join(", ", missingProviders); throw new Exception($"Missing PublishedProvider result for organisation group '{organisationGroup.OrganisationGroupResult.GroupReason}' '{organisationGroup.OrganisationGroupResult.GroupTypeCode}' '{organisationGroup.OrganisationGroupResult.GroupTypeIdentifier}' '{organisationGroup.OrganisationGroupResult.IdentifierValue}'. Provider IDs={providerIdsString}"); } List <AggregateFundingLine> fundingLineAggregates = new List <AggregateFundingLine>( fundingValueAggregator.GetTotals(templateMetadataContents, publishedProviderVersionsForOrganisationGroup)); IEnumerable <Common.TemplateMetadata.Models.FundingLine> fundingLineDefinitions = templateMetadataContents.RootFundingLines.Flatten(_ => _.FundingLines) ?? Enumerable.Empty <Common.TemplateMetadata.Models.FundingLine>(); // Add in calculations in numerator/demoninator and percentagechange targets List <PublishingModels.FundingLine> fundingLines = GenerateFundingLines(fundingLineAggregates, fundingLineDefinitions); List <FundingCalculation> calculations = GenerateCalculations(fundingLineAggregates.Flatten(_ => _.FundingLines) .SelectMany(c => c.Calculations ?? Enumerable.Empty <AggregateFundingCalculation>())); decimal?totalFunding = publishedProviderVersionsForOrganisationGroup.Sum(_ => _.TotalFunding); PublishedFundingVersion publishedFundingVersion = new PublishedFundingVersion { FundingStreamId = publishedFundingInput.FundingStream.Id, FundingStreamName = publishedFundingInput.FundingStream.Name, TotalFunding = totalFunding, FundingPeriod = new PublishedFundingPeriod { Type = Enum.Parse <PublishedFundingPeriodType>(fundingPeriod.Type.GetValueOrDefault().ToString()), Period = fundingPeriod.Period, EndDate = fundingPeriod.EndDate, StartDate = fundingPeriod.StartDate, Name = fundingPeriod.Name, }, SpecificationId = publishedFundingInput.SpecificationId, OrganisationGroupTypeCode = organisationGroup.OrganisationGroupResult.GroupTypeCode.ToString(), OrganisationGroupTypeIdentifier = organisationGroup.OrganisationGroupResult.GroupTypeIdentifier.ToString(), OrganisationGroupIdentifierValue = organisationGroup.OrganisationGroupResult.IdentifierValue, OrganisationGroupTypeClassification = organisationGroup.OrganisationGroupResult.GroupTypeClassification.ToString(), OrganisationGroupName = organisationGroup.OrganisationGroupResult.Name, OrganisationGroupSearchableName = organisationGroup.OrganisationGroupResult.SearchableName, OrganisationGroupIdentifiers = _mapper.Map <IEnumerable <PublishedOrganisationGroupTypeIdentifier> >(organisationGroup.OrganisationGroupResult.Identifiers), FundingLines = fundingLines, Calculations = calculations, SchemaVersion = templateMetadataContents.SchemaVersion, Status = PublishedFundingStatus.Approved, GroupingReason = organisationGroup.OrganisationGroupResult.GroupReason.AsMatchingEnum <PublishingModels.GroupingReason>(), ProviderFundings = publishedProviderVersionsForOrganisationGroup.Select(_ => _.FundingId), TemplateVersion = templateVersion, StatusChangedDate = publishedFundingInput.PublishingDates.StatusChangedDate.TrimToTheSecond(), EarliestPaymentAvailableDate = publishedFundingInput.PublishingDates.EarliestPaymentAvailableDate.TrimToTheMinute(), ExternalPublicationDate = publishedFundingInput.PublishingDates.ExternalPublicationDate.TrimToTheMinute(), }; publishedFundingVersion.FundingId = _publishedFundingIdGeneratorResolver.GetService(templateMetadataContents.SchemaVersion).GetFundingId(publishedFundingVersion); PublishedFunding publishedFundingResult = organisationGroup.PublishedFunding; if (publishedFundingResult == null) { publishedFundingResult = new PublishedFunding() { Current = publishedFundingVersion, }; } yield return(publishedFundingResult, publishedFundingVersion); } }
public SaveFundingDateValidator( IPolicyRepository policyRepository, IPolicyResiliencePolicies policyResiliencePolicies ) { Guard.ArgumentNotNull(policyRepository, nameof(policyRepository)); Guard.ArgumentNotNull(policyResiliencePolicies?.PolicyRepository, nameof(policyResiliencePolicies.PolicyRepository)); ResiliencePolicy policyRepositoryPolicy = policyResiliencePolicies.PolicyRepository; RuleFor(model => model.FundingStreamId) .NotEmpty() .WithMessage("No funding stream id was provided to SaveFundingDate") .CustomAsync(async(name, context, cancellationToken) => { FundingDate model = context.ParentContext.InstanceToValidate as FundingDate; if (!string.IsNullOrWhiteSpace(model.FundingStreamId)) { FundingStream fundingStream = await policyRepositoryPolicy.ExecuteAsync(() => policyRepository.GetFundingStreamById(model.FundingStreamId)); if (fundingStream == null) { context.AddFailure("Funding stream not found"); } } }); RuleFor(model => model.FundingPeriodId) .NotEmpty() .WithMessage("No funding period id was provided to SaveFundingDate") .CustomAsync(async(name, context, cancellationToken) => { FundingDate model = context.ParentContext.InstanceToValidate as FundingDate; if (!string.IsNullOrWhiteSpace(model.FundingPeriodId)) { FundingPeriod fundingPeriod = await policyRepositoryPolicy.ExecuteAsync(() => policyRepository.GetFundingPeriodById(model.FundingPeriodId)); if (fundingPeriod == null) { context.AddFailure("Funding period not found"); } } }); RuleFor(model => model.Patterns) .NotEmpty() .WithMessage("No funding date pattern was provided to SaveFundingDate") .Custom((name, context) => { FundingDate model = context.ParentContext.InstanceToValidate as FundingDate; if (model.Patterns == null) { return; } foreach (FundingDatePattern fundingDatePattern in model.Patterns) { if (fundingDatePattern.Occurrence == default || string.IsNullOrEmpty(fundingDatePattern.Period) || fundingDatePattern.PeriodYear == default || fundingDatePattern.PaymentDate == default) { context.AddFailure("FundingDatePattern information missing"); } } if (model.Patterns.GroupBy(x => new { x.Period, x.PeriodYear, x.Occurrence }).Any(_ => _.Count() > 1)) { context.AddFailure("Duplicate funding data pattern"); } }); }
/// <summary> /// Generate a feed from CSV files (from a spreadsheet). /// </summary> /// <param name="fundingPeriodStartYear">Optional - </param> /// <param name="fundingPeriodEndYear">Optional - </param> /// <param name="fundingPeriodCodes">Optional - The period codes to limit to (e.g. AY1920).</param> /// <param name="organisationGroupIdentifiers">Optional - The group identifiers to limit by (e.g. UKPRN 12345678).</param> /// <param name="organisationGroupTypes">Optional - The group types to limit to (e.g. Region, LocalAuthority).</param> /// <param name="organisationIdentifiers">Optional - The organisation identifiers to limit to (e.g. UKPRN 12345678).</param> /// <param name="organisationTypes">Optional - The organisation types to return.</param> /// <param name="variationReasons">Optional - Filter to only organisations with these variation reasons types</param> /// <param name="ukprns">Optional - Only get these UKPRNs back.</param> /// <param name="groupingReasons">Optional - The grouping reasons we want to get back (e.g. Information and/or Payment).</param> /// <param name="statuses">Optional - The status of the funding (e.g. Released).</param> /// <param name="minStatusChangeDate">Optional - Only get records back that were changed after this date.</param> /// <param name="fundingLineTypes">Optional - limit the types of lines we want to get back (e.g. Information and/or Payment).</param> /// <param name="templateLineIds">Optional - Filter the lines to these ids only.</param> /// <returns>An array of FeedResponseContentModel objects./returns> public static FeedResponseContentModel[] GenerateFeed(int?fundingPeriodStartYear, int?fundingPeriodEndYear, string[] fundingPeriodCodes, OrganisationIdentifier[] organisationGroupIdentifiers, OrganisationType[] organisationGroupTypes, OrganisationIdentifier[] organisationIdentifiers, OrganisationType[] organisationTypes, VariationReason[] variationReasons, string[] ukprns, GroupingReason[] groupingReasons, FundingStatus[] statuses, DateTime?minStatusChangeDate, FundingLineType[] fundingLineTypes, string[] templateLineIds) { var totalList = new List <FeedResponseContentModel>(); // Check period dates if ((fundingPeriodStartYear != null && fundingPeriodStartYear != 2019) || (fundingPeriodEndYear != null && fundingPeriodEndYear != 2020)) { return(totalList.ToArray()); } // Check period codes if (fundingPeriodCodes?.Any() == true && fundingPeriodCodes?.Contains("AY1920") == false) { return(totalList.ToArray()); } // Check statuses if (statuses?.Any() == true && !statuses.Contains(FundingStatus.Released)) { return(totalList.ToArray()); } // Check feed cut off date if (minStatusChangeDate != null && minStatusChangeDate.Value > new DateTime(2019, 3, 1)) { return(totalList.ToArray()); } // If we only want information type, we are out of luck if (groupingReasons?.Any() == true && groupingReasons?.Contains(GroupingReason.Payment) == false) { return(totalList.ToArray()); } var fundingVersion = "1-0"; var templateVersion = "1.0"; var schemaVersion = "1.0"; var ukOffset = new TimeSpan(0, 0, 0); var period = new FundingPeriod { Code = "AY1920", Name = "Academic year 2019-20", Type = PeriodType.AcademicYear, StartDate = new DateTimeOffset(2019, 9, 1, 0, 0, 0, ukOffset), EndDate = new DateTimeOffset(2020, 8, 31, 0, 0, 0, ukOffset) }; var stream = new StreamWithTemplateVersion { Code = "PESports", Name = "PE + Sport Premium", TemplateVersion = templateVersion, }; var processFile = new ProcessPesportsCsv(); var financialYearPeriod1920 = new FundingPeriod { Code = "FY1920", Name = "Financial Year 2019-20", Type = PeriodType.FinancialYear, StartDate = new DateTimeOffset(2019, 4, 1, 0, 0, 0, ukOffset), EndDate = new DateTimeOffset(2020, 3, 30, 0, 0, 0, ukOffset) }; var financialYearPeriod2021 = new FundingPeriod { Code = "FY2021", Name = "Financial Year 2020-21", Type = PeriodType.FinancialYear, StartDate = new DateTimeOffset(2020, 4, 1, 0, 0, 0, ukOffset), EndDate = new DateTimeOffset(2021, 3, 30, 0, 0, 0, ukOffset) }; var providerTypes = new List <string> { "MaintainedSchools", "Academies", "NonMaintainedSpecialSchools" }; foreach (var providerType in providerTypes) { if ((providerType == "MaintainedSchools" || providerType == "NonMaintainedSpecialSchools") && organisationGroupTypes?.Any() == true && organisationGroupTypes?.Contains(OrganisationType.Provider) == false) { continue; } else if (providerType == "Academies" && organisationGroupTypes?.Any() == true && organisationGroupTypes?.Contains(OrganisationType.AcademyTrust) == false) { continue; } var groupByLa = false; switch (providerType) { case "MaintainedSchools": groupByLa = true; break; } var orgGroups = processFile.GetOrgsOrOrgGroups($"{providerType}.csv", groupByLa); totalList.AddRange(ProcessOrgGroups(orgGroups, providerType, financialYearPeriod1920, financialYearPeriod2021, period, stream, schemaVersion, fundingVersion, organisationGroupIdentifiers, organisationIdentifiers, organisationTypes, variationReasons, ukprns, fundingLineTypes, templateLineIds) ); } return(totalList.ToArray()); }
/// <summary> /// Get provider funding from component parts. /// </summary> /// <param name="provider">A provider object.</param> /// <param name="financialYearPeriod1920">Period data for year1.</param> /// <param name="financialYearPeriod2021">Period data for year2.</param> /// <param name="period">Funding period.</param> /// <param name="stream">Data about a stream.</param> /// <param name="providerType">The type of provider (e.g. NonMaintainedSpecialSchools).</param> /// <param name="code">The code that identifies the provider (e.g. ukprn).</param> /// <returns>A provider funding object.</returns> private static ProviderFunding GetProviderFunding(Provider provider, FundingPeriod financialYearPeriod1920, FundingPeriod financialYearPeriod2021, FundingPeriod period, Stream stream, string providerType, string code) { var ukprn = $"MOCKUKPRN{provider.LaEstablishmentNo}"; var identifiers = new List <OrganisationIdentifier> { new OrganisationIdentifier { Type = OrganisationIdentifierType.UKPRN, Value = ukprn } }; if (providerType != "NonMaintainedSpecialSchools" && providerType != "Academies") { identifiers.Add(new OrganisationIdentifier { Type = OrganisationIdentifierType.LACode, Value = provider.LaEstablishmentNo }); } else { identifiers.Add(new OrganisationIdentifier { Type = OrganisationIdentifierType.URN, Value = code }); identifiers.Add(new OrganisationIdentifier { Type = OrganisationIdentifierType.DfeNumber, Value = code }); } var fundingVersion = "1-0"; return(new ProviderFunding { Id = $"{stream.Code}_{period.Code}_{ukprn}_{fundingVersion}", FundingVersion = fundingVersion.Replace("-", "."), FundingPeriodCode = period.Code, FundingStreamCode = stream.Code, Organisation = new Organisation { Name = provider.Name, SearchableName = FundingController.SanitiseName(provider.Name), OrganisationDetails = new OrganisationDetails() { DateClosed = null, DateOpened = new DateTimeOffset(2012, 12, 2, 0, 0, 0, 0, TimeSpan.Zero), PhaseOfEducation = "PhaseOfEducation", Status = "Open", OpenReason = ProviderOpenReason.NotRecorded, CloseReason = null, TrustName = null, TrustStatus = TrustStatus.NotApplicable, Address = new OrganisationAddress { Postcode = "MOCK POSTCODE", Town = "MOCK TOWN" } }, ProviderType = providerType, ProviderSubType = "Provider SubType", ProviderVersionId = "1.0", Identifiers = identifiers, }, FundingValue = new FundingValue { TotalValue = provider.TotalAllocation, // 16200, // "Maintained Schools" -> F3 FundingValueByDistributionPeriod = new List <FundingValueByDistributionPeriod> { new FundingValueByDistributionPeriod { DistributionPeriodCode = financialYearPeriod1920.Code, Value = provider.OctoberPayment, //9450, // "Maintained Schools" -> G3 FundingLines = new List <FundingLine> { new FundingLine { Name = "Total Allocation", // TemplateLineId = 1, Type = FundingLineType.Payment, Value = provider.OctoberPayment, //9450, // "Maintained Schools" -> G3 ProfilePeriods = new List <FundingLinePeriod> { new FundingLinePeriod // ProfiorPeriods { Occurence = 1, Year = 2019, TypeValue = "October", ProfiledValue = provider.OctoberPayment, //9450, // "Maintained Schools" -> G3 Type = FundingLinePeriodType.CalendarMonth, PeriodCode = financialYearPeriod1920.Code } }, Calculations = new List <Calculation> { new Calculation { Name = "Total Allocation", Type = CalculationType.Cash, TemplateCalculationId = 1, Value = provider.TotalAllocation, //"16200", // "Maintained Schools" ValueFormat = CalculationValueFormat.Currency, FormulaText = "School with pupils with less than 17 eligible pupils (X) = 1000 * X School with pupils with more than 16 eligible pupils (X) =((1 * 16000) + (10 * X))", ReferenceData = new List <ReferenceData> { new ReferenceData { Name = "Eligible pupils", Value = provider.EligiblePupilsCount.ToString(), // "20", // "Maintained Schools" Format = ReferenceDataValueFormat.Number }, } } } } } }, new FundingValueByDistributionPeriod { DistributionPeriodCode = financialYearPeriod2021.Code, Value = 6750, // "Maintained Schools" -> H3 FundingLines = new List <FundingLine> { new FundingLine { Name = "April payment",// "Maintained Schools" TemplateLineId = 2, Type = FundingLineType.Payment, Value = provider.AprilPayment, //6750, // "Maintained Schools" -> H3 ProfilePeriods = new List <FundingLinePeriod> { new FundingLinePeriod { Occurence = 1, Year = 2020, TypeValue = "April", ProfiledValue = provider.AprilPayment, //6750, // "Maintained Schools" -> H3 Type = FundingLinePeriodType.CalendarMonth, PeriodCode = financialYearPeriod2021.Code } }, Calculations = new List <Calculation> { new Calculation { Name = "Total Allocation", Type = CalculationType.Cash, TemplateCalculationId = 1, Value = provider.TotalAllocation, //"16200", // "Maintained Schools" ValueFormat = CalculationValueFormat.Currency, FormulaText = "School with pupils with less than 17 eligible pupils (X) = 1000 * X School with pupils with more than 16 eligible pupils (X) =((1 * 16000) + (10 * X))", ReferenceData = new List <ReferenceData> { new ReferenceData { Name = "Eligible pupils", Value = provider.EligiblePupilsCount.ToString(), // "20", // "Maintained Schools" Format = ReferenceDataValueFormat.Number }, } } } } } } } } }); }
public void GivenTheFundingPeriodExistsInThePoliciesService(Table table) { FundingPeriod fundingPeriod = table.CreateInstance <FundingPeriod>(); _policiesStepContext.Repo.SaveFundingPeriod(fundingPeriod); }
public object GetExamples() { var ukOffset = new TimeSpan(0, 0, 0); var fundingVersion = "1.0"; var period = new FundingPeriod { Code = "AY1920", Name = "Academic year 2019-20", Type = PeriodType.AcademicYear, StartDate = new DateTimeOffset(2019, 9, 1, 0, 0, 0, ukOffset), EndDate = new DateTimeOffset(2020, 8, 31, 0, 0, 0, ukOffset) }; var templateVersion = "2.1"; var stream = new StreamWithTemplateVersion { Code = "PESports", Name = "PE + Sport Premium", TemplateVersion = templateVersion, }; var schemaVersion = "1.0"; var groupingOrg = new OrganisationGroup() { Type = OrganisationType.LocalAuthority, Name = "Camden", SearchableName = "Camden", Identifiers = new List <OrganisationIdentifier> { new OrganisationIdentifier { Type = OrganisationIdentifierType.LACode, Value = "203" }, new OrganisationIdentifier { Type = OrganisationIdentifierType.UKPRN, Value = "12345678" } } }; var id = $"{stream.Code}_{period.Code}_{groupingOrg.Type}_{groupingOrg.Name}_{fundingVersion}"; var financialYearPeriod1920 = new FundingPeriod { Code = "FY1920", Name = "Financial Year 2019-20", Type = PeriodType.FinancialYear, StartDate = new DateTimeOffset(2019, 4, 1, 0, 0, 0, ukOffset), EndDate = new DateTimeOffset(2020, 3, 30, 0, 0, 0, ukOffset) }; var financialYearPeriod2021 = new FundingPeriod { Code = "FY2021", Name = "Financial Year 2020-21", Type = PeriodType.FinancialYear, StartDate = new DateTimeOffset(2020, 4, 1, 0, 0, 0, ukOffset), EndDate = new DateTimeOffset(2021, 3, 30, 0, 0, 0, ukOffset) }; return(new LogicalBaseModel { SchemaUri = "http://example.org/#schema", SchemaVersion = schemaVersion, Funding = new FundingProvider { FundingStream = stream, FundingPeriod = period, OrganisationGroup = groupingOrg, Id = id, FundingVersion = fundingVersion, ExternalPublicationDate = new DateTimeOffset(2019, 9, 1, 0, 0, 0, new TimeSpan(1, 0, 0)), PaymentDate = DateTimeOffset.Now, Status = FundingStatus.Released, StatusChangedDate = DateTimeOffset.Now, GroupingReason = GroupingReason.Payment, FundingValue = new FundingValue { FundingValueByDistributionPeriod = new List <FundingValueByDistributionPeriod> { new FundingValueByDistributionPeriod { DistributionPeriodCode = financialYearPeriod1920.Code, Value = 1400, FundingLines = new List <FundingLine> { new FundingLine { Name = "Total funding line", FundingLineCode = "TotalFundingLine", TemplateLineId = 1, Type = FundingLineType.Payment, Value = 1400, ProfilePeriods = new List <FundingLinePeriod> { new FundingLinePeriod { Occurence = 1, Year = 2019, TypeValue = "October", ProfiledValue = 1400, Type = FundingLinePeriodType.CalendarMonth, PeriodCode = financialYearPeriod1920.Code } }, } } }, new FundingValueByDistributionPeriod { DistributionPeriodCode = financialYearPeriod2021.Code, Value = 1000, FundingLines = new List <FundingLine> { new FundingLine { Name = "Total funding line", FundingLineCode = "FundingLineCode2", TemplateLineId = 1, Type = FundingLineType.Payment, Value = 1000, ProfilePeriods = new List <FundingLinePeriod> { new FundingLinePeriod { Occurence = 1, Year = 2020, TypeValue = "April", ProfiledValue = 1000, Type = FundingLinePeriodType.CalendarMonth, PeriodCode = financialYearPeriod2021.Code } } } } } }, TotalValue = 2400 }, ProviderFundings = new List <ProviderFunding> { new ProviderFunding { Id = $"{stream.Code}_{period.Code}_87654321_{fundingVersion}", FundingVersion = fundingVersion, FundingPeriodCode = period.Code, FundingStreamCode = stream.Code, Organisation = new Organisation { Name = "Example School 1", SearchableName = "ExampleSchool1", ProviderType = "School", Identifiers = new List <OrganisationIdentifier> { new OrganisationIdentifier { Type = OrganisationIdentifierType.URN, Value = "123453" }, new OrganisationIdentifier { Type = OrganisationIdentifierType.UKPRN, Value = "87654321" } } }, FundingValue = new FundingValue { TotalValue = 1200, FundingValueByDistributionPeriod = new List <FundingValueByDistributionPeriod> { new FundingValueByDistributionPeriod { DistributionPeriodCode = financialYearPeriod1920.Code, Value = 700, FundingLines = new List <FundingLine> { new FundingLine { Name = "Total funding line", FundingLineCode = "TotalFundingLine", TemplateLineId = 1, Type = FundingLineType.Payment, Value = 700, ProfilePeriods = new List <FundingLinePeriod> { new FundingLinePeriod { Occurence = 1, Year = 2019, TypeValue = "October", ProfiledValue = 700, Type = FundingLinePeriodType.CalendarMonth, PeriodCode = financialYearPeriod1920.Code } }, Calculations = new List <Calculation> { new Calculation { Name = "Number of pupils", Type = CalculationType.PupilNumber, TemplateCalculationId = 1, Value = "456", ValueFormat = CalculationValueFormat.Number, FormulaText = "Something * something", ReferenceData = new List <ReferenceData> { new ReferenceData { Name = "Academic year 2018 to 2019 pupil number on roll", Value = "1", Format = ReferenceDataValueFormat.Number, TemplateReferenceId = 1, } } }, new Calculation { Name = "Number of pupils", Type = CalculationType.PupilNumber, TemplateCalculationId = 1, Value = "456", ValueFormat = CalculationValueFormat.Number, FormulaText = "Something * something", ReferenceData = new List <ReferenceData> { new ReferenceData { Name = "Academic year 2018 to 2019 pupil number on roll", Value = "1", Format = ReferenceDataValueFormat.Number, TemplateReferenceId = 2, } } } }, } } }, new FundingValueByDistributionPeriod { DistributionPeriodCode = financialYearPeriod2021.Code, Value = 500, FundingLines = new List <FundingLine> { new FundingLine { Name = "Total funding line", FundingLineCode = "TotalFundingLine2", TemplateLineId = 1, Type = FundingLineType.Payment, Value = 500, ProfilePeriods = new List <FundingLinePeriod> { new FundingLinePeriod { Occurence = 1, Year = 2020, TypeValue = "April", ProfiledValue = 500, Type = FundingLinePeriodType.CalendarMonth, PeriodCode = financialYearPeriod2021.Code } } } } } } }, }, new ProviderFunding { Id = $"{stream.Code}_{period.Code}_87654322_{fundingVersion}", FundingVersion = fundingVersion, FundingPeriodCode = period.Code, FundingStreamCode = stream.Code, Organisation = new Organisation { Name = "Example School 2", SearchableName = "ExampleSchool2", ProviderType = "School", Identifiers = new List <OrganisationIdentifier> { new OrganisationIdentifier { Type = OrganisationIdentifierType.URN, Value = "123453" }, new OrganisationIdentifier { Type = OrganisationIdentifierType.UKPRN, Value = "87654322" } } }, FundingValue = new FundingValue { TotalValue = 1200, FundingValueByDistributionPeriod = new List <FundingValueByDistributionPeriod> { new FundingValueByDistributionPeriod { DistributionPeriodCode = financialYearPeriod1920.Code, Value = 700, FundingLines = new List <FundingLine> { new FundingLine { Name = "Total funding line", FundingLineCode = "TotalFundingLine", TemplateLineId = 1, Type = FundingLineType.Payment, Value = 700, ProfilePeriods = new List <FundingLinePeriod> { new FundingLinePeriod { Occurence = 1, Year = 2019, TypeValue = "October", ProfiledValue = 700, Type = FundingLinePeriodType.CalendarMonth, PeriodCode = financialYearPeriod1920.Code } } } } }, new FundingValueByDistributionPeriod { DistributionPeriodCode = financialYearPeriod2021.Code, Value = 500, FundingLines = new List <FundingLine> { new FundingLine { Name = "Total funding line", FundingLineCode = "TotalFundingLine2", TemplateLineId = 1, Type = FundingLineType.Payment, Value = 500, ProfilePeriods = new List <FundingLinePeriod> { new FundingLinePeriod { Occurence = 1, Year = 2020, TypeValue = "April", ProfiledValue = 500, Type = FundingLinePeriodType.CalendarMonth, PeriodCode = financialYearPeriod2021.Code } } } } } } } } } } }); }
/// <summary> /// Get the provider funding from the spreadsheet /// </summary> /// <param name="id">The id to lookup.</param> /// <returns>A provider funding object.</returns> public static ProviderFunding GenerateProviderFunding(string id) { var idParts = id.Split('_'); var code = idParts[2].Replace("MOCKUKPRN", string.Empty); var ukOffset = new TimeSpan(0, 0, 0); var period = new FundingPeriod { Code = "AY1920", Name = "Academic year 2019-20", Type = PeriodType.AcademicYear, StartDate = new DateTimeOffset(2019, 9, 1, 0, 0, 0, ukOffset), EndDate = new DateTimeOffset(2020, 8, 31, 0, 0, 0, ukOffset) }; var templateVersion = "1.0"; var stream = new StreamWithTemplateVersion { Code = "PESports", Name = "PE + Sport Premium", TemplateVersion = templateVersion, }; var financialYearPeriod1920 = new FundingPeriod { Code = "FY1920", Name = "Financial Year 2019-20", Type = PeriodType.FinancialYear, StartDate = new DateTimeOffset(2019, 4, 1, 0, 0, 0, ukOffset), EndDate = new DateTimeOffset(2020, 3, 30, 0, 0, 0, ukOffset) }; var financialYearPeriod2021 = new FundingPeriod { Code = "FY2021", Name = "Financial Year 2020-21", Type = PeriodType.FinancialYear, StartDate = new DateTimeOffset(2020, 4, 1, 0, 0, 0, ukOffset), EndDate = new DateTimeOffset(2021, 3, 30, 0, 0, 0, ukOffset) }; var processFile = new ProcessPesportsCsv(); var orgGroups = new List <OrgGroup>(); orgGroups.AddRange(processFile.GetOrgsOrOrgGroups("MaintainedSchools.csv", true)); orgGroups.AddRange(processFile.GetOrgsOrOrgGroups("Academies.csv", false)); orgGroups.AddRange(processFile.GetOrgsOrOrgGroups("MaintainedSchools.csv", false)); foreach (var orgGroup in orgGroups) { foreach (var provider in orgGroup.Providers) { if (provider.LaEstablishmentNo == code) { return(GetProviderFunding(provider, financialYearPeriod1920, financialYearPeriod2021, period, stream, orgGroup.Type, orgGroup.Code)); } } } return(null); }
/// <summary> /// Process org groups into feed models. /// </summary> /// <param name="orgGroups">List of org groups.</param> /// <param name="providerType">The provider types we are looking at.</param> /// <param name="financialYearPeriod1920">Data about the first financial period.</param> /// <param name="financialYearPeriod2021">Data about the second financial period.</param> /// <param name="period">Period to use.</param> /// <param name="stream">Stream to use.</param> /// <param name="schemaVersion">Schema version number.</param> /// <param name="fundingVersion">Funding version number.</param> /// <param name="organisationGroupIdentifiers">Optional - The group identifiers to limit by (e.g. UKPRN 12345678).</param> /// <param name="organisationIdentifiers">Optional - The organisation identifiers to limit to (e.g. UKPRN 12345678).</param> /// <param name="organisationTypes">Optional - The organisation types to return.</param> /// <param name="variationReasons">Optional - Filter to only organisations with these variation reasons types</param> /// <param name="ukprns">Optional - Only get these UKPRNs back.</param> /// <param name="fundingLineTypes">Optional - limit the types of lines we want to get back (e.g. Information and/or Payment).</param> /// <param name="templateLineIds">Optional - Filter the lines to these ids only.</param> /// <returns>A list of feed response models.</returns> private static List <FeedResponseContentModel> ProcessOrgGroups(List <OrgGroup> orgGroups, string providerType, FundingPeriod financialYearPeriod1920, FundingPeriod financialYearPeriod2021, FundingPeriod period, StreamWithTemplateVersion stream, string schemaVersion, string fundingVersion, OrganisationIdentifier[] organisationGroupIdentifiers, OrganisationIdentifier[] organisationIdentifiers, OrganisationType[] organisationTypes, VariationReason[] variationReasons, string[] ukprns, FundingLineType[] fundingLineTypes, string[] templateLineIds) { var returnList = new List <FeedResponseContentModel>(); // Limit by org group identifiers if (organisationGroupIdentifiers?.Any() == true) { foreach (var organisationGroupIdentifier in organisationGroupIdentifiers) { orgGroups = orgGroups.Where(orgGroup => orgGroup.Type != organisationGroupIdentifier.Type.ToString() || orgGroup.Code == organisationGroupIdentifier.Value).ToList(); } } // Limit by org identifiers if (organisationIdentifiers?.Any() == true) { foreach (var orgGroup in orgGroups) { orgGroup.Providers = orgGroup.Providers.Where(provider => organisationIdentifiers.Any(oi => oi.Type != OrganisationIdentifierType.LACode || oi.Value == provider.LaEstablishmentNo)).ToList(); } } foreach (var orgGroup in orgGroups) { var orgType = providerType == "NonMaintainedSpecialSchools" || providerType == "Academies" ? (providerType == "NonMaintainedSpecialSchools" ? OrganisationType.Provider : OrganisationType.AcademyTrust) : OrganisationType.LocalAuthority; var ukprn = $"MOCKUKPRN{orgGroup.Code}"; var groupingOrg = ConvertToOrganisationGroup(orgGroup, ukprn, orgType); var id = $"{stream.Code}_{period.Code}_{groupingOrg.Type}_{ukprn}_{fundingVersion}"; var data = new FeedBaseModel { SchemaUri = "http://example.org/#schema", SchemaVersion = schemaVersion, Funding = new FundingFeed { Id = id, FundingStream = stream, FundingPeriod = period, OrganisationGroup = groupingOrg, FundingVersion = fundingVersion.Replace("-", "."), ExternalPublicationDate = new DateTimeOffset(2019, 9, 1, 0, 0, 0, new TimeSpan(1, 0, 0)), PaymentDate = DateTimeOffset.Now, Status = FundingStatus.Released, StatusChangedDate = DateTimeOffset.Now, GroupingReason = GroupingReason.Payment, ProviderFundings = GetProviderFundingIds(orgGroup, period, stream, fundingVersion, organisationTypes, variationReasons, ukprns), FundingValue = new FundingValue { TotalValue = orgGroup.TotalAllocation, FundingValueByDistributionPeriod = new List <FundingValueByDistributionPeriod> { new FundingValueByDistributionPeriod { DistributionPeriodCode = financialYearPeriod1920.Code, Value = orgGroup.OctoberTotal, FundingLines = new List <FundingLine> { new FundingLine { Name = "Total funding line", TemplateLineId = 1, Type = FundingLineType.Payment, Value = orgGroup.OctoberTotal, ProfilePeriods = new List <FundingLinePeriod> { new FundingLinePeriod { Occurence = 1, Year = 2019, TypeValue = "October", ProfiledValue = orgGroup.OctoberTotal, Type = FundingLinePeriodType.CalendarMonth, PeriodCode = financialYearPeriod1920.Code } }, } } }, new FundingValueByDistributionPeriod { DistributionPeriodCode = financialYearPeriod2021.Code, Value = orgGroup.AprilTotal, FundingLines = new List <FundingLine> { new FundingLine { Name = "Total funding line", TemplateLineId = 2, Type = FundingLineType.Payment, Value = orgGroup.AprilTotal, ProfilePeriods = new List <FundingLinePeriod> { new FundingLinePeriod { Occurence = 1, Year = 2020, TypeValue = "April", ProfiledValue = orgGroup.AprilTotal, Type = FundingLinePeriodType.CalendarMonth, PeriodCode = financialYearPeriod2021.Code } } } } } } } }, }; if (fundingLineTypes?.Any() == true) { foreach (var dperiod in data.Funding.FundingValue.FundingValueByDistributionPeriod) { dperiod.FundingLines = dperiod.FundingLines.Where(line => fundingLineTypes.Contains(line.Type)).ToList(); //TODO - filter at lower levels } } if (templateLineIds?.Any() == true) { foreach (var dperiod in data.Funding.FundingValue.FundingValueByDistributionPeriod) { dperiod.FundingLines = dperiod.FundingLines.Where(line => templateLineIds.Contains(line.TemplateLineId.ToString())).ToList(); //TODO - filter at lower levels } } var host = "http://example.org"; returnList.Add(new FeedResponseContentModel { Content = data, Id = data.Funding.Id, Author = new FeedResponseAuthor { Email = "*****@*****.**", Name = "Calculate Funding Service" }, Title = data.Funding.Id, Updated = DateTime.Now, Link = new FeedLink[] { new FeedLink { Href = $"{host}/api/funding/feed/byId/{data.Funding.Id}", Rel = "self" } } }); } ; return(returnList); }