Beispiel #1
0
        public async Task <SupplementaryDataWrapper> RunFileValidators(
            ISourceFileModel sourceFileModel,
            SupplementaryDataWrapper wrapper)
        {
            foreach (var model in wrapper.SupplementaryDataLooseModels)
            {
                foreach (var validator in _validators)
                {
                    if (await validator.IsValid(sourceFileModel, model))
                    {
                        continue;
                    }

                    wrapper.ValidErrorModels.Add(new ValidationErrorModel
                    {
                        RuleName     = validator.ErrorName,
                        ErrorMessage = validator.ErrorMessage,
                        IsWarning    = false
                    });
                    return(wrapper);
                }
            }

            return(wrapper);
        }
        public async Task <string> GenerateReport(
            IEsfJobContext esfJobContext,
            ISourceFileModel sourceFile,
            SupplementaryDataWrapper wrapper,
            CancellationToken cancellationToken)
        {
            var fundingSummaryReportModels = await _modelBuilder.Build(esfJobContext, cancellationToken);

            string fileName = GetExternalFilename(esfJobContext.UkPrn, ReportName, esfJobContext.JobId, esfJobContext.SubmissionDateTimeUtc, _excelExtension);

            using (var workbook = _excelFileService.NewWorkbook())
            {
                workbook.Worksheets.Clear();

                foreach (var tab in fundingSummaryReportModels)
                {
                    var worksheet = _excelFileService.GetWorksheetFromWorkbook(workbook, tab.TabName);

                    await _renderService.RenderAsync(esfJobContext, tab, worksheet);
                }

                await _excelFileService.SaveWorkbookAsync(workbook, fileName, esfJobContext.BlobContainerName, cancellationToken);
            }

            return(fileName);
        }
        public async Task ExecuteTasks(
            IReadOnlyList <ITaskItem> tasks,
            SourceFileModel sourceFileModel,
            SupplementaryDataWrapper supplementaryDataWrapper,
            CancellationToken cancellationToken)
        {
            foreach (ITaskItem taskItem in tasks)
            {
                if (taskItem.SupportsParallelExecution)
                {
                    Parallel.ForEach(
                        taskItem.Tasks,
                        new ParallelOptions {
                        CancellationToken = cancellationToken
                    },
                        async task => { await HandleTask(supplementaryDataWrapper, task, sourceFileModel, cancellationToken); });
                }
                else
                {
                    var subTasks = taskItem.Tasks;
                    foreach (var task in subTasks)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            break;
                        }

                        await HandleTask(supplementaryDataWrapper, task, sourceFileModel, cancellationToken);
                    }
                }
            }
        }
        public async Task RunTasks(
            IJobContextMessage jobContextMessage,
            IReadOnlyList <ITaskItem> tasks,
            CancellationToken cancellationToken)
        {
            var wrapper         = new SupplementaryDataWrapper();
            var sourceFileModel = new SourceFileModel();

            if (tasks.SelectMany(t => t.Tasks).Contains(Constants.ValidationTask))
            {
                sourceFileModel = _fileHelper.GetSourceFileData(jobContextMessage);

                wrapper = await _fileValidationService.GetFile(sourceFileModel, cancellationToken);

                if (!wrapper.ValidErrorModels.Any())
                {
                    wrapper = _fileValidationService.RunFileValidators(sourceFileModel, wrapper);
                }

                if (wrapper.ValidErrorModels.Any())
                {
                    await _storageController.StoreValidationOnly(sourceFileModel, wrapper, cancellationToken);

                    await _reportingController.FileLevelErrorReport(wrapper, sourceFileModel, cancellationToken);

                    return;
                }
            }

            await _taskHelper.ExecuteTasks(tasks, sourceFileModel, wrapper, cancellationToken);
        }
        public async Task TestFundingReportGeneration(string sourceFileName, string collectionName, int expectedZipEntryCount)
        {
            var dateTime = DateTime.UtcNow;
            var filename = $"10005752/1/ESF-2108 ESF (Round 2) Supplementary Data Funding Report {dateTime:yyyyMMdd-HHmmss}";

            var supplementaryDataWrapper = new SupplementaryDataWrapper()
            {
                SupplementaryDataLooseModels = GetSupplementaryDataLooseModels(),
                SupplementaryDataModels      = GetSupplementaryDataModels(),
                ValidErrorModels             = new List <ValidationErrorModel>()
            };

            Mock <IDateTimeProvider> dateTimeProviderMock = new Mock <IDateTimeProvider>();

            dateTimeProviderMock.Setup(x => x.GetNowUtc()).Returns(dateTime);
            dateTimeProviderMock.Setup(x => x.ConvertUtcToUk(It.IsAny <DateTime>())).Returns(dateTime);

            var testStream = new MemoryStream();

            var csvServiceMock = new Mock <ICsvFileService>();

            csvServiceMock.Setup(x => x.WriteAsync <FundingReportModel, FundingReportMapper>(It.IsAny <List <FundingReportModel> >(), $"{filename}.csv", It.IsAny <string>(), It.IsAny <CancellationToken>(), null, null))
            .Returns(Task.CompletedTask);

            Mock <IReferenceDataService> referenceDataService = new Mock <IReferenceDataService>();

            referenceDataService.Setup(m => m.GetLarsVersion(It.IsAny <CancellationToken>())).ReturnsAsync("123456");
            referenceDataService.Setup(m => m.GetOrganisationVersion(It.IsAny <CancellationToken>())).ReturnsAsync("234567");
            referenceDataService.Setup(m => m.GetPostcodeVersion(It.IsAny <CancellationToken>())).ReturnsAsync("345678");
            referenceDataService.Setup(m => m.GetProviderName(It.IsAny <int>(), It.IsAny <CancellationToken>())).Returns("Foo College");
            referenceDataService.Setup(m =>
                                       m.GetDeliverableUnitCosts(It.IsAny <string>(), It.IsAny <IList <string> >()))
            .Returns(new List <DeliverableUnitCost>());

            Mock <IVersionInfo> versionInfo = new Mock <IVersionInfo>();

            versionInfo.Setup(m => m.ServiceReleaseVersion).Returns("1.2.3.4");
            var valueProvider = new ValueProvider();

            var fundigReport = new FundingReport(
                dateTimeProviderMock.Object,
                csvServiceMock.Object,
                referenceDataService.Object);

            SourceFileModel sourceFile = GetEsfSourceFileModel();

            sourceFile.FileName = sourceFileName;

            var esfJobContextMock = new Mock <IEsfJobContext>();

            esfJobContextMock.Setup(x => x.UkPrn).Returns(10005752);
            esfJobContextMock.Setup(x => x.JobId).Returns(1);
            esfJobContextMock.Setup(x => x.BlobContainerName).Returns("TestContainer");
            esfJobContextMock.Setup(x => x.CollectionYear).Returns(1819);
            esfJobContextMock.Setup(x => x.CollectionName).Returns(collectionName);

            await fundigReport.GenerateReport(esfJobContextMock.Object, sourceFile, supplementaryDataWrapper, CancellationToken.None);

            csvServiceMock.VerifyAll();
        }
