protected override void MakeAdjustmentsFromProfileVariationPointer(ProfileVariationPointer variationPointer)
        {
            FundingLine closedFundingLine = RefreshState.FundingLines?
                                            .SingleOrDefault(_ => _.FundingLineCode == variationPointer.FundingLineId);
            FundingLine successorFundingLine = SuccessorRefreshState?.FundingLines?
                                               .SingleOrDefault(_ => _.FundingLineCode == variationPointer.FundingLineId);

            if (closedFundingLine == null || successorFundingLine == null)
            {
                throw new ArgumentOutOfRangeException(nameof(variationPointer),
                                                      $"Did not locate a funding line for variation pointer with fundingLineId {variationPointer.FundingLineId}");
            }

            ProfilePeriod[] orderedClosedProfilePeriods = new YearMonthOrderedProfilePeriods(closedFundingLine)
                                                          .ToArray();
            ProfilePeriod[] orderedSuccessorProfilePeriods = new YearMonthOrderedProfilePeriods(successorFundingLine)
                                                             .ToArray();

            int variationPointerIndex = GetProfilePeriodIndexForVariationPoint(variationPointer, orderedClosedProfilePeriods);

            for (int profilePeriod = variationPointerIndex; profilePeriod < orderedClosedProfilePeriods.Length; profilePeriod++)
            {
                ProfilePeriod successorProfilePeriod = orderedSuccessorProfilePeriods[profilePeriod];

                successorProfilePeriod.ProfiledValue = successorProfilePeriod.ProfiledValue + orderedClosedProfilePeriods[profilePeriod].ProfiledValue;
            }
        }
        public async Task SetProfileVariationPointer()
        {
            string specificationId        = NewRandomString();
            ProfileVariationPointer model = new ProfileVariationPointer();

            await AssertPutRequest($"{specificationId}/profilevariationpointer",
                                   HttpStatusCode.OK,
                                   () => _client.SetProfileVariationPointer(specificationId, model));
        }
        protected int GetProfilePeriodIndexForVariationPoint(ProfileVariationPointer variationPointer, ProfilePeriod[] profilePeriods)
        {
            int variationPointerIndex = profilePeriods.IndexOf(_ => _.Occurrence == variationPointer.Occurrence &&
                                                               _.Year == variationPointer.Year &&
                                                               _.TypeValue == variationPointer.TypeValue);

            if (variationPointerIndex == -1)
            {
                throw new ArgumentOutOfRangeException(nameof(variationPointer),
                                                      $"Did not locate profile period corresponding to variation pointer for funding line id {variationPointer.FundingLineId}");
            }

            return(variationPointerIndex);
        }
