private async Task ApplyTransaction(BankTransactionClient transactionClient, DocumentId documentId, decimal balance, params decimal[] amounts)
    {
        TrxBatch <TrxRequest> requestBatch = new TrxBatch <TrxRequest>
        {
            Items = amounts.Select(x => new TrxRequest
            {
                AccountId = documentId.Path,
                Type      = x >= 0 ? TrxType.Credit : TrxType.Debit,
                Amount    = Math.Abs(x),
            }).ToList(),
        };

        TrxBatch <TrxRequestResponse> response = await transactionClient.Set(requestBatch);

        response.Should().NotBeNull();
        response.Items.Count.Should().Be(amounts.Length);
        response.Items.All(x => x.Status == TrxStatus.Success).Should().BeTrue();

        response.Items
        .Zip(requestBatch.Items)
        .All(x => x.First.ReferenceId == x.Second.Id)
        .Should().BeTrue();

        TrxBalance?balanceTrx = await transactionClient.GetBalance(documentId);

        balanceTrx.Should().NotBeNull();
        balanceTrx !.Balance.Should().Be(balance);
    }
예제 #2
0
    public async Task <TrxBatch <TrxRequestResponse> > Set(TrxBatch <TrxRequest> batch, CancellationToken token)
    {
        _logger.LogTrace($"Setting transaction for id={batch.Id}, count={batch.Items.Count}");

        IEnumerable <IGrouping <string, TrxRequest> > groups = batch.Items
                                                               .GroupBy(x => x.AccountId);

        List <TrxRequestResponse> responses = new();

        foreach (IGrouping <string, TrxRequest> group in groups)
        {
            BankAccount?bankAccount = await _bankAccountService.Get((DocumentId)group.Key, token);

            if (bankAccount == null)
            {
                _logger.LogError($"Account not found for directoryId={group.Key}");
                responses.AddRange(group.Select(x => new TrxRequestResponse
                {
                    ReferenceId = x.Id,
                    Status      = TrxStatus.Failed
                }));

                continue;
            }

            BankAccount entry = bankAccount with
            {
                Transactions = bankAccount.Transactions
                               .Concat(group
                                       .OrderBy(x => x.Date)
                                       .Select(x => new TrxRecord
                {
                    Type   = x.Type,
                    Amount = x.Amount,
                    Memo   = $"RequestId={x.Id}",
                }))
                               .ToList()
            };

            _logger.LogTrace($"Add transactions to accountId={group.Key}");
            await _bankAccountService.Set(entry, token);

            responses.AddRange(group.Select(x => new TrxRequestResponse
            {
                ReferenceId = x.Id,
                Status      = TrxStatus.Success
            }));
        }

        return(new TrxBatch <TrxRequestResponse>
        {
            Items = responses,
        });
    }
}
예제 #3
0
        public async Task <IActionResult> Set([FromBody] TrxBatch <TrxRequest> batch, CancellationToken token)
        {
            if (batch.Items.Count == 0)
            {
                return(BadRequest("Batch is empty"));
            }

            TrxBatch <TrxRequestResponse> response = await _service.Set(batch, token);

            return(Ok(response));
        }
예제 #4
0
    public async Task <TrxBatch <TrxRequestResponse> > Set(TrxBatch <TrxRequest> batch, CancellationToken token = default)
    {
        _logger.LogTrace($"Posting accountId={batch.Id}");

        HttpResponseMessage response = await _httpClient.PostAsJsonAsync($"api/transaction", batch, token);

        response.EnsureSuccessStatusCode();

        string json = await response.Content.ReadAsStringAsync();

        return(Json.Default.Deserialize <TrxBatch <TrxRequestResponse> >(json)
               .VerifyNotNull("Deserialize failed"));
    }