Beispiel #6
0
        public void TestController()
        {
            Mock <IReferenceDataCache> cacheMock = new Mock <IReferenceDataCache>();

            cacheMock.Setup(m => m.GetUlnLookup(It.IsAny <IList <long?> >(), It.IsAny <CancellationToken>())).Returns(new List <UniqueLearnerNumber>());

            Mock <IFcsCodeMappingHelper> mapperMock = new Mock <IFcsCodeMappingHelper>();

            mapperMock.Setup(m =>
                             m.GetFcsDeliverableCode(It.IsAny <SupplementaryDataModel>(), It.IsAny <CancellationToken>())).Returns(1);

            Mock <IPopulationService> popMock = new Mock <IPopulationService>();

            popMock.Setup(m => m.PrePopulateUlnCache(It.IsAny <IList <long?> >(), It.IsAny <CancellationToken>()));

            SupplementaryDataModelMapper mapper = new SupplementaryDataModelMapper();

            var looseValidation = GetLooseValidators();
            var validators      = GetValidators(cacheMock, mapperMock);
            var controller      = new ValidationController(looseValidation, validators, popMock.Object, mapper);

            var wrapper = new SupplementaryDataWrapper
            {
                SupplementaryDataLooseModels = GetSupplementaryDataList()
            };

            controller.ValidateData(wrapper, GetEsfSourceFileModel(), CancellationToken.None);

            //Assert.True(controller.Errors.Any());
        }
