public async Task ZerosProfilesAfterProfileVariationPointersInSpecificationOnEachMatchingFundingLine()
        {
            string fundingLineOneId = NewRandomString();
            string fundingLineTwoId = NewRandomString();
            int    year             = 2020;
            int    occurence        = 1;
            string typeValue        = "January";

            GivenTheVariationPointersForTheSpecification(NewVariationPointer(_ => _.WithFundingLineId(fundingLineOneId)
                                                                             .WithOccurence(occurence)
                                                                             .WithYear(year)
                                                                             .WithTypeValue(typeValue)),
                                                         NewVariationPointer(_ => _.WithFundingLineId(fundingLineTwoId)
                                                                             .WithOccurence(occurence)
                                                                             .WithYear(year)
                                                                             .WithTypeValue(typeValue)));

            decimal periodOneAmount = 293487M;

            ProfilePeriod periodOne   = NewProfilePeriod(0, 2020, "January", periodOneAmount);
            ProfilePeriod periodTwo   = NewProfilePeriod(1, 2020, "January", 2973864M);
            ProfilePeriod periodThree = NewProfilePeriod(0, 2020, "February", 123764M);
            ProfilePeriod periodFour  = NewProfilePeriod(1, 2020, "January", 6487234M);
            ProfilePeriod periodFive  = NewProfilePeriod(2, 2020, "January", 1290837M);

            AndTheFundingLines(NewFundingLine(_ => _.WithFundingLineCode(fundingLineOneId)
                                              .WithDistributionPeriods(NewDistributionPeriod(dp => dp.WithProfilePeriods(periodOne, periodTwo, periodThree)),
                                                                       NewDistributionPeriod(dp => dp.WithProfilePeriods(periodFour, periodFive)))));

            await WhenTheChangeIsApplied();

            ThenProfilePeriodsShouldBeZeroAmount(periodTwo, periodThree, periodFive, periodFour);
            AndTheProfilePeriodAmountShouldBe(periodOne, periodOneAmount);
        }
        private bool FundingLinesMatches(IEnumerable <FundingLine> fundingLines)
        {
            FundingLine fundingLine = fundingLines.FirstOrDefault();

            if (fundingLine == null)
            {
                return(false);
            }

            ProfilePeriod firstProfilePeriod = fundingLine.DistributionPeriods?.SingleOrDefault(_ => _.DistributionPeriodId == _distributionPeriod1Id)?.ProfilePeriods.FirstOrDefault();
            ProfilePeriod lastProfilePeriod  = fundingLine.DistributionPeriods?.SingleOrDefault(_ => _.DistributionPeriodId == _distributionPeriod2Id)?.ProfilePeriods.FirstOrDefault();

            if (firstProfilePeriod == null || lastProfilePeriod == null)
            {
                return(false);
            }

            return(firstProfilePeriod.ProfiledValue == _profilePeriod1ProfiledAmount &&
                   firstProfilePeriod.Occurrence == _profilePeriod1Occurence &&
                   firstProfilePeriod.Type == _profilePeriod1Type &&
                   firstProfilePeriod.TypeValue == _profilePeriod1TypeValue &&
                   firstProfilePeriod.Year == _profilePeriod1Year &&
                   lastProfilePeriod.ProfiledValue == _profilePeriod2ProfiledAmount &&
                   lastProfilePeriod.Occurrence == _profilePeriod2Occurence &&
                   lastProfilePeriod.Type == _profilePeriod2Type &&
                   lastProfilePeriod.TypeValue == _profilePeriod2TypeValue &&
                   lastProfilePeriod.Year == _profilePeriod2Year);
        }
        public void ProjectsDistributionPeriodsAndProfilePeriodsOrderedByYearThenProfilePeriodMonthThenOccurence_ExampleOne()
        {
            ProfilePeriod lastPeriod   = NewProfilePeriod(2, 2021, "December");
            ProfilePeriod firstPeriod  = NewProfilePeriod(0, 2020, "December");
            ProfilePeriod secondPeriod = NewProfilePeriod(1, 2020, "December");
            ProfilePeriod thirdPeriod  = NewProfilePeriod(0, 2021, "January");

            FundingLine fundingLine = NewFundingLine(_ => _.WithDistributionPeriods(NewDistributionPeriod(
                                                                                        dp => dp.WithProfilePeriods(thirdPeriod, secondPeriod)),
                                                                                    NewDistributionPeriod(dp => dp.WithProfilePeriods(lastPeriod, firstPeriod))));

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

            orderedProfilePeriods[0]
            .Should()
            .BeSameAs(firstPeriod);

            orderedProfilePeriods[1]
            .Should()
            .BeSameAs(secondPeriod);

            orderedProfilePeriods[2]
            .Should()
            .BeSameAs(thirdPeriod);

            orderedProfilePeriods[3]
            .Should()
            .BeSameAs(lastPeriod);
        }
        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;
            }
        }
