public async Task CalculateProfileService_ShouldCorrectlyProfileEdgeCaseAllocationJustWithinPatternMonths() { // arrange FundingStreamPeriodProfilePattern pattern = TestResource.FromJson <FundingStreamPeriodProfilePattern>( NamespaceResourcesResideIn, "Resources.PESPORTSPREM.json"); // first period rouonds down ProfileRequest peSportsPremReq1 = new ProfileRequest( fundingStreamId: "PSG", fundingPeriodId: "AY-1819", fundingLineCode: "FL1", fundingValue: 1000); IProfilePatternRepository mockProfilePatternRepository = Substitute.For <IProfilePatternRepository>(); mockProfilePatternRepository .GetProfilePattern(Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>()) .Returns(pattern); ICalculateProfileService calculateProfileService = GetCalculateProfileServiceWithMockedDependencies(mockProfilePatternRepository); // act IActionResult responseResult = await calculateProfileService.ProcessProfileAllocationRequest(peSportsPremReq1); // assert responseResult .Should().BeOfType <OkObjectResult>(); OkObjectResult responseAsOkObjectResult = responseResult as OkObjectResult; AllocationProfileResponse response = responseAsOkObjectResult.Value as AllocationProfileResponse; response.DeliveryProfilePeriods.ToArray().FirstOrDefault(q => q.TypeValue == "October").ProfileValue.Should().Be(583.00M); response.DeliveryProfilePeriods.ToArray().FirstOrDefault(q => q.TypeValue == "April").ProfileValue.Should().Be(417.00M); response.DeliveryProfilePeriods.Length.Should().Be(3); }
public void GuardsAgainstProfiledAmountsAndCarryOverNotBeingSameAsFundingValueInTheSuppliedRequestAfterReProfiling() { ReProfileRequest request = NewReProfileRequest(); AllocationProfileResponse profileResponse = NewAllocationProfileResponse(); string key = NewRandomString(); FundingStreamPeriodProfilePattern profilePattern = NewFundingStreamPeriodProfilePattern(_ => _.WithReProfilingConfiguration(NewProfilePatternReProfilingConfiguration(cfg => cfg.WithIsEnabled(true) .WithIncreasedAmountStrategyKey(key)))); GivenTheProfilePattern(request, profilePattern); AndTheReProfilingStrategy(key); AndTheProfiling(request, profilePattern, profileResponse); AndTheReProfilingStrategyResponse(profileResponse, request, profilePattern, NewReProfileStrategyResult()); _service .Awaiting(_ => _.ReProfile(request)) .Should() .Throw <InvalidOperationException>() .Which .Message .Should() .Be($"Profile amounts (0) and carry over amount (0) does not equal funding line total requested ({request.FundingLineTotal}) from strategy."); }
public async Task CalculateProfileService_ShouldCorrectlyProfileFullLengthAllocationWithRoundUp() { // arrange FundingStreamPeriodProfilePattern pattern = TestResource.FromJson <FundingStreamPeriodProfilePattern>( NamespaceResourcesResideIn, "Resources.DSG.json"); // first period rouonds down ProfileRequest peSportsPremReq1 = new ProfileRequest( fundingStreamId: "DSG", fundingPeriodId: "FY-2021", fundingLineCode: "DSG-002", fundingValue: 10000543); IProfilePatternRepository mockProfilePatternRepository = Substitute.For <IProfilePatternRepository>(); mockProfilePatternRepository .GetProfilePattern(Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>()) .Returns(pattern); ICalculateProfileService calculateProfileService = GetCalculateProfileServiceWithMockedDependencies(mockProfilePatternRepository); // act IActionResult responseResult = await calculateProfileService.ProcessProfileAllocationRequest(peSportsPremReq1); // assert responseResult .Should().BeOfType <OkObjectResult>(); OkObjectResult responseAsOkObjectResult = responseResult as OkObjectResult; AllocationProfileResponse response = responseAsOkObjectResult.Value as AllocationProfileResponse; response.DeliveryProfilePeriods.ToArray().FirstOrDefault(q => q.TypeValue == "April").ProfileValue.Should().Be(400021M); response.DeliveryProfilePeriods.ToArray().LastOrDefault(q => q.TypeValue == "March").ProfileValue.Should().Be(400039M); response.DeliveryProfilePeriods.Length.Should().Be(25); }
public async Task ProfilesEachProviderFundingValueInTheSuppliedBatches() { decimal fundingValueOne = NewRandomFundingValue(); decimal fundingValueTwo = NewRandomFundingValue(); decimal fundingValueThree = NewRandomFundingValue(); ProfileBatchRequest request = NewProfileBatchRequest(_ => _.WithFundingValues(fundingValueOne, fundingValueTwo, fundingValueThree)); FundingStreamPeriodProfilePattern profilePattern = NewProfilePattern(); AllocationProfileResponse allocationProfileResponseOne = NewAllocationProfileResponse(); AllocationProfileResponse allocationProfileResponseTwo = NewAllocationProfileResponse(); AllocationProfileResponse allocationProfileResponseThree = NewAllocationProfileResponse(); GivenTheValidationResult(request, NewValidationResult()); AndTheProfilePattern(request, profilePattern); AndTheProfilingResponse(request, profilePattern, fundingValueOne, allocationProfileResponseOne); AndTheProfilingResponse(request, profilePattern, fundingValueTwo, allocationProfileResponseTwo); AndTheProfilingResponse(request, profilePattern, fundingValueThree, allocationProfileResponseThree); OkObjectResult result = await WhenTheBatchProfileRequestIsProcessed(request) as OkObjectResult; result?.Value .Should() .BeEquivalentTo(new[] { new BatchAllocationProfileResponse(request.GetFundingValueKey(fundingValueOne), fundingValueOne, allocationProfileResponseOne), new BatchAllocationProfileResponse(request.GetFundingValueKey(fundingValueTwo), fundingValueTwo, allocationProfileResponseTwo), new BatchAllocationProfileResponse(request.GetFundingValueKey(fundingValueThree), fundingValueThree, allocationProfileResponseThree) }); }
private void AndTheReProfilingStrategyResponse(AllocationProfileResponse profileResponse, ReProfileRequest request, FundingStreamPeriodProfilePattern profilePattern, ReProfileStrategyResult response) => _reProfilingStrategy.Setup(_ => _.ReProfile(It.Is <ReProfileContext>(ctx => ReferenceEquals(ctx.Request, request) && ReferenceEquals(ctx.ProfilePattern, profilePattern) && ReferenceEquals(ctx.ProfileResult, profileResponse)))) .Returns(response);
public BatchAllocationProfileResponse(string key, decimal fundingValue, AllocationProfileResponse allocationProfileResponse) : base(allocationProfileResponse.DeliveryProfilePeriods, allocationProfileResponse.DistributionPeriods) { ProfilePatternKey = allocationProfileResponse.ProfilePatternKey; ProfilePatternDisplayName = allocationProfileResponse.ProfilePatternDisplayName; Key = key; FundingValue = fundingValue; }
private void AndTheProfiling(ReProfileRequest request, FundingStreamPeriodProfilePattern profilePattern, AllocationProfileResponse response) => _profiling.Setup(_ => _.ProfileAllocation(It.Is <ProfileRequest>(req => req.FundingStreamId == request.FundingStreamId && req.FundingPeriodId == request.FundingPeriodId && req.FundingLineCode == request.FundingLineCode && req.FundingValue == request.FundingLineTotal && req.ProfilePatternKey == request.ProfilePatternKey), profilePattern, request.FundingLineTotal)) .Returns(response);
public async Task CalculateProfileService_ShouldCorrectlyCalculateNormalPESportsPremium() { // arrange FundingStreamPeriodProfilePattern pattern = TestResource.FromJson <FundingStreamPeriodProfilePattern>( NamespaceResourcesResideIn, "Resources.PESPORTSPREM.json"); ProfileRequest peSportsPremReq = new ProfileRequest( fundingStreamId: "PSG", fundingPeriodId: "AY-1819", fundingLineCode: "FL1", fundingValue: 200); IProfilePatternRepository mockProfilePatternRepository = Substitute.For <IProfilePatternRepository>(); mockProfilePatternRepository .GetProfilePattern(Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>()) .Returns(pattern); ICalculateProfileService calculateProfileService = GetCalculateProfileServiceWithMockedDependencies(mockProfilePatternRepository); // act IActionResult responseResult = await calculateProfileService.ProcessProfileAllocationRequest(peSportsPremReq); // assert responseResult .Should() .BeOfType <OkObjectResult>(); OkObjectResult responseAsOkObjectResult = responseResult as OkObjectResult; AllocationProfileResponse response = responseAsOkObjectResult.Value as AllocationProfileResponse; DeliveryProfilePeriod deliveryProfilePeriodReturnedForOct = response.DeliveryProfilePeriods.ToArray().FirstOrDefault(q => q.TypeValue == "October"); DeliveryProfilePeriod deliveryProfilePeriodReturnedForApr = response.DeliveryProfilePeriods.ToArray().FirstOrDefault(q => q.TypeValue == "April"); response.DeliveryProfilePeriods.Length.Should().Be(3); deliveryProfilePeriodReturnedForOct .Should().NotBeNull(); deliveryProfilePeriodReturnedForOct .ProfileValue .Should().Be(117M); deliveryProfilePeriodReturnedForApr .Should().NotBeNull(); deliveryProfilePeriodReturnedForApr .ProfileValue .Should().Be(83M); }
public async Task <IActionResult> ProcessProfileAllocationRequest(ProfileRequest profileRequest) { Guard.ArgumentNotNull(profileRequest, nameof(profileRequest)); _logger.Information($"Retrieved a request {profileRequest}"); try { FundingStreamPeriodProfilePattern profilePattern = await GetProfilePattern(profileRequest); if (profilePattern == null) { _logger.Error("Unable to find profile pattern for FundingStream = {fundingStreamId}, FundingPeriodId={FundingPeriodId}, FundingLineCode={FundingLineCode}, ProfilePatternKey={ProfilePatternKey}, ProviderType={ProviderType}, ProviderSubType={ProviderSubType}", profileRequest.FundingStreamId, profileRequest.FundingPeriodId, profileRequest.FundingLineCode, profileRequest.ProfilePatternKey, profileRequest.ProviderType, profileRequest.ProviderSubType); } ProfileValidationResult validationResult = ProfileRequestValidator.ValidateRequestAgainstPattern(profileRequest, profilePattern); if (validationResult.Code != HttpStatusCode.OK) { _logger.Information($"Returned status code of {validationResult.Code} for {profileRequest}"); return(new StatusCodeResult((int)validationResult.Code)); } AllocationProfileResponse profilingResult = ProfileAllocation(profileRequest, profilePattern, profileRequest.FundingValue); profilingResult.ProfilePatternKey = profilePattern.ProfilePatternKey; profilingResult.ProfilePatternDisplayName = profilePattern.ProfilePatternDisplayName; _logger.Information($"Returned Ok for {profileRequest}"); return(new OkObjectResult(profilingResult)); } catch (Exception ex) { LogError(ex, profileRequest); throw; } }
public async Task CalculateProfileService_ProcessProfileAllocationRequest_WhenFinancialEnvelopeShouldBeReturned_ThenObjectSetSuccessfully() { // arrange FundingStreamPeriodProfilePattern pattern = TestResource.FromJson <FundingStreamPeriodProfilePattern>( NamespaceResourcesResideIn, "Resources.PESPORTSPREM.json"); // first period rouonds down ProfileRequest peSportsPremReq1 = new ProfileRequest( fundingStreamId: "PSG", fundingPeriodId: "AY-1819", fundingLineCode: "FL1", fundingValue: 6); IProfilePatternRepository mockProfilePatternRepository = Substitute.For <IProfilePatternRepository>(); mockProfilePatternRepository .GetProfilePattern(Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>()) .Returns(pattern); ICalculateProfileService calculateProfileService = GetCalculateProfileServiceWithMockedDependencies(mockProfilePatternRepository); // act IActionResult responseResult = await calculateProfileService.ProcessProfileAllocationRequest(peSportsPremReq1); // assert responseResult .Should() .BeOfType <OkObjectResult>(); OkObjectResult responseAsOkObjectResult = responseResult as OkObjectResult; AllocationProfileResponse response = responseAsOkObjectResult.Value as AllocationProfileResponse; response .DeliveryProfilePeriods .Should() .NotBeNull(); response .DeliveryProfilePeriods .Should() .HaveCount(3); }
public async Task ProfilesFundingLinesNormallyThenReProfilesUsingTheseResultsWithSameAmountStrategyIfFundingTheSame() { decimal newFundingTotal = NewRandomTotal(); ReProfileRequest request = NewReProfileRequest(_ => _.WithFundingValue(newFundingTotal) .WithExistingFundingValue(newFundingTotal)); AllocationProfileResponse profileResponse = NewAllocationProfileResponse(); string key = NewRandomString(); FundingStreamPeriodProfilePattern profilePattern = NewFundingStreamPeriodProfilePattern(_ => _.WithReProfilingConfiguration(NewProfilePatternReProfilingConfiguration(cfg => cfg.WithIsEnabled(true) .WithSameAmountStrategyKey(key)))); DistributionPeriods distributionPeriods1 = NewDistributionPeriods(); DeliveryProfilePeriod deliveryProfilePeriod1 = NewDeliveryProfilePeriod(_ => _.WithProfiledValue(10)); DeliveryProfilePeriod deliveryProfilePeriod2 = NewDeliveryProfilePeriod(_ => _.WithProfiledValue(newFundingTotal - 20)); GivenTheProfilePattern(request, profilePattern); AndTheReProfilingStrategy(key); AndTheProfiling(request, profilePattern, profileResponse); AndTheReProfilingStrategyResponse(profileResponse, request, profilePattern, NewReProfileStrategyResult(_ => _.WithDistributionPeriods(distributionPeriods1) .WithDeliveryProfilePeriods(deliveryProfilePeriod1, deliveryProfilePeriod2) .WithCarryOverAmount(10))); ActionResult <ReProfileResponse> reProfileResponse = await WhenTheFundingLineIsReProfiled(request); reProfileResponse? .Value .Should() .BeEquivalentTo(new ReProfileResponse { DistributionPeriods = new [] { distributionPeriods1 }, CarryOverAmount = 10, DeliveryProfilePeriods = new [] { deliveryProfilePeriod1, deliveryProfilePeriod2 }, ProfilePatternKey = profilePattern.ProfilePatternKey, ProfilePatternDisplayName = profilePattern.ProfilePatternDisplayName }); }
private ReProfileContext CreateReProfilingContext(ReProfileRequest reProfileRequest, FundingStreamPeriodProfilePattern profilePattern) { AllocationProfileResponse profileResult = _calculateProfileService.ProfileAllocation(new ProfileRequest { FundingLineCode = reProfileRequest.FundingLineCode, FundingPeriodId = reProfileRequest.FundingPeriodId, FundingStreamId = reProfileRequest.FundingStreamId, FundingValue = reProfileRequest.FundingLineTotal, ProfilePatternKey = reProfileRequest.ProfilePatternKey }, profilePattern, reProfileRequest.FundingLineTotal); return(new ReProfileContext { Request = reProfileRequest, ProfilePattern = profilePattern, ProfileResult = profileResult }); }
private Task ProfileProviderFundingValues(CancellationToken token, dynamic context, IEnumerable <decimal> providerFundingValues) { BatchProfileRequestContext batchProfileRequestContext = (BatchProfileRequestContext)context; foreach (decimal providerFundingValue in providerFundingValues) { ProfileBatchRequest request = batchProfileRequestContext.Request; AllocationProfileResponse allocationProfileResponse = ProfileAllocation(request, batchProfileRequestContext.ProfilePattern, providerFundingValue); batchProfileRequestContext.AddResponse( new BatchAllocationProfileResponse(request.GetFundingValueKey(providerFundingValue), providerFundingValue, allocationProfileResponse)); } return(Task.CompletedTask); }
public void ProfileAllocation_ShouldSetProfilePatternKeyAndDisplayNameInResponse() { string profilePatternKey = NewRandomString(); string profilePatternDisplayName = NewRandomString(); ProfileBatchRequest profileRequest = NewProfileBatchRequest(_ => _.WithFundingStreamId(NewRandomString())); FundingStreamPeriodProfilePattern profilePattern = NewFundingStreamPeriodProfilePattern(_ => _.WithProfilePattern() .WithProfilePatternKey(profilePatternKey) .WithProfilePatternDisplayName(profilePatternDisplayName)); IFundingValueProfiler profiler = new FundingValueProfiler(); AllocationProfileResponse response = profiler.ProfileAllocation(profileRequest, profilePattern, decimal.MinValue); response.Should() .NotBeNull(); response.ProfilePatternKey .Should().Be(profilePatternKey); response.ProfilePatternDisplayName .Should().Be(profilePatternDisplayName); }
private void AndTheProfilingResponse(ProfileRequestBase request, FundingStreamPeriodProfilePattern profilePattern, decimal fundingValue, AllocationProfileResponse allocationProfileResponse) => _fundingValueProfiler.Setup(_ => _.ProfileAllocation(request, profilePattern, fundingValue)) .Returns(allocationProfileResponse);
public ReProfileContextBuilder WithAllocationProfileResponse(AllocationProfileResponse response) { _response = response; return(this); }
public void WhenAValidProfileIsProvidedWithMultipleProfilesPerDistributionPeriod_ThenCorrectResultsProduced() { // Arrange ProfileRequest profileRequest = new ProfileRequest() { FundingLineCode = "TestFLC", FundingPeriodId = "AY-1920", FundingStreamId = "PSG", FundingValue = 12000, }; FundingStreamPeriodProfilePattern fundingStreamPeriodProfilePattern = new FundingStreamPeriodProfilePattern() { FundingLineId = "TestFLC", FundingPeriodId = "AY-1920", FundingStreamId = "PSG", FundingStreamPeriodEndDate = DateTime.Parse("2020-08-31T23:59:59"), FundingStreamPeriodStartDate = DateTime.Parse("2019-09-01T00:00:00"), ProfilePattern = new ProfilePeriodPattern[] { new ProfilePeriodPattern(PeriodType.CalendarMonth, "October", DateTime.Parse("2019-09-01T00:00:00"), DateTime.Parse("2020-03-31T23:59:59"), 1920, 1, "FY-1920", 38.33333333M), new ProfilePeriodPattern(PeriodType.CalendarMonth, "November", DateTime.Parse("2019-09-01T00:00:00"), DateTime.Parse("2020-03-31T23:59:59"), 1920, 1, "FY-1920", 20M), new ProfilePeriodPattern(PeriodType.CalendarMonth, "April", DateTime.Parse("2020-04-01T00:00:00"), DateTime.Parse("2020-08-31T23:59:59"), 1920, 1, "FY-2021", 58.33333333M), } }; // Act AllocationProfileResponse result = _service.ProfileAllocation(profileRequest, fundingStreamPeriodProfilePattern, profileRequest.FundingValue); // Assert result .Should() .BeEquivalentTo(new AllocationProfileResponse() { DeliveryProfilePeriods = new DeliveryProfilePeriod[] { new DeliveryProfilePeriod() { DistributionPeriod = "FY-1920", Occurrence = 1, ProfileValue = 4600, Type = PeriodType.CalendarMonth, TypeValue = "October", Year = 1920, }, new DeliveryProfilePeriod() { DistributionPeriod = "FY-1920", Occurrence = 1, ProfileValue = 2400, Type = PeriodType.CalendarMonth, TypeValue = "November", Year = 1920, }, new DeliveryProfilePeriod() { DistributionPeriod = "FY-2021", Occurrence = 1, ProfileValue = 5000, Type = PeriodType.CalendarMonth, TypeValue = "April", Year = 1920, } }, DistributionPeriods = new DistributionPeriods[] { new DistributionPeriods() { DistributionPeriodCode = "FY-1920", Value = 7000, }, new DistributionPeriods() { DistributionPeriodCode = "FY-2021", Value = 5000, } } }); }
public async Task CalculateProfileService_ShouldCorrectlyCalculateNormalPESportsPremium_WithRounding() { // arrange FundingStreamPeriodProfilePattern pattern = TestResource.FromJson <FundingStreamPeriodProfilePattern>( NamespaceResourcesResideIn, "Resources.PESPORTSPREM.json"); // first period rouonds down ProfileRequest peSportsPremReq1 = new ProfileRequest( fundingStreamId: "PSG", fundingPeriodId: "AY-1819", fundingLineCode: "FL1", fundingValue: 200); // first period rounds up ProfileRequest peSportsPremReq2 = new ProfileRequest( fundingStreamId: "PSG", fundingPeriodId: "AY-1819", fundingLineCode: "FL1", fundingValue: 500); ProfileRequest peSportsPremReq3 = new ProfileRequest( fundingStreamId: "PSG", fundingPeriodId: "AY-1819", fundingLineCode: "FL1", fundingValue: int.MaxValue); IProfilePatternRepository mockProfilePatternRepository = Substitute.For <IProfilePatternRepository>(); mockProfilePatternRepository .GetProfilePattern(Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>()) .Returns(pattern); ICalculateProfileService calculateProfileService = GetCalculateProfileServiceWithMockedDependencies(mockProfilePatternRepository); // act IActionResult responseResult1 = await calculateProfileService.ProcessProfileAllocationRequest(peSportsPremReq1); IActionResult responseResult2 = await calculateProfileService.ProcessProfileAllocationRequest(peSportsPremReq2); IActionResult responseResult3 = await calculateProfileService.ProcessProfileAllocationRequest(peSportsPremReq3); // assert responseResult1 .Should().BeOfType <OkObjectResult>(); responseResult2 .Should().BeOfType <OkObjectResult>(); responseResult3 .Should().BeOfType <OkObjectResult>(); OkObjectResult responseAsOkObjectResult1 = responseResult1 as OkObjectResult; OkObjectResult responseAsOkObjectResult2 = responseResult2 as OkObjectResult; OkObjectResult responseAsOkObjectResult3 = responseResult3 as OkObjectResult; AllocationProfileResponse response1 = responseAsOkObjectResult1.Value as AllocationProfileResponse; AllocationProfileResponse response2 = responseAsOkObjectResult2.Value as AllocationProfileResponse; AllocationProfileResponse response3 = responseAsOkObjectResult3.Value as AllocationProfileResponse; response1.DeliveryProfilePeriods.ToArray().FirstOrDefault(q => q.TypeValue == "October").ProfileValue.Should().Be(117M); response1.DeliveryProfilePeriods.ToArray().FirstOrDefault(q => q.TypeValue == "April").ProfileValue.Should().Be(83M); response1.DeliveryProfilePeriods.ToArray().LastOrDefault(q => q.TypeValue == "April").ProfileValue.Should().Be(0M); response1.DeliveryProfilePeriods.Length.Should().Be(3); response2.DeliveryProfilePeriods.ToArray().FirstOrDefault(q => q.TypeValue == "October").ProfileValue.Should().Be(292M); response2.DeliveryProfilePeriods.ToArray().FirstOrDefault(q => q.TypeValue == "April").ProfileValue.Should().Be(208M); response2.DeliveryProfilePeriods.ToArray().LastOrDefault(q => q.TypeValue == "April").ProfileValue.Should().Be(0M); response2.DeliveryProfilePeriods.Length.Should().Be(3); response3.DeliveryProfilePeriods.ToArray().FirstOrDefault(q => q.TypeValue == "October").ProfileValue.Should().Be(1252698794M); response3.DeliveryProfilePeriods.ToArray().FirstOrDefault(q => q.TypeValue == "April").ProfileValue.Should().Be(894784853M); response3.DeliveryProfilePeriods.ToArray().LastOrDefault(q => q.TypeValue == "April").ProfileValue.Should().Be(0M); response3.DeliveryProfilePeriods.Length.Should().Be(3); }