Beispiel #1
0
        private bool HasNoPaidPeriods(ProviderVariationContext providerVariationContext,
                                      PublishedProviderVersion priorState)
        {
            foreach (ProfileVariationPointer variationPointer in providerVariationContext.VariationPointers ?? ArraySegment <ProfileVariationPointer> .Empty)
            {
                FundingLine fundingLine = priorState?.FundingLines.SingleOrDefault(_ => _.FundingLineCode == variationPointer.FundingLineId);

                if (fundingLine == null)
                {
                    continue;
                }

                YearMonthOrderedProfilePeriods periods = new YearMonthOrderedProfilePeriods(fundingLine);

                int variationPointerIndex = periods.IndexOf(_ => _.Occurrence == variationPointer.Occurrence &&
                                                            _.Type.ToString() == variationPointer.PeriodType &&
                                                            _.Year == variationPointer.Year &&
                                                            _.TypeValue == variationPointer.TypeValue);

                if (variationPointerIndex > 0)
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #2
0
        public Task DetermineVariations(ProviderVariationContext providerVariationContext, IEnumerable <string> fundingLineCodes)
        {
            Guard.ArgumentNotNull(providerVariationContext, nameof(providerVariationContext));

            PublishedProviderVersion priorState = providerVariationContext.PriorState;

            if (priorState == null ||
                priorState.Provider.Status == Closed ||
                providerVariationContext.UpdatedProvider.Status != Closed ||
                !providerVariationContext.UpdatedProvider.Successor.IsNullOrWhitespace())
            {
                return(Task.CompletedTask);
            }

            if (providerVariationContext.UpdatedTotalFunding != priorState.TotalFunding)
            {
                providerVariationContext.RecordErrors("Unable to run Closure variation as TotalFunding has changed during the refresh funding");

                return(Task.CompletedTask);
            }


            providerVariationContext.QueueVariationChange(new ZeroRemainingProfilesChange(providerVariationContext));
            providerVariationContext.QueueVariationChange(new ZeroInitialPaymentProfilesChange(providerVariationContext));
            providerVariationContext.QueueVariationChange(new ReAdjustFundingValuesForProfileValuesChange(providerVariationContext));

            return(Task.CompletedTask);
        }
        protected virtual bool HasNoProfilingChanges(PublishedProviderVersion priorState,
                                                     PublishedProviderVersion refreshState,
                                                     ProviderVariationContext providerVariationContext)
        {
            IDictionary <string, FundingLine> latestFundingLines =
                refreshState.FundingLines.Where(_ => _.Type == FundingLineType.Payment)
                .ToDictionary(_ => _.FundingLineCode);

            bool hasNoProfilingChanges = true;

            foreach (FundingLine previousFundingLine in priorState.FundingLines.Where(_ => _.Type == FundingLineType.Payment &&
                                                                                      _.Value.HasValue &&
                                                                                      ExtraFundingLinePredicate(refreshState, _)))
            {
                string fundingLineCode = previousFundingLine.FundingLineCode;

                if (!latestFundingLines.TryGetValue(fundingLineCode, out FundingLine latestFundingLine))
                {
                    continue;
                }

                ProfilePeriod[] priorProfiling  = new YearMonthOrderedProfilePeriods(previousFundingLine).ToArray();
                ProfilePeriod[] latestProfiling = new YearMonthOrderedProfilePeriods(latestFundingLine).ToArray();

                if (!priorProfiling.Select(AsLiteral)
                    .SequenceEqual(latestProfiling.Select(AsLiteral)))
                {
                    providerVariationContext.AddAffectedFundingLineCode(fundingLineCode);

                    hasNoProfilingChanges = false;
                }
            }

            return(hasNoProfilingChanges);
        }
        protected ProfileVariationPointerChange(ProviderVariationContext variationContext, string changeName)
            : base(variationContext)
        {
            Guard.IsNullOrWhiteSpace(changeName, nameof(changeName));

            _changeName = changeName;
        }
Beispiel #5
0
        public async Task TracksConfiguredPropertiesForVariationReasons(ProviderVariationContext variationContext,
                                                                        VariationReason[] expectedVariationReasons)
        {
            expectedVariationReasons ??= new VariationReason[0];

            await _metadataVariationStrategy.DetermineVariations(variationContext, null);

            variationContext
            .VariationReasons
            .OrderBy(_ => _)
            .Should()
            .BeEquivalentTo(expectedVariationReasons.OrderBy(_ => _));

            if (expectedVariationReasons.AnyWithNullCheck())
            {
                variationContext.QueuedChanges
                .FirstOrDefault()
                .Should()
                .BeOfType <MetaDataVariationsChange>();
            }
            else
            {
                variationContext.QueuedChanges
                .Should()
                .BeNullOrEmpty();
            }
        }
 protected async Task <PublishedProvider> GetOrCreateSuccessorProvider(ProviderVariationContext providerVariationContext,
                                                                       string successorId)
 {
     return(providerVariationContext.GetPublishedProviderRefreshState(successorId) ??
            providerVariationContext.AddMissingProvider(await _providerService.CreateMissingPublishedProviderForPredecessor(
                                                            providerVariationContext.PublishedProvider,
                                                            successorId, providerVariationContext.ProviderVersionId)));
 }
        public async Task ExecutesVariationStrategiesSpecifiedInSuppliedFundingVariationsAndReturnsVariationResult(
            FundingVariation[] fundingVariations)
        {
            IEnumerable <ProfileVariationPointer> variationPointers = ArraySegment <ProfileVariationPointer> .Empty;
            PublishedProvider existingPublishedProvider             = NewPublishedProvider();
            Provider          updatedProvider     = NewApiProvider();
            decimal           updatedTotalFunding = new RandomNumberBetween(0, 1000);
            IDictionary <string, PublishedProviderSnapShots> allPublishedProviderSnapShots     = new Dictionary <string, PublishedProviderSnapShots>();
            IDictionary <string, PublishedProvider>          allPublishedProviderRefreshStates = new Dictionary <string, PublishedProvider>();
            string providerVersionId = NewRandomString();

            ProviderVariationContext providerVariationContext = await _factory.CreateRequiredVariationChanges(existingPublishedProvider,
                                                                                                              updatedTotalFunding,
                                                                                                              updatedProvider,
                                                                                                              fundingVariations,
                                                                                                              allPublishedProviderSnapShots,
                                                                                                              allPublishedProviderRefreshStates,
                                                                                                              variationPointers,
                                                                                                              providerVersionId);

            providerVariationContext
            .UpdatedTotalFunding
            .Should()
            .Be(updatedTotalFunding);

            providerVariationContext
            .ReleasedState
            .Should()
            .BeSameAs(existingPublishedProvider.Released);

            providerVariationContext
            .UpdatedProvider
            .Should()
            .BeSameAs(updatedProvider);

            providerVariationContext
            .ProviderVersionId
            .Should()
            .BeSameAs(providerVersionId);

            Received.InOrder(() =>
            {
                foreach (FundingVariation fundingVariation in fundingVariations.OrderBy(_ => _.Order))
                {
                    _variationStrategyServiceLocator.GetService(fundingVariation.Name);
                    _variationStrategy.DetermineVariations(Arg.Is <ProviderVariationContext>(
                                                               ctx => ctx.UpdatedTotalFunding == updatedTotalFunding &&
                                                               ReferenceEquals(ctx.ReleasedState, existingPublishedProvider.Released) &&
                                                               ctx.ProviderId == existingPublishedProvider.Current.ProviderId &&
                                                               ReferenceEquals(ctx.UpdatedProvider, updatedProvider) &&
                                                               ReferenceEquals(ctx.AllPublishedProviderSnapShots, allPublishedProviderSnapShots) &&
                                                               ReferenceEquals(ctx.AllPublishedProvidersRefreshStates, allPublishedProviderRefreshStates) &&
                                                               ctx.ProviderVersionId == providerVersionId),
                                                           fundingVariation.FundingLineCodes);
                }
            });
        }
Beispiel #8
0
            public void Run(ProviderVariationContext providerVariationContext)
            {
                string priorValue   = (string)_priorStateAccessor.GetValue(providerVariationContext.PriorState.Provider);
                string currentValue = (string)_updatedStateAccessor.GetValue(providerVariationContext.UpdatedProvider);

                if (priorValue != currentValue)
                {
                    providerVariationContext.AddVariationReasons(_variationReason);
                }
            }
        public async Task AddsVariationContextsToBeAppliedLater()
        {
            ProviderVariationContext contextOne = NewVariationContext();
            ProviderVariationContext contextTwo = NewVariationContext();

            GivenTheVariationContextWasAdded(contextOne);
            AndTheVariationContextWasAdded(contextTwo);

            await WhenTheVariationsAreApplied();

            await ThenTheVariationsWereApplied(contextOne);
            await AndTheVariationsWereApplied(contextTwo);
        }
Beispiel #10
0
        private static ProviderVariationContext NewProviderVariationContext(Action <ProviderVariationContextBuilder> setUp = null)
        {
            ProviderVariationContextBuilder variationContextBuilder = new ProviderVariationContextBuilder();

            setUp?.Invoke(variationContextBuilder);

            ProviderVariationContext providerVariationContext = variationContextBuilder.Build();

            providerVariationContext.AllPublishedProviderSnapShots      = AsDictionary(new PublishedProviderSnapShots(providerVariationContext.PublishedProvider));
            providerVariationContext.AllPublishedProvidersRefreshStates = AsDictionary(providerVariationContext.PublishedProvider);

            return(providerVariationContext);
        }
        public async Task DetermineVariations(ProviderVariationContext providerVariationContext, IEnumerable <string> fundingLineCodes)
        {
            Guard.ArgumentNotNull(providerVariationContext, nameof(providerVariationContext));

            Provider updatedProvider = providerVariationContext.UpdatedProvider;

            string successorId = updatedProvider.Successor;

            PublishedProviderVersion priorState = providerVariationContext.PriorState;

            if (priorState == null ||
                priorState.Provider.Status == Closed ||
                updatedProvider.Status != Closed ||
                successorId.IsNullOrWhitespace())
            {
                return;
            }

            if (providerVariationContext.UpdatedTotalFunding != priorState.TotalFunding)
            {
                providerVariationContext.RecordErrors("Unable to run Closure with Successor variation as TotalFunding has changed during the refresh funding");

                return;
            }

            PublishedProvider successorProvider = await GetOrCreateSuccessorProvider(providerVariationContext, successorId);

            if (successorProvider == null)
            {
                providerVariationContext.RecordErrors($"Unable to run Closure with Successor variation as could not locate or create a successor provider with id:{successorId}");

                return;
            }

            string providerId = providerVariationContext.ProviderId;

            if (successorProvider.HasPredecessor(providerId))
            {
                return;
            }

            providerVariationContext.SuccessorRefreshState = successorProvider.Current;

            successorProvider.AddPredecessor(providerId);

            providerVariationContext.QueueVariationChange(new TransferRemainingProfilesToSuccessorChange(providerVariationContext));
            providerVariationContext.QueueVariationChange(new ReAdjustSuccessorFundingValuesForProfileValueChange(providerVariationContext));
            providerVariationContext.QueueVariationChange(new ZeroRemainingProfilesChange(providerVariationContext));
            providerVariationContext.QueueVariationChange(new ReAdjustFundingValuesForProfileValuesChange(providerVariationContext));
        }
Beispiel #12
0
        public ProviderVariationContext Build()
        {
            ProviderVariationContext providerVariationContext = new ProviderVariationContext
            {
                UpdatedProvider     = _currentState,
                PublishedProvider   = _publishedProvider,
                UpdatedTotalFunding = _updatedTotalFunding
            };

            if (_errors?.Any() == true)
            {
                providerVariationContext.ErrorMessages.AddRange(_errors);
            }

            return(providerVariationContext);
        }
Beispiel #13
0
        public async Task <IDictionary <string, PublishedProvider> > PrepareVariedProviders(decimal?updatedTotalFunding,
                                                                                            IDictionary <string, PublishedProvider> allPublishedProviderRefreshStates,
                                                                                            PublishedProvider existingPublishedProvider,
                                                                                            Provider updatedProvider,
                                                                                            IEnumerable <FundingVariation> variations,
                                                                                            IEnumerable <ProfileVariationPointer> variationPointers,
                                                                                            string snapshotId,
                                                                                            string specificationProviderVersionId)
        {
            Guard.ArgumentNotNull(updatedTotalFunding, nameof(updatedTotalFunding));
            Guard.ArgumentNotNull(allPublishedProviderRefreshStates, nameof(allPublishedProviderRefreshStates));
            Guard.ArgumentNotNull(existingPublishedProvider, nameof(existingPublishedProvider));
            Guard.ArgumentNotNull(updatedProvider, nameof(updatedProvider));

            bool shouldRunVariations = variations.AnyWithNullCheck() &&
                                       !string.IsNullOrWhiteSpace(snapshotId);

            _logger.Verbose($"Variations enabled = {shouldRunVariations}");

            if (!shouldRunVariations || !_snapshots.TryGetValue(snapshotId, out IDictionary <string, PublishedProviderSnapShots> publishedProviderSnapshots))
            {
                return(null);
            }

            _logger.Verbose($"Number of snapshot providers = {publishedProviderSnapshots.Count}");

            ProviderVariationContext variationContext = await _detectProviderVariations.CreateRequiredVariationChanges(existingPublishedProvider,
                                                                                                                       updatedTotalFunding,
                                                                                                                       updatedProvider,
                                                                                                                       variations,
                                                                                                                       publishedProviderSnapshots,
                                                                                                                       allPublishedProviderRefreshStates,
                                                                                                                       variationPointers,
                                                                                                                       specificationProviderVersionId);

            if (variationContext.HasVariationChanges)
            {
                _applyProviderVariations.AddVariationContext(variationContext);

                if (variationContext.NewProvidersToAdd.Any())
                {
                    return(variationContext.NewProvidersToAdd.ToDictionary(_ => _.Current.ProviderId));
                }
            }

            return(null);
        }
Beispiel #14
0
        public Task DetermineVariations(ProviderVariationContext providerVariationContext, IEnumerable <string> fundingLineCodes)
        {
            Guard.ArgumentNotNull(providerVariationContext, nameof(providerVariationContext));

            PublishedProviderVersion priorState = providerVariationContext.PriorState;

            if (priorState == null ||
                priorState.Provider.Status == Closed ||
                providerVariationContext.UpdatedProvider.Status == Closed)
            {
                return(Task.CompletedTask);
            }

            providerVariationContext.QueueVariationChange(new AdjustDsgProfilesForUnderOverPaymentChange(providerVariationContext));
            providerVariationContext.QueueVariationChange(new ReAdjustFundingValuesForProfileValuesChange(providerVariationContext));

            return(Task.CompletedTask);
        }
Beispiel #15
0
        public Task DetermineVariations(ProviderVariationContext providerVariationContext, IEnumerable <string> fundingLineCodes)
        {
            if (providerVariationContext.PriorState == null || providerVariationContext.UpdatedProvider == null)
            {
                return(Task.CompletedTask);
            }

            foreach (VariationCheck variationCheck in VariationChecks)
            {
                variationCheck.Run(providerVariationContext);
            }

            if (providerVariationContext.VariationReasons.AnyWithNullCheck())
            {
                providerVariationContext.QueueVariationChange(new MetaDataVariationsChange(providerVariationContext));
            }

            return(Task.CompletedTask);
        }
        public Task DetermineVariations(ProviderVariationContext providerVariationContext, IEnumerable <string> fundingLineCodes)
        {
            Guard.ArgumentNotNull(providerVariationContext, nameof(providerVariationContext));

            PublishedProviderVersion priorState = providerVariationContext.PriorState;

            if (priorState == null ||
                priorState.Provider.Status == Closed ||
                providerVariationContext.UpdatedProvider.Status == Closed ||
                providerVariationContext.UpdatedTotalFunding == priorState.TotalFunding)
            {
                return(Task.CompletedTask);
            }

            providerVariationContext.AddVariationReasons(VariationReason.FundingUpdated);

            providerVariationContext.QueueVariationChange(new MetaDataVariationsChange(providerVariationContext));

            return(Task.CompletedTask);
        }
Beispiel #17
0
        private bool HasNoCarryOverChanges(PublishedProviderVersion priorState,
                                           PublishedProviderVersion refreshState,
                                           ProviderVariationContext providerVariationContext)
        {
            bool hasNoCarryOverChanges = true;

            foreach (ProfilingCarryOver carryOver in priorState.CarryOvers ?? ArraySegment <ProfilingCarryOver> .Empty)
            {
                ProfilingCarryOver latestCustomProfile = refreshState.CarryOvers?.SingleOrDefault(_ => _.FundingLineCode == carryOver.FundingLineCode);

                if ((latestCustomProfile?.Amount).GetValueOrDefault() != carryOver.Amount)
                {
                    providerVariationContext.AddAffectedFundingLineCode(carryOver.FundingLineCode);

                    hasNoCarryOverChanges = false;
                }
            }

            return(hasNoCarryOverChanges);
        }
Beispiel #18
0
        public Task DetermineVariations(ProviderVariationContext providerVariationContext,
                                        IEnumerable <string> fundingLineCodes)
        {
            Guard.ArgumentNotNull(providerVariationContext, nameof(providerVariationContext));

            PublishedProviderVersion priorState   = providerVariationContext.PriorState;
            PublishedProviderVersion refreshState = providerVariationContext.RefreshState;

            if (priorState == null ||
                providerVariationContext.ReleasedState == null ||
                priorState.Provider.Status == Closed ||
                providerVariationContext.UpdatedProvider.Status == Closed ||
                HasNoProfilingChanges(priorState, refreshState, providerVariationContext) ||
                HasNoPaidPeriods(providerVariationContext, priorState))
            {
                return(Task.CompletedTask);
            }

            providerVariationContext.QueueVariationChange(new ReProfileVariationChange(providerVariationContext));

            return(Task.CompletedTask);
        }
        public async Task DetermineVariations(ProviderVariationContext providerVariationContext, IEnumerable <string> fundingLineCodes)
        {
            Guard.ArgumentNotNull(providerVariationContext, nameof(providerVariationContext));

            Provider updatedProvider = providerVariationContext.UpdatedProvider;

            string successorId = updatedProvider.Successor;

            PublishedProviderVersion priorState = providerVariationContext.PriorState;

            if (priorState == null ||
                priorState.Provider.Status == Closed ||
                updatedProvider.Status != Closed ||
                successorId.IsNullOrWhitespace())
            {
                return;
            }

            PublishedProvider successorProvider = await GetOrCreateSuccessorProvider(providerVariationContext, successorId);

            if (successorProvider == null)
            {
                providerVariationContext.RecordErrors(
                    $"Unable to run Pupil Number Successor variation as could not locate or create a successor provider with id:{successorId}");

                return;
            }

            string providerId = providerVariationContext.ProviderId;

            providerVariationContext.SuccessorRefreshState = successorProvider.Current;

            successorProvider.AddPredecessor(providerId);

            providerVariationContext.QueueVariationChange(new MovePupilNumbersToSuccessorChange(providerVariationContext));
        }
Beispiel #20
0
        public async Task <ProviderVariationContext> CreateRequiredVariationChanges(PublishedProvider existingPublishedProvider,
                                                                                    decimal?updatedTotalFunding,
                                                                                    Provider provider,
                                                                                    IEnumerable <FundingVariation> variations,
                                                                                    IDictionary <string, PublishedProviderSnapShots> allPublishedProviderSnapShots,
                                                                                    IDictionary <string, PublishedProvider> allPublishedProviderRefreshStates,
                                                                                    IEnumerable <ProfileVariationPointer> variationPointers,
                                                                                    string providerVersionId)
        {
            Guard.ArgumentNotNull(existingPublishedProvider, nameof(existingPublishedProvider));
            Guard.ArgumentNotNull(updatedTotalFunding, nameof(updatedTotalFunding));
            Guard.ArgumentNotNull(provider, nameof(provider));
            Guard.ArgumentNotNull(variations, nameof(variations));
            Guard.ArgumentNotNull(allPublishedProviderRefreshStates, nameof(allPublishedProviderRefreshStates));
            Guard.ArgumentNotNull(allPublishedProviderSnapShots, nameof(allPublishedProviderSnapShots));

            ProviderVariationContext providerVariationContext = new ProviderVariationContext
            {
                PublishedProvider                  = existingPublishedProvider,
                UpdatedProvider                    = provider,
                UpdatedTotalFunding                = updatedTotalFunding,
                AllPublishedProviderSnapShots      = allPublishedProviderSnapShots,
                AllPublishedProvidersRefreshStates = allPublishedProviderRefreshStates,
                ProviderVersionId                  = providerVersionId,
                VariationPointers                  = variationPointers
            };

            foreach (FundingVariation configuredVariation in variations.OrderBy(_ => _.Order))
            {
                IVariationStrategy variationStrategy = _variationStrategyServiceLocator.GetService(configuredVariation.Name);

                await variationStrategy.DetermineVariations(providerVariationContext, configuredVariation.FundingLineCodes);
            }

            return(providerVariationContext);
        }
 public MetaDataVariationsChange(ProviderVariationContext variationContext)
     : base(variationContext)
 {
 }
 private async Task AndTheVariationsWereApplied(ProviderVariationContext variationContext)
 {
     await ThenTheVariationsWereApplied(variationContext);
 }
Beispiel #23
0
        public void SetUp()
        {
            _variationContext = new ProviderVariationContext();

            _applyProviderVariations = Substitute.For <IApplyProviderVariations>();
        }
Beispiel #24
0
 protected override bool HasNoProfilingChanges(PublishedProviderVersion priorState,
                                               PublishedProviderVersion refreshState,
                                               ProviderVariationContext providerVariationContext) =>
 base.HasNoProfilingChanges(priorState, refreshState, providerVariationContext) &&
 HasNoCarryOverChanges(priorState, refreshState, providerVariationContext);
        protected VariationChange(ProviderVariationContext variationContext)
        {
            Guard.ArgumentNotNull(variationContext, nameof(variationContext));

            VariationContext = variationContext;
        }
 public ReAdjustFundingValuesForProfileValuesChange(ProviderVariationContext variationContext) : base(variationContext)
 {
 }
 public ReProfileVariationChange(ProviderVariationContext variationContext)
     : base(variationContext)
 {
 }
 public ZeroInitialPaymentProfilesChange(ProviderVariationContext variationContext)
     : base(variationContext)
 {
 }
Beispiel #29
0
 public ZeroAllProfiles(ProviderVariationContext variationContext)
     : base(variationContext)
 {
 }
Beispiel #30
0
        public void ProviderVariationContextTestBaseSetUp()
        {
            _queuedChangeIndex = 0;

            VariationContext = NewVariationContext();
        }