Exemplo n.º 5
0
 protected void AndTheProfilePeriodAmountShouldBe(ProfilePeriod profilePeriod, decimal expectedAmount)
 {
     profilePeriod
     .ProfiledValue
     .Should()
     .Be(expectedAmount);
 }
Exemplo n.º 6
0
        private DistributionPeriod[] NewDistributionPeriods(Action <DistributionPeriodBuilder> setUp = null)
        {
            DistributionPeriodBuilder distributionPeriodBuilder = new DistributionPeriodBuilder();

            setUp?.Invoke(distributionPeriodBuilder);
            ProfilePeriod profilePeriodOne = NewProfilePeriod();
            ProfilePeriod profilePeriodTwo = NewProfilePeriod();

            distributionPeriodBuilder.WithProfilePeriods(profilePeriodOne,
                                                         profilePeriodTwo);
            distributionPeriodBuilder.WithValue(profilePeriodOne.ProfiledValue + profilePeriodTwo.ProfiledValue);

            return(new [] { distributionPeriodBuilder.Build() });
        }
        private void AdjustPeriodsForUnderPayment(int variationPointerIndex,
                                                  decimal latestPeriodAmount,
                                                  ProfilePeriod[] orderedSnapShotProfilePeriods,
                                                  ProfilePeriod[] orderRefreshProfilePeriods)
        {
            decimal amountAlreadyPaid            = orderedSnapShotProfilePeriods.Take(variationPointerIndex).Sum(_ => _.ProfiledValue);
            decimal amountThatShouldHaveBeenPaid = latestPeriodAmount * variationPointerIndex;

            decimal amountUnderPaid = Math.Abs(amountAlreadyPaid - amountThatShouldHaveBeenPaid);

            ProfilePeriod periodToAdjust = orderRefreshProfilePeriods[variationPointerIndex];

            periodToAdjust.ProfiledValue = periodToAdjust.ProfiledValue + amountUnderPaid;
        }
 private void AndPaidProfilePeriodExists(string distributionId,
                                         ProfilePeriod profilePeriod,
                                         ProfilePatternKey profilePatternKey)
 {
     _profilingService.Verify(_ =>
                              _.ProfileFundingLines(It.Is <IEnumerable <FundingLine> >(fl => PaidProfileFundingLinesMatches(fl, distributionId, profilePeriod)),
                                                    _fundingStreamId,
                                                    _fundingPeriodId,
                                                    It.Is <IEnumerable <ProfilePatternKey> >(ppk =>
                                                                                             ppk.Any(k => k.FundingLineCode == profilePatternKey.FundingLineCode &&
                                                                                                     k.Key == profilePatternKey.Key)),
                                                    null,
                                                    null),
                              Times.Once);
 }
        private IEnumerable <ExistingProfilePeriod> BuildExistingProfilePeriods(ProfilePeriod[] profilePeriods, int paidUpToIndex)
        {
            for (int period = 0; period < profilePeriods.Length; period++)
            {
                ProfilePeriod profilePeriod = profilePeriods[period];

                yield return(new ExistingProfilePeriod
                {
                    DistributionPeriod = profilePeriod.DistributionPeriodId,
                    Occurrence = profilePeriod.Occurrence,
                    Type = profilePeriod.Type.AsMatchingEnum <PeriodType>(),
                    Year = profilePeriod.Year,
                    TypeValue = profilePeriod.TypeValue,
                    ProfileValue = period < paidUpToIndex ? profilePeriod.ProfiledValue : (decimal?)null
                });
            }
        }
