public async Task <IActionResult> ApplyCustomProfile(ApplyCustomProfileRequest request, Reference author)
        {
            Guard.ArgumentNotNull(request, nameof(request));
            Guard.ArgumentNotNull(author, nameof(author));

            ValidationResult validationResult = await _requestValidation.ValidateAsync(request);

            if (!validationResult.IsValid)
            {
                string validationErrors = validationResult.Errors.Select(_ => _.ErrorMessage).Join(", ");

                _logger.Information(
                    $"Unable to process apply custom profile request. Request was invalid. \n{validationErrors}");

                return(validationResult.AsBadRequest());
            }

            string publishedProviderId = request.PublishedProviderId;
            string fundingLineCode     = request.FundingLineCode;

            PublishedProvider publishedProvider = await _publishedFundingResilience.ExecuteAsync(() =>
                                                                                                 _publishedFundingRepository.GetPublishedProviderById(publishedProviderId, publishedProviderId));

            PublishedProviderVersion currentProviderVersion = publishedProvider.Current;

            foreach (IGrouping <string, ProfilePeriod> profilePeriods in request.ProfilePeriods.GroupBy(_ => _.DistributionPeriodId))
            {
                string distributionPeriodId = profilePeriods.Key;

                currentProviderVersion.UpdateDistributionPeriodForFundingLine(
                    fundingLineCode,
                    distributionPeriodId,
                    profilePeriods);

                currentProviderVersion.AddOrUpdateCustomProfile(fundingLineCode, request.CarryOver, distributionPeriodId);
            }

            if (request.HasCarryOver)
            {
                currentProviderVersion.AddCarryOver(fundingLineCode,
                                                    ProfilingCarryOverType.CustomProfile,
                                                    request.CarryOver.GetValueOrDefault());
            }
            else
            {
                currentProviderVersion.RemoveCarryOver(fundingLineCode);
            }

            currentProviderVersion.AddProfilingAudit(fundingLineCode, author);

            await _publishedProviderVersionCreation.UpdatePublishedProviderStatus(new[] { publishedProvider },
                                                                                  author,
                                                                                  currentProviderVersion.Status switch
            {
                PublishedProviderStatus.Draft => PublishedProviderStatus.Draft,
                _ => PublishedProviderStatus.Updated
            },
        private async Task ReProfileFundingLine(string fundingLineCode,
                                                PublishedProviderVersion refreshState,
                                                IApplyProviderVariations variationApplications)
        {
            FundingLine fundingLine = refreshState.FundingLines.SingleOrDefault(_ => _.FundingLineCode == fundingLineCode);

            string providerId = refreshState.ProviderId;

            if (fundingLine == null)
            {
                throw new NonRetriableException($"Could not locate funding line {fundingLineCode} for published provider version {providerId}");
            }

            ReProfileRequest reProfileRequest = await variationApplications.ReProfilingRequestBuilder.BuildReProfileRequest(refreshState.SpecificationId,
                                                                                                                            refreshState.FundingStreamId,
                                                                                                                            refreshState.FundingPeriodId,
                                                                                                                            providerId,
                                                                                                                            fundingLineCode,
                                                                                                                            null,
                                                                                                                            ProfileConfigurationType.RuleBased,
                                                                                                                            fundingLine.Value);

            ReProfileResponse reProfileResponse = (await variationApplications.ResiliencePolicies.ProfilingApiClient.ExecuteAsync(()
                                                                                                                                  => variationApplications.ProfilingApiClient.ReProfile(reProfileRequest)))?.Content;

            if (reProfileResponse == null)
            {
                throw new NonRetriableException($"Could not re profile funding line {fundingLineCode} for provider {providerId}");
            }

            IEnumerable <DistributionPeriod> distributionPeriods = variationApplications.ReProfilingResponseMapper.MapReProfileResponseIntoDistributionPeriods(reProfileResponse);

            foreach (DistributionPeriod distributionPeriod in distributionPeriods)
            {
                refreshState.UpdateDistributionPeriodForFundingLine(fundingLineCode,
                                                                    distributionPeriod.DistributionPeriodId,
                                                                    distributionPeriod.ProfilePeriods);
            }
        }