Beispiel #7
0
        public async Task <SupplementaryDataWrapper> GetFile(
            IEsfJobContext esfJobContext,
            ISourceFileModel sourceFileModel,
            CancellationToken cancellationToken)
        {
            SupplementaryDataWrapper wrapper = new SupplementaryDataWrapper();
            ICollection <SupplementaryDataLooseModel> esfRecords = new List <SupplementaryDataLooseModel>();
            IList <ValidationErrorModel> errors = new List <ValidationErrorModel>();

            try
            {
                esfRecords = await _eSFProviderService.GetESFRecordsFromFile(esfJobContext, cancellationToken);

                if (esfRecords == null || !esfRecords.Any())
                {
                    _logger.LogInfo("No ESF records to process");
                }
            }
            catch (ValidationException ex)
            {
                _logger.LogError($"The file format is incorrect, key: {sourceFileModel.FileName}", ex);

                errors.Add(new ValidationErrorModel
                {
                    RuleName     = "Fileformat_01",
                    ErrorMessage = "The file format is incorrect. Please check the field headers are as per the Guidance document.",
                    IsWarning    = false
                });
            }

            wrapper.SupplementaryDataLooseModels = esfRecords;
            wrapper.ValidErrorModels             = errors;
            return(wrapper);
        }
Beispiel #8
0
 public async Task Execute(
     SourceFileModel sourceFile,
     SupplementaryDataWrapper supplementaryDataWrapper,
     CancellationToken cancellationToken)
 {
     await _reportingController.ProduceReports(supplementaryDataWrapper, sourceFile, cancellationToken);
 }
 public async Task Execute(
     IEsfJobContext esfJobContext,
     ISourceFileModel sourceFile,
     SupplementaryDataWrapper wrapper,
     CancellationToken cancellationToken)
 {
     await _controller.ValidateData(wrapper, sourceFile, cancellationToken);
 }
