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());
    }
Example #2
0
    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);
    }