private IReProfilingStrategy GetReProfilingStrategy(ReProfileRequest reProfileRequest, FundingStreamPeriodProfilePattern profilePattern) { string key = profilePattern.GetReProfilingStrategyKeyForFundingAmountChange(reProfileRequest.FundingLineTotalChange); return(_reProfilingStrategyLocator.GetStrategy(key)); }
public async Task <IActionResult> PreviewProfilingChange(ProfilePreviewRequest request) { Guard.ArgumentNotNull(request, nameof(request)); ReProfileRequest reProfileRequest = await _reProfilingRequestBuilder.BuildReProfileRequest(request.SpecificationId, request.FundingStreamId, request.FundingPeriodId, request.ProviderId, request.FundingLineCode, request.ProfilePatternKey, request.ConfigurationType); ApiResponse <ReProfileResponse> reProfilingApiResponse = await _profilingResilience.ExecuteAsync(() => _profiling.ReProfile(reProfileRequest)); ReProfileResponse reProfileResponse = reProfilingApiResponse?.Content; if (reProfileResponse == null) { throw new InvalidOperationException( $"Did not received a valid re-profiling response for profile pattern preview request {request}"); } ExistingProfilePeriod[] existingProfilePeriods = reProfileRequest.ExistingPeriods.ToArray(); int isPaidTo = GetIsPaidTo(existingProfilePeriods); ProfileTotal[] profileTotals = BuildProfileTotals(reProfileResponse, existingProfilePeriods, isPaidTo); await AddFundingDatesToProfileTotals(request, profileTotals); return(new OkObjectResult(profileTotals)); }
private void GivenTheProfilePattern(ReProfileRequest request, FundingStreamPeriodProfilePattern profilePattern) => _profilePatterns.Setup(_ => _.GetProfilePattern(request.FundingStreamId, request.FundingPeriodId, request.FundingLineCode, request.ProfilePatternKey)) .ReturnsAsync(profilePattern);
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."); }
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);
private decimal AdjustForUnderOrOverPayment(ReProfileContext context) { decimal carryOverAmount = 0; ReProfileRequest reProfileRequest = context.Request; IProfilePeriod[] orderedRefreshProfilePeriods = new YearMonthOrderedProfilePeriods <IProfilePeriod>(context.ProfileResult.DeliveryProfilePeriods) .ToArray(); IExistingProfilePeriod[] orderedExistingProfilePeriods = new YearMonthOrderedProfilePeriods <IExistingProfilePeriod>(reProfileRequest.ExistingPeriods) .ToArray(); // get the last profile period paid IExistingProfilePeriod existingProfilePeriod = orderedExistingProfilePeriods.LastOrDefault(_ => _.IsPaid); // the variation pointer is the index of the next period after the last paid profile period int variationPointerIndex = existingProfilePeriod == null ? 0 : Array.IndexOf(orderedExistingProfilePeriods, existingProfilePeriod) + 1; decimal previousFundingLineValuePaid = orderedExistingProfilePeriods.Take(variationPointerIndex).Sum(_ => _.GetProfileValue()); decimal latestFundingLineValuePaid = orderedRefreshProfilePeriods.Take(variationPointerIndex).Sum(_ => _.GetProfileValue()); decimal latestFundingLineValue = reProfileRequest.FundingLineTotal; decimal fundingChange = latestFundingLineValuePaid - previousFundingLineValuePaid; decimal latestPeriodAmount = (int)(latestFundingLineValue / orderedRefreshProfilePeriods.Length); AdjustPeriodsForFundingAlreadyReleased(variationPointerIndex, orderedExistingProfilePeriods, orderedRefreshProfilePeriods); if (fundingChange < 0) { if (AdjustingPeriodsForOverPaymentLeavesRemainder(variationPointerIndex, latestPeriodAmount, orderedExistingProfilePeriods, orderedRefreshProfilePeriods, out decimal remainingOverPayment)) { carryOverAmount = remainingOverPayment; } } else if (fundingChange > 0) { AdjustPeriodsForUnderPayment(variationPointerIndex, latestPeriodAmount, orderedExistingProfilePeriods, orderedRefreshProfilePeriods); } else { AdjustPeriodsForNoTotalAllocationChange(variationPointerIndex, latestPeriodAmount, orderedExistingProfilePeriods, orderedRefreshProfilePeriods, out carryOverAmount); } return(carryOverAmount); }
private void AndTheTheReProfileRequest(FundingLine fundingLine, ReProfileRequest reProfileRequest) => _reProfileRequestBuilder.Setup(_ => _.BuildReProfileRequest(RefreshState.SpecificationId, RefreshState.FundingStreamId, RefreshState.FundingPeriodId, RefreshState.ProviderId, fundingLine.FundingLineCode, null, ProfileConfigurationType.RuleBased, fundingLine.Value)) .ReturnsAsync(reProfileRequest);
private void GivenTheReProfileRequest(ProfilePreviewRequest previewRequest, ReProfileRequest reProfileRequest) => _reProfilingRequestBuilder.Setup(_ => _.BuildReProfileRequest(previewRequest.SpecificationId, previewRequest.FundingStreamId, previewRequest.FundingPeriodId, previewRequest.ProviderId, previewRequest.FundingLineCode, previewRequest.ProfilePatternKey, previewRequest.ConfigurationType, null)) .ReturnsAsync(reProfileRequest);
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 ReturnsBadRequestIfTheMatchingPatternHasNoReProfilingConfiguration() { ReProfileRequest request = NewReProfileRequest(); GivenTheProfilePattern(request, NewFundingStreamPeriodProfilePattern()); ActionResult <ReProfileResponse> result = await WhenTheFundingLineIsReProfiled(request); result .Result .Should() .BeOfType <BadRequestObjectResult>() .Which .Value .Should() .Be("Re-profiling is not enabled or has not been configured"); }
public async Task ReProfilesFundingLinesInTheRefreshStateWhereTheyShowAsAffectedFundingLineCodes() { FundingLine fundingLineOne = NewFundingLine(); FundingLine fundingLineTwo = NewFundingLine(); FundingLine fundingLineThree = NewFundingLine(); ReProfileRequest reProfileRequestOne = NewReProfileRequest(); ReProfileRequest reProfileRequestThree = NewReProfileRequest(); ReProfileResponse reProfileResponseOne = NewReProfileResponse(); ReProfileResponse reProfileResponseThree = NewReProfileResponse(); DistributionPeriod[] distributionPeriodsOne = NewDistributionPeriods(); DistributionPeriod[] distributionPeriodsTwo = NewDistributionPeriods(); DistributionPeriod[] distributionPeriodsThree = NewDistributionPeriods(); fundingLineOne.DistributionPeriods = NewDistributionPeriods(_ => _.WithDistributionPeriodId(distributionPeriodsOne.Single().DistributionPeriodId)); fundingLineTwo.DistributionPeriods = distributionPeriodsTwo; fundingLineThree.DistributionPeriods = NewDistributionPeriods(_ => _.WithDistributionPeriodId(distributionPeriodsThree.Single().DistributionPeriodId)); GivenTheFundingLines(fundingLineOne, fundingLineTwo, fundingLineThree); AndTheAffectedFundingLineCodes(fundingLineOne.FundingLineCode, fundingLineThree.FundingLineCode); AndTheTheReProfileRequest(fundingLineOne, reProfileRequestOne); AndTheTheReProfileRequest(fundingLineThree, reProfileRequestThree); AndTheReProfileResponse(reProfileRequestOne, reProfileResponseOne); AndTheReProfileResponse(reProfileRequestThree, reProfileResponseThree); AndTheReProfileResponseMapping(reProfileResponseOne, distributionPeriodsOne); AndTheReProfileResponseMapping(reProfileResponseThree, distributionPeriodsThree); await WhenTheChangeIsApplied(); fundingLineOne.DistributionPeriods .Should() .BeEquivalentTo <DistributionPeriod>(distributionPeriodsOne); fundingLineTwo.DistributionPeriods .Should() .BeSameAs(distributionPeriodsTwo); fundingLineThree.DistributionPeriods .Should() .BeEquivalentTo <DistributionPeriod>(distributionPeriodsThree); }
private void AndTheReProfileRequest(string specificationId, string fundingStreamId, string fundingPeriodId, string providerId, string fundingLineCode, string profilePatternKey, ProfileConfigurationType configurationType, decimal?fundingLineTotal, ReProfileRequest profileRequest) { _reProfilingRequestBuilder.Setup(_ => _.BuildReProfileRequest(specificationId, fundingStreamId, fundingPeriodId, providerId, fundingLineCode, profilePatternKey, configurationType, fundingLineTotal)) .ReturnsAsync(profileRequest); }
public async Task ReturnsBadRequestIfTheReProfilingConfigurationSuppliesAnUnsupportedStrategy() { ReProfileRequest request = NewReProfileRequest(); GivenTheProfilePattern(request, NewFundingStreamPeriodProfilePattern(_ => _.WithReProfilingConfiguration(NewProfilePatternReProfilingConfiguration(cfg => cfg.WithIsEnabled(true))))); ActionResult <ReProfileResponse> result = await WhenTheFundingLineIsReProfiled(request); result .Result .Should() .BeOfType <BadRequestObjectResult>() .Which .Value .Should() .Be("Re-profiling is not enabled for this scenario or the strategy was not found"); }
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 async Task ReProfileFundingLine(string fundingLineCode, PublishedProviderVersion refreshState, IApplyProviderVariations variationApplications) { FundingLine fundingLine = refreshState.FundingLines.SingleOrDefault(_ => _.FundingLineCode == fundingLineCode); string providerId = refreshState.ProviderId; if (fundingLine == null) { throw new NonRetriableException($"Could not locate funding line {fundingLineCode} for published provider version {providerId}"); } ReProfileRequest reProfileRequest = await variationApplications.ReProfilingRequestBuilder.BuildReProfileRequest(refreshState.SpecificationId, refreshState.FundingStreamId, refreshState.FundingPeriodId, providerId, fundingLineCode, null, ProfileConfigurationType.RuleBased, fundingLine.Value); ReProfileResponse reProfileResponse = (await variationApplications.ResiliencePolicies.ProfilingApiClient.ExecuteAsync(() => variationApplications.ProfilingApiClient.ReProfile(reProfileRequest)))?.Content; if (reProfileResponse == null) { throw new NonRetriableException($"Could not re profile funding line {fundingLineCode} for provider {providerId}"); } IEnumerable <DistributionPeriod> distributionPeriods = variationApplications.ReProfilingResponseMapper.MapReProfileResponseIntoDistributionPeriods(reProfileResponse); foreach (DistributionPeriod distributionPeriod in distributionPeriods) { refreshState.UpdateDistributionPeriodForFundingLine(fundingLineCode, distributionPeriod.DistributionPeriodId, distributionPeriod.ProfilePeriods); } }
public async Task <ActionResult <ReProfileResponse> > ReProfile(ReProfileRequest reProfileRequest) { FundingStreamPeriodProfilePattern profilePattern = await _profilePatternService.GetProfilePattern(reProfileRequest.FundingStreamId, reProfileRequest.FundingPeriodId, reProfileRequest.FundingLineCode, reProfileRequest.ProfilePatternKey); if (profilePattern == null) { return(new NotFoundObjectResult("Profile pattern not found")); } if (profilePattern.ReProfilingConfiguration == null || !profilePattern.ReProfilingConfiguration.ReProfilingEnabled) { return(new BadRequestObjectResult("Re-profiling is not enabled or has not been configured")); } IReProfilingStrategy strategy = GetReProfilingStrategy(reProfileRequest, profilePattern); if (strategy == null) { return(new BadRequestObjectResult("Re-profiling is not enabled for this scenario or the strategy was not found")); } ReProfileContext context = CreateReProfilingContext(reProfileRequest, profilePattern); ReProfileStrategyResult strategyResult = strategy.ReProfile(context); VerifyProfileAmountsReturnedMatchRequestedFundingLineValue(reProfileRequest, strategyResult); return(new ReProfileResponse { DeliveryProfilePeriods = strategyResult.DeliveryProfilePeriods, DistributionPeriods = strategyResult.DistributionPeriods, ProfilePatternDisplayName = profilePattern.ProfilePatternDisplayName, ProfilePatternKey = profilePattern.ProfilePatternKey, CarryOverAmount = strategyResult.CarryOverAmount }); }
private async Task ReProfileFundingLine(PublishedProviderVersion newPublishedProviderVersion, ProfilePatternKey profilePatternKey, string fundingLineCode, FundingLine fundingLine) { ReProfileRequest reProfileRequest = await _profilingRequestBuilder.BuildReProfileRequest(newPublishedProviderVersion.SpecificationId, newPublishedProviderVersion.FundingStreamId, newPublishedProviderVersion.FundingPeriodId, newPublishedProviderVersion.ProviderId, fundingLineCode, profilePatternKey.Key, ProfileConfigurationType.Custom, fundingLine.Value); ReProfileResponse reProfileResponse = (await _profilingPolicy.ExecuteAsync(() => _profiling.ReProfile(reProfileRequest)))?.Content; if (reProfileResponse == null) { string error = $"Unable to re-profile funding line {fundingLineCode} on specification {newPublishedProviderVersion.SpecificationId} with profile pattern {profilePatternKey.Key}"; _logger.Error(error); throw new InvalidOperationException(error); } fundingLine.DistributionPeriods = _reProfilingResponseMapper.MapReProfileResponseIntoDistributionPeriods(reProfileResponse); newPublishedProviderVersion.RemoveCarryOver(fundingLineCode); if (reProfileResponse.CarryOverAmount > 0) { newPublishedProviderVersion.AddCarryOver(fundingLineCode, ProfilingCarryOverType.CustomProfile, reProfileResponse.CarryOverAmount); } }
public ReProfileContextBuilder WithReProfileRequest(ReProfileRequest request) { _request = request; return(this); }
private async Task <ActionResult <ReProfileResponse> > WhenTheFundingLineIsReProfiled(ReProfileRequest request) => await _service.ReProfile(request);
public async Task BuildsReProfileRequestsOutOfExistingFundingInformationUsingPublishedProvidersAndVariationPointers() { string providerId = NewRandomString(); string fundingStreamId = NewRandomString(); string fundingPeriodId = NewRandomString(); string fundingLineCode = NewRandomString(); string specificationId = NewRandomString(); string profilePattern = NewRandomString(); decimal fundingLineTotal = NewRandomAmount(); ProfileConfigurationType profileConfigurationType = NewRandomProfileConfigurationType(); GivenThePublishedProvider(fundingStreamId, fundingPeriodId, providerId, NewPublishedProvider(_ => _.WithCurrent(NewPublisherProviderVersion(pvp => pvp.WithFundingLines(NewFundingLine(), NewFundingLine(fl => fl.WithFundingLineCode(fundingLineCode) .WithDistributionPeriods(NewDistributionPeriod(dp => dp.WithProfilePeriods(NewProfilePeriod(pp => pp.WithDistributionPeriodId("dp1") .WithAmount(23) .WithOccurence(0) .WithYear(2021) .WithType(ProfilePeriodType.CalendarMonth) .WithTypeValue("January")), NewProfilePeriod(pp => pp.WithDistributionPeriodId("dp1") .WithAmount(24) .WithOccurence(1) .WithYear(2021) .WithType(ProfilePeriodType.CalendarMonth) .WithTypeValue("January")), NewProfilePeriod(pp => pp.WithDistributionPeriodId("dp1") .WithAmount(25) .WithOccurence(0) .WithYear(2021) .WithType(ProfilePeriodType.CalendarMonth) .WithTypeValue("March")), NewProfilePeriod(pp => pp.WithDistributionPeriodId("dp1") .WithAmount(26) .WithOccurence(0) .WithYear(2021) .WithType(ProfilePeriodType.CalendarMonth) .WithTypeValue("April")) ))))))))); ReProfileRequest reProfileRequest = await WhenTheReProfileRequestIsBuilt(specificationId, fundingStreamId, fundingPeriodId, providerId, fundingLineCode, profilePattern, profileConfigurationType, fundingLineTotal); reProfileRequest .Should() .BeEquivalentTo(new ReProfileRequest { ConfigurationType = profileConfigurationType, FundingLineCode = fundingLineCode, ExistingFundingLineTotal = 23 + 24 + 25 + 26, FundingLineTotal = fundingLineTotal, FundingPeriodId = fundingPeriodId, FundingStreamId = fundingStreamId, ProfilePatternKey = profilePattern, ExistingPeriods = new [] { NewExististingProfilePeriod(_ => _.WithOccurrence(0) .WithDistributionPeriod("dp1") .WithValue(null) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("January") .WithYear(2021)), NewExististingProfilePeriod(_ => _.WithOccurrence(1) .WithDistributionPeriod("dp1") .WithValue(null) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("January") .WithYear(2021)), NewExististingProfilePeriod(_ => _.WithOccurrence(0) .WithDistributionPeriod("dp1") .WithValue(null) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("March") .WithYear(2021)), NewExististingProfilePeriod(_ => _.WithOccurrence(0) .WithDistributionPeriod("dp1") .WithValue(null) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("April") .WithYear(2021)) } }); }
public async Task <ActionResult <ReProfileResponse> > Post([FromBody] ReProfileRequest request) => await _reProfilingService.ReProfile(request);
private static void VerifyProfileAmountsReturnedMatchRequestedFundingLineValue(ReProfileRequest reProfileRequest, ReProfileStrategyResult strategyResult) { decimal profileTotals = (strategyResult.DeliveryProfilePeriods?.Sum(_ => _.ProfileValue)).GetValueOrDefault(); decimal totalAmount = profileTotals + strategyResult.CarryOverAmount; if (totalAmount != reProfileRequest.FundingLineTotal) { throw new InvalidOperationException( $"Profile amounts ({profileTotals}) and carry over amount ({strategyResult.CarryOverAmount}) does not equal funding line total requested ({reProfileRequest.FundingLineTotal}) from strategy."); } }
public async Task ReProfilesFundingLineAndMapsResultsIntoProfileTotals() { ProfilePreviewRequest previewRequest = NewProfilePreviewRequest(); string distributionPeriod = NewRandomString(); ReProfileRequest expectedReProfileRequest = NewReProfileRequest(_ => _.WithFundingLineTotal(999) .WithExistingFundingLineTotal(1000) .WithExistingProfilePeriods(NewExistingProfilePeriod(exp => exp.WithDistributionPeriod(distributionPeriod) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("January") .WithValue(23) .WithYear(2021) .WithOccurrence(0)), NewExistingProfilePeriod(exp => exp.WithDistributionPeriod(distributionPeriod) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("January") .WithValue(24) .WithYear(2021) .WithOccurrence(1)), NewExistingProfilePeriod(exp => exp.WithDistributionPeriod(distributionPeriod) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("February") .WithValue(null) .WithYear(2021) .WithOccurrence(0)), NewExistingProfilePeriod(exp => exp.WithDistributionPeriod(distributionPeriod) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("March") .WithValue(null) .WithYear(2021) .WithOccurrence(0)), NewExistingProfilePeriod(exp => exp.WithDistributionPeriod(distributionPeriod) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("April") .WithValue(null) .WithYear(2021) .WithOccurrence(0)), NewExistingProfilePeriod(exp => exp.WithDistributionPeriod(distributionPeriod) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("May") .WithValue(null) .WithYear(2021) .WithOccurrence(0)) )); ReProfileResponse expectedReProfileResponse = NewReProfileResponse(_ => _.WithCarryOverAmount(992) .WithDeliveryProfilePeriods(NewDeliveryProfilePeriod(exp => exp.WithDistributionPeriod(distributionPeriod) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("January") .WithValue(33) .WithYear(2021) .WithOccurrence(0)), NewDeliveryProfilePeriod(exp => exp.WithDistributionPeriod(distributionPeriod) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("January") .WithValue(34) .WithYear(2021) .WithOccurrence(1)), NewDeliveryProfilePeriod(exp => exp.WithDistributionPeriod(distributionPeriod) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("February") .WithValue(35) .WithYear(2021) .WithOccurrence(0)), NewDeliveryProfilePeriod(exp => exp.WithDistributionPeriod(distributionPeriod) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("March") .WithValue(36) .WithYear(2021) .WithOccurrence(0)), NewDeliveryProfilePeriod(exp => exp.WithDistributionPeriod(distributionPeriod) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("April") .WithValue(37) .WithYear(2021) .WithOccurrence(0)), NewDeliveryProfilePeriod(exp => exp.WithDistributionPeriod(distributionPeriod) .WithPeriodType(PeriodType.CalendarMonth) .WithTypeValue("May") .WithValue(38) .WithYear(2021) .WithOccurrence(0)))); DateTimeOffset expectedActualDateOne = NewRandomDate(); DateTimeOffset expectedActualDateTwo = NewRandomDate(); DateTimeOffset expectedActualDateThree = NewRandomDate(); DateTimeOffset expectedActualDateFour = NewRandomDate(); FundingDate expectedFundingDate = NewFundingDate(_ => _.WithPatterns(NewFundingDatePattern(fdp => fdp.WithOccurrence(0) .WithPeriod("January") .WithPeriodYear(2021) .WithPaymentDate(expectedActualDateOne)), NewFundingDatePattern(fdp => fdp.WithOccurrence(0) .WithPeriod("February") .WithPeriodYear(2021) .WithPaymentDate(expectedActualDateTwo)), NewFundingDatePattern(fdp => fdp.WithOccurrence(0) .WithPeriod("April") .WithPeriodYear(2021) .WithPaymentDate(expectedActualDateThree)), NewFundingDatePattern(fdp => fdp.WithOccurrence(0) .WithPeriod("May") .WithPeriodYear(2021) .WithPaymentDate(expectedActualDateFour)), NewFundingDatePattern())); GivenTheReProfileRequest(previewRequest, expectedReProfileRequest); AndTheReProfileResponse(expectedReProfileRequest, expectedReProfileResponse); AndTheFundingDate(previewRequest, expectedFundingDate); OkObjectResult response = await WhenTheProfilePatternChangeIsPreviewed(previewRequest) as OkObjectResult; response? .Value .Should() .BeEquivalentTo(new [] { NewProfileTotal(_ => _.WithOccurrence(0) .WithDistributionPeriod(distributionPeriod) .WithValue(23) .WithYear(2021) .WithPeriodType("CalenderMonth") .WithTypeValue("January") .WithIsPaid(true) .WithInstallmentNumber(1) .WithActualDate(expectedActualDateOne)), NewProfileTotal(_ => _.WithOccurrence(1) .WithDistributionPeriod(distributionPeriod) .WithValue(24) .WithYear(2021) .WithPeriodType("CalenderMonth") .WithTypeValue("January") .WithIsPaid(true) .WithInstallmentNumber(2) .WithActualDate(null)), NewProfileTotal(_ => _.WithOccurrence(0) .WithDistributionPeriod(distributionPeriod) .WithValue(35) .WithYear(2021) .WithPeriodType("CalenderMonth") .WithTypeValue("February") .WithIsPaid(false) .WithInstallmentNumber(3) .WithActualDate(expectedActualDateTwo)), NewProfileTotal(_ => _.WithOccurrence(0) .WithDistributionPeriod(distributionPeriod) .WithValue(36) .WithYear(2021) .WithPeriodType("CalenderMonth") .WithTypeValue("March") .WithIsPaid(false) .WithInstallmentNumber(4) .WithActualDate(null)), NewProfileTotal(_ => _.WithOccurrence(0) .WithDistributionPeriod(distributionPeriod) .WithValue(37) .WithYear(2021) .WithPeriodType("CalenderMonth") .WithTypeValue("April") .WithIsPaid(false) .WithInstallmentNumber(5) .WithActualDate(expectedActualDateThree)), NewProfileTotal(_ => _.WithOccurrence(0) .WithDistributionPeriod(distributionPeriod) .WithValue(38) .WithYear(2021) .WithPeriodType("CalenderMonth") .WithTypeValue("May") .WithIsPaid(false) .WithInstallmentNumber(6) .WithActualDate(expectedActualDateFour)) }); }
private void AndTheReProfileResponse(ReProfileRequest request, ReProfileResponse expectedResponse) => _profiling.Setup(_ => _.ReProfile(request)) .ReturnsAsync(new ApiResponse <ReProfileResponse>(HttpStatusCode.OK, expectedResponse));
public async Task <ApiResponse <ReProfileResponse> > ReProfile(ReProfileRequest request) { Guard.ArgumentNotNull(request, nameof(request)); return(await PostAsync <ReProfileResponse, ReProfileRequest>("reprofile", request)); }
public async Task AssignProfilePatternKeyForFundingLineWithAlreadyPaidProfilePeriodsUsesReProfileResponseResultsFromApi() { string fundingLineCode = NewRandomString(); string existingProfilePatternKey = NewRandomString(); string newProfilePatterFundingKey = NewRandomString(); string specificationId = NewRandomString(); int occurence = NewRandomNumberBetween(1, 100); ProfilePeriodType profilePeriodType = NewRandomEnum <ProfilePeriodType>(); string typeValue = NewRandomString(); int year = NewRandomNumberBetween(2019, 2021); string distributionPeriodId = NewRandomString(); decimal carryOverAmount = NewRandomNumberBetween(1, int.MaxValue); GivenTheFundingConfiguration(true); ProfilePatternKey profilePatternKey = NewProfilePatternKey(_ => _.WithFundingLineCode(fundingLineCode).WithKey(newProfilePatterFundingKey)); ProfilePeriod paidProfilePeriod = NewProfilePeriod(pp => pp .WithDistributionPeriodId(distributionPeriodId) .WithType(profilePeriodType) .WithTypeValue(typeValue) .WithYear(year) .WithOccurence(occurence)); FundingLine fundingLine = NewFundingLine(_ => _ .WithFundingLineCode(fundingLineCode) .WithDistributionPeriods( NewDistributionPeriod(dp => dp .WithDistributionPeriodId(distributionPeriodId) .WithProfilePeriods(paidProfilePeriod)) )); PublishedProviderVersion existingPublishedProviderVersion = NewPublishedProviderVersion(ppv => ppv .WithFundingStreamId(_fundingStreamId) .WithFundingPeriodId(_fundingPeriodId) .WithSpecificationId(specificationId) .WithProfilePatternKeys( NewProfilePatternKey(_ => _.WithFundingLineCode(fundingLineCode) .WithKey(existingProfilePatternKey))) .WithFundingLines(fundingLine) ); PublishedProvider publishedProvider = NewPublishedProvider(_ => _.WithCurrent(existingPublishedProviderVersion)); PublishedProviderCreateVersionRequest publishedProviderCreateVersionRequest = NewPublishedProviderCreateVersionRequest(_ => _.WithPublishedProvider(publishedProvider) .WithNewVersion(existingPublishedProviderVersion)); IEnumerable <ProfileVariationPointer> profileVariationPointers = NewProfileVariationPointers(_ => _ .WithFundingLineId(fundingLineCode) .WithFundingStreamId(_fundingStreamId) .WithOccurence(occurence) .WithPeriodType(profilePeriodType.ToString()) .WithTypeValue(typeValue) .WithYear(year)); ReProfileRequest reProfileRequest = NewReProfileRequest(); ReProfileResponse reProfileResponse = NewReProfileResponse(_ => _.WithCarryOverAmount(carryOverAmount) .WithDeliveryProfilePeriods(NewDeliveryProfilePeriod(dpp => dpp.WithOccurrence(1) .WithValue(10) .WithYear(2021) .WithTypeValue("JANUARY") .WithPeriodType(PeriodType.CalendarMonth) .WithDistributionPeriod("dp1")), NewDeliveryProfilePeriod(dpp => dpp.WithOccurrence(1) .WithValue(20) .WithYear(2022) .WithTypeValue("JANUARY") .WithPeriodType(PeriodType.CalendarMonth) .WithDistributionPeriod("dp2")))); GivenThePublishedProvider(publishedProvider); AndThePublishedProviderCreateVersionRequest(publishedProvider, publishedProviderCreateVersionRequest); AndTheNewCreatedPublishedProvider(publishedProvider, publishedProviderCreateVersionRequest); AndTheProfileVariationPointers(profileVariationPointers, specificationId); AndTheReProfileRequest(existingPublishedProviderVersion.SpecificationId, existingPublishedProviderVersion.FundingStreamId, existingPublishedProviderVersion.FundingPeriodId, existingPublishedProviderVersion.ProviderId, profilePatternKey.FundingLineCode, profilePatternKey.Key, ProfileConfigurationType.Custom, fundingLine.Value, reProfileRequest); AndTheReProfileResponse(reProfileRequest, reProfileResponse); AndTheProfileFundingLines(profilePatternKey); AndTheSavePublishedProviderVersionResponse(HttpStatusCode.OK, existingPublishedProviderVersion); AndTheUpsertPublishedProviderResponse(HttpStatusCode.OK, publishedProvider); IActionResult result = await WhenProfilePatternKeyIsAssigned(_fundingStreamId, _fundingPeriodId, _providerId, profilePatternKey); ThenResultShouldBe(result, HttpStatusCode.OK); AndProfilePatternKeyWasUpdated(existingPublishedProviderVersion, profilePatternKey); fundingLine.DistributionPeriods .Count() .Should() .Be(2); DistributionPeriod firstDistributionPeriod = fundingLine.DistributionPeriods.SingleOrDefault(_ => _.DistributionPeriodId == "dp1"); firstDistributionPeriod.ProfilePeriods .Should() .BeEquivalentTo(NewProfilePeriod(_ => _.WithAmount(10) .WithTypeValue("JANUARY") .WithDistributionPeriodId("dp1") .WithType(ProfilePeriodType.CalendarMonth) .WithOccurence(1) .WithYear(2021))); DistributionPeriod secondDistributionPeriod = fundingLine.DistributionPeriods.SingleOrDefault(_ => _.DistributionPeriodId == "dp2"); secondDistributionPeriod.ProfilePeriods .Should() .BeEquivalentTo(NewProfilePeriod(_ => _.WithAmount(20) .WithTypeValue("JANUARY") .WithDistributionPeriodId("dp2") .WithType(ProfilePeriodType.CalendarMonth) .WithOccurence(1) .WithYear(2022))); existingPublishedProviderVersion.CarryOvers .Should() .BeEquivalentTo(NewCarryOver(_ => _.WithAmount(carryOverAmount) .WithFundingLineCode(fundingLineCode) .WithType(ProfilingCarryOverType.CustomProfile))); AndThePublishedProviderWasProcessed(publishedProvider); AndTheProfilingAuditWasUpdatedForTheFundingLine(publishedProvider, profilePatternKey.FundingLineCode, _author); }