diff --git a/pom.xml b/pom.xml
index 3994d594..10c9147b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,6 +5,18 @@
com.abc
bank
1.0-SNAPSHOT
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 11
+
+
+
+
jar
bank
@@ -20,5 +32,12 @@
4.11
test
+
+
+ org.mockito
+ mockito-core
+ 4.7.0
+ test
+
diff --git a/src/main/java/com/abc/Account.java b/src/main/java/com/abc/Account.java
deleted file mode 100644
index 099691e0..00000000
--- a/src/main/java/com/abc/Account.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.abc;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class Account {
-
- public static final int CHECKING = 0;
- public static final int SAVINGS = 1;
- public static final int MAXI_SAVINGS = 2;
-
- private final int accountType;
- public List transactions;
-
- public Account(int accountType) {
- this.accountType = accountType;
- this.transactions = new ArrayList();
- }
-
- public void deposit(double amount) {
- if (amount <= 0) {
- throw new IllegalArgumentException("amount must be greater than zero");
- } else {
- transactions.add(new Transaction(amount));
- }
- }
-
-public void withdraw(double amount) {
- if (amount <= 0) {
- throw new IllegalArgumentException("amount must be greater than zero");
- } else {
- transactions.add(new Transaction(-amount));
- }
-}
-
- public double interestEarned() {
- double amount = sumTransactions();
- switch(accountType){
- case SAVINGS:
- if (amount <= 1000)
- return amount * 0.001;
- else
- return 1 + (amount-1000) * 0.002;
-// case SUPER_SAVINGS:
-// if (amount <= 4000)
-// return 20;
- case MAXI_SAVINGS:
- if (amount <= 1000)
- return amount * 0.02;
- if (amount <= 2000)
- return 20 + (amount-1000) * 0.05;
- return 70 + (amount-2000) * 0.1;
- default:
- return amount * 0.001;
- }
- }
-
- public double sumTransactions() {
- return checkIfTransactionsExist(true);
- }
-
- private double checkIfTransactionsExist(boolean checkAll) {
- double amount = 0.0;
- for (Transaction t: transactions)
- amount += t.amount;
- return amount;
- }
-
- public int getAccountType() {
- return accountType;
- }
-
-}
diff --git a/src/main/java/com/abc/Bank.java b/src/main/java/com/abc/Bank.java
deleted file mode 100644
index 5dd535bd..00000000
--- a/src/main/java/com/abc/Bank.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.abc;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class Bank {
- private List customers;
-
- public Bank() {
- customers = new ArrayList();
- }
-
- public void addCustomer(Customer customer) {
- customers.add(customer);
- }
-
- public String customerSummary() {
- String summary = "Customer Summary";
- for (Customer c : customers)
- summary += "\n - " + c.getName() + " (" + format(c.getNumberOfAccounts(), "account") + ")";
- return summary;
- }
-
- //Make sure correct plural of word is created based on the number passed in:
- //If number passed in is 1 just return the word otherwise add an 's' at the end
- private String format(int number, String word) {
- return number + " " + (number == 1 ? word : word + "s");
- }
-
- public double totalInterestPaid() {
- double total = 0;
- for(Customer c: customers)
- total += c.totalInterestEarned();
- return total;
- }
-
- public String getFirstCustomer() {
- try {
- customers = null;
- return customers.get(0).getName();
- } catch (Exception e){
- e.printStackTrace();
- return "Error";
- }
- }
-}
diff --git a/src/main/java/com/abc/Customer.java b/src/main/java/com/abc/Customer.java
deleted file mode 100644
index 31571685..00000000
--- a/src/main/java/com/abc/Customer.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.abc;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static java.lang.Math.abs;
-
-public class Customer {
- private String name;
- private List accounts;
-
- public Customer(String name) {
- this.name = name;
- this.accounts = new ArrayList();
- }
-
- public String getName() {
- return name;
- }
-
- public Customer openAccount(Account account) {
- accounts.add(account);
- return this;
- }
-
- public int getNumberOfAccounts() {
- return accounts.size();
- }
-
- public double totalInterestEarned() {
- double total = 0;
- for (Account a : accounts)
- total += a.interestEarned();
- return total;
- }
-
- public String getStatement() {
- String statement = null;
- statement = "Statement for " + name + "\n";
- double total = 0.0;
- for (Account a : accounts) {
- statement += "\n" + statementForAccount(a) + "\n";
- total += a.sumTransactions();
- }
- statement += "\nTotal In All Accounts " + toDollars(total);
- return statement;
- }
-
- private String statementForAccount(Account a) {
- String s = "";
-
- //Translate to pretty account type
- switch(a.getAccountType()){
- case Account.CHECKING:
- s += "Checking Account\n";
- break;
- case Account.SAVINGS:
- s += "Savings Account\n";
- break;
- case Account.MAXI_SAVINGS:
- s += "Maxi Savings Account\n";
- break;
- }
-
- //Now total up all the transactions
- double total = 0.0;
- for (Transaction t : a.transactions) {
- s += " " + (t.amount < 0 ? "withdrawal" : "deposit") + " " + toDollars(t.amount) + "\n";
- total += t.amount;
- }
- s += "Total " + toDollars(total);
- return s;
- }
-
- private String toDollars(double d){
- return String.format("$%,.2f", abs(d));
- }
-}
diff --git a/src/main/java/com/abc/Transaction.java b/src/main/java/com/abc/Transaction.java
deleted file mode 100644
index c1f7c67e..00000000
--- a/src/main/java/com/abc/Transaction.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.abc;
-
-import java.util.Calendar;
-import java.util.Date;
-
-public class Transaction {
- public final double amount;
-
- private Date transactionDate;
-
- public Transaction(double amount) {
- this.amount = amount;
- this.transactionDate = DateProvider.getInstance().now();
- }
-
-}
diff --git a/src/main/java/com/abc/account/Account.java b/src/main/java/com/abc/account/Account.java
new file mode 100644
index 00000000..98aaabc6
--- /dev/null
+++ b/src/main/java/com/abc/account/Account.java
@@ -0,0 +1,85 @@
+package com.abc.account;
+
+import com.abc.customer.Customer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public abstract class Account {
+
+ private final Customer customer;
+ private final AccountType accountType;
+ private final List transactions;
+ private double balance;
+
+ protected Account(Customer customer, AccountType accountType) {
+ this.customer = customer;
+ this.accountType = accountType;
+ this.transactions = new ArrayList<>();
+ }
+
+ public final void deposit(double amount) {
+ if (amount <= 0) {
+ throw new IllegalArgumentException("Amount must be greater than zero.");
+ }
+ transactions.add(new Transaction(Transaction.TransactionType.DEPOSIT, amount));
+ balance += amount;
+ }
+
+ public final void withdraw(double amount) {
+ if (amount <= 0) {
+ throw new IllegalArgumentException("Amount must be greater than zero.");
+ }
+ if (balance < amount) {
+ throw new IllegalArgumentException("Insufficient founds.");
+ }
+ transactions.add(new Transaction(Transaction.TransactionType.WITHDREW, amount));
+ balance -= amount;
+ }
+
+ public void transfer(double amount, Account targetAccount) {
+ if (targetAccount == this) {
+ throw new IllegalArgumentException("Target account must be a different account.");
+ }
+ if (targetAccount == null) {
+ throw new IllegalArgumentException("Target account cannot be null.");
+ }
+ withdraw(amount);
+ targetAccount.deposit(amount);
+ }
+
+ // Currently it's the same as the account balance, but I choose not to remove it.
+ // Later it could be easily extended with a parameter (eg. time interval)
+ public double sumTransactions() {
+ double amount = 0.0;
+ for (Transaction t : transactions)
+ amount += t.getAmount();
+ return amount;
+ }
+
+ public Transaction getLastTransaction() {
+ if (transactions.isEmpty()) {
+ return null;
+ }
+ return transactions.get(transactions.size() - 1);
+ }
+
+ public abstract double calcInterestEarned();
+
+ public double getBalance() {
+ return balance;
+ }
+
+ public Customer getCustomer() {
+ return customer;
+ }
+
+ public AccountType getAccountType() {
+ return accountType;
+ }
+
+ public List getTransactions() {
+ return Collections.unmodifiableList(transactions);
+ }
+}
diff --git a/src/main/java/com/abc/account/AccountFactory.java b/src/main/java/com/abc/account/AccountFactory.java
new file mode 100644
index 00000000..4ce5f975
--- /dev/null
+++ b/src/main/java/com/abc/account/AccountFactory.java
@@ -0,0 +1,21 @@
+package com.abc.account;
+
+import com.abc.customer.Customer;
+
+public class AccountFactory {
+
+ private AccountFactory() {
+ }
+
+ public static Account create(Customer customer, AccountType accountType) {
+ switch (accountType) {
+ case CHECKING:
+ return new CheckingAccount(customer, accountType);
+ case SAVINGS:
+ return new SavingsAccount(customer, accountType);
+ case MAXI_SAVINGS:
+ return new MaxiSavingsAccount(customer, accountType);
+ }
+ throw new IllegalArgumentException("Invalid account type.");
+ }
+}
diff --git a/src/main/java/com/abc/account/AccountType.java b/src/main/java/com/abc/account/AccountType.java
new file mode 100644
index 00000000..190fda10
--- /dev/null
+++ b/src/main/java/com/abc/account/AccountType.java
@@ -0,0 +1,17 @@
+package com.abc.account;
+
+public enum AccountType {
+ CHECKING("Checking Account"),
+ SAVINGS("Savings Account"),
+ MAXI_SAVINGS("Maxi Savings Account");
+
+ private final String prettyName;
+
+ AccountType(String prettyName) {
+ this.prettyName = prettyName;
+ }
+
+ public String getPrettyName() {
+ return prettyName;
+ }
+}
diff --git a/src/main/java/com/abc/account/CheckingAccount.java b/src/main/java/com/abc/account/CheckingAccount.java
new file mode 100644
index 00000000..1fe8fc5f
--- /dev/null
+++ b/src/main/java/com/abc/account/CheckingAccount.java
@@ -0,0 +1,16 @@
+package com.abc.account;
+
+import com.abc.customer.Customer;
+
+public class CheckingAccount extends Account {
+
+ CheckingAccount(Customer customer, AccountType accountType) {
+ super(customer, accountType);
+ }
+
+ @Override
+ public double calcInterestEarned() {
+ double amount = getBalance();
+ return amount * 0.001;
+ }
+}
diff --git a/src/main/java/com/abc/account/MaxiSavingsAccount.java b/src/main/java/com/abc/account/MaxiSavingsAccount.java
new file mode 100644
index 00000000..acf2784c
--- /dev/null
+++ b/src/main/java/com/abc/account/MaxiSavingsAccount.java
@@ -0,0 +1,34 @@
+package com.abc.account;
+
+import com.abc.customer.Customer;
+import com.abc.util.DateProvider;
+
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+public class MaxiSavingsAccount extends Account {
+
+ MaxiSavingsAccount(Customer customer, AccountType accountType) {
+ super(customer, accountType);
+ }
+
+ @Override
+ public double calcInterestEarned() {
+ double amount = getBalance();
+ if (calcDayDiff() > 10) {
+ return amount * 0.05;
+ } else {
+ return amount * 0.001;
+ }
+ }
+
+ private long calcDayDiff() {
+ Transaction transaction = getLastTransaction();
+ if (transaction == null) {
+ return Long.MAX_VALUE;
+ }
+ Date today = DateProvider.getInstance().now();
+ long diffInMillis = Math.abs(today.getTime() - transaction.getTransactionDate().getTime());
+ return TimeUnit.DAYS.convert(diffInMillis, TimeUnit.MILLISECONDS);
+ }
+}
diff --git a/src/main/java/com/abc/account/SavingsAccount.java b/src/main/java/com/abc/account/SavingsAccount.java
new file mode 100644
index 00000000..d260fad8
--- /dev/null
+++ b/src/main/java/com/abc/account/SavingsAccount.java
@@ -0,0 +1,19 @@
+package com.abc.account;
+
+import com.abc.customer.Customer;
+
+public class SavingsAccount extends Account {
+
+ SavingsAccount(Customer customer, AccountType accountType) {
+ super(customer, accountType);
+ }
+
+ @Override
+ public double calcInterestEarned() {
+ double amount = getBalance();
+ if (amount <= 1000)
+ return amount * 0.001;
+ else
+ return 1 + (amount - 1000) * 0.002;
+ }
+}
diff --git a/src/main/java/com/abc/account/Transaction.java b/src/main/java/com/abc/account/Transaction.java
new file mode 100644
index 00000000..06311db8
--- /dev/null
+++ b/src/main/java/com/abc/account/Transaction.java
@@ -0,0 +1,32 @@
+package com.abc.account;
+
+import com.abc.util.DateProvider;
+
+import java.util.Date;
+
+public class Transaction {
+ private final double amount;
+ private final Date transactionDate;
+ private final TransactionType transactionType;
+
+ public enum TransactionType {
+ WITHDREW, DEPOSIT;
+ }
+
+ public Transaction(TransactionType transactionType, double amount) {
+ this.transactionType = transactionType;
+ this.amount = amount;
+ this.transactionDate = DateProvider.getInstance().now();
+ }
+
+ public double getAmount() {
+ if (transactionType == TransactionType.WITHDREW) {
+ return -amount;
+ }
+ return amount;
+ }
+
+ public Date getTransactionDate() {
+ return transactionDate;
+ }
+}
diff --git a/src/main/java/com/abc/bank/Bank.java b/src/main/java/com/abc/bank/Bank.java
new file mode 100644
index 00000000..6e27705c
--- /dev/null
+++ b/src/main/java/com/abc/bank/Bank.java
@@ -0,0 +1,58 @@
+package com.abc.bank;
+
+import com.abc.account.Account;
+import com.abc.account.AccountFactory;
+import com.abc.account.AccountType;
+import com.abc.customer.Customer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class Bank {
+ private final List customers;
+
+ public Bank() {
+ customers = new ArrayList<>();
+ }
+
+ public void addCustomer(Customer customer) {
+ if (customer != null && !customers.contains(customer)) {
+ customers.add(customer);
+ customer.setBank(this);
+ }
+ }
+
+ public String createCustomerSummary() {
+ StringBuilder summary = new StringBuilder("Customer Summary");
+ for (Customer customer : customers) {
+ int numberOfAccounts = customer.getNumberOfAccounts();
+ String pluralFormat = pluralFormat(numberOfAccounts, " account");
+ String customerSummary = String.format("\n - %s (%s%s)",
+ customer.getName(),
+ numberOfAccounts,
+ pluralFormat);
+ summary.append(customerSummary);
+ }
+ return summary.toString();
+ }
+
+ private String pluralFormat(int number, String word) {
+ return number == 1 ? word : word + "s";
+ }
+
+ public double totalInterestPaid() {
+ double total = 0;
+ for (Customer customer : customers)
+ total += customer.totalInterestEarned();
+ return total;
+ }
+
+ public Account createAccount(Customer customer, AccountType accountType) {
+ return AccountFactory.create(customer, accountType);
+ }
+
+ public List getCustomers() {
+ return Collections.unmodifiableList(customers);
+ }
+}
diff --git a/src/main/java/com/abc/customer/Customer.java b/src/main/java/com/abc/customer/Customer.java
new file mode 100644
index 00000000..7b2a04f5
--- /dev/null
+++ b/src/main/java/com/abc/customer/Customer.java
@@ -0,0 +1,60 @@
+package com.abc.customer;
+
+import com.abc.bank.Bank;
+import com.abc.account.Account;
+import com.abc.account.AccountType;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class Customer {
+ private final String name;
+ private final List accounts;
+ private Bank bank;
+
+ public Customer(String name) {
+ this.name = name;
+ this.accounts = new ArrayList<>();
+ }
+
+ public Account openAccount(AccountType accountType) {
+ if (bank == null) {
+ throw new IllegalArgumentException("Customer should be assigned to a bank first.");
+ }
+ Account account = bank.createAccount(this, accountType);
+ accounts.add(account);
+ return account;
+ }
+
+ public int getNumberOfAccounts() {
+ return accounts.size();
+ }
+
+ public double totalInterestEarned() {
+ double total = 0.0;
+ for (Account a : accounts)
+ total += a.calcInterestEarned();
+ return total;
+ }
+
+ public String getStatement() {
+ return CustomerStatement.create(this);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List getAccounts() {
+ return Collections.unmodifiableList(accounts);
+ }
+
+ public Bank getBank() {
+ return bank;
+ }
+
+ public void setBank(Bank bank) {
+ this.bank = bank;
+ }
+}
diff --git a/src/main/java/com/abc/customer/CustomerStatement.java b/src/main/java/com/abc/customer/CustomerStatement.java
new file mode 100644
index 00000000..73eecb72
--- /dev/null
+++ b/src/main/java/com/abc/customer/CustomerStatement.java
@@ -0,0 +1,58 @@
+package com.abc.customer;
+
+import com.abc.account.Transaction;
+import com.abc.account.Account;
+
+import static java.lang.Math.abs;
+
+public final class CustomerStatement {
+
+ private CustomerStatement() {
+ }
+
+ private static final String LINE_BREAK = "\n";
+
+ public static String create(Customer customer) {
+ StringBuilder statement = new StringBuilder("Statement for ");
+ statement.append(customer.getName());
+ statement.append(LINE_BREAK);
+ for (Account account : customer.getAccounts()) {
+ statement.append(LINE_BREAK);
+ statement.append(statementForAccount(account));
+ statement.append(LINE_BREAK);
+ }
+ statement.append(LINE_BREAK);
+ statement.append("Total In All Accounts ");
+ statement.append(toDollars(sumAllTransactions(customer)));
+ return statement.toString();
+ }
+
+ private static String statementForAccount(Account account) {
+ StringBuilder sb = new StringBuilder(account.getAccountType().getPrettyName());
+ sb.append(LINE_BREAK);
+ for (Transaction t : account.getTransactions()) {
+ if (t.getAmount() < 0) {
+ sb.append(" withdrawal ");
+ } else {
+ sb.append(" deposit ");
+ }
+ sb.append(toDollars(t.getAmount()));
+ sb.append(LINE_BREAK);
+ }
+ sb.append("Total ");
+ sb.append(toDollars(account.sumTransactions()));
+ return sb.toString();
+ }
+
+ private static double sumAllTransactions(Customer customer) {
+ double total = 0.0;
+ for (Account account : customer.getAccounts()) {
+ total += account.sumTransactions();
+ }
+ return total;
+ }
+
+ private static String toDollars(double d) {
+ return String.format("$%,.2f", abs(d));
+ }
+}
diff --git a/src/main/java/com/abc/DateProvider.java b/src/main/java/com/abc/util/DateProvider.java
similarity index 86%
rename from src/main/java/com/abc/DateProvider.java
rename to src/main/java/com/abc/util/DateProvider.java
index 035ee90b..f76a96c5 100644
--- a/src/main/java/com/abc/DateProvider.java
+++ b/src/main/java/com/abc/util/DateProvider.java
@@ -1,4 +1,4 @@
-package com.abc;
+package com.abc.util;
import java.util.Calendar;
import java.util.Date;
@@ -6,6 +6,9 @@
public class DateProvider {
private static DateProvider instance = null;
+ private DateProvider() {
+ }
+
public static DateProvider getInstance() {
if (instance == null)
instance = new DateProvider();
diff --git a/src/test/java/com/abc/BankTest.java b/src/test/java/com/abc/BankTest.java
deleted file mode 100644
index f8a82896..00000000
--- a/src/test/java/com/abc/BankTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.abc;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class BankTest {
- private static final double DOUBLE_DELTA = 1e-15;
-
- @Test
- public void customerSummary() {
- Bank bank = new Bank();
- Customer john = new Customer("John");
- john.openAccount(new Account(Account.CHECKING));
- bank.addCustomer(john);
-
- assertEquals("Customer Summary\n - John (1 account)", bank.customerSummary());
- }
-
- @Test
- public void checkingAccount() {
- Bank bank = new Bank();
- Account checkingAccount = new Account(Account.CHECKING);
- Customer bill = new Customer("Bill").openAccount(checkingAccount);
- bank.addCustomer(bill);
-
- checkingAccount.deposit(100.0);
-
- assertEquals(0.1, bank.totalInterestPaid(), DOUBLE_DELTA);
- }
-
- @Test
- public void savings_account() {
- Bank bank = new Bank();
- Account checkingAccount = new Account(Account.SAVINGS);
- bank.addCustomer(new Customer("Bill").openAccount(checkingAccount));
-
- checkingAccount.deposit(1500.0);
-
- assertEquals(2.0, bank.totalInterestPaid(), DOUBLE_DELTA);
- }
-
- @Test
- public void maxi_savings_account() {
- Bank bank = new Bank();
- Account checkingAccount = new Account(Account.MAXI_SAVINGS);
- bank.addCustomer(new Customer("Bill").openAccount(checkingAccount));
-
- checkingAccount.deposit(3000.0);
-
- assertEquals(170.0, bank.totalInterestPaid(), DOUBLE_DELTA);
- }
-
-}
diff --git a/src/test/java/com/abc/CustomerTest.java b/src/test/java/com/abc/CustomerTest.java
deleted file mode 100644
index b8df9498..00000000
--- a/src/test/java/com/abc/CustomerTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.abc;
-
-import org.junit.Ignore;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class CustomerTest {
-
- @Test //Test customer statement generation
- public void testApp(){
-
- Account checkingAccount = new Account(Account.CHECKING);
- Account savingsAccount = new Account(Account.SAVINGS);
-
- Customer henry = new Customer("Henry").openAccount(checkingAccount).openAccount(savingsAccount);
-
- checkingAccount.deposit(100.0);
- savingsAccount.deposit(4000.0);
- savingsAccount.withdraw(200.0);
-
- assertEquals("Statement for Henry\n" +
- "\n" +
- "Checking Account\n" +
- " deposit $100.00\n" +
- "Total $100.00\n" +
- "\n" +
- "Savings Account\n" +
- " deposit $4,000.00\n" +
- " withdrawal $200.00\n" +
- "Total $3,800.00\n" +
- "\n" +
- "Total In All Accounts $3,900.00", henry.getStatement());
- }
-
- @Test
- public void testOneAccount(){
- Customer oscar = new Customer("Oscar").openAccount(new Account(Account.SAVINGS));
- assertEquals(1, oscar.getNumberOfAccounts());
- }
-
- @Test
- public void testTwoAccount(){
- Customer oscar = new Customer("Oscar")
- .openAccount(new Account(Account.SAVINGS));
- oscar.openAccount(new Account(Account.CHECKING));
- assertEquals(2, oscar.getNumberOfAccounts());
- }
-
- @Ignore
- public void testThreeAcounts() {
- Customer oscar = new Customer("Oscar")
- .openAccount(new Account(Account.SAVINGS));
- oscar.openAccount(new Account(Account.CHECKING));
- assertEquals(3, oscar.getNumberOfAccounts());
- }
-}
diff --git a/src/test/java/com/abc/TransactionTest.java b/src/test/java/com/abc/TransactionTest.java
deleted file mode 100644
index 28983234..00000000
--- a/src/test/java/com/abc/TransactionTest.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.abc;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertTrue;
-
-public class TransactionTest {
- @Test
- public void transaction() {
- Transaction t = new Transaction(5);
- assertTrue(t instanceof Transaction);
- }
-}
diff --git a/src/test/java/com/abc/account/AccountTest.java b/src/test/java/com/abc/account/AccountTest.java
new file mode 100644
index 00000000..30f2da05
--- /dev/null
+++ b/src/test/java/com/abc/account/AccountTest.java
@@ -0,0 +1,81 @@
+package com.abc.account;
+
+import com.abc.customer.Customer;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class AccountTest {
+
+ private final String TEST_CUSTOMER_NAME = "Josh";
+ private final double DELTA = 1e-15;
+
+ @Test
+ public void testDeposit() {
+ Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS);
+ account.deposit(150.0);
+ account.deposit(350.0);
+ account.deposit(100.0);
+ assertEquals(600.0, account.getBalance(), DELTA);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testDepositWithZeroAmount() {
+ Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS);
+ account.deposit(0.0);
+ }
+
+ @Test
+ public void testWithdraw() {
+ Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS);
+ account.deposit(600.0);
+ account.withdraw(100.0);
+ assertEquals(500.0, account.getBalance(), DELTA);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testWithdrawWithZeroAmount() {
+ Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS);
+ account.deposit(100.0);
+ account.withdraw(0.0);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testWithdrawIfAmountGreaterThanBalance() {
+ Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS);
+ account.deposit(100.0);
+ account.withdraw(2000.0);
+ }
+
+ @Test
+ public void testSumTransactions() {
+ Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS);
+ account.deposit(100.0);
+ account.withdraw(20.0);
+ account.deposit(200.0);
+ account.withdraw(100.0);
+ assertEquals(180.0, account.sumTransactions(), DELTA);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTransferWhenTargetAccountIsNull() {
+ Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS);
+ account.transfer(100.0, null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testTransferWhenTargetAccountIsTheSameAccount() {
+ Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS);
+ account.transfer(100.0, account);
+ }
+
+ @Test
+ public void testTransfer() {
+ Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS);
+ Account targetAccount = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.CHECKING);
+ account.deposit(100.0);
+ account.transfer(30.0, targetAccount);
+ assertEquals(70.0, account.getBalance(), DELTA);
+ assertEquals(30.0, targetAccount.getBalance(), DELTA);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/abc/account/CheckingAccountTest.java b/src/test/java/com/abc/account/CheckingAccountTest.java
new file mode 100644
index 00000000..014f5ddf
--- /dev/null
+++ b/src/test/java/com/abc/account/CheckingAccountTest.java
@@ -0,0 +1,19 @@
+package com.abc.account;
+
+import com.abc.customer.Customer;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class CheckingAccountTest {
+
+ private final String TEST_CUSTOMER_NAME = "Josh";
+ private final double DELTA = 1e-15;
+
+ @Test
+ public void testCalcInterestEarned() {
+ Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.CHECKING);
+ account.deposit(1900.0);
+ assertEquals(1.9, account.calcInterestEarned(), DELTA);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/abc/account/MaxiSavingsAccountTest.java b/src/test/java/com/abc/account/MaxiSavingsAccountTest.java
new file mode 100644
index 00000000..54c1f457
--- /dev/null
+++ b/src/test/java/com/abc/account/MaxiSavingsAccountTest.java
@@ -0,0 +1,55 @@
+package com.abc.account;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class MaxiSavingsAccountTest {
+
+ @Mock
+ private Transaction mockTransaction;
+
+ @Mock
+ private MaxiSavingsAccount mockAccount;
+
+ private final double DELTA = 1e-15;
+
+ @Test
+ public void testCalcInterestEarnedWhenLastTransactionInLessThan10Days() {
+ when(mockAccount.getLastTransaction()).thenReturn(mockTransaction);
+ when(mockAccount.getBalance()).thenReturn(900.0);
+ when(mockTransaction.getTransactionDate()).thenReturn(
+ new Date());
+ when(mockAccount.calcInterestEarned()).thenCallRealMethod();
+ assertEquals(0.9, mockAccount.calcInterestEarned(), DELTA);
+ }
+
+ @Test
+ public void testCalcInterestEarnedWhenLastTransactionInMoreThan10Days() throws ParseException {
+ when(mockAccount.getLastTransaction()).thenReturn(mockTransaction);
+ when(mockAccount.getBalance()).thenReturn(900.0);
+ when(mockTransaction.getTransactionDate()).thenReturn(
+ new SimpleDateFormat("MM/dd/yyyy").parse("08/16/2022"));
+ when(mockAccount.calcInterestEarned()).thenCallRealMethod();
+ assertEquals(45, mockAccount.calcInterestEarned(), DELTA);
+ }
+
+ @Test
+ public void testCalcInterestEarnedWithNoTransactions() {
+ when(mockAccount.getLastTransaction()).thenReturn(null);
+ when(mockAccount.getBalance()).thenCallRealMethod();
+ when(mockAccount.calcInterestEarned()).thenCallRealMethod();
+ assertEquals(0, mockAccount.calcInterestEarned(), DELTA);
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/abc/account/SavingsAccountTest.java b/src/test/java/com/abc/account/SavingsAccountTest.java
new file mode 100644
index 00000000..dc506bec
--- /dev/null
+++ b/src/test/java/com/abc/account/SavingsAccountTest.java
@@ -0,0 +1,26 @@
+package com.abc.account;
+
+import com.abc.customer.Customer;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class SavingsAccountTest {
+
+ private final String TEST_CUSTOMER_NAME = "Josh";
+ private final double DELTA = 1e-15;
+
+ @Test
+ public void testCalcInterestEarnedWithAmountLessThan1000() {
+ Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS);
+ account.deposit(900.0);
+ assertEquals(0.9, account.calcInterestEarned(), DELTA);
+ }
+
+ @Test
+ public void testCalcInterestEarnedWithAmountGreaterThan1000() {
+ Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS);
+ account.deposit(1900.0);
+ assertEquals(2.8, account.calcInterestEarned(), DELTA);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/abc/bank/BankTest.java b/src/test/java/com/abc/bank/BankTest.java
new file mode 100644
index 00000000..39b05c1a
--- /dev/null
+++ b/src/test/java/com/abc/bank/BankTest.java
@@ -0,0 +1,70 @@
+package com.abc.bank;
+
+import com.abc.account.AccountType;
+import com.abc.customer.Customer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class BankTest {
+
+ private final double DELTA = 1e-15;
+
+ @Mock
+ private Customer mockCustomer1;
+ @Mock
+ private Customer mockCustomer2;
+ @Mock
+ private Customer mockCustomer3;
+
+ @Test
+ public void testCustomerSummary() {
+ when(mockCustomer1.getName()).thenReturn("John");
+ when(mockCustomer1.getNumberOfAccounts()).thenReturn(1);
+ when(mockCustomer2.getName()).thenReturn("James");
+ when(mockCustomer2.getNumberOfAccounts()).thenReturn(2);
+
+ Bank bank = new Bank();
+ bank.addCustomer(mockCustomer1);
+ bank.addCustomer(mockCustomer2);
+
+ assertEquals(
+ "Customer Summary\n - John (1 account)\n - James (2 accounts)",
+ bank.createCustomerSummary());
+ }
+
+ @Test
+ public void testAddCustomer() {
+ Bank bank = new Bank();
+ bank.addCustomer(mockCustomer1);
+ bank.addCustomer(mockCustomer2);
+ bank.addCustomer(mockCustomer3);
+ bank.addCustomer(mockCustomer1);
+ bank.addCustomer(null);
+ assertEquals(3, bank.getCustomers().size());
+ }
+
+ @Test
+ public void testTotalInterestPaid() {
+ when(mockCustomer1.totalInterestEarned()).thenReturn(1.0);
+ when(mockCustomer2.totalInterestEarned()).thenReturn(2.0);
+ when(mockCustomer3.totalInterestEarned()).thenReturn(3.0);
+ Bank bank = new Bank();
+ bank.addCustomer(mockCustomer1);
+ bank.addCustomer(mockCustomer2);
+ bank.addCustomer(mockCustomer3);
+ assertEquals(6.0, bank.totalInterestPaid(), DELTA);
+ }
+
+ @Test
+ public void testCreateAccount() {
+ Bank bank = new Bank();
+ assertNotNull(bank.createAccount(mockCustomer1, AccountType.CHECKING));
+ }
+}
diff --git a/src/test/java/com/abc/customer/CustomerStatementTest.java b/src/test/java/com/abc/customer/CustomerStatementTest.java
new file mode 100644
index 00000000..ec04380a
--- /dev/null
+++ b/src/test/java/com/abc/customer/CustomerStatementTest.java
@@ -0,0 +1,58 @@
+package com.abc.customer;
+
+import com.abc.account.*;
+import com.abc.bank.Bank;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CustomerStatementTest {
+
+ @Mock
+ private Customer mockCustomer;
+
+ @Mock
+ private SavingsAccount mockSavingsAccount;
+
+ @Mock
+ private CheckingAccount mockCheckingAccount;
+
+ @Test
+ public void create() {
+ Transaction transaction1 = new Transaction(Transaction.TransactionType.DEPOSIT, 100.0);
+ Transaction transaction2 = new Transaction(Transaction.TransactionType.DEPOSIT, 4000.0);
+ Transaction transaction3 = new Transaction(Transaction.TransactionType.WITHDREW, 200.0);
+
+ when(mockCustomer.getName()).thenReturn("Henry");
+ when(mockCustomer.getAccounts()).thenReturn(new ArrayList<>(Arrays.asList(mockCheckingAccount, mockSavingsAccount)));
+ when(mockCheckingAccount.getTransactions()).thenReturn(new ArrayList<>(Arrays.asList(transaction1)));
+ when(mockSavingsAccount.getTransactions()).thenReturn(new ArrayList<>(Arrays.asList(transaction2, transaction3)));
+ when(mockCheckingAccount.getAccountType()).thenReturn(AccountType.CHECKING);
+ when(mockSavingsAccount.getAccountType()).thenReturn(AccountType.SAVINGS);
+ when(mockCheckingAccount.sumTransactions()).thenReturn(100.0);
+ when(mockSavingsAccount.sumTransactions()).thenReturn(3800.0);
+ when(mockCustomer.getStatement()).thenCallRealMethod();
+
+ assertEquals("Statement for Henry\n" +
+ "\n" +
+ "Checking Account\n" +
+ " deposit $100.00\n" +
+ "Total $100.00\n" +
+ "\n" +
+ "Savings Account\n" +
+ " deposit $4,000.00\n" +
+ " withdrawal $200.00\n" +
+ "Total $3,800.00\n" +
+ "\n" +
+ "Total In All Accounts $3,900.00", mockCustomer.getStatement());
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/abc/customer/CustomerTest.java b/src/test/java/com/abc/customer/CustomerTest.java
new file mode 100644
index 00000000..c41eef4a
--- /dev/null
+++ b/src/test/java/com/abc/customer/CustomerTest.java
@@ -0,0 +1,52 @@
+package com.abc.customer;
+
+import com.abc.account.AccountFactory;
+import com.abc.bank.Bank;
+import com.abc.account.AccountType;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CustomerTest {
+
+ @Mock
+ private Bank mockBank;
+
+ @Test
+ public void testGetNumberOfAccountsWith0Accounts() {
+ Customer oscar = new Customer("Oscar");
+ assertEquals(0, oscar.getNumberOfAccounts());
+ }
+
+ @Test
+ public void testGetNumberOfAccountsWith3Accounts() {
+ Bank bank = new Bank();
+ Customer oscar = new Customer("Oscar");
+ bank.addCustomer(oscar);
+ for (int i = 0; i < 3; i++) {
+ oscar.openAccount(AccountType.SAVINGS);
+ }
+ assertEquals(3, oscar.getNumberOfAccounts());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testOpenAccountWhenBankIsNull() {
+ Customer customer = new Customer("Anna");
+ customer.openAccount(AccountType.CHECKING);
+ }
+
+ @Test
+ public void testOpenAccount() {
+ Customer customer = new Customer("Anna");
+ customer.setBank(mockBank);
+ when(mockBank.createAccount(customer, AccountType.CHECKING))
+ .thenReturn(AccountFactory.create(customer,AccountType.CHECKING));
+ assertNotNull(customer.openAccount(AccountType.CHECKING));
+ }
+}