Exemplo n.º 10
0
        public void ThenTheUpsertedProviderVersionForHasTheFollowingFundingLineProfilePeriods(string providerId,
                                                                                              IEnumerable <ExpectedFundingLineProfileValues> expectedFundingLineProfileValues)
        {
            PublishedProviderVersion publishedProviderVersion = GetUpsertedPublishedProviderVersion(providerId);

            foreach (ExpectedFundingLineProfileValues expectedFundingLineProfileValue in expectedFundingLineProfileValues)
            {
                FundingLine fundingLine = publishedProviderVersion.FundingLines.SingleOrDefault(_ =>
                                                                                                _.FundingLineCode == expectedFundingLineProfileValue.FundingLineCode);

                fundingLine
                .Should()
                .NotBeNull();

                foreach (ExpectedDistributionPeriod expectedDistributionPeriod in expectedFundingLineProfileValue.ExpectedDistributionPeriods)
                {
                    DistributionPeriod distributionPeriod = fundingLine.DistributionPeriods.SingleOrDefault(_ =>
                                                                                                            _.DistributionPeriodId == expectedDistributionPeriod.DistributionPeriodId);

                    distributionPeriod
                    .Should()
                    .NotBeNull();

                    foreach (ExpectedProfileValue expectedProfileValue in expectedDistributionPeriod.ExpectedProfileValues)
                    {
                        ProfilePeriod profilePeriod = distributionPeriod
                                                      .ProfilePeriods.SingleOrDefault(
                            _ => _.Type == expectedProfileValue.Type &&
                            _.TypeValue == expectedProfileValue.TypeValue &&
                            _.Year == expectedProfileValue.Year &&
                            _.Occurrence == expectedProfileValue.Occurrence);

                        profilePeriod
                        .Should()
                        .NotBeNull();

                        profilePeriod
                        .ProfiledValue
                        .Should()
                        .Be(expectedProfileValue.ProfiledValue);
                    }
                }
            }
        }
        public async Task SkipsProcessingPeriodIfAVariationPointerIsSet()
        {
            string fundingLineOneId = NewRandomString();
            string fundingLineTwoId = NewRandomString();
            int    year             = 2020;
            int    occurence        = 1;
            string typeValue        = "January";

            GivenTheVariationPointersForTheSpecification(NewVariationPointer(_ => _.WithFundingLineId(fundingLineOneId)
                                                                             .WithOccurence(occurence)
                                                                             .WithYear(year)
                                                                             .WithTypeValue(typeValue)),
                                                         NewVariationPointer(_ => _.WithFundingLineId(fundingLineTwoId)
                                                                             .WithOccurence(occurence)
                                                                             .WithYear(year)
                                                                             .WithTypeValue(typeValue)));

            decimal periodOneAmount   = 293487M;
            decimal periodTwoAmount   = 2973864M;
            decimal periodThreeAmount = 123764M;
            decimal periodFourAmount  = 6487234M;
            decimal periodFiveAmount  = 1290837M;

            ProfilePeriod periodOne   = NewProfilePeriod(0, 2020, "January", periodOneAmount);
            ProfilePeriod periodTwo   = NewProfilePeriod(1, 2020, "January", periodTwoAmount);
            ProfilePeriod periodThree = NewProfilePeriod(0, 2020, "February", periodThreeAmount);
            ProfilePeriod periodFour  = NewProfilePeriod(1, 2020, "January", periodFourAmount);
            ProfilePeriod periodFive  = NewProfilePeriod(2, 2020, "January", periodFiveAmount);

            AndTheFundingLines(NewFundingLine(_ => _.WithFundingLineCode(fundingLineOneId)
                                              .WithDistributionPeriods(NewDistributionPeriod(dp => dp.WithProfilePeriods(periodOne, periodTwo, periodThree)),
                                                                       NewDistributionPeriod(dp => dp.WithProfilePeriods(periodFour, periodFive)))));

            await WhenTheChangeIsApplied();

            AndTheProfilePeriodAmountShouldBe(periodOne, periodOneAmount);
            AndTheProfilePeriodAmountShouldBe(periodTwo, periodTwoAmount);
            AndTheProfilePeriodAmountShouldBe(periodThree, periodThreeAmount);
            AndTheProfilePeriodAmountShouldBe(periodFour, periodFourAmount);
            AndTheProfilePeriodAmountShouldBe(periodFive, periodFiveAmount);

            AndNoVariationChangesWereQueued();
        }
        public async Task OverridesProfilePeriodsOnPublishedProviderVersionAndGeneratesNewVersion(PublishedProviderStatus currentStatus,
                                                                                                  PublishedProviderStatus expectedRequestedStatus)
        {
            string        fundingLineOne = NewRandomString();
            ProfilePeriod profilePeriod1 = NewProfilePeriod(_ => _.WithDistributionPeriodId("FY-2021"));
            ProfilePeriod profilePeriod2 = NewProfilePeriod(_ => _.WithDistributionPeriodId("FY-2022"));

            ApplyCustomProfileRequest request = NewApplyCustomProfileRequest(_ => _
                                                                             .WithFundingLineCode(fundingLineOne)
                                                                             .WithProfilePeriods(profilePeriod1, profilePeriod2));

            PublishedProvider publishedProvider = NewPublishedProvider(_ => _.WithCurrent(
                                                                           NewPublishedProviderVersion(ppv =>
                                                                                                       ppv.WithPublishedProviderStatus(currentStatus)
                                                                                                       .WithFundingLines(NewFundingLine(fl =>
                                                                                                                                        fl.WithFundingLineCode(fundingLineOne)
                                                                                                                                        .WithDistributionPeriods(NewDistributionPeriod(dp =>
                                                                                                                                                                                       dp.WithDistributionPeriodId("FY-2021")
                                                                                                                                                                                       .WithProfilePeriods(profilePeriod1)),
                                                                                                                                                                 NewDistributionPeriod(dp =>
                                                                                                                                                                                       dp.WithDistributionPeriodId("FY-2022")
                                                                                                                                                                                       .WithProfilePeriods(profilePeriod2))))
                                                                                                                         ))));

            Reference author = NewAuthor();

            GivenTheValidationResultForTheRequest(NewValidationResult(), request);
            AndThePublishedProvider(request.PublishedProviderId, publishedProvider);

            IActionResult result = await WhenTheCustomProfileIsApplied(request, author);

            result
            .Should()
            .BeOfType <NoContentResult>();

            IEnumerable <ProfilePeriod> profilePeriods = request.ProfilePeriods;
            FundingLine fundingLine = publishedProvider.Current.FundingLines.Single(fl => fl.FundingLineCode == fundingLineOne);

            AndTheCustomProfilePeriodsWereUsedOn(fundingLine, profilePeriods);
            AndANewProviderVersionWasCreatedFor(publishedProvider, expectedRequestedStatus, author);
            AndProfilingAuditUpdatedForFundingLines(publishedProvider, new[] { fundingLineOne }, author);
        }
        public async Task ZerosProfilesWhenNoVariationsPointersAreSetInSpecificationOnEachMatchingFundingLine()
        {
            string fundingLineOneId = NewRandomString();
            int    year             = 2020;

            decimal periodOneAmount = 293487M;

            ProfilePeriod periodOne   = NewProfilePeriod(0, year, "January", periodOneAmount);
            ProfilePeriod periodTwo   = NewProfilePeriod(1, year, "January", 2973864M);
            ProfilePeriod periodThree = NewProfilePeriod(0, year, "February", 123764M);
            ProfilePeriod periodFour  = NewProfilePeriod(1, year, "January", 6487234M);
            ProfilePeriod periodFive  = NewProfilePeriod(2, year, "January", 1290837M);

            AndTheFundingLines(NewFundingLine(_ => _.WithFundingLineCode(fundingLineOneId)
                                              .WithFundingLineType(FundingLineType.Payment)
                                              .WithDistributionPeriods(NewDistributionPeriod(dp => dp.WithProfilePeriods(periodOne, periodTwo, periodThree)),
                                                                       NewDistributionPeriod(dp => dp.WithProfilePeriods(periodFour, periodFive)))));

            await WhenTheChangeIsApplied();

            ThenProfilePeriodsShouldBeZeroAmount(periodOne, periodTwo, periodThree, periodFour, periodFive);
        }
        private bool PaidProfileFundingLinesMatches(IEnumerable <FundingLine> fundingLines,
                                                    string distributionId,
                                                    ProfilePeriod profilePeriod)
        {
            FundingLine fundingLine = fundingLines.FirstOrDefault();

            ProfilePeriod paidProfilePeriod = fundingLine
                                              .DistributionPeriods
                                              .SingleOrDefault(_ => _.DistributionPeriodId == distributionId)
                                              ?.ProfilePeriods
                                              .FirstOrDefault();

            if (paidProfilePeriod == null)
            {
                return(false);
            }

            return(paidProfilePeriod.ProfiledValue == profilePeriod.ProfiledValue &&
                   paidProfilePeriod.Occurrence == profilePeriod.Occurrence &&
                   paidProfilePeriod.Type == profilePeriod.Type &&
                   paidProfilePeriod.TypeValue == profilePeriod.TypeValue &&
                   paidProfilePeriod.Year == profilePeriod.Year);
        }
        private bool AdjustingPeriodsForOverPaymentLeavesRemainder(int variationPointerIndex,
                                                                   decimal latestPeriodAmount,
                                                                   ProfilePeriod[] orderedSnapShotProfilePeriods,
                                                                   ProfilePeriod[] orderRefreshProfilePeriods,
                                                                   out decimal remainingOverPayment)
        {
            decimal amountAlreadyPaid            = orderedSnapShotProfilePeriods.Take(variationPointerIndex).Sum(_ => _.ProfiledValue);
            decimal amountThatShouldHaveBeenPaid = latestPeriodAmount * variationPointerIndex;

            remainingOverPayment = amountAlreadyPaid - amountThatShouldHaveBeenPaid;

            for (int profilePeriod = variationPointerIndex; profilePeriod < orderRefreshProfilePeriods.Length; profilePeriod++)
            {
                if (remainingOverPayment <= 0)
                {
                    break;
                }

                ProfilePeriod periodToAdjust = orderRefreshProfilePeriods[profilePeriod];

                decimal adjustedProfileValue = periodToAdjust.ProfiledValue - remainingOverPayment;

                if (adjustedProfileValue < 0)
                {
                    remainingOverPayment = Math.Abs(adjustedProfileValue);
                    adjustedProfileValue = 0;
                }
                else
                {
                    remainingOverPayment = 0;
                }

                periodToAdjust.ProfiledValue = adjustedProfileValue;
            }

            return(remainingOverPayment != 0);
        }
 private string AsLiteral(ProfilePeriod profilePeriod)
 {
     return($"{profilePeriod.Year}{profilePeriod.Type}{profilePeriod.TypeValue}{profilePeriod.Occurrence}{profilePeriod.ProfiledValue}");
 }
        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);
        }
 protected void ThenTheProfilePeriodAmountShouldBe(ProfilePeriod profilePeriod, decimal expectedAmount)
 {
     AndTheProfilePeriodAmountShouldBe(profilePeriod, expectedAmount);
 }