Beispiel #10
0
 public Task Execute(
     SourceFileModel sourceFile,
     SupplementaryDataWrapper wrapper,
     CancellationToken cancellationToken)
 {
     _controller.ValidateData(wrapper, sourceFile, cancellationToken);
     return(Task.CompletedTask);
 }
 public async Task ProduceReports(
     IEsfJobContext esfJobContext,
     SupplementaryDataWrapper wrapper,
     ISourceFileModel sourceFile,
     CancellationToken cancellationToken)
 {
     await ProduceReports(esfJobContext, wrapper, sourceFile, cancellationToken, true);
 }
        public async Task <bool> StoreData(
            SourceFileModel sourceFile,
            SupplementaryDataWrapper wrapper,
            CancellationToken cancellationToken)
        {
            bool successfullyCommitted = false;

            using (SqlConnection connection =
                       new SqlConnection(_dbConfiguration.ESFNonEFConnectionString))
            {
                SqlTransaction transaction = null;
                try
                {
                    await connection.OpenAsync(cancellationToken);

                    if (cancellationToken.IsCancellationRequested)
                    {
                        return(false);
                    }

                    transaction = connection.BeginTransaction();

                    var ukPrn = Convert.ToInt32(sourceFile.UKPRN);

                    var storeClear = new StoreClear(connection, transaction);
                    await storeClear.ClearAsync(ukPrn, sourceFile.ConRefNumber, cancellationToken);

                    int fileId = await _storeFileDetails.StoreAsync(connection, transaction, cancellationToken, sourceFile);

                    await _storeValidation.StoreAsync(connection, transaction, fileId, wrapper.ValidErrorModels, cancellationToken);

                    await _store.StoreAsync(connection, transaction, fileId, wrapper.SupplementaryDataModels, cancellationToken);

                    transaction.Commit();
                    successfullyCommitted = true;
                }
                catch (Exception ex)
                {
                    _logger.LogError("Failed to persist to DEDs", ex);
                }
                finally
                {
                    if (!successfullyCommitted)
                    {
                        try
                        {
                            transaction?.Rollback();
                        }
                        catch (Exception ex2)
                        {
                            _logger.LogError("Failed to rollback DEDs persist transaction", ex2);
                        }
                    }
                }
            }

            return(successfullyCommitted);
        }
Beispiel #13
0
        public ICollection <FundingReportModel> BuildModels(SupplementaryDataWrapper wrapper)
        {
            var fundingModels = new List <FundingReportModel>();

            foreach (var model in wrapper.SupplementaryDataModels)
            {
                if (wrapper.ValidErrorModels.Any(vm =>
                                                 vm.IsWarning == false &&
                                                 vm.ConRefNumber.CaseInsensitiveEquals(model.ConRefNumber) &&
                                                 vm.DeliverableCode.CaseInsensitiveEquals(model.DeliverableCode) &&
                                                 vm.CostType.CaseInsensitiveEquals(model.CostType) &&
                                                 vm.CalendarYear.CaseInsensitiveEquals(model.CalendarYear.ToString()) &&
                                                 vm.CalendarMonth.CaseInsensitiveEquals(model.CalendarMonth.ToString()) &&
                                                 vm.ReferenceType.CaseInsensitiveEquals(model.ReferenceType) &&
                                                 vm.Reference.CaseInsensitiveEquals(model.Reference)))
                {
                    continue;
                }

                var fundModel = new FundingReportModel
                {
                    ConRefNumber               = model.ConRefNumber,
                    DeliverableCode            = model.DeliverableCode,
                    CostType                   = model.CostType,
                    CalendarYear               = model.CalendarYear,
                    CalendarMonth              = model.CalendarMonth,
                    Reference                  = model.Reference,
                    ReferenceType              = model.ReferenceType,
                    ULN                        = model.ULN,
                    ProviderSpecifiedReference = model.ProviderSpecifiedReference,
                    LearnAimRef                = model.LearnAimRef,
                    SupplementaryDataPanelDate = model.SupplementaryDataPanelDate?.ToString("dd/MM/yyyy"),
                    Value                      = model.Value
                };

                if (ESFConstants.UnitCostDeliverableCodes.Contains(model.DeliverableCode))
                {
                    var unitCost = _referenceDataService.GetDeliverableUnitCosts(model.ConRefNumber, new List <string> {
                        model.DeliverableCode
                    })
                                   .FirstOrDefault(uc => uc.DeliverableCode.CaseInsensitiveEquals(model.DeliverableCode) &&
                                                   uc.ConRefNum.CaseInsensitiveEquals(model.ConRefNumber))
                                   ?.UnitCost ?? 0M;
                    unitCost = model.CostType?.CaseInsensitiveEquals(ESFConstants.UnitCostDeductionCostType)
                               ?? false ? unitCost * -1 : unitCost;

                    fundModel.Value = unitCost;
                }

                fundingModels.Add(fundModel);
            }

            return(fundingModels);
        }
 private IList <SupplementaryDataModel> FilterOutInvalidRows(
     SupplementaryDataWrapper wrapper)
 {
     return(wrapper.SupplementaryDataModels.Where(model => !wrapper.ValidErrorModels.Any(e => e.ConRefNumber == model.ConRefNumber &&
                                                                                         e.DeliverableCode == model.DeliverableCode &&
                                                                                         e.CalendarYear == model.CalendarYear.ToString() &&
                                                                                         e.CalendarMonth == model.CalendarMonth.ToString() &&
                                                                                         e.ReferenceType == model.ReferenceType &&
                                                                                         e.Reference == model.Reference &&
                                                                                         !e.IsWarning)).ToList());
 }
