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 static DistributionPeriods[] MapIntoDistributionPeriods(ReProfileContext context) { return(context.ProfileResult.DeliveryProfilePeriods.GroupBy(_ => _.DistributionPeriod) .Select(_ => new DistributionPeriods { Value = _.Sum(dp => dp.ProfileValue), DistributionPeriodCode = _.Key }) .ToArray()); }
public ReProfileStrategyResult ReProfile(ReProfileContext context) { decimal carryOverAmount = AdjustForUnderOrOverPayment(context); //TODO; put this change under test for the distribution periods stuff return(new ReProfileStrategyResult { DistributionPeriods = MapIntoDistributionPeriods(context), DeliveryProfilePeriods = context.ProfileResult.DeliveryProfilePeriods, CarryOverAmount = carryOverAmount }); }
public void SetUp() { _context = new ReProfileContext(); _year = NewRandomYear(); _month = NewRandomMonth(); _context = new ReProfileContext { Request = new ReProfileRequest(), ProfileResult = new AllocationProfileResponse() }; _reProfiling = new ReProfileDsgFundingLine(); }
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 }); }