public async Task AssignProfilePatternKeyReturnsBadRequestIfNewPublishedProviderVersionCreationFailed()
        {
            string fundingLineCode            = NewRandomString();
            string existingProfilePatternKey  = NewRandomString();
            string newProfilePatterFundingKey = NewRandomString();

            GivenTheFundingConfiguration(true);
            ProfilePatternKey profilePatternKey = NewProfilePatternKey(_ => _.WithFundingLineCode(fundingLineCode).WithKey(newProfilePatterFundingKey));

            FundingLine fundingLine = NewFundingLine(_ => _.WithFundingLineCode(fundingLineCode));
            PublishedProviderVersion existingPublishedProviderVersion =
                NewPublishedProviderVersion(ppv => ppv
                                            .WithFundingStreamId(_fundingStreamId)
                                            .WithFundingPeriodId(_fundingPeriodId)
                                            .WithProfilePatternKeys(
                                                NewProfilePatternKey(_ => _.WithFundingLineCode(fundingLineCode).WithKey(existingProfilePatternKey)))
                                            .WithFundingLines(fundingLine)
                                            );

            PublishedProvider publishedProvider = NewPublishedProvider(_ => _.WithCurrent(existingPublishedProviderVersion));

            GivenThePublishedProvider(publishedProvider);

            IActionResult result = await WhenProfilePatternKeyIsAssigned(_fundingStreamId, _fundingPeriodId, _providerId, profilePatternKey);

            ThenResultShouldBe(result, HttpStatusCode.BadRequest);
        }
        public async Task AssignProfilePatternKeyReturnsNotModifiedIfMatchingProfilePatternKeyExists()
        {
            string fundingLineCode = NewRandomString();
            string key             = NewRandomString();

            GivenTheFundingConfiguration(true);
            ProfilePatternKey profilePatternKey = NewProfilePatternKey(_ => _.WithFundingLineCode(fundingLineCode).WithKey(key));

            PublishedProvider publishedProvider = NewPublishedProvider(_ => _.WithCurrent(
                                                                           NewPublishedProviderVersion(ppv => ppv.WithProfilePatternKeys(
                                                                                                           NewProfilePatternKey(ppk => ppk.WithFundingLineCode(fundingLineCode).WithKey(key))))));

            GivenThePublishedProvider(publishedProvider);

            StatusCodeResult result = await WhenProfilePatternKeyIsAssigned(_fundingStreamId, _fundingPeriodId, _providerId, profilePatternKey) as StatusCodeResult;

            result
            .Should()
            .NotBeNull();

            result
            .StatusCode
            .Should()
            .Be((int)HttpStatusCode.NotModified);
        }
 public async Task <IActionResult> AssignProfilePatternKeyToPublishedProvider(
     [FromRoute] string fundingStreamId,
     [FromRoute] string fundingPeriodId,
     [FromRoute] string providerId,
     [FromBody] ProfilePatternKey profilePatternKey)
 {
     return(await _publishedProviderProfilingService.AssignProfilePatternKey(
                fundingStreamId, fundingPeriodId, providerId, profilePatternKey, Request.GetUserOrDefault()));
 }