Beispiel #15
0
        public async Task Execute(
            SourceFileModel sourceFile,
            SupplementaryDataWrapper supplementaryDataWrapper,
            CancellationToken cancellationToken)
        {
            var success = await _storageController.StoreData(sourceFile, supplementaryDataWrapper, cancellationToken);

            if (!success)
            {
                _logger.LogError("Failed to save data to the data store.");
            }
        }
Beispiel #16
0
        public async Task GenerateReport_ThreeFundingYears()
        {
            var ukprn        = 12345678;
            var jobid        = 1;
            var reportFolder = "FundingSummaryTestThreeYears";

            TestFixture(reportFolder, ukprn, jobid);

            var esfJobContext     = new Mock <IEsfJobContext>();
            var sourceFile        = new Mock <ISourceFileModel>();
            var wrapper           = new SupplementaryDataWrapper();
            var cancellationToken = CancellationToken.None;

            var testModels = new List <IFundingSummaryReportTab>
            {
                new FundingSummaryReportTab
                {
                    Title   = FundingSummaryReportConstants.BodyTitle,
                    TabName = "ConRef1",
                    Header  = TestHeader("ConRef1", 3),
                    Body    = TestBodyModels(3),
                    Footer  = TestFooter()
                },
                new FundingSummaryReportTab
                {
                    Title   = FundingSummaryReportConstants.BodyTitle,
                    TabName = "ConRef2",
                    Header  = TestHeader("ConRef2", 3),
                    Body    = TestBodyModels(3),
                    Footer  = TestFooter()
                }
            };

            esfJobContext.Setup(x => x.UkPrn).Returns(ukprn);
            esfJobContext.Setup(x => x.JobId).Returns(jobid);
            esfJobContext.Setup(x => x.StartCollectionYearAbbreviation).Returns("20");
            esfJobContext.Setup(x => x.CollectionYear).Returns(2021);
            esfJobContext.Setup(x => x.ReturnPeriod).Returns("R05");
            esfJobContext.Setup(x => x.CurrentPeriod).Returns(5);
            esfJobContext.Setup(x => x.BlobContainerName).Returns(reportFolder);

            var modelBuilder     = new Mock <IFundingSummaryReportModelBuilder>();
            var renderService    = new FundingSummaryReportRenderService();
            var dateTimeProvider = new Mock <IDateTimeProvider>();
            var fileService      = new FileSystemFileService();
            var excelFileService = new ExcelFileService(fileService);

            modelBuilder.Setup(x => x.Build(esfJobContext.Object, cancellationToken)).ReturnsAsync(testModels);

            await NewReport(modelBuilder.Object, renderService, dateTimeProvider.Object, excelFileService)
            .GenerateReport(esfJobContext.Object, sourceFile.Object, wrapper, cancellationToken);
        }
