public async Task Handle(GenerateAccountProjectionCommand message)
        {
            _telemetry.AddEmployerAccountId(message.EmployerAccountId);
            var stopwatch = new Stopwatch();

            stopwatch.Start();
            var projections = await _accountProjectionRepository.InitialiseProjection(message.EmployerAccountId);

            var startDate = new DateTime(
                GetValue(message.StartPeriod?.Year, DateTime.Today.Year),
                GetValue(message.StartPeriod?.Month, DateTime.Today.Month),
                GetValue(message.StartPeriod?.Day, DateTime.Today.Day));

            var messageProjectionSource = await _accountProjectionService.GetOriginalProjectionSource(message.EmployerAccountId, message.ProjectionSource);

            if (messageProjectionSource == ProjectionSource.LevyDeclaration)
            {
                projections.BuildLevyTriggeredProjections(startDate, _config.NumberOfMonthsToProject);
            }
            else
            {
                projections.BuildPayrollPeriodEndTriggeredProjections(startDate, _config.NumberOfMonthsToProject);
            }

            var expiringFunds = await _expiredFundsService.GetExpiringFunds(projections.Projections, message.EmployerAccountId, messageProjectionSource, startDate);

            if (expiringFunds.Any())
            {
                projections.UpdateProjectionsWithExpiredFunds(expiringFunds);
            }

            await _accountProjectionRepository.Store(projections);

            stopwatch.Stop();
            _telemetry.TrackDuration("BuildAccountProjection", stopwatch.Elapsed);
        }
        public async Task <EstimationPageViewModel> CostEstimation(string hashedAccountId, string estimateName,
                                                                   bool?apprenticeshipRemoved)
        {
            var accountId = GetAccountId(hashedAccountId);

            await RefreshCurrentBalance(accountId);

            var accountEstimation = await _estimationRepository.Get(accountId);

            var estimationProjector = await _estimationProjectionRepository.Get(accountEstimation, _config.FeatureExpiredFunds);

            estimationProjector.BuildProjections();
            var projection     = estimationProjector.Projections.FirstOrDefault();
            var projectionType = projection?.ProjectionGenerationType ?? ProjectionGenerationType.LevyDeclaration;
            var expiredFunds   = await _expiredFundsService.GetExpiringFunds(estimationProjector.Projections, accountId, projectionType, DateTime.UtcNow);

            if (expiredFunds.Any())
            {
                estimationProjector.ApplyExpiredFunds(expiredFunds);
            }

            var viewModel = new EstimationPageViewModel
            {
                HashedAccountId       = hashedAccountId,
                EstimationName        = accountEstimation == null ? estimateName : accountEstimation.Name,
                ApprenticeshipRemoved = apprenticeshipRemoved.GetValueOrDefault(),
                Apprenticeships       = new EstimationApprenticeshipsViewModel
                {
                    VirtualApprenticeships = accountEstimation?.Apprenticeships?.Select(o =>
                                                                                        new EstimationApprenticeshipViewModel
                    {
                        Id = o.Id,
                        CompletionPayment   = o.TotalCompletionAmount,
                        ApprenticesCount    = o.ApprenticesCount,
                        CourseTitle         = o.CourseTitle,
                        Level               = o.Level,
                        MonthlyPayment      = o.TotalInstallmentAmount,
                        MonthlyPaymentCount = o.TotalInstallments,
                        StartDate           = o.StartDate,
                        TotalCost           = o.TotalCost,
                        FundingSource       = o.FundingSource
                    }).ToList(),
                },
                TransferAllowances = new EstimationTransferAllowanceVewModel
                {
                    AnnualTransferAllowance = estimationProjector.TransferAllowance,
                    Records = estimationProjector?.Projections?.Skip(1)
                              .Select(o => new EstimationTransferAllowance
                    {
                        Date               = new DateTime(o.Year, o.Month, 1),
                        ActualCost         = o.ActualCosts.TransferFundsOut,
                        EstimatedCost      = o.TransferModelledCosts.TransferFundsOut,
                        RemainingAllowance = o.AvailableTransferFundsBalance
                    }).ToList(),
                },
                AccountFunds =
                    new AccountFundsViewModel
                {
                    MonthlyInstallmentAmount = estimationProjector.MonthlyInstallmentAmount,
                    Records = GetAccountFunds(estimationProjector.Projections?.Skip(1))
                }
            };

            return(viewModel);
        }