Beispiel #4
0
        public async Task <IActionResult> AssignProfilePatternKey(
            string fundingStreamId,
            string fundingPeriodId,
            string providerId,
            ProfilePatternKey profilePatternKey,
            Reference author)
        {
            Guard.IsNullOrWhiteSpace(fundingStreamId, nameof(fundingStreamId));
            Guard.IsNullOrWhiteSpace(fundingPeriodId, nameof(fundingPeriodId));
            Guard.IsNullOrWhiteSpace(providerId, nameof(providerId));
            Guard.ArgumentNotNull(profilePatternKey, nameof(profilePatternKey));

            PublishedProvider publishedProvider = await _publishingResiliencePolicy.ExecuteAsync(async() =>
                                                                                                 await _publishedFundingRepository.GetPublishedProvider(fundingStreamId, fundingPeriodId, providerId));

            if (publishedProvider == null)
            {
                return(new StatusCodeResult((int)HttpStatusCode.NotFound));
            }

            FundingConfiguration fundingConfiguration = await _policiesService.GetFundingConfiguration(fundingStreamId, fundingPeriodId);

            if (fundingConfiguration == null || !fundingConfiguration.EnableUserEditableRuleBasedProfiles)
            {
                return(new BadRequestObjectResult($"User not allowed to edit rule based profiles for funding stream - '{fundingStreamId}' and funding period - '{fundingPeriodId}'"));
            }

            if (MatchingProfilePatternKeyExists(publishedProvider.Current, profilePatternKey))
            {
                return(new StatusCodeResult((int)HttpStatusCode.NotModified));
            }

            PublishedProvider modifiedPublishedProvider = await CreateVersion(publishedProvider, author);

            if (modifiedPublishedProvider == null)
            {
                return(new StatusCodeResult((int)HttpStatusCode.BadRequest));
            }

            PublishedProviderVersion newPublishedProviderVersion = publishedProvider.Current;

            newPublishedProviderVersion.SetProfilePatternKey(profilePatternKey, author);

            await ProfileFundingLineValues(newPublishedProviderVersion, profilePatternKey);

            await _publishedProviderErrorDetection.ProcessPublishedProvider(publishedProvider, _ => _ is FundingLineValueProfileMismatchErrorDetector);

            await SavePublishedProvider(publishedProvider, newPublishedProviderVersion);

            return(new StatusCodeResult((int)HttpStatusCode.OK));
        }
 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);
 }
        public async Task AssignProfilePatternKeyReturnsNotFoundIfPublishedProviderDoesNotExist()
        {
            GivenThePublishedProvider(null);
            GivenTheFundingConfiguration(true);

            ProfilePatternKey profilePatternKey = NewProfilePatternKey();
            StatusCodeResult  result            = await WhenProfilePatternKeyIsAssigned(_fundingStreamId, _fundingPeriodId, _providerId, profilePatternKey) as StatusCodeResult;

            result
            .Should()
            .NotBeNull();

            result
            .StatusCode
            .Should()
            .Be((int)HttpStatusCode.NotFound);
        }
        private static void EnsurePublishedProvidersHaveProfilePatternDetails(BatchProfilingResponseModel response,
                                                                              ProfilingBatch batch)
        {
            ProfilePatternKey profilePatternKey = new ProfilePatternKey
            {
                Key             = response.ProfilePatternKey,
                FundingLineCode = batch.FundingLineCode
            };

            foreach (PublishedProviderVersion publishedProviderVersion in batch.PublishedProviders)
            {
                lock (publishedProviderVersion)
                {
                    publishedProviderVersion.SetProfilePatternKey(profilePatternKey.DeepCopy());
                }
            }
        }
        public async Task <IActionResult> AssignProfilePatternKeyToPublishedProvider(
            [FromRoute] string fundingStreamId,
            [FromRoute] string fundingPeriodId,
            [FromRoute] string providerId,
            [FromBody] ProfilePatternKey profilePatternKey)
        {
            Guard.ArgumentNotNull(fundingStreamId, nameof(fundingStreamId));
            Guard.ArgumentNotNull(fundingPeriodId, nameof(fundingPeriodId));
            Guard.ArgumentNotNull(providerId, nameof(providerId));
            Guard.ArgumentNotNull(profilePatternKey, nameof(profilePatternKey));

            HttpStatusCode apiResponse =
                await _publishingApiClient.AssignProfilePatternKeyToPublishedProvider(
                    fundingStreamId, fundingPeriodId, providerId, profilePatternKey);

            return(StatusCode((int)apiResponse));
        }
        public async Task AssignProfilePatternKeyReturnsOkAndUpdatesPatternKeyWithNewVersion()
        {
            string fundingLineCode            = NewRandomString();
            string existingProfilePatternKey  = NewRandomString();
            string newProfilePatterFundingKey = NewRandomString();
            string specificationId            = NewRandomString();

            GivenTheFundingConfiguration(true);
            ProfilePatternKey profilePatternKey = NewProfilePatternKey(_ => _.WithFundingLineCode(fundingLineCode).WithKey(newProfilePatterFundingKey));

            FundingLine fundingLine = NewFundingLine(_ => _.WithFundingLineCode(fundingLineCode));
            PublishedProviderVersion existingPublishedProviderVersion =
                NewPublishedProviderVersion(ppv => ppv
                                            .WithFundingStreamId(_fundingStreamId)
                                            .WithSpecificationId(specificationId)
                                            .WithFundingPeriodId(_fundingPeriodId)
                                            .WithProfilePatternKeys(
                                                NewProfilePatternKey(_ => _.WithFundingLineCode(fundingLineCode).WithKey(existingProfilePatternKey)))
                                            .WithFundingLines(fundingLine)
                                            );

            PublishedProvider        publishedProvider           = NewPublishedProvider(_ => _.WithCurrent(existingPublishedProviderVersion));
            PublishedProviderVersion newPublishedProviderVersion = existingPublishedProviderVersion;
            PublishedProviderCreateVersionRequest publishedProviderCreateVersionRequest =
                NewPublishedProviderCreateVersionRequest(_ => _
                                                         .WithPublishedProvider(publishedProvider)
                                                         .WithNewVersion(newPublishedProviderVersion));

            GivenThePublishedProvider(publishedProvider);
            AndThePublishedProviderCreateVersionRequest(publishedProvider, publishedProviderCreateVersionRequest);
            AndTheNewCreatedPublishedProvider(publishedProvider, publishedProviderCreateVersionRequest);
            AndTheProfileVariationPointers(null, specificationId);
            AndTheProfileFundingLines(profilePatternKey);
            AndTheSavePublishedProviderVersionResponse(HttpStatusCode.OK, existingPublishedProviderVersion);
            AndTheUpsertPublishedProviderResponse(HttpStatusCode.OK, publishedProvider);

            IActionResult result = await WhenProfilePatternKeyIsAssigned(_fundingStreamId, _fundingPeriodId, _providerId, profilePatternKey);

            ThenResultShouldBe(result, HttpStatusCode.OK);
            AndProfilePatternKeyWasUpdated(newPublishedProviderVersion, profilePatternKey);
            AndThePublishedProviderWasProcessed(publishedProvider);
            AndTheProfilingAuditWasUpdatedForTheFundingLine(publishedProvider, profilePatternKey.FundingLineCode, _author);
        }
        public void SetUp()
        {
            _customProfileService = new Mock <ICustomProfileService>();
            _publishedProviderProfilingService = new Mock <IPublishedProviderProfilingService>();

            _controller = new ProfilingActionsController(
                _publishedProviderProfilingService.Object,
                _customProfileService.Object);

            _fundingStreamId = NewRandomString();
            _fundPeriodId    = NewRandomString();
            _providerId      = NewRandomString();
            _correlationId   = NewRandomString();
            _userId          = NewRandomString();
            _userName        = NewRandomString();

            _profilePatternKey = new ProfilePatternKey {
                FundingLineCode = NewRandomString(), Key = NewRandomString()
            };

            HttpContext     context         = Substitute.For <HttpContext>();
            HttpRequest     request         = Substitute.For <HttpRequest>();
            ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.Sid, _userId),
                new Claim(ClaimTypes.Name, _userName)
            }));

            context.Request.Returns(request);
            request.HttpContext.Returns(context);
            context.User.Returns(claimsPrincipal);

            _controller.ControllerContext = new ControllerContext
            {
                HttpContext = context
            };

            request.Headers.Returns(new HeaderDictionary(new Dictionary <string, StringValues>
            {
                { "sfa-correlationId", new StringValues(_correlationId) }
            }));
        }
        private void AndTheProfileFundingLines(ProfilePatternKey profilePatternKey)
        {
            _profilingService.Setup(_ =>
                                    _.ProfileFundingLines(
                                        It.Is <IEnumerable <FundingLine> >(fl =>
                                                                           FundingLinesMatches(fl)),
                                        It.Is <string>(fs => fs == _fundingStreamId),
                                        It.Is <string>(fp => fp == _fundingPeriodId),
                                        It.Is <IEnumerable <ProfilePatternKey> >(ppk =>
                                                                                 ppk.Any(k => k.FundingLineCode == profilePatternKey.FundingLineCode &&
                                                                                         k.Key == profilePatternKey.Key)),
                                        null,
                                        null)
                                    ).Returns <IEnumerable <FundingLine>, string, string, IEnumerable <ProfilePatternKey>, string, string>(
                (fundingLines, fs, fp, keys, pt, pst) =>
            {
                FundingLine fundingLine         = fundingLines.FirstOrDefault();
                fundingLine.DistributionPeriods = NewDistributionPeriods(
                    dp => dp
                    .WithDistributionPeriodId(_distributionPeriod1Id)
                    .WithProfilePeriods(NewProfilePeriods(
                                            pp => pp
                                            .WithAmount(_profilePeriod1ProfiledAmount)
                                            .WithOccurence(_profilePeriod1Occurence)
                                            .WithType(_profilePeriod1Type)
                                            .WithTypeValue(_profilePeriod1TypeValue)
                                            .WithYear(_profilePeriod1Year)
                                            ).ToArray()),
                    dp => dp
                    .WithDistributionPeriodId(_distributionPeriod2Id)
                    .WithProfilePeriods(NewProfilePeriods(
                                            pp => pp
                                            .WithAmount(_profilePeriod2ProfiledAmount)
                                            .WithOccurence(_profilePeriod2Occurence)
                                            .WithType(_profilePeriod2Type)
                                            .WithTypeValue(_profilePeriod2TypeValue)
                                            .WithYear(_profilePeriod2Year)
                                            ).ToArray())).ToList();

                return(Task.FromResult(ArraySegment <ProfilePatternKey> .Empty.AsEnumerable()));
            });
        }
