public void Condense()
        {
            var learnerOne   = new FM81Learner();
            var learnerTwo   = new FM81Learner();
            var learnerThree = new FM81Learner();
            var learnerFour  = new FM81Learner();
            var learnerFive  = new FM81Learner();
            var learnerSix   = new FM81Learner();

            var globalOne = new FM81Global()
            {
                Learners = new List <FM81Learner>()
                {
                    learnerOne,
                    learnerTwo,
                },
            };

            var globalTwo = new FM81Global()
            {
                Learners = new List <FM81Learner>
                {
                    learnerThree,
                    learnerFour,
                },
            };

            var globalThree = new FM81Global()
            {
                Learners = new List <FM81Learner>
                {
                    learnerFive,
                    learnerSix,
                },
            };

            var fundingOutputs = new List <FM81Global>()
            {
                globalOne,
                globalTwo,
                globalThree,
            };

            var fundingOutput = NewService().Condense(fundingOutputs, 1, "2021");

            fundingOutput.Should().Be(globalOne);
            fundingOutput.Learners.Should().HaveCount(6);
            fundingOutput.Learners.Should().Contain(new[] { learnerOne, learnerTwo, learnerThree, learnerFour, learnerFive, learnerSix });
        }
        public async Task GenerateReport(IReportServiceContext reportServiceContext, ZipArchive archive, bool isFis, CancellationToken cancellationToken)
        {
            Task <IMessage>   ilrFileTask = _ilrProviderService.GetIlrFile(reportServiceContext, cancellationToken);
            Task <FM81Global> fm81Task    =
                _fm81TrailBlazerProviderService.GetFM81Data(reportServiceContext, cancellationToken);
            Task <List <string> > validLearnersTask =
                _validLearnersService.GetLearnersAsync(reportServiceContext, cancellationToken);

            await Task.WhenAll(ilrFileTask, fm81Task, validLearnersTask);

            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }

            List <ILearner> learners =
                ilrFileTask.Result?.Learners?.Where(x => validLearnersTask.Result.Contains(x.LearnRefNumber)).ToList();

            if (learners == null)
            {
                _logger.LogWarning("Failed to get learners for Trailblazer Apprenticeships Occupancy Report");
                return;
            }

            string[] learnAimRefs = learners.SelectMany(x => x.LearningDeliveries).Select(x => x.LearnAimRef).Distinct().ToArray();
            Dictionary <string, LarsLearningDelivery> larsLearningDeliveries = await _larsProviderService.GetLearningDeliveriesAsync(learnAimRefs, cancellationToken);

            var fm81Data = fm81Task.Result;
            var trailblazerAppsOccupancyModels = new List <TrailblazerAppsOccupancyModel>();

            foreach (var learner in learners)
            {
                FM81Learner fm81Learner = fm81Data?.Learners?.SingleOrDefault(x => string.Equals(x.LearnRefNumber, learner.LearnRefNumber, StringComparison.OrdinalIgnoreCase));
                foreach (ILearningDelivery learningDelivery in learner.LearningDeliveries)
                {
                    if (!CheckIsApplicableLearner(learningDelivery))
                    {
                        continue;
                    }

                    LarsLearningDelivery larsDelivery             = larsLearningDeliveries.SingleOrDefault(x => string.Equals(x.Key, learningDelivery.LearnAimRef, StringComparison.OrdinalIgnoreCase)).Value;
                    LearningDelivery     ruleBaseLearningDelivery = fm81Learner?.LearningDeliveries
                                                                    ?.SingleOrDefault(x => x.AimSeqNumber == learningDelivery.AimSeqNumber);
                    trailblazerAppsOccupancyModels.Add(_trailblazerAppsOccupancyModelBuilder
                                                       .BuildTrailblazerAppsOccupancyModel(
                                                           learner,
                                                           learningDelivery,
                                                           larsDelivery,
                                                           ruleBaseLearningDelivery));
                }
            }

            trailblazerAppsOccupancyModels.Sort(new TrailblazerAppsOccupancyModelComparer());

            var csv = GetReportCsv(trailblazerAppsOccupancyModels);

            var jobId            = reportServiceContext.JobId;
            var ukPrn            = reportServiceContext.Ukprn.ToString();
            var externalFileName = GetExternalFilename(ukPrn, jobId, reportServiceContext.SubmissionDateTimeUtc);
            var fileName         = GetFilename(ukPrn, jobId, reportServiceContext.SubmissionDateTimeUtc);

            await _streamableKeyValuePersistenceService.SaveAsync($"{externalFileName}.csv", csv, cancellationToken);

            await WriteZipEntry(archive, $"{fileName}.csv", csv);
        }
        public async Task <FM81Global> GetFM81Data(IReportServiceContext reportServiceContext, CancellationToken cancellationToken)
        {
            await _getDataLock.WaitAsync(cancellationToken);

            try
            {
                if (_loadedDataAlready)
                {
                    return(_fundingOutputs);
                }

                cancellationToken.ThrowIfCancellationRequested();

                _loadedDataAlready = true;

                int ukPrn = reportServiceContext.Ukprn;
                if (string.Equals(reportServiceContext.CollectionName, "ILR1819", StringComparison.OrdinalIgnoreCase))
                {
                    string fm81Filename = reportServiceContext.FundingFM81OutputKey;
                    string fm81         = await _storage.GetAsync(fm81Filename, cancellationToken);

                    if (string.IsNullOrEmpty(fm81))
                    {
                        _fundingOutputs = null;
                        return(_fundingOutputs);
                    }

                    _fundingOutputs = _jsonSerializationService.Deserialize <FM81Global>(fm81);
                }
                else
                {
                    FM81Global fm81Global = new FM81Global();
                    using (var ilrContext = _ilrRulebaseContextFactory())
                    {
                        var fm81GlobalDb = await ilrContext.TBL_globals.FirstOrDefaultAsync(x => x.UKPRN == ukPrn, cancellationToken);

                        using (var ilrValidContext = _ilrValidContextFactory())
                        {
                            TBL_LearningDelivery[] res = await ilrContext.TBL_LearningDeliveries.Where(x => x.UKPRN == ukPrn)
                                                         .Include(x => x.TBL_LearningDelivery_PeriodisedValues).ToArrayAsync(cancellationToken);

                            IGrouping <string, TBL_LearningDelivery>[] learners = res.GroupBy(x => x.LearnRefNumber).ToArray();

                            fm81Global.Learners = new List <FM81Learner>();

                            foreach (IGrouping <string, TBL_LearningDelivery> fm81LearningDeliveries in learners)
                            {
                                var learningDeliveryDto = new List <ILR.FundingService.FM81.FundingOutput.Model.Output.LearningDelivery>();
                                foreach (var ld in fm81LearningDeliveries)
                                {
                                    var ldPeriodisedValues = ld.TBL_LearningDelivery_PeriodisedValues.Select(ldpv => new LearningDeliveryPeriodisedValue()
                                    {
                                        AttributeName = ldpv.AttributeName,
                                        Period1       = ldpv.Period_1,
                                        Period2       = ldpv.Period_2,
                                        Period3       = ldpv.Period_3,
                                        Period4       = ldpv.Period_4,
                                        Period5       = ldpv.Period_5,
                                        Period6       = ldpv.Period_6,
                                        Period7       = ldpv.Period_7,
                                        Period8       = ldpv.Period_8,
                                        Period9       = ldpv.Period_9,
                                        Period10      = ldpv.Period_10,
                                        Period11      = ldpv.Period_11,
                                        Period12      = ldpv.Period_12
                                    }).ToList();

                                    learningDeliveryDto.Add(new LearningDelivery()
                                    {
                                        AimSeqNumber = ld.AimSeqNumber,
                                        LearningDeliveryPeriodisedValues = ldPeriodisedValues,
                                        LearningDeliveryValues           = new LearningDeliveryValue()
                                        {
                                            FundLine      = ld.FundLine,
                                            AchApplicDate = ld.AchApplicDate // todo: finish the entire LearningDeliveryValue here
                                        }
                                    });
                                }

                                FM81Learner learner = new FM81Learner()
                                {
                                    LearnRefNumber     = fm81LearningDeliveries.Key,
                                    LearningDeliveries = learningDeliveryDto
                                };

                                fm81Global.Learners.Add(learner);
                            }
                        }

                        if (fm81GlobalDb != null)
                        {
                            fm81Global.LARSVersion     = fm81GlobalDb.LARSVersion;
                            fm81Global.CurFundYr       = fm81GlobalDb.CurFundYr;
                            fm81Global.RulebaseVersion = fm81GlobalDb.RulebaseVersion;
                            fm81Global.UKPRN           = fm81GlobalDb.UKPRN;
                        }
                    }

                    _fundingOutputs = fm81Global;
                }
            }
            finally
            {
                _getDataLock.Release();
            }

            return(_fundingOutputs);
        }