Пример #4
0
        private bool IsProfileTotalPaid(
            ProfileVariationPointer profileVariationPointer,
            ProfileTotal profileTotal)
        {
            if (profileVariationPointer == null)
            {
                return(false);
            }

            if (profileTotal.Year > profileVariationPointer.Year || (profileTotal.Year == profileVariationPointer.Year &&
                                                                     MonthNumberFor(profileTotal.TypeValue) >= MonthNumberFor(profileVariationPointer.TypeValue)))
            {
                return(false);
            }

            return(true);
        }
        public async Task <ReProfileRequest> BuildReProfileRequest(string specificationId,
                                                                   string fundingStreamId,
                                                                   string fundingPeriodId,
                                                                   string providerId,
                                                                   string fundingLineCode,
                                                                   string profilePatternKey,
                                                                   ProfileConfigurationType configurationType,
                                                                   decimal?fundingLineTotal = null)
        {
            Guard.IsNullOrWhiteSpace(specificationId, nameof(specificationId));
            Guard.IsNullOrWhiteSpace(fundingStreamId, nameof(fundingStreamId));
            Guard.IsNullOrWhiteSpace(fundingPeriodId, nameof(fundingPeriodId));
            Guard.IsNullOrWhiteSpace(providerId, nameof(providerId));
            Guard.IsNullOrWhiteSpace(fundingLineCode, nameof(fundingLineCode));

            ProfileVariationPointer profileVariationPointer = await GetProfileVariationPointerForFundingLine(specificationId,
                                                                                                             fundingLineCode,
                                                                                                             fundingStreamId);

            ProfilePeriod[] orderedProfilePeriodsForFundingLine = await GetOrderedProfilePeriodsForFundingLine(fundingStreamId,
                                                                                                               fundingPeriodId,
                                                                                                               providerId,
                                                                                                               fundingLineCode);

            int paidUpToIndex = GetProfilePeriodIndexForVariationPointer(profileVariationPointer, orderedProfilePeriodsForFundingLine);

            IEnumerable <ExistingProfilePeriod> existingProfilePeriods = BuildExistingProfilePeriods(orderedProfilePeriodsForFundingLine, paidUpToIndex);

            decimal existingFundingLineTotal = orderedProfilePeriodsForFundingLine.Sum(_ => _.ProfiledValue);

            return(new ReProfileRequest
            {
                ProfilePatternKey = profilePatternKey,
                ConfigurationType = configurationType,
                FundingLineCode = fundingLineCode,
                FundingPeriodId = fundingPeriodId,
                FundingStreamId = fundingStreamId,
                FundingLineTotal = fundingLineTotal.GetValueOrDefault(existingFundingLineTotal),
                ExistingFundingLineTotal = existingFundingLineTotal,
                ExistingPeriods = existingProfilePeriods
            });
        }
        private void ZeroProfilesFromVariationPoint(ProfileVariationPointer variationPointer)
        {
            FundingLine fundingLine = RefreshState.FundingLines?
                                      .SingleOrDefault(_ => _.FundingLineCode == variationPointer.FundingLineId);

            if (fundingLine == null)
            {
                throw new ArgumentOutOfRangeException(nameof(variationPointer),
                                                      $"Did not locate a funding line for variation pointer with fundingLineId {variationPointer.FundingLineId}");
            }

            ProfilePeriod[] orderedProfilePeriods = new YearMonthOrderedProfilePeriods(fundingLine)
                                                    .ToArray();

            int variationPointerIndex = GetProfilePeriodIndexForVariationPoint(variationPointer, orderedProfilePeriods);

            for (int profilePeriod = variationPointerIndex; profilePeriod < orderedProfilePeriods.Length; profilePeriod++)
            {
                orderedProfilePeriods[profilePeriod].ProfiledValue = 0;
            }
        }
 private async Task <ValidatedApiResponse <HttpStatusCode> > WhenTheSpecificationProfileVariationPointerSet(string specificationId, ProfileVariationPointer profileVariationPointer)
 {
     return(await _client.SetProfileVariationPointer(specificationId, profileVariationPointer));
 }
 protected abstract void MakeAdjustmentsFromProfileVariationPointer(ProfileVariationPointer variationPointer);
 public Task <HttpStatusCode> SetProfileVariationPointer(string specificationId, ProfileVariationPointer profileVariationPointer)
 {
     throw new NotImplementedException();
 }
 protected override void MakeAdjustmentsFromProfileVariationPointer(ProfileVariationPointer variationPointer)
 {
     ZeroProfilesFromVariationPoint(variationPointer);
 }
        protected override void MakeAdjustmentsFromProfileVariationPointer(ProfileVariationPointer variationPointer)
        {
            PublishedProvider previousSnapshot = VariationContext.GetPublishedProviderOriginalSnapShot(ProviderId);

            if (previousSnapshot == null)
            {
                return;
            }

            string fundingLineId = variationPointer.FundingLineId;

            FundingLine latestFundingLine = RefreshState.FundingLines?
                                            .SingleOrDefault(_ => _.FundingLineCode == fundingLineId);
            FundingLine previousFundingLine = previousSnapshot.Current?.FundingLines?
                                              .SingleOrDefault(_ => _.FundingLineCode == fundingLineId);

            if (latestFundingLine == null || previousFundingLine == null)
            {
                RecordErrors($"Did not locate all funding lines for variation pointer with fundingLineId {fundingLineId}");

                return;
            }

            if (latestFundingLine.Value == null && previousFundingLine.Value == null)
            {
                return;
            }

            ProfilePeriod[] orderedRefreshProfilePeriods = new YearMonthOrderedProfilePeriods(latestFundingLine)
                                                           .ToArray();
            ProfilePeriod[] orderedSnapShotProfilePeriods = new YearMonthOrderedProfilePeriods(previousFundingLine)
                                                            .ToArray();

            int variationPointerIndex = GetProfilePeriodIndexForVariationPoint(variationPointer, orderedRefreshProfilePeriods);

            decimal previousFundingLineValuePaid = orderedSnapShotProfilePeriods.Take(variationPointerIndex).Sum(_ => _.ProfiledValue);
            decimal latestFundingLineValuePaid   = orderedRefreshProfilePeriods.Take(variationPointerIndex).Sum(_ => _.ProfiledValue);
            decimal latestFundingLineValue       = latestFundingLine.Value.GetValueOrDefault();

            decimal fundingChange      = latestFundingLineValuePaid - previousFundingLineValuePaid;
            decimal latestPeriodAmount = (int)(latestFundingLineValue / orderedRefreshProfilePeriods.Length);

            AdjustPeriodsForFundingAlreadyReleased(variationPointerIndex,
                                                   orderedSnapShotProfilePeriods,
                                                   orderedRefreshProfilePeriods);

            if (fundingChange < 0)
            {
                if (AdjustingPeriodsForOverPaymentLeavesRemainder(variationPointerIndex,
                                                                  latestPeriodAmount,
                                                                  orderedSnapShotProfilePeriods,
                                                                  orderedRefreshProfilePeriods,
                                                                  out decimal remainingOverPayment))
                {
                    if (remainingOverPayment > 0)
                    {
                        RefreshState.AddCarryOver(fundingLineId, ProfilingCarryOverType.DSGReProfiling, remainingOverPayment);
                    }
                }
            }
            else if (fundingChange > 0)
            {
                AdjustPeriodsForUnderPayment(variationPointerIndex,
                                             latestPeriodAmount,
                                             orderedSnapShotProfilePeriods,
                                             orderedRefreshProfilePeriods);
            }
            else
            {
                AdjustPeriodsForNoTotalAllocationChange(variationPointerIndex,
                                                        latestPeriodAmount,
                                                        orderedSnapShotProfilePeriods,
                                                        orderedRefreshProfilePeriods,
                                                        fundingLineId);
            }
        }
        public async Task <HttpStatusCode> SetProfileVariationPointer(string specificationId, ProfileVariationPointer profileVariationPointer)
        {
            Guard.IsNullOrWhiteSpace(specificationId, nameof(specificationId));
            Guard.ArgumentNotNull(profileVariationPointer, nameof(profileVariationPointer));

            return(await PutAsync($"{UrlRoot}/{specificationId}/profilevariationpointer", profileVariationPointer));
        }