Beispiel #12
0
        public async Task AssignProfilePatternKeyToPublishedProvider()
        {
            string            fundingStreamId   = NewRandomString();
            string            fundingPeriodId   = NewRandomString();
            string            providerId        = NewRandomString();
            ProfilePatternKey profilePatternKey = new ProfilePatternKey {
                FundingLineCode = NewRandomString(), Key = NewRandomString()
            };
            string expectedUri = $"publishedprovider/fundingStream/{fundingStreamId}/fundingPeriod/{fundingPeriodId}/provider/{providerId}";

            GivenTheStatusCode(expectedUri, HttpStatusCode.OK, HttpMethod.Post);

            HttpStatusCode response = await _client.AssignProfilePatternKeyToPublishedProvider(fundingStreamId, fundingPeriodId, providerId, profilePatternKey);

            response
            .Should()
            .NotBeNull();

            response
            .Should()
            .Be(HttpStatusCode.OK);
        }
        public async Task AssignProfilePatternKeyReturnsBadRequestIfFundingConfigurationIsNotEnableedUserEditableRuleBasedProfiles()
        {
            string fundingLineCode = NewRandomString();
            string key             = NewRandomString();

            PublishedProvider publishedProvider = NewPublishedProvider(_ => _.WithCurrent(
                                                                           NewPublishedProviderVersion(ppv => ppv.WithProfilePatternKeys(
                                                                                                           NewProfilePatternKey(ppk => ppk.WithFundingLineCode(fundingLineCode).WithKey(key))))));

            GivenThePublishedProvider(publishedProvider);

            GivenTheFundingConfiguration(false);
            ProfilePatternKey      profilePatternKey = NewProfilePatternKey();
            BadRequestObjectResult result            = await WhenProfilePatternKeyIsAssigned(_fundingStreamId, _fundingPeriodId, _providerId, profilePatternKey) as BadRequestObjectResult;

            result
            .Should()
            .NotBeNull();

            result
            .Value
            .Should()
            .Be($"User not allowed to edit rule based profiles for funding stream - '{_fundingStreamId}' and funding period - '{_fundingPeriodId}'");
        }
