diff --git a/src/main/class-diagram.png b/src/main/class-diagram.png new file mode 100644 index 000000000..6ed531ec9 Binary files /dev/null and b/src/main/class-diagram.png differ diff --git a/src/main/domain-model.md b/src/main/domain-model.md new file mode 100644 index 000000000..bdd168c66 --- /dev/null +++ b/src/main/domain-model.md @@ -0,0 +1,69 @@ +# Domain model for Bank challenge + +## BankAccount +| Classes | Member | Methods | Scenario | Output | +|-------------|-----------------------------------------------|-------------------------|------------------------------------|-------------------------------------------------------------------| +| BankAccount | | | | | +| | balance: double | | | | +| | accountNumber: int | | | | +| | transactions: HashMap | | | | +| | | deposit(double amount) | amount > 0 | deposit amount, update balance | +| | | | amount = 0 | nothing happens to balance | +| | | withdraw(double amount) | amount < balance | amount is withdrawn, update balance | +| | | | amount > balance | amount is not withdrawn, user is told that amount exceeds balance | +| | | generateBankStatement() | transactions is empty | no statement is returned | +| | | | transactions has at least one item | generate statement | + + +## CurrentAccount +| Classes | Member | Methods | Scenario | Output | +|----------------|-----------------------------------------------|-------------------------|------------------------------------|-------------------------------------------------------------------| +| CurrentAccount | | | | | +| | balance: double | | | | +| | accountNumber: int | | | | +| | transactions: HashMap | | | | +| | | deposit(double amount) | amount > 0 | deposit amount, update balance | +| | | | amount = 0 | nothing happens to balance | +| | | withdraw(double amount) | amount < balance | amount is withdrawn, update balance | +| | | | amount > balance | amount is not withdrawn, user is told that amount exceeds balance | +| | | generateBankStatement() | transactions is empty | no statement is returned | +| | | | transactions has at least one item | generate statement | + +## SavingsAccount +| Classes | Member | Methods | Scenario | Output | +|----------------|-----------------------------------------------|---------------------------------|------------------------------------|-------------------------------------------------------------------| +| CurrentAccount | | | | | +| | balance: double | | | | +| | accountNumber: int | | | | +| | transactions: HashMap | | | | +| | | deposit(double amount) | amount > 0 | deposit amount, update balance | +| | | | amount = 0 | nothing happens to balance | +| | | withdraw(double amount) | amount < balance | amount is withdrawn, update balance | +| | | | amount > balance | amount is not withdrawn, user is told that amount exceeds balance | +| | | generateBankStatement() | transactions is empty | no statement is returned | +| | | | transactions has at least one item | generate statement | +| | | requestOverdraft(double amount) | amount < balance | no overdraft can be requested | +| | | | amountrequested > balance | overdraft is requested and returned | + +## Transaction +| Classes | Member | Methods | Scenario | Output | +|-------------|----------------------|-----------------------|------------------------------------------------------------------------------------------------|-----------------------| +| Transaction | | | | | +| | date: LocalDate | | | | +| | double: creditAmount | | | | +| | double: debitAmount | | | | +| | double: amount | | | | +| | | generateTransaction() | localDate not empty && (creditAmount not empty \|\| debitAmount not empty) && amount not empty | generate trans | +| | | | localDate empty \|\| (creditAmount empty \|\| debitAmount empty) \|\| amount empty | do not generate trans | + +## Overdraft +| Classes | Member | Methods | Scenario | Output | +|-----------|--------------------------------|---------------------------------------|--------------------------------|-------------------------| +| Overdraft | | | | | +| | double: amountRequested | | | | +| | double: balance | | | | +| | boolean: approved | | | | +| | CurrentAccount: currentAccount | | | | +| | double: MAX_OVERDRAFT | | | | +| | | approvedOrDenied(Overdraft overdraft) | if requested exceeds max limit | not allowed to withdraw | +| | | | if requested is within limit | allowed to withdraw | diff --git a/src/main/extension-class-diagram.png b/src/main/extension-class-diagram.png new file mode 100644 index 000000000..2891ebf53 Binary files /dev/null and b/src/main/extension-class-diagram.png differ diff --git a/src/main/java/com/booleanuk/core/BankAccount.java b/src/main/java/com/booleanuk/core/BankAccount.java new file mode 100644 index 000000000..6df319896 --- /dev/null +++ b/src/main/java/com/booleanuk/core/BankAccount.java @@ -0,0 +1,107 @@ +package com.booleanuk.core; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +abstract class BankAccount { + protected double balance; + protected static int accountNumber = 0; + protected List transactions = new ArrayList<>(); + Branch DEFAULT_BRANCH = Branch.OSLO; + + public BankAccount() { + accountNumber++; + } + + public double getBalance() { + return balance; + } + + public int getAccountNumber() { + return accountNumber; + } + + public List getTransactions() { + return transactions; + } + + public Branch getDEFAULT_BRANCH() { + return DEFAULT_BRANCH; + } + + public void setNewBranch(Branch DEFAULT_BRANCH) { + this.DEFAULT_BRANCH = DEFAULT_BRANCH; + } + + public String formatDate() { + LocalDateTime date = LocalDateTime.now(); + DateTimeFormatter formattedDate = DateTimeFormatter.ofPattern("dd-MM-yyy HH:mm:ss"); + String formatted = date.format(formattedDate); + + return formatted; + } + + void deposit(double amount) { + if (amount <= 0) { + return; + } + + balance += amount; + + String formatted = formatDate(); + Transactions newTrans = new Transactions(formatted, amount, 0.0, balance); + transactions.add(newTrans); + } + + void withdraw(double amount) { + if (amount > balance || balance == 0) { + return; + } + + balance -= amount; + + String formatted = formatDate(); + Transactions newTrans = new Transactions(formatted, 0.0, amount, balance); + transactions.add(newTrans); + } + + String generateStatement() { + StringBuilder statement = new StringBuilder(); + statement.append("date || credit || debit || balance\n"); + + for (Transactions t : transactions) { + + String date = t.getDateTime(); + String credit = t.getCreditAmount() > 0 ? String.format("%.2f", t.getCreditAmount()) : " "; + String debit = t.getDebitAmount() > 0 ? String.format("%.2f", t.getDebitAmount()) : " "; + String balanceStr = String.format("%.2f", t.getAmount()); + + statement.append(String.format("%s || %s || %s || %s\n", date, credit, debit, balanceStr)); + } + + return statement.toString(); + } + + public double getBalanceExt() { + double balance = 0.0; + + for (int i = 0; i < transactions.size(); i++) { + if(transactions.get(i).getCreditAmount() > 0.0) { + balance += transactions.get(i).getCreditAmount(); + } + + if (transactions.get(i).getDebitAmount() > 0.0) { + balance -= transactions.get(i).getDebitAmount(); + } + } + + return balance; + } + + public void withdrawWithOverdraft(double amount) { + balance -= amount; + } +} diff --git a/src/main/java/com/booleanuk/core/Branch.java b/src/main/java/com/booleanuk/core/Branch.java new file mode 100644 index 000000000..2fb2d24b2 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Branch.java @@ -0,0 +1,8 @@ +package com.booleanuk.core; + +enum Branch { + OSLO, + BERGEN, + TRONDHEIM, + STAVANGER +} 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..4792cce96 --- /dev/null +++ b/src/main/java/com/booleanuk/core/CurrentAccount.java @@ -0,0 +1,13 @@ +package com.booleanuk.core; + +public class CurrentAccount extends BankAccount { + + public Overdraft requestOverdraft(double amount) { + if (amount < balance) { + withdraw(amount); + } + + Overdraft overdraft = new Overdraft(this, amount, this.balance); + return overdraft; + } +} diff --git a/src/main/java/com/booleanuk/core/Overdraft.java b/src/main/java/com/booleanuk/core/Overdraft.java new file mode 100644 index 000000000..7a26a50b5 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Overdraft.java @@ -0,0 +1,34 @@ +package com.booleanuk.core; + +public class Overdraft { + private double amountRequested; + private double balance; + private boolean approved = false; + private CurrentAccount currentAccount; + private double MAX_OVERDRAFT = -500; + + public Overdraft(CurrentAccount currentAccount, double amount, double balance) { + this.currentAccount = currentAccount; + this.amountRequested = amount; + this.balance = balance; + } + + public boolean approvedOrDenied(Overdraft overdraft) { + if ((overdraft.balance - overdraft.amountRequested) < MAX_OVERDRAFT ) { + approved = false; + } + else { + currentAccount.withdrawWithOverdraft(overdraft.amountRequested); + approved = true; + } + return approved; + } + + public double getMAX_OVERDRAFT() { + return MAX_OVERDRAFT; + } + + public void setMAX_OVERDRAFT(double MAX_OVERDRAFT) { + this.MAX_OVERDRAFT = MAX_OVERDRAFT; + } +} 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..7c2cf868d --- /dev/null +++ b/src/main/java/com/booleanuk/core/SavingsAccount.java @@ -0,0 +1,3 @@ +package com.booleanuk.core; + +public class SavingsAccount extends BankAccount { } diff --git a/src/main/java/com/booleanuk/core/Transactions.java b/src/main/java/com/booleanuk/core/Transactions.java new file mode 100644 index 000000000..d1eefd218 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Transactions.java @@ -0,0 +1,31 @@ +package com.booleanuk.core; + +public class Transactions { + private String dateTime; + private double creditAmount; + private double debitAmount; + private double amount; + + public Transactions(String dateTime, double creditAmount, double debitAmount, double amount) { + this.dateTime = dateTime; + this.creditAmount = creditAmount; + this.debitAmount = debitAmount; + this.amount = amount; + } + + public String getDateTime() { + return dateTime; + } + + public double getAmount() { + return amount; + } + + public double getDebitAmount() { + return debitAmount; + } + + public double getCreditAmount() { + return creditAmount; + } +} diff --git a/src/test/java/com/booleanuk/core/BankAccountTest.java b/src/test/java/com/booleanuk/core/BankAccountTest.java new file mode 100644 index 000000000..a0929ebfd --- /dev/null +++ b/src/test/java/com/booleanuk/core/BankAccountTest.java @@ -0,0 +1,92 @@ +package com.booleanuk.core; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class BankAccountTest { + @Test + public void testDepositToAccount() { + BankAccount bankAccount = new CurrentAccount(); + bankAccount.deposit(100); + + Assertions.assertEquals(100, bankAccount.getBalance()); + + bankAccount.deposit(1234); + Assertions.assertEquals(1334, bankAccount.getBalance()); + + BankAccount bankAccount1 = new SavingsAccount(); + bankAccount1.deposit(250); + + Assertions.assertEquals(250, bankAccount1.getBalance()); + } + + @Test + public void testWithdrawFromAccount() { + BankAccount bankAccount = new CurrentAccount(); + bankAccount.withdraw(100); + + bankAccount.deposit(10000); + bankAccount.withdraw(2000); + + Assertions.assertEquals(8000, bankAccount.getBalance()); + + Assertions.assertEquals(8000, bankAccount.getBalance()); + } + + @Test + public void testGetTransaction() { + BankAccount bankAccount = new CurrentAccount(); + bankAccount.deposit(1000); + bankAccount.deposit(300); + bankAccount.withdraw(500); + + String transStat = bankAccount.generateStatement(); + boolean test = transStat.isEmpty(); + + Assertions.assertEquals(false, transStat.isEmpty()); + } + + @Test + public void testExtensionBalanceMethod() { + BankAccount bankAccount = new CurrentAccount(); + bankAccount.deposit(1000); + bankAccount.deposit(5000); + bankAccount.withdraw(200); + + Assertions.assertEquals(5800.0, bankAccount.getBalanceExt()); + + //System.out.println(bankAccount.generateStatement()); + } + + @Test + public void testExtensionGetAndSetBranch() { + BankAccount bankAccount = new CurrentAccount(); + BankAccount bankAccount1 = new SavingsAccount(); + + Branch newBranch = Branch.BERGEN; + + Assertions.assertEquals(Branch.OSLO, bankAccount.getDEFAULT_BRANCH()); + Assertions.assertEquals(Branch.OSLO, bankAccount1.getDEFAULT_BRANCH()); + + bankAccount1.setNewBranch(newBranch); + + Assertions.assertEquals(newBranch, bankAccount1.getDEFAULT_BRANCH()); + } + + @Test + public void testExtensionApprovalOfOverdraft() { + CurrentAccount bankAccount = new CurrentAccount(); + bankAccount.deposit(100); + Overdraft overdraft = bankAccount.requestOverdraft(150); + boolean approve = overdraft.approvedOrDenied(overdraft); + + //System.out.println(bankAccount.getBalance()); + + Assertions.assertEquals(true, approve); + + Overdraft overdraft1 = bankAccount.requestOverdraft(1000); + boolean deny = overdraft1.approvedOrDenied(overdraft1); + + Assertions.assertEquals(false, deny); + } +}