Beispiel #17
0
        public async Task <string> GenerateReport(
            IEsfJobContext esfJobContext,
            ISourceFileModel sourceFile,
            SupplementaryDataWrapper wrapper,
            CancellationToken cancellationToken)
        {
            var report = GetValidationReport(wrapper.SupplementaryDataModels, wrapper.ValidErrorModels);

            var externalFilename = GetExternalFilename(sourceFile.UKPRN, sourceFile.JobId ?? 0, sourceFile.SuppliedDate ?? DateTime.MinValue, ReportExtension);

            await SaveJson(esfJobContext, externalFilename, report, cancellationToken);

            return(externalFilename);
        }
        public async Task <string> GenerateReport(
            IEsfJobContext esfJobContext,
            ISourceFileModel sourceFile,
            SupplementaryDataWrapper wrapper,
            CancellationToken cancellationToken)
        {
            ReportFileName = $"{sourceFile.ConRefNumber} " + ReportFileName;

            string externalFileName = GetExternalFilename(sourceFile.UKPRN, sourceFile.JobId ?? 0, sourceFile.SuppliedDate ?? DateTime.MinValue, _reportExtension);

            await WriteCsv(esfJobContext, externalFileName, wrapper.ValidErrorModels.OrderBy(s => s.IsWarning).ThenBy(s => s.RuleName), cancellationToken);

            return(externalFileName);
        }
Beispiel #19
0
        public async Task <bool> StoreValidationOnly(
            ISourceFileModel sourceFile,
            SupplementaryDataWrapper wrapper,
            CancellationToken cancellationToken)
        {
            bool successfullyCommitted = false;

            using (SqlConnection connection =
                       new SqlConnection(_dbConfiguration.ESFR2ConnectionString))
            {
                SqlTransaction transaction = null;
                try
                {
                    await connection.OpenAsync(cancellationToken);

                    cancellationToken.ThrowIfCancellationRequested();

                    transaction = connection.BeginTransaction();

                    int fileId = await _storeFileDetails.StoreAsync(connection, transaction, sourceFile, cancellationToken);

                    await _storeValidation.StoreAsync(connection, transaction, fileId, wrapper.ValidErrorModels, cancellationToken);

                    transaction.Commit();
                    successfullyCommitted = true;
                }
                catch (Exception ex)
                {
                    _logger.LogError("Failed to persist to DEDs", ex);
                    throw;
                }
                finally
                {
                    if (!successfullyCommitted)
                    {
                        try
                        {
                            transaction?.Rollback();
                        }
                        catch (Exception ex2)
                        {
                            _logger.LogError("Failed to rollback DEDs persist transaction", ex2);
                            throw;
                        }
                    }
                }
            }

            return(successfullyCommitted);
        }
        public async Task ExecuteTasks(
            IEsfJobContext esfJobContext,
            ISourceFileModel sourceFileModel,
            SupplementaryDataWrapper supplementaryDataWrapper,
            CancellationToken cancellationToken)
        {
            var tasks = esfJobContext.Tasks;

            foreach (var task in tasks)
            {
                cancellationToken.ThrowIfCancellationRequested();
                await HandleTask(esfJobContext, supplementaryDataWrapper, task, sourceFileModel, cancellationToken);
            }
        }
        public async Task GenerateReport(
            SourceFileModel sourceFile,
            SupplementaryDataWrapper wrapper,
            ZipArchive archive,
            CancellationToken cancellationToken)
        {
            string csv = GetCsv(wrapper.ValidErrorModels);

            string externalFileName = GetExternalFilename(sourceFile.UKPRN, sourceFile.JobId ?? 0, sourceFile.SuppliedDate ?? DateTime.MinValue);
            string fileName         = GetFilename(sourceFile.UKPRN, sourceFile.JobId ?? 0, sourceFile.SuppliedDate ?? DateTime.MinValue);

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

            await WriteZipEntry(archive, $"{fileName}.csv", csv);
        }