Beispiel #14
0
        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);
            }
        }
 private void AndProfilePatternKeyWasUpdated(PublishedProviderVersion publishedProviderVersion,
                                             ProfilePatternKey profilePatternKey)
 {
     Assert.AreEqual(publishedProviderVersion.ProfilePatternKeys.SingleOrDefault(_ => _.FundingLineCode == profilePatternKey.FundingLineCode), profilePatternKey);
 }
Beispiel #16
0
 private bool MatchingProfilePatternKeyExists(
     PublishedProviderVersion publishedProviderVersion,
     ProfilePatternKey profilePatternKey)
 {
     return(publishedProviderVersion?.ProfilePatternKeys != null && publishedProviderVersion.ProfilePatternKeys.Contains(profilePatternKey));
 }
Beispiel #17
0
 private async Task ProfileFundingLine(FundingLine fundingLine, PublishedProviderVersion newPublishedProviderVersion, ProfilePatternKey profilePatternKey)
 {
     await _profilingService.ProfileFundingLines(
         new[] { fundingLine },
         newPublishedProviderVersion.FundingStreamId,
         newPublishedProviderVersion.FundingPeriodId,
         new[] { profilePatternKey });
 }
Beispiel #18
0
        private async Task ProfileFundingLineValues(PublishedProviderVersion newPublishedProviderVersion, ProfilePatternKey profilePatternKey)
        {
            string fundingLineCode = profilePatternKey.FundingLineCode;

            FundingLine fundingLine = newPublishedProviderVersion.FundingLines.SingleOrDefault(_ => _.FundingLineCode == fundingLineCode);

            if (fundingLine == null)
            {
                string error = $"Did not locate a funding line with code {fundingLineCode} on published provider version {newPublishedProviderVersion.PublishedProviderId}";

                _logger.Error(error);

                throw new InvalidOperationException(error);
            }

            ApiResponse <IEnumerable <ProfileVariationPointer> > variationPointersResponse =
                await _specificationResiliencePolicy.ExecuteAsync(() =>
                                                                  _specificationsApiClient.GetProfileVariationPointers(newPublishedProviderVersion.SpecificationId));

            IEnumerable <ProfileVariationPointer> profileVariationPointers = variationPointersResponse?
                                                                             .Content?
                                                                             .Where(_ =>
                                                                                    _.FundingLineId == fundingLineCode &&
                                                                                    _.FundingStreamId == newPublishedProviderVersion.FundingStreamId);

            if (ThereArePaidProfilePeriodsOnTheFundingLine(profileVariationPointers))
            {
                await ReProfileFundingLine(newPublishedProviderVersion, profilePatternKey, fundingLineCode, fundingLine);
            }
            else
            {
                await ProfileFundingLine(fundingLine, newPublishedProviderVersion, profilePatternKey);
            }
        }
        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);
        }
 private async Task <IActionResult> WhenProfilePatternKeyIsAssigned(string fundingStreamId,
                                                                    string fundingPeriodId,
                                                                    string providerId,
                                                                    ProfilePatternKey profilePatternKey) => await _service.AssignProfilePatternKey(fundingStreamId, fundingPeriodId, providerId, profilePatternKey, _author);