using System.Collections.Generic;
using System.Threading.Tasks;
public static class BankSample
public static BankDbContext Database { get; } = new BankDbContext();
public static async Task Main()
new BankSampleTests().RunTests();
var owner = new Owner(new Guid());
var checkingAccount = SetupAccount(owner, BankAccountType.Checking, 325);
var savingsAccount = SetupAccount(owner, BankAccountType.Checking, 100);
Console.WriteLine(checkingAccount != null && savingsAccount != null
? "Accounts set up successfuly"
: "Error setting up accounts");
private static IBankAccount SetupAccount(Owner owner, BankAccountType accountType, decimal initialDeposit)
BankAccount account = null;
account = new BankAccount(new Guid(), owner.Id, BankAccountType.Checking);
account.DepositAsync(initialDeposit);
if (ex is ArgumentException)
Console.WriteLine($"WARNING: {ex.Message}");
Console.WriteLine($"ERROR: ex.Message");
public class BankAccount : IBankAccount
public BankAccount(Guid id, Guid ownerId, BankAccountType accountType, decimal initialBalance = 0)
this.AccountType = accountType;
this.Balance = initialBalance;
public async Task<ITransaction> DepositAsync(decimal amount)
throw new ArgumentException("amount", "Amount must be greater than zero.");
var transaction = new Transaction(this.OwnerId, this.Id, amount);
BankSample.Database.Transactions.AddAsync(transaction);
BankSample.Database.SaveChangesAsync();
public async Task<ITransaction> WithdrawAsync(decimal amount)
throw new ArgumentException(nameof(amount), "Amount must be greater than zero.");
if (!this.AllowOverdraft && this.Balance + - amount < 0)
throw new OverdraftException(this.Balance - amount);
var transaction = new Transaction(this.OwnerId, this.OwnerId, amount);
BankSample.Database.Transactions.AddAsync(transaction);
public Guid OwnerId { get; }
public decimal Balance { get; private set; }
public decimal InterestRate { get; private set; }
public bool IsOverdrawn => this.Balance < 0;
public bool AllowOverdraft { get; set; }
public BankAccountType AccountType { get; }
public class Transaction : ITransaction
public Transaction(Guid ownerId, Guid accountId, decimal amount)
this.AccountId = accountId;
public Guid OwnerId { get; }
public Guid AccountId { get; }
public DateTime Time { get; }
public decimal Amount { get; }
public string FirstName { get; set; }
public string LastName { get; set; }
public class OverdraftException : Exception
public OverdraftException(decimal overdraftAmount)
this.OverdraftAmount = overdraftAmount;
public decimal OverdraftAmount { get; private set; }
public enum BankAccountType
public class BankDbContext
this.BankAccounts = new DbSet<IBankAccount>();
this.Transactions = new DbSet<ITransaction>();
this.Owners = new DbSet<IOwner>();
public DbSet<IBankAccount> BankAccounts { get; private set; }
public DbSet<ITransaction> Transactions { get; private set; }
public DbSet<IOwner> Owners { get; private set; }
public async void SaveChangesAsync()
public class DbSet<TEntity>
private IList<TEntity> entities;
public async Task AddAsync(TEntity entity)
this.entities.Add(entity);
public interface IBankAccount
decimal InterestRate { get; }
BankAccountType AccountType { get; }
bool IsOverdrawn { get; }
bool AllowOverdraft { get; set; }
Task<ITransaction> DepositAsync(decimal amount);
Task<ITransaction> WithdrawAsync(decimal amount);
public interface ITransaction
string FirstName { get; set; }
string LastName { get; set; }
public class BankSampleTests
public async Task RunTests()
new BankAccountTests().RunTests();
public class BankAccountTests
public async Task RunTests()
this.Initial_Balance_Test();
this.Deposit_Invalid_Test();
this.Deposit_Balance_Test();
this.Deposit_Transaction_Test();
public void Initial_Balance_Test()
public void Deposit_Invalid_Test()
public void Deposit_Balance_Test()
public void Deposit_Transaction_Test()