diff --git a/class-diagram.png b/class-diagram.png new file mode 100644 index 000000000..59be96425 Binary files /dev/null and b/class-diagram.png differ diff --git a/domain-model.md b/domain-model.md new file mode 100644 index 000000000..5284adbb3 --- /dev/null +++ b/domain-model.md @@ -0,0 +1,42 @@ +| Class | Attribute | Method | Scenario | Output | +|----------------|--------------------------|-------------------------|----------------|-------------------| +| Account | List ledger | getLedger() | | List | +| | String id | deposit(int arg) | | newBalance | +| | float balance | withdraw(int arg) | arg <= balance | newBalance | +| | | | arg > balance | | +| | | getBalance() | | balance | +| | | getTransactionHistory() | | String history | +| SavingAccount | | | | | +| CurrentAccount | | | | | +| | | | | | +| Transaction | float deltaBalance | getDeltaBalance() | | deltaBalance | +| | LocalDateTime timeStamp | getTimeStamp() | | timestamp | +Extension: + +| Class | Attribute | Method | Scenario | Output | +|----------------|--------------------------|-------------------------------|----------------|--------------------| +| Account | List ledger | getLedger() | | List | +| | String id | deposit(int arg) | | newBalance | +| | float balance | withdraw(int arg) | arg <= balance | newBalance | +| | float overdraft | | arg > balance | | +| | | getBalance() | | balance | +| | | getTransactionHistory() | | String history | +| | | getBalanceFromLedger() | | float balance | +| | | | | | +| SavingAccount | | | | | +| CurrentAccount | | | | | +| | | | | | +| Transaction | float deltaBalance | getDeltaBalance() | | deltaBalance | +| | LocalDateTime timeStamp | getTimeStamp() | | timestamp | +| Branch | List accounts | getAccounts() | | List accs | +| | List request | getRequests() | | List reqs | +| | | acceptRequest(Request) | | void | +| | | denyRequest(Request) | | void | +| | | createRequest(Account, float) | | void | +| | | addAccount(Account) | | void | +| Request | Account acc | | | | +| | float overdraft | | | | + + + + 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..9378bc79a --- /dev/null +++ b/src/main/java/com/booleanuk/core/Account.java @@ -0,0 +1,99 @@ +package com.booleanuk.core; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +public class Account { + List ledger; + String id; + float balance; + + public Account(List ledger, String id, float balance){ + this.ledger = ledger; + this. id = id; + this.balance = balance; + } + + + public String getTransactionHistory(){ + List transactions = new ArrayList<>(ledger); //Clone list to not affect attribute + + + + List rows = new ArrayList<>(); + + float balance = 0; + for(Transaction tr : transactions){ + balance += tr.getDeltaBalance(); + StringBuilder sb = new StringBuilder(); + String dateStr = tr.getTimeStamp().format(DateTimeFormatter.ofPattern("dd/MM/uuuu")); + sb.append(String.format("%-11s||", dateStr)); + if(tr.getDeltaBalance()>0){ + sb.append(String.format(" %-8.2f||", tr.getDeltaBalance())); + sb.append(String.format(" %-7s||" ,"")); + } else { + sb.append(String.format(" %-8s||" ,"")); + sb.append(String.format(" %-7.2f||", -tr.getDeltaBalance())); + } + sb.append(String.format(" %.2f", balance)); + sb.append("\n"); + rows.add(sb.toString()); + } + rows.add("date || credit || debit || balance\n"); + String ret = rows.reversed().stream().reduce("", ( (acc,curr) -> acc+curr)); + return ret; + } + + public float deposit(float val){ + this.setBalance(this.getBalance()+val); + + this.addLedgerEntry(val); + + return this.getBalance(); + } + + public float withdraw(float amount) throws InsufficientFundsException{ + if(amount > this.getBalance()){ + throw new InsufficientFundsException(); + } else { + this.setBalance(this.getBalance()-amount); + + this.addLedgerEntry(-amount); + + return this.getBalance(); + } + + } + + private void addLedgerEntry(float val){ + Transaction transaction = new Transaction(val, LocalDate.now()); + ledger.add(transaction); + } + + public List getLedger() { + return ledger; + } + + public void setLedger(List ledger) { + this.ledger = ledger; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public float getBalance() { + return balance; + } + + public void setBalance(float balance) { + this.balance = balance; + } +} 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..f5737d946 --- /dev/null +++ b/src/main/java/com/booleanuk/core/CurrentAccount.java @@ -0,0 +1,9 @@ +package com.booleanuk.core; + +import java.util.List; + +public class CurrentAccount extends Account{ + public CurrentAccount(List ledger, String id, float balance){ + super(ledger, id, balance); + } +} diff --git a/src/main/java/com/booleanuk/core/InsufficientFundsException.java b/src/main/java/com/booleanuk/core/InsufficientFundsException.java new file mode 100644 index 000000000..11d926155 --- /dev/null +++ b/src/main/java/com/booleanuk/core/InsufficientFundsException.java @@ -0,0 +1,11 @@ +package com.booleanuk.core; + +public class InsufficientFundsException extends Exception{ + public InsufficientFundsException(String message){ + super(message); + } + + public InsufficientFundsException(){ + super(); + } +} 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..309f8369d --- /dev/null +++ b/src/main/java/com/booleanuk/core/SavingsAccount.java @@ -0,0 +1,9 @@ +package com.booleanuk.core; + +import java.util.List; + +public class SavingsAccount extends Account{ + public SavingsAccount(List ledger, String id, float balance){ + super(ledger, id, balance); + } +} diff --git a/src/main/java/com/booleanuk/core/Transaction.java b/src/main/java/com/booleanuk/core/Transaction.java new file mode 100644 index 000000000..3d4dea617 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Transaction.java @@ -0,0 +1,30 @@ +package com.booleanuk.core; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +public class Transaction { + private float deltaBalance; + private LocalDate timeStamp; + + public Transaction(float deltaBalance ,LocalDate timeStamp){ + this.deltaBalance = deltaBalance; + this.timeStamp = timeStamp; + } + + public float getDeltaBalance() { + return deltaBalance; + } + + public LocalDate getTimeStamp() { + return timeStamp; + } + + public void setDeltaBalance(float deltaBalance) { + this.deltaBalance = deltaBalance; + } + + public void setTimeStamp(LocalDate timeStamp) { + this.timeStamp = timeStamp; + } +} diff --git a/src/main/java/com/booleanuk/extension/.gitkeep b/src/main/java/com/booleanuk/extension/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/src/main/java/com/booleanuk/extension/Account.java b/src/main/java/com/booleanuk/extension/Account.java new file mode 100644 index 000000000..3e74d24b5 --- /dev/null +++ b/src/main/java/com/booleanuk/extension/Account.java @@ -0,0 +1,117 @@ +package com.booleanuk.extension; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +public class Account { + List ledger; + String id; + float balance; + float overdraft; + + + + public Account(List ledger, String id, float balance){ + this.ledger = ledger; + this. id = id; + this.balance = balance; + this.overdraft = 0; + } + + public float getBalanceFromLedger(){ + float acc = 0; + for(Transaction curr : ledger){ + acc += curr.getDeltaBalance(); + } + return acc; + } + + public String getTransactionHistory(){ + List transactions = new ArrayList<>(ledger); //Clone list to not affect attribute + + + + List rows = new ArrayList<>(); + + float balance = 0; + for(Transaction tr : transactions){ + balance += tr.getDeltaBalance(); + StringBuilder sb = new StringBuilder(); + String dateStr = tr.getTimeStamp().format(DateTimeFormatter.ofPattern("dd/MM/uuuu")); + sb.append(String.format("%-11s||", dateStr)); + if(tr.getDeltaBalance()>0){ + sb.append(String.format(" %-8.2f||", tr.getDeltaBalance())); + sb.append(String.format(" %-7s||" ,"")); + } else { + sb.append(String.format(" %-8s||" ,"")); + sb.append(String.format(" %-7.2f||", -tr.getDeltaBalance())); + } + sb.append(String.format(" %.2f", balance)); + sb.append("\n"); + rows.add(sb.toString()); + } + rows.add("date || credit || debit || balance\n"); + String ret = rows.reversed().stream().reduce("", ( (acc,curr) -> acc+curr)); + return ret; + } + + public float deposit(float val){ + this.setBalance(this.getBalance()+val); + + this.addLedgerEntry(val); + + return this.getBalance(); + } + + public float getOverdraft() { + return overdraft; + } + + public void setOverdraft(float overdraft) { + this.overdraft = overdraft; + } + + public float withdraw(float amount) throws InsufficientFundsException { + if(amount > this.getBalance()+overdraft){ + throw new InsufficientFundsException(); + } else { + this.setBalance(this.getBalance()-amount); + + this.addLedgerEntry(-amount); + + return this.getBalance(); + } + + } + + private void addLedgerEntry(float val){ + Transaction transaction = new Transaction(val, LocalDate.now()); + ledger.add(transaction); + } + + public List getLedger() { + return ledger; + } + + public void setLedger(List ledger) { + this.ledger = ledger; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public float getBalance() { + return balance; + } + + public void setBalance(float balance) { + this.balance = balance; + } +} diff --git a/src/main/java/com/booleanuk/extension/Branch.java b/src/main/java/com/booleanuk/extension/Branch.java new file mode 100644 index 000000000..efcd0881c --- /dev/null +++ b/src/main/java/com/booleanuk/extension/Branch.java @@ -0,0 +1,41 @@ +package com.booleanuk.extension; + +import java.util.List; + +public class Branch { + private List accounts; + private List requests; + + public Branch(List accounts, List requests){ + + this.accounts = accounts; + this.requests = requests; + } + + public void createRequest(Account acc, float overdraft){ + Request req = new Request(acc, overdraft); + this.getRequests().add(req); + } + + public void acceptRequest(Request req){ + req.getAcc().setOverdraft(req.getOverdraft()); + req.getAcc().getOverdraft(); + requests.remove(req); + } + + public void denyRequest(Request req){ + requests.remove(req); + } + + public List getAccounts() { + return accounts; + } + + public void addAccount(Account acc){ + this.accounts.add(acc); + } + + public List getRequests() { + return requests; + } +} diff --git a/src/main/java/com/booleanuk/extension/CurrentAccount.java b/src/main/java/com/booleanuk/extension/CurrentAccount.java new file mode 100644 index 000000000..eb8a39d03 --- /dev/null +++ b/src/main/java/com/booleanuk/extension/CurrentAccount.java @@ -0,0 +1,9 @@ +package com.booleanuk.extension; + +import java.util.List; + +public class CurrentAccount extends Account { + public CurrentAccount(List ledger, String id, float balance){ + super(ledger, id, balance); + } +} diff --git a/src/main/java/com/booleanuk/extension/InsufficientFundsException.java b/src/main/java/com/booleanuk/extension/InsufficientFundsException.java new file mode 100644 index 000000000..eb416bdee --- /dev/null +++ b/src/main/java/com/booleanuk/extension/InsufficientFundsException.java @@ -0,0 +1,11 @@ +package com.booleanuk.extension; + +public class InsufficientFundsException extends Exception{ + public InsufficientFundsException(String message){ + super(message); + } + + public InsufficientFundsException(){ + super(); + } +} diff --git a/src/main/java/com/booleanuk/extension/Request.java b/src/main/java/com/booleanuk/extension/Request.java new file mode 100644 index 000000000..211d72136 --- /dev/null +++ b/src/main/java/com/booleanuk/extension/Request.java @@ -0,0 +1,27 @@ +package com.booleanuk.extension; + +public class Request { + private Account acc; + private float overdraft; + + public Request(Account acc, float overdraft){ + this.acc = acc; + this.overdraft = overdraft; + } + + public Account getAcc() { + return acc; + } + + public void setAcc(Account acc) { + this.acc = acc; + } + + public float getOverdraft() { + return this.overdraft; + } + + public void setOverdraft(float overdraft) { + this.overdraft = overdraft; + } +} diff --git a/src/main/java/com/booleanuk/extension/SavingsAccount.java b/src/main/java/com/booleanuk/extension/SavingsAccount.java new file mode 100644 index 000000000..3c6fef6ba --- /dev/null +++ b/src/main/java/com/booleanuk/extension/SavingsAccount.java @@ -0,0 +1,9 @@ +package com.booleanuk.extension; + +import java.util.List; + +public class SavingsAccount extends Account { + public SavingsAccount(List ledger, String id, float balance){ + super(ledger, id, balance); + } +} diff --git a/src/main/java/com/booleanuk/extension/Transaction.java b/src/main/java/com/booleanuk/extension/Transaction.java new file mode 100644 index 000000000..bc39fb808 --- /dev/null +++ b/src/main/java/com/booleanuk/extension/Transaction.java @@ -0,0 +1,29 @@ +package com.booleanuk.extension; + +import java.time.LocalDate; + +public class Transaction { + private float deltaBalance; + private LocalDate timeStamp; + + public Transaction(float deltaBalance ,LocalDate timeStamp){ + this.deltaBalance = deltaBalance; + this.timeStamp = timeStamp; + } + + public float getDeltaBalance() { + return deltaBalance; + } + + public LocalDate getTimeStamp() { + return timeStamp; + } + + public void setDeltaBalance(float deltaBalance) { + this.deltaBalance = deltaBalance; + } + + public void setTimeStamp(LocalDate timeStamp) { + this.timeStamp = timeStamp; + } +} diff --git a/src/test/java/com/booleanuk/core/AccountTest.java b/src/test/java/com/booleanuk/core/AccountTest.java new file mode 100644 index 000000000..1aa93a929 --- /dev/null +++ b/src/test/java/com/booleanuk/core/AccountTest.java @@ -0,0 +1,92 @@ +package com.booleanuk.core; + +import com.sun.source.tree.AssertTree; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.sql.Array; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class AccountTest { + float delta = 0.0001f; + + private Account generateAccount(){ + return new Account(new ArrayList(), UUID.randomUUID().toString(), 0); + } + + + + @Test + public void testDeposit(){ + Account acc = generateAccount(); + + Assertions.assertEquals(0, acc.getBalance(), delta); + float testInsert = 100f; + Assertions.assertEquals(testInsert, acc.deposit(testInsert), delta); + Assertions.assertEquals(testInsert, acc.getBalance()); + } + + @Test + public void testTransactionGeneration(){ + Account acc = generateAccount(); + + acc.deposit(10); + try{ + acc.withdraw(5); + } catch(InsufficientFundsException e){ + Assertions.fail("Withdraw threw exception"); + } + + Assertions.assertEquals(2, acc.getLedger().size()); + } + + @Test + public void testWithdrawValid(){ + Account acc = generateAccount(); + + Assertions.assertEquals(0, acc.getBalance(), delta); + float testInsert = 150f; + float testWithdraw = 100f; + acc.deposit(testInsert); + try { + Assertions.assertEquals(testInsert - testWithdraw, acc.withdraw(testWithdraw), delta); + } catch(InsufficientFundsException e){ + Assertions.fail("Withdraw threw exception"); + } + Assertions.assertEquals(testInsert-testWithdraw, acc.getBalance()); + } + + @Test + public void testWithDrawMoreThanBalance(){ + Account acc = generateAccount(); + acc.deposit(50); + + Assertions.assertThrows(InsufficientFundsException.class ,() -> acc.withdraw(100)); + } + + @Test + public void testLedgerReturnString(){ + Account acc = generateAccount(); + acc.deposit(1000); + acc.deposit(2000); + try{ + acc.withdraw(500); + } catch(InsufficientFundsException e){ + Assertions.fail(); + } + + String now = LocalDate.now().format(DateTimeFormatter.ofPattern("dd/MM/uuuu")).toString(); + System.out.println(acc.getTransactionHistory()); + Assertions.assertTrue(acc.getTransactionHistory().contains( + "date || credit || debit || balance\n" + + now + " || || 500.00 || 2500.00\n" + + now + " || 2000.00 || || 3000.00\n" + + now + " || 1000.00 || || 1000.00")); + } + + +} diff --git a/src/test/java/com/booleanuk/extension/.gitkeep b/src/test/java/com/booleanuk/extension/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/java/com/booleanuk/extension/AccountTest.java b/src/test/java/com/booleanuk/extension/AccountTest.java new file mode 100644 index 000000000..af0bcf67c --- /dev/null +++ b/src/test/java/com/booleanuk/extension/AccountTest.java @@ -0,0 +1,101 @@ +package com.booleanuk.extension; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.UUID; + +public class AccountTest { + float delta = 0.0001f; + + private Account generateAccount(){ + return new Account(new ArrayList(), UUID.randomUUID().toString(), 0); + } + + + + @Test + public void testDeposit(){ + Account acc = generateAccount(); + + Assertions.assertEquals(0, acc.getBalance(), delta); + float testInsert = 100f; + Assertions.assertEquals(testInsert, acc.deposit(testInsert), delta); + Assertions.assertEquals(testInsert, acc.getBalance()); + } + + @Test + public void testTransactionGeneration(){ + Account acc = generateAccount(); + + acc.deposit(10); + try{ + acc.withdraw(5); + } catch(InsufficientFundsException e){ + Assertions.fail("Withdraw threw exception"); + } + + Assertions.assertEquals(2, acc.getLedger().size()); + } + + @Test + public void testWithdrawValid(){ + Account acc = generateAccount(); + + Assertions.assertEquals(0, acc.getBalance(), delta); + float testInsert = 150f; + float testWithdraw = 100f; + acc.deposit(testInsert); + try { + Assertions.assertEquals(testInsert - testWithdraw, acc.withdraw(testWithdraw), delta); + } catch(InsufficientFundsException e){ + Assertions.fail("Withdraw threw exception"); + } + Assertions.assertEquals(testInsert-testWithdraw, acc.getBalance()); + } + + @Test + public void testWithDrawMoreThanBalance(){ + Account acc = generateAccount(); + acc.deposit(50); + + Assertions.assertThrows(InsufficientFundsException.class ,() -> acc.withdraw(100)); + } + + @Test + public void testLedgerReturnString(){ + Account acc = generateAccount(); + acc.deposit(1000); + acc.deposit(2000); + try{ + acc.withdraw(500); + } catch(InsufficientFundsException e){ + Assertions.fail(); + } + + String now = LocalDate.now().format(DateTimeFormatter.ofPattern("dd/MM/uuuu")).toString(); + System.out.println(acc.getTransactionHistory()); + Assertions.assertTrue(acc.getTransactionHistory().contains( + "date || credit || debit || balance\n" + + now + " || || 500.00 || 2500.00\n" + + now + " || 2000.00 || || 3000.00\n" + + now + " || 1000.00 || || 1000.00")); + } + + @Test + public void testGetBalanceFromLedger(){ + Account acc = generateAccount(); + acc.deposit(1000); + acc.deposit(2000); + try{ + acc.withdraw(500); + } catch(InsufficientFundsException e){ + Assertions.fail(); + } + + Assertions.assertEquals(2500, acc.getBalanceFromLedger()); + } +} diff --git a/src/test/java/com/booleanuk/extension/BranchTest.java b/src/test/java/com/booleanuk/extension/BranchTest.java new file mode 100644 index 000000000..d3e1d991e --- /dev/null +++ b/src/test/java/com/booleanuk/extension/BranchTest.java @@ -0,0 +1,60 @@ +package com.booleanuk.extension; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.UUID; + +public class BranchTest { + + private Branch generateBranch(){ + Branch branch = new Branch(new ArrayList(), new ArrayList()); + branch.addAccount(new Account(new ArrayList(), UUID.randomUUID().toString(), 0)); + return branch; + } + + @Test + public void testCreateRequest(){ + Branch branch = generateBranch(); + Account acc = branch.getAccounts().get(0); + branch.createRequest(acc, 2000); + Assertions.assertEquals(1, branch.getRequests().size()); + } + + @Test + public void testAcceptRequest(){ + Branch branch = generateBranch(); + Account acc = branch.getAccounts().get(0); + branch.createRequest(acc, 2000); + Request req = branch.getRequests().get(0); + + branch.acceptRequest(req); + + Assertions.assertEquals(2000, acc.getOverdraft()); + } + + @Test + public void testDenyRequest(){ + Branch branch = generateBranch(); + Account acc = branch.getAccounts().get(0); + branch.createRequest(acc, 2000); + Request req = branch.getRequests().getFirst(); + + branch.denyRequest(req); + + Assertions.assertEquals(0, acc.getOverdraft()); + } + + @Test + public void testOverDraft(){ + Branch branch = generateBranch(); + Account acc = branch.getAccounts().getFirst(); + branch.createRequest(acc, 2000); + Request req = branch.getRequests().getFirst(); + branch.acceptRequest(req); + + Assertions.assertDoesNotThrow(() -> acc.withdraw(1500)); + } + +}