Пример #13
0
        public async Task <IActionResult> GetPublishedProviderProfileTotalsForSpecificationForProviderForFundingLine(
            string specificationId,
            string providerId,
            string fundingStreamId,
            string fundingLineCode)
        {
            Guard.IsNullOrWhiteSpace(specificationId, nameof(specificationId));
            Guard.IsNullOrWhiteSpace(fundingStreamId, nameof(fundingStreamId));
            Guard.IsNullOrWhiteSpace(fundingLineCode, nameof(fundingLineCode));
            Guard.IsNullOrWhiteSpace(providerId, nameof(providerId));

            PublishedProviderVersion latestPublishedProviderVersion = await _resilience.ExecuteAsync(() =>
                                                                                                     _publishedFunding.GetLatestPublishedProviderVersionBySpecificationId(
                                                                                                         specificationId,
                                                                                                         fundingStreamId,
                                                                                                         providerId));

            if (latestPublishedProviderVersion == null)
            {
                return(new NotFoundResult());
            }

            IEnumerable <ProfileVariationPointer> profileVariationPointers
                = await _specificationService.GetProfileVariationPointers(specificationId);

            TemplateMetadataDistinctFundingLinesContents templateMetadataDistinctFundingLinesContents =
                await _policiesService.GetDistinctTemplateMetadataFundingLinesContents(
                    fundingStreamId,
                    latestPublishedProviderVersion.FundingPeriodId,
                    latestPublishedProviderVersion.TemplateVersion);

            IEnumerable <FundingStreamPeriodProfilePattern> fundingStreamPeriodProfilePatterns =
                await _profilingService.GetProfilePatternsForFundingStreamAndFundingPeriod(
                    latestPublishedProviderVersion.FundingStreamId,
                    latestPublishedProviderVersion.FundingPeriodId);

            (string profilePatternKey, string profilePatternName, string profilePatternDescription) =
                GetProfilePatternDetails(fundingLineCode, latestPublishedProviderVersion, fundingStreamPeriodProfilePatterns);

            FundingLineProfile fundingLineProfile = new FundingLineProfile
            {
                FundingLineCode = fundingLineCode,
                FundingLineName = templateMetadataDistinctFundingLinesContents?.FundingLines?
                                  .FirstOrDefault(_ => _.FundingLineCode == fundingLineCode)?.Name,
                ProfilePatternKey         = profilePatternKey,
                ProfilePatternName        = profilePatternName,
                ProfilePatternDescription = profilePatternDescription,
                ProviderId      = latestPublishedProviderVersion.ProviderId,
                UKPRN           = latestPublishedProviderVersion.Provider.UKPRN,
                ProviderName    = latestPublishedProviderVersion.Provider.Name,
                CarryOverAmount = latestPublishedProviderVersion.GetCarryOverTotalForFundingLine(fundingLineCode) ?? 0
            };

            ProfileVariationPointer currentProfileVariationPointer
                = profileVariationPointers?.SingleOrDefault(_ =>
                                                            _.FundingStreamId == fundingStreamId && _.FundingLineId == fundingLineCode);

            ProfileTotal[] profileTotals = new PaymentFundingLineProfileTotals(latestPublishedProviderVersion, fundingLineCode)
                                           .ToArray();

            fundingLineProfile.TotalAllocation = latestPublishedProviderVersion
                                                 .FundingLines
                                                 .Where(_ => _.Type == FundingLineType.Payment)
                                                 .SingleOrDefault(_ => _.FundingLineCode == fundingLineCode)
                                                 ?.Value;

            fundingLineProfile.ProfileTotalAmount = profileTotals.Sum(_ => _.Value);

            FundingDate fundingDate = await _policiesService.GetFundingDate(
                fundingStreamId,
                latestPublishedProviderVersion.FundingPeriodId,
                fundingLineCode);

            for (int index = 0; index < profileTotals.Count(); index++)
            {
                ProfileTotal profileTotal = profileTotals[index];
                profileTotal.InstallmentNumber = index + 1;

                profileTotal.IsPaid = IsProfileTotalPaid(currentProfileVariationPointer, profileTotal);

                profileTotal.ActualDate = fundingDate?.Patterns?.SingleOrDefault(_ =>
                                                                                 _.Occurrence == profileTotal.Occurrence &&
                                                                                 _.Period == profileTotal.TypeValue &&
                                                                                 _.PeriodYear == profileTotal.Year)?.PaymentDate;
            }

            fundingLineProfile.AmountAlreadyPaid = profileTotals.Where(_ => _.IsPaid).Sum(_ => _.Value);
            fundingLineProfile.RemainingAmount   = fundingLineProfile.TotalAllocation - fundingLineProfile.AmountAlreadyPaid;

            foreach (ProfileTotal profileTotal in profileTotals.Where(_ => !_.IsPaid))
            {
                profileTotal.ProfileRemainingPercentage = fundingLineProfile.TotalAllocation.HasValue && fundingLineProfile.TotalAllocation > 0 ?
                                                          profileTotal.Value / (fundingLineProfile.TotalAllocation - fundingLineProfile.AmountAlreadyPaid) * 100 : 0;
            }

            fundingLineProfile.ProfileTotals = profileTotals;

            fundingLineProfile.LastUpdatedDate = latestPublishedProviderVersion.GetLatestFundingLineDate(fundingLineCode);
            fundingLineProfile.LastUpdatedUser = latestPublishedProviderVersion.GetLatestFundingLineUser(fundingLineCode);

            return(new OkObjectResult(fundingLineProfile));
        }