diff --git a/src/main/java/com/booleanuk/core/Account.java b/src/main/java/com/booleanuk/core/Account.java new file mode 100644 index 000000000..417515e4e --- /dev/null +++ b/src/main/java/com/booleanuk/core/Account.java @@ -0,0 +1,99 @@ +package com.booleanuk.core; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public abstract class Account { + private final String branch; + private final Manager manager; + private final HashMap> transactions; + private final int id; + + public Account(String branch, int id, Manager manager){ + this.branch = branch; + this.manager = manager; + this.id = id; + this.transactions = new HashMap<>(); + } + + public int getId(){ + return this.id; + } + + public double getBalance(){ + double balance = 0.0; + for (Map.Entry> entry : transactions.entrySet()) { + List value = entry.getValue(); + for (int trans : value) { + balance += trans; + } + } + return balance; + } + + public String getBranch(){ + return this.branch; + } + + public HashMap> getTransactions(){ + return this.transactions; + } + + public boolean deposit(int amount){ + if (amount < 0) { return false; } + // create transaction + String date = currentDate(); + if (!transactions.containsKey(date)){ + transactions.put(date, new ArrayList<>(){{add(amount);}}); + } else { + transactions.get(date).add(amount); + } + return true; + } + + public boolean withdraw(int amount){ + if (!manager.approveDraft(amount, getBalance()) || getBalance()-amount < 0 && this instanceof SavingsAccount) { + return false; + } + // create transaction + String date = currentDate(); + if (!transactions.containsKey(date)){ + transactions.put(date, new ArrayList<>(){{add(-amount);}}); + } else { + transactions.get(date).add(-amount); + } + return true; + } + + public String currentDate(){ + LocalDateTime time = LocalDateTime.now(); + String day = String.valueOf(time.getDayOfMonth()); + String month = String.valueOf(time.getMonthValue()); + String year = String.valueOf(time.getYear()); + return day + "/" + month + "/" + year; + } + + public String generateStatement(){ + StringBuilder res = new StringBuilder(); + String start = "|" + "Date " + " |" + "Deposit" + " |" + "Withdraw" +" |" + "Balance" + " |\n"; + res.append(start); + double total = 0; + for (Map.Entry> entry : transactions.entrySet()) { + String date = entry.getKey(); + List value = entry.getValue(); + for (int trans : value) { + total += trans; + String curr; + if (trans > 0) { + curr = "|" + date + " |" + trans + " | |" + total + " |\n"; + } else { + curr = "|" + date + " |" + " |" + trans + " |" + total + " |\n"; + } + res.append(curr); + } + } + return res.toString(); + } +} diff --git a/src/main/java/com/booleanuk/core/Bank.java b/src/main/java/com/booleanuk/core/Bank.java new file mode 100644 index 000000000..303f3ea38 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Bank.java @@ -0,0 +1,39 @@ +package com.booleanuk.core; +import java.util.ArrayList; +import java.util.List; + +public class Bank { + private final String name; + private final List allAccounts; + private int idIncrementer; + Manager manager; + + public Bank(String name, Manager manager){ + this.name = name; + this.allAccounts = new ArrayList<>(); + this.idIncrementer = 1; + this.manager = manager; + } + + public String getName(){ + return this.name; + } + + public List getAllAccounts(){ + return this.allAccounts; + } + + public Account createCurrentAccount(Customer customer){ + Account newAccount = new CurrentAccount(customer.getBranch(), idIncrementer, manager); + allAccounts.add(newAccount); + this.idIncrementer++; + return newAccount; + } + + public Account createSavingsAccount(Customer customer){ + Account newAccount = new SavingsAccount(customer.getBranch(), idIncrementer, manager); + allAccounts.add(newAccount); + this.idIncrementer++; + return newAccount; + } +} diff --git a/src/main/java/com/booleanuk/core/CurrentAccount.java b/src/main/java/com/booleanuk/core/CurrentAccount.java new file mode 100644 index 000000000..1e4a1a979 --- /dev/null +++ b/src/main/java/com/booleanuk/core/CurrentAccount.java @@ -0,0 +1,8 @@ +package com.booleanuk.core; + +public class CurrentAccount extends Account { + + public CurrentAccount(String branch, int id, Manager manager){ + super(branch, id, manager); + } +} diff --git a/src/main/java/com/booleanuk/core/Customer.java b/src/main/java/com/booleanuk/core/Customer.java new file mode 100644 index 000000000..1a16646a6 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Customer.java @@ -0,0 +1,59 @@ +package com.booleanuk.core; + +public class Customer { + private final Bank bank; + private final String name; + private final String branch; + private SavingsAccount savingsAccount = null; + private CurrentAccount currentAccount = null; + + public Customer(Bank bank, String name, String branch){ + this.bank = bank; + this.name = name; + this.branch = branch; + } + + public String getName(){ + return this.name; + } + + public String getBranch(){ + return this.branch; + } + + public SavingsAccount getSavingsAccount(){ + return this.savingsAccount; + } + + public CurrentAccount getCurrentAccount(){ + return this.currentAccount; + } + + public boolean createCurrentAccount(){ + if (currentAccount != null){ return false; } + + Account newAccount = this.bank.createCurrentAccount(this); + this.currentAccount = (CurrentAccount) newAccount; + return currentAccount != null; + } + + public boolean createSavingsAccount(){ + if (savingsAccount != null) { return false; } + + Account newAccount = this.bank.createSavingsAccount(this); + this.savingsAccount = (SavingsAccount) newAccount; + return savingsAccount != null; + } + + public boolean deposit(Account account, int amount){ + return account.deposit(amount); + } + + public boolean withdraw(Account account, int amount){ + return account.withdraw(amount); + } + + public String generateStatement(Account account){ + return account.generateStatement(); + } +} diff --git a/src/main/java/com/booleanuk/core/DomainModel.md b/src/main/java/com/booleanuk/core/DomainModel.md new file mode 100644 index 000000000..fb8aa41f9 --- /dev/null +++ b/src/main/java/com/booleanuk/core/DomainModel.md @@ -0,0 +1,39 @@ + +| Class | Method | Scenario | Output | +|----------|---------------------------------------------|---------------------------------------------|--------| +| Customer | createCurrentAccount() | If current account already exists | false | +| | | If no current account exists | true | +| | | | | +| Customer | createSavingsAccount() | If savings account already exists | false | +| | | If no savings account exists | true | +| | | | | +| Customer | generateBankStatements(Account account)) | If account does not exist | null | +| | | If account exists | String | +| | | | | +| Customer | deposit(Account account, int amount) | If amount < 0 | false | +| | | If amount is > 0 | true | +| | | | | +| Customer | withdraw(Account account, int amount) | If amount is larger than balance | false | +| | | If amount is less or equal to balance | true | +| | | | | +| Bank | createCurrentAccount(Customer customer) | If customer has a current account | false | +| | | If customer does not have a current account | true | +| | | | | +| Bank | createSavingsAccount(Customer customer) | If customer has a savings account | false | +| | | If customer does not have a savings account | true | +| | | | | +| Bank | generateStatement(Account account) | If account does not exist | null | +| | | If account exists | String | +| | | | | +| Account | deposit(int amount) | If amount is < 0 | false | +| | | If amount is > 0 | true | +| | | | | +| Account | withdraw(int amount) | If amount is larger than balance | false | +| | | If amount is less or equal to balance | true | +| | | | | +| Account | generateStatement() | If list of statements is empty | null | +| | | If list of statements is not empty | String | +| | | | | +| Manager | approveDraft(double amount, double currBal) | If amount is too large | false | +| | | If amount is within the negative limit | true | +| | | | | diff --git a/src/main/java/com/booleanuk/core/Manager.java b/src/main/java/com/booleanuk/core/Manager.java new file mode 100644 index 000000000..789adb2de --- /dev/null +++ b/src/main/java/com/booleanuk/core/Manager.java @@ -0,0 +1,15 @@ +package com.booleanuk.core; + +public class Manager { + String name; + double draftLimit; + + public Manager(String name, double draftLimit){ + this.name = name; + this.draftLimit = draftLimit; + } + + public boolean approveDraft(double amount, double currentBalance){ + return (currentBalance-amount) > draftLimit; + } +} diff --git a/src/main/java/com/booleanuk/core/SavingsAccount.java b/src/main/java/com/booleanuk/core/SavingsAccount.java new file mode 100644 index 000000000..f68fe752a --- /dev/null +++ b/src/main/java/com/booleanuk/core/SavingsAccount.java @@ -0,0 +1,8 @@ +package com.booleanuk.core; + +public class SavingsAccount extends Account{ + + public SavingsAccount(String branch, int id, Manager manager){ + super(branch, id, manager); + } +} diff --git a/src/main/java/com/booleanuk/core/bank-class-diagram.png b/src/main/java/com/booleanuk/core/bank-class-diagram.png new file mode 100644 index 000000000..6cee882be Binary files /dev/null and b/src/main/java/com/booleanuk/core/bank-class-diagram.png differ diff --git a/src/test/java/com/booleanuk/core/BankChallengeTests.java b/src/test/java/com/booleanuk/core/BankChallengeTests.java new file mode 100644 index 000000000..b72904ebe --- /dev/null +++ b/src/test/java/com/booleanuk/core/BankChallengeTests.java @@ -0,0 +1,137 @@ +package com.booleanuk.core; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import java.time.LocalDateTime; + +public class BankChallengeTests { + + @Test + public void testAccountCreation(){ + + Manager manager = new Manager("Bard", -1000); + Bank bank = new Bank("Nordea", manager); + Customer jim = new Customer(bank, "Jim", "NewYork"); + Customer bob = new Customer(bank, "Bob", "Oslo"); + + jim.createCurrentAccount(); + bob.createCurrentAccount(); + + // Ids should be different + Assertions.assertTrue(jim.getCurrentAccount().getId() != bob.getCurrentAccount().getId()); + // Customers should only be able to create 1 current account and 1 savings account + Assertions.assertFalse(jim.createCurrentAccount()); + Assertions.assertTrue(bob.createSavingsAccount()); + Assertions.assertEquals(1, jim.getCurrentAccount().getId()); + Assertions.assertEquals("NewYork", jim.getCurrentAccount().getBranch()); + Assertions.assertEquals("Nordea", bank.getName()); + Assertions.assertEquals(3, bank.getAllAccounts().size()); + Assertions.assertEquals("Jim", jim.getName()); + Assertions.assertInstanceOf(CurrentAccount.class, jim.getCurrentAccount()); + Assertions.assertInstanceOf(SavingsAccount.class, bob.getSavingsAccount()); + } + + @Test + public void testDepositAndWithdraw(){ + + Manager manager = new Manager("Bard", -10000); + Bank bank = new Bank("DNB", manager); + Customer jim = new Customer(bank, "Jim", "Ohio"); + Customer bob = new Customer(bank, "Bob", "Nevada"); + + jim.createCurrentAccount(); + bob.createSavingsAccount(); + + LocalDateTime time = LocalDateTime.now(); + String day = String.valueOf(time.getDayOfMonth()); + String month = String.valueOf(time.getMonthValue()); + String year = String.valueOf(time.getYear()); + String date = day + "/" + month + "/" + year; + + jim.deposit(jim.getCurrentAccount(), 500); + jim.deposit(jim.getCurrentAccount(), 200); + + Assertions.assertEquals(2, jim.getCurrentAccount().getTransactions().get(date).size()); + Assertions.assertEquals(700, jim.getCurrentAccount().getBalance()); + Assertions.assertEquals(0, bob.getSavingsAccount().getBalance()); + Assertions.assertTrue(jim.withdraw(jim.getCurrentAccount(), 600)); + Assertions.assertTrue(jim.deposit(jim.getCurrentAccount(), 100)); + } + + @Test + public void testGenerateStatement(){ + + Manager manager = new Manager("Bard", -1000); + Bank bank = new Bank("Storebrand", manager); + Customer jim = new Customer(bank, "Jim", "Oslo"); + Customer bob = new Customer(bank, "Bob", "Oslo"); + + jim.createCurrentAccount(); + bob.createSavingsAccount(); + + jim.deposit(jim.getCurrentAccount(), 500); + jim.withdraw(jim.getCurrentAccount(), 150); + jim.deposit(jim.getCurrentAccount(), 500); + jim.deposit(jim.getCurrentAccount(), 500); + jim.deposit(jim.getCurrentAccount(), 500); + jim.withdraw(jim.getCurrentAccount(), 200); + jim.withdraw(jim.getCurrentAccount(), 100); + jim.withdraw(jim.getCurrentAccount(), 105); + + System.out.println(jim.generateStatement(jim.getCurrentAccount())); + Assertions.assertTrue(jim.generateStatement(jim.getCurrentAccount()).contains(jim.getCurrentAccount().currentDate())); + } + + @Test + public void testExtensionOne(){ + + Manager manager = new Manager("Bard", -1000); + Bank bank = new Bank("Storebrand", manager); + Customer jim = new Customer(bank, "Jim", "Oslo"); + + jim.createCurrentAccount(); + jim.deposit(jim.getCurrentAccount(), 500); + jim.withdraw(jim.getCurrentAccount(), 150); + + Assertions.assertEquals(350.0, jim.getCurrentAccount().getBalance()); + } + + @Test + public void testExtensionTwo(){ + + Manager manager = new Manager("Bard", -1000); + Bank bank = new Bank("Storebrand", manager); + Customer jim = new Customer(bank, "Jim", "Oslo"); + + jim.createCurrentAccount(); + jim.deposit(jim.getCurrentAccount(), 500); + jim.withdraw(jim.getCurrentAccount(), 150); + + Assertions.assertEquals(jim.getCurrentAccount().getBranch(), jim.getBranch()); + Assertions.assertEquals("Oslo", jim.getCurrentAccount().getBranch()); + } + + @Test + public void testExtensionThreeAndFour(){ + + Manager manager = new Manager("Bard", -1000); + Bank bank = new Bank("Storebrand", manager); + Customer jim = new Customer(bank, "Jim", "Oslo"); + + jim.createCurrentAccount(); + jim.createSavingsAccount(); + + jim.deposit(jim.getCurrentAccount(), 500); + jim.deposit(jim.getSavingsAccount(), 500); + jim.withdraw(jim.getCurrentAccount(), 150); + jim.withdraw(jim.getSavingsAccount(), 150); + // this next request should be approved since the limit for overdrafting is set to 1000 + boolean approved = jim.withdraw(jim.getCurrentAccount(), 500); + // this next request should not be approved, since it runs over the limit of 1000 + boolean notApprovedSavings = jim.withdraw(jim.getSavingsAccount(), 400); + boolean notApproved = jim.withdraw(jim.getCurrentAccount(), 1000); + + Assertions.assertTrue(approved); + Assertions.assertFalse(notApprovedSavings); + Assertions.assertFalse(notApproved); + } +}