using IO.Swagger.Models.db;
using IO.Swagger.Models.RequestDto;
using IO.Swagger.Services;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IO.Swagger.Repositories
{
///
/// The EF implementation of this interface
///
///
public class TransactionRepository : ITransactionRepository
{
private readonly BankDbContext context;
///
/// Initializes a new instance of the class.
///
/// The context.
/// context
public TransactionRepository(BankDbContext context)
{
this.context = context ?? throw new ArgumentNullException(nameof(context));
}
///
public async Task> GetTransactionsForUser(int userId)
{
var transactions = await context.Transactions.Where(t => t.ToUserId == userId || t.FromUserId == userId)
.Include(t => t.Currency)
.Include(t => t.FromUser)
.Include(t => t.ToUser)
.OrderByDescending(t => t.TransactionTime)
.ToListAsync();
foreach (var t in transactions)
if (t.ToUserId != t.FromUserId && t.FromUserId == userId)
t.Amount *= -1;
return transactions;
}
///
public async Task>> GetBalancesForUser(int userId)
{
var transactions = await context.Transactions.Where(t => t.ToUserId == userId || t.FromUserId == userId)
.Include(t => t.Currency)
.GroupBy(t => t.Currency)
.Select(g => Tuple.Create(
g.Key,
g.Sum(t => t.ToUserId != t.FromUserId && t.FromUserId == userId
? -t.Amount
: t.Amount
)
)
)
.ToListAsync();
return transactions;
}
///
public async Task TransferPhysical(WalletTransferPhysicalBody request, int fromUserId)
{
var trimmedDest = request.DestUserEmail.Trim().ToLower();
var destUser = await context.Users.FirstOrDefaultAsync(u => u.Email == trimmedDest);
if (destUser == null)
return TransactionReturnCode.UnknownDestinationUser;
var balances = await GetBalancesForUser(fromUserId);
var balance = balances.FirstOrDefault(b => b.Item1.CurrencyId == request.CurrencyId);
if (balance == null || balance.Item2 < request.Amount)
return TransactionReturnCode.InsufficientFunds;
await context.Transactions.AddAsync(new Transaction
{
Amount = request.Amount,
CurrencyId = request.CurrencyId,
ToUserId = destUser.Id,
FromUserId = fromUserId,
Memo = request.Memo
});
return await context.SaveChangesAsync() > 0 ? TransactionReturnCode.Success : TransactionReturnCode.DbError;
}
}
}