private async Task <string> DownloadStatement(Account account, TransactionImportJob job, CancellationToken cancellationToken) { var downloadResult = await _bankStatementWebScraper.DownloadStatement(account, job.FromDate, job.ToDate); job.Status = downloadResult.StatusMessage; if (!downloadResult.Successful) { _logger.LogWarning("Failed to download statement for {account} for the period {start} to {end}. Reason: {reason}", job.AccountId, job.FromDate.ToString("yyyy-MM-dd"), job.ToDate.ToString("yyyy-MM-dd"), downloadResult.StatusMessage); _unitOfWork.BeginTransaction(); await _transactionImportJobs.Save(job, cancellationToken); _unitOfWork.Commit(); var unexpectedFiles = Directory.GetFiles(_options.UnprocessedStatementDirectory); if (unexpectedFiles.Any()) { _logger.LogError("Found unprocessed statements where none were expected."); throw new InvalidOperationException($"Scraper reported no downloaded files, but files were found in the directory. Path: '{_options.UnprocessedStatementDirectory}'"); } return(null); } var files = Directory.GetFiles(_options.UnprocessedStatementDirectory); return(files.Single()); }
public async Task Save(TransactionImportJob entity, CancellationToken cancellationToken) { const string sql = @" MERGE INTO [staging].[TransactionImportJob] AS [target] USING ( SELECT @Id AS [Id], @FromDate AS [FromDate], @ToDate AS [ToDate], @AccountId AS [AccountId], @TransactionCount AS [TransactionCount], @Status AS [Status], @SourceFileName AS [SourceFileName] ) AS [source] ON ( [target].[FromDate] = [source].FromDate AND [target].[ToDate] = [source].ToDate AND [target].AccountId = [source].AccountId ) WHEN NOT MATCHED THEN INSERT ( [Id], [FromDate], [ToDate], [AccountId], [TransactionCount], [Status], [SourceFileName] ) VALUES ( [source].[Id], [source].[FromDate], [source].[ToDate], [source].[AccountId], [source].[TransactionCount], [source].[Status], [source].[SourceFileName] ) WHEN MATCHED THEN UPDATE SET [target].[FromDate] = [source].[FromDate], [target].[ToDate] = [source].[ToDate], [target].[AccountId] = [source].[AccountId], [target].[TransactionCount] = [source].[TransactionCount], [target].[Status] = [source].[Status], [target].[SourceFileName] = [source].[SourceFileName] OUTPUT $action AS MergeAction, inserted.Id ;"; var command = new CommandDefinition(sql, entity, _unitOfWork.Transaction, cancellationToken: cancellationToken); var results = await _unitOfWork.Connection.QueryAsync <MergeResult>(command); var result = results.SingleOrDefault(); if (result != null) { entity.Id = result.Id; } }
private async Task <TransactionImportJob> CreateTransactionImportJob(Account account, CancellationToken cancellationToken) { _unitOfWork.BeginTransaction(); var jobs = await _transactionImportJobs.ListJobs(account, cancellationToken); var latestJob = jobs.Where(x => x.TransactionCount > 0 && x.AccountId == account.Id) .OrderByDescending(x => x.ToDate).FirstOrDefault(); const int yearsToCapture = 3; var fromDate = latestJob?.ToDate ?? DateTimeOffset.Now.AddYears(-yearsToCapture); var job = new TransactionImportJob { Id = Guid.NewGuid(), AccountId = account.Id, FromDate = fromDate, ToDate = DateTimeOffset.Now, TransactionCount = 0, Status = "Pending" }; await _transactionImportJobs.Save(job, cancellationToken); _unitOfWork.Commit(); return(job); }