Beispiel #22
0
        public async Task <string> GenerateReport(
            IEsfJobContext esfJobContext,
            ISourceFileModel sourceFile,
            SupplementaryDataWrapper wrapper,
            CancellationToken cancellationToken)
        {
            var reportModels = BuildModels(wrapper);

            ReportFileName = $"{sourceFile.ConRefNumber} " + ReportFileName;
            string externalFileName = GetExternalFilename(esfJobContext.UkPrn, esfJobContext.JobId, sourceFile.SuppliedDate ?? DateTime.MinValue, _reportExtension);

            await WriteCsv(esfJobContext, externalFileName, reportModels, cancellationToken);

            return(externalFileName);
        }
        public async Task GenerateReport(
            SourceFileModel sourceFile,
            SupplementaryDataWrapper wrapper,
            ZipArchive archive,
            CancellationToken cancellationToken)
        {
            var report = GetValidationReport(wrapper.SupplementaryDataModels, wrapper.ValidErrorModels);

            var fileName         = GetFilename(sourceFile.UKPRN, sourceFile.JobId ?? 0, sourceFile.SuppliedDate ?? DateTime.MinValue);
            var externalFilename = GetExternalFilename(sourceFile.UKPRN, sourceFile.JobId ?? 0, sourceFile.SuppliedDate ?? DateTime.MinValue);

            var json = _jsonSerializationService.Serialize(report);

            await SaveJson(externalFilename, json, cancellationToken);
            await WriteZipEntry(archive, $"{fileName}.json", json);
        }
        public async Task <string> GenerateReport(
            IEsfJobContext esfJobContext,
            ISourceFileModel sourceFile,
            SupplementaryDataWrapper wrapper,
            CancellationToken cancellationToken)
        {
            var externalFileName = GetExternalFilename(esfJobContext.UkPrn, esfJobContext.JobId, sourceFile?.SuppliedDate ?? DateTime.MinValue, ReportExtension);

            cancellationToken.ThrowIfCancellationRequested();

            var ukPrn        = esfJobContext.UkPrn;
            var reportModels = await GetModels(ukPrn, esfJobContext.CollectionYear, cancellationToken);

            await WriteCsv(esfJobContext, externalFileName, reportModels, cancellationToken);

            return(externalFileName);
        }
        private async Task HandleTask(
            SupplementaryDataWrapper wrapper,
            string task,
            SourceFileModel sourceFile,
            CancellationToken cancellationToken)
        {
            var orderedHandlers = _taskHandlers.OrderBy(t => t.Order);

            foreach (var handler in orderedHandlers)
            {
                if (!handler.IsMatch(task))
                {
                    continue;
                }

                await handler.Execute(sourceFile, wrapper, cancellationToken);

                break;
            }
        }
        public async Task ProduceReports(
            SupplementaryDataWrapper wrapper,
            SourceFileModel sourceFile,
            CancellationToken cancellationToken)
        {
            _logger.LogInfo("ESF Reporting service called");

            if (!wrapper.SupplementaryDataModels.Any() && string.IsNullOrEmpty(sourceFile.FileName))
            {
                // todo ... get data from ESF database, only received reporting task
            }

            using (var memoryStream = new MemoryStream())
            {
                using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return;
                    }

                    foreach (var validationReport in _validationReports)
                    {
                        await validationReport.GenerateReport(sourceFile, wrapper, archive, cancellationToken);
                    }

                    foreach (var report in _esfReports)
                    {
                        await report.GenerateReport(wrapper, sourceFile, archive, cancellationToken);
                    }

                    if (cancellationToken.IsCancellationRequested)
                    {
                        return;
                    }
                }

                await _streamableKeyValuePersistenceService.SaveAsync($"{sourceFile.UKPRN}_{sourceFile.JobId}_Reports.zip", memoryStream, cancellationToken);
            }
        }
        private async Task ProduceReports(
            IEsfJobContext esfJobContext,
            SupplementaryDataWrapper wrapper,
            ISourceFileModel sourceFile,
            CancellationToken cancellationToken,
            bool passedFileValidation)
        {
            _logger.LogInfo("ESF Reporting service called");

            var reportNames = new List <string>();

            try
            {
                if (!string.IsNullOrWhiteSpace(sourceFile?.FileName))
                {
                    foreach (var validationReport in _validationReports)
                    {
                        reportNames.Add(await validationReport.GenerateReport(esfJobContext, sourceFile, wrapper, cancellationToken));
                    }
                }

                if (passedFileValidation)
                {
                    var reportsToRun = _esfReports.Where(r => esfJobContext.Tasks.Contains(r.TaskName, StringComparer.OrdinalIgnoreCase));
                    foreach (var report in reportsToRun)
                    {
                        reportNames.Add(await report.GenerateReport(esfJobContext, sourceFile, wrapper, cancellationToken));
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message, ex);
                throw;
            }

            var zipFileName = $"{esfJobContext.UkPrn}/{esfJobContext.JobId}{ReportNameConstants.ZipName}";

            await _zipService.CreateZipAsync(zipFileName, reportNames, esfJobContext.BlobContainerName, cancellationToken);
        }
        public async Task RunTasks(
            IEsfJobContext esfJobContext,
            CancellationToken cancellationToken)
        {
            var wrapper         = new SupplementaryDataWrapper();
            var sourceFileModel = _sourceFileModelBuilder.BuildDefault(esfJobContext);

            _periodHelper.CacheCurrentPeriod(esfJobContext);

            _excelFileService.ApplyLicense(Assembly.GetExecutingAssembly().GetManifestResourceStream(LicenseResource));

            if (esfJobContext.Tasks.Contains(Constants.ValidationTask))
            {
                sourceFileModel = _sourceFileModelBuilder.Build(esfJobContext);

                wrapper = await _fileValidationService.GetFile(esfJobContext, sourceFileModel, cancellationToken);

                if (!wrapper.ValidErrorModels.Any())
                {
                    await _validationErrorMessageService.PopulateErrorMessages(cancellationToken);

                    wrapper = await _fileValidationService.RunFileValidators(sourceFileModel, wrapper);
                }

                if (wrapper.ValidErrorModels.Any())
                {
                    await _storageController.StoreValidationOnly(sourceFileModel, wrapper, cancellationToken);

                    await _reportingController.FileLevelErrorReport(esfJobContext, wrapper, sourceFileModel, cancellationToken);

                    return;
                }
            }

            await _taskHelper.ExecuteTasks(esfJobContext, sourceFileModel, wrapper, cancellationToken);

            await _reportingController.ProduceReports(esfJobContext, wrapper, sourceFileModel, cancellationToken);
        }
        public async Task GenerateReport(
            SupplementaryDataWrapper wrapper,
            SourceFileModel sourceFile,
            ZipArchive archive,
            CancellationToken cancellationToken)
        {
            var externalFileName = GetExternalFilename(sourceFile.UKPRN, sourceFile.JobId ?? 0, sourceFile.SuppliedDate ?? DateTime.MinValue);
            var fileName         = GetFilename(sourceFile.UKPRN, sourceFile.JobId ?? 0, sourceFile.SuppliedDate ?? DateTime.MinValue);

            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }

            var    ukPrn = Convert.ToInt32(sourceFile.UKPRN);
            string csv   = await GetCsv(ukPrn, cancellationToken);

            if (csv != null)
            {
                await _storage.SaveAsync($"{externalFileName}.csv", csv, cancellationToken);
                await WriteZipEntry(archive, $"{fileName}.csv", csv);
            }
        }
        public async Task FileLevelErrorReport(
            SupplementaryDataWrapper wrapper,
            SourceFileModel sourceFile,
            CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }

            using (var memoryStream = new MemoryStream())
            {
                using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
                {
                    foreach (var validationReport in _validationReports)
                    {
                        await validationReport.GenerateReport(sourceFile, wrapper, archive, cancellationToken);
                    }
                }

                await _streamableKeyValuePersistenceService.SaveAsync($"{sourceFile.UKPRN}_{sourceFile.JobId}_Reports.zip", memoryStream, cancellationToken);
            }
        }