From ebd335e8d9411c6a3ce4fc4b4e160528dca69b10 Mon Sep 17 00:00:00 2001 From: hannaklh Date: Wed, 20 Aug 2025 10:04:02 +0200 Subject: [PATCH 1/7] red stage --- src/COREEXERCISE.md | 50 +++++++++++++ src/main/java/com/booleanuk/core/Account.java | 67 +++++++++++++++++ .../com/booleanuk/core/CurrentAccount.java | 15 ++++ .../java/com/booleanuk/core/Customer.java | 36 ++++++++++ .../com/booleanuk/core/SavingsAccount.java | 16 +++++ .../java/com/booleanuk/core/Transaction.java | 71 +++++++++++++++++++ src/main/java/com/booleanuk/core/main.java | 7 ++ .../java/com/booleanuk/core/AccountTest.java | 57 +++++++++++++++ 8 files changed, 319 insertions(+) create mode 100644 src/COREEXERCISE.md create mode 100644 src/main/java/com/booleanuk/core/Account.java create mode 100644 src/main/java/com/booleanuk/core/CurrentAccount.java create mode 100644 src/main/java/com/booleanuk/core/Customer.java create mode 100644 src/main/java/com/booleanuk/core/SavingsAccount.java create mode 100644 src/main/java/com/booleanuk/core/Transaction.java create mode 100644 src/main/java/com/booleanuk/core/main.java create mode 100644 src/test/java/com/booleanuk/core/AccountTest.java diff --git a/src/COREEXERCISE.md b/src/COREEXERCISE.md new file mode 100644 index 000000000..c12c119e5 --- /dev/null +++ b/src/COREEXERCISE.md @@ -0,0 +1,50 @@ +# Bank exercise + +### Core excercise + +**User Stories** + +``` +As a customer, +So I can safely store and use my money, +I want to create a current account. + +As a customer, +So I can save for a rainy day, +I want to create a savings account. + +As a customer, +So I can keep a record of my finances, +I want to generate bank statements with transaction dates, amounts, and balance at the time of transaction. + +As a customer, +So I can use my account, +I want to deposit and withdraw funds. +``` +**Domain Models** + +| Classes | Members | Methods | Scenario | Outputs | +|------------|-------------------|-------------------|----------|---------| +| `Customer` | `properties` | `getters/setters` | | | +| | `Account account` | `createAccount` | | | + +| Classes | Members | Methods | Scenario | Outputs | +|-----------|-----------------------------------|---------------------------|-------------------------------|---------| +| `Account` | `List transactions` | `generateBankStatement()` | If there are any transactions | String | +| | | | If there are no transactions | String | + +| Classes | Members | Methods | Scenario | Outputs | +|-----------|---------------------|-------------|------------------------------|---------| +| `Account` | `BigDecimal amount` | `deposit()` | If amount is a valid int | String | +| | | | If amount is not a valid int | String | + +| Classes | Members | Methods | Scenario | Outputs | +|-----------|---------------------|--------------|-----------------------------------|---------| +| `Account` | `BigDecimal amount` | `withdraw()` | If amount is a valid int | String | +| | | | If amount is a valid int | String | +| | | | If amount is greater than balance | String | + + +| Classes | Members | Methods | Scenario | Outputs | +|---------------|--------------|--------------------|----------|---------| +| `Transaction` | `properties` | `getters/setters` | | | 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..4d2247232 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Account.java @@ -0,0 +1,67 @@ +package com.booleanuk.core; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +public abstract class Account { + private Customer customer; + private int id; + private List transactions; + private BigDecimal balance = new BigDecimal(0); + + public Account(Customer customer, int id) { + this.customer = customer; + this.id = id; + this.transactions = new ArrayList<>(); + } + public Account(Customer customer, int id, BigDecimal balance) { + this.customer = customer; + this.id = id; + this.balance = balance; + this.transactions = new ArrayList<>(); + } + public Account () {} + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(Customer customer) { + this.customer = customer; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public List getTransactions() { + return transactions; + } + + public void setTransactions(List transactions) { + this.transactions = transactions; + } + + public BigDecimal getBalance() { + return balance; + } + + public void setBalance(BigDecimal balance) { + this.balance = balance; + } + + public String deposit(BigDecimal amount){ + return ""; + } + public String withdraw(BigDecimal amount){ + return ""; + } + public String generateBankStatements() { + return ""; + } +} 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..1bdd8f6dd --- /dev/null +++ b/src/main/java/com/booleanuk/core/CurrentAccount.java @@ -0,0 +1,15 @@ +package com.booleanuk.core; + +import java.math.BigDecimal; + +public class CurrentAccount extends Account{ + public CurrentAccount(Customer customer, int id) { + super(customer, id); + } + + public CurrentAccount(Customer customer, int id, BigDecimal balance) { + super(customer, id, balance); + } + public CurrentAccount() { + } +} 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..0090bc06b --- /dev/null +++ b/src/main/java/com/booleanuk/core/Customer.java @@ -0,0 +1,36 @@ +package com.booleanuk.core; + +import java.util.ArrayList; +import java.util.List; + +public class Customer { + private String name; + private int id; + private List accounts; + + public Customer(String name, int id) { + this.name = name; + this.id = id; + this.accounts = new ArrayList<>(); + } + + public Customer() {} + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public String createAccount( Account account) { + return ""; + } +} 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..c44022a40 --- /dev/null +++ b/src/main/java/com/booleanuk/core/SavingsAccount.java @@ -0,0 +1,16 @@ +package com.booleanuk.core; + +import java.math.BigDecimal; + +public class SavingsAccount extends Account{ + public SavingsAccount(Customer customer, int id) { + super(customer, id); + } + + public SavingsAccount(Customer customer, int id, BigDecimal balance) { + super(customer, id, balance); + } + + public SavingsAccount() { + } +} 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..b9e26bce4 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Transaction.java @@ -0,0 +1,71 @@ +package com.booleanuk.core; + +import java.math.BigDecimal; +import java.time.LocalDate; + +public class Transaction { + private int id; + private LocalDate date; + private BigDecimal amount; + private String type; + private BigDecimal balance; + private Account account; + + public Transaction(int id, LocalDate date, BigDecimal amount, String type, BigDecimal balance, Account account) { + this.id = id; + this.date = date; + this.amount = amount; + this.type = type; + this.balance = balance; + this.account = account; + } + public Transaction() {} + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public LocalDateTime getDate() { + return date; + } + + public void setDate(LocalDate date) { + this.date = date; + } + + public BigDecimal getAmount() { + return amount; + } + + public void setAmount(BigDecimal amount) { + this.amount = amount; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public BigDecimal getBalance() { + return balance; + } + + public void setBalance(BigDecimal balance) { + this.balance = balance; + } + + public Account getAccount() { + return account; + } + + public void setAccount(Account account) { + this.account = account; + } +} diff --git a/src/main/java/com/booleanuk/core/main.java b/src/main/java/com/booleanuk/core/main.java new file mode 100644 index 000000000..2517d5f0e --- /dev/null +++ b/src/main/java/com/booleanuk/core/main.java @@ -0,0 +1,7 @@ +package com.booleanuk.core; + +public class main { + public static void main(String[] args) { + System.out.println("date\t||\tcredit\t||\tdebit\t||\t balance\n14/01/12\t||\t100\t1100"); + } +} 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..cd394fa27 --- /dev/null +++ b/src/test/java/com/booleanuk/core/AccountTest.java @@ -0,0 +1,57 @@ +package com.booleanuk.core; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; + +public class AccountTest { + @Test + public void shouldCreateAccount() { + Customer customer = new Customer("Hanna Håkansson", 1); + Account savings = new SavingsAccount(customer, 1); + Account current = new CurrentAccount(customer, 2); + Assertions.assertEquals("Account " + savings.getId()+ " was added to " + customer.getName(), customer.createAccount(savings)); + Assertions.assertEquals("Account " + current.getId()+ " was added to " + customer.getName(), customer.createAccount(current)); + + } + + @Test + public void shouldDeposit() { + Customer customer = new Customer("Hanna Håkansson", 1); + Account savings = new SavingsAccount(customer, 1); + + BigDecimal amount = new BigDecimal(123); + Assertions.assertEquals(amount +" was deposited to your account" , savings.deposit(amount)); + } + @Test + public void shouldWithdraw() { + Customer customer = new Customer("Hanna Håkansson", 1); + Account savings = new SavingsAccount(customer, 1, new BigDecimal(1000)); + BigDecimal amount = new BigDecimal(100); + + + Assertions.assertEquals(amount +" was withdrawn from your account" , savings.withdraw(amount)); + } + @Test + public void shouldNotWithdraw() { + Customer customer = new Customer("Hanna Håkansson", 1); + Account savings = new SavingsAccount(customer, 1, new BigDecimal(1000)); + + BigDecimal amount = new BigDecimal(100); + + Assertions.assertEquals("There is not enough balance in your account. Balance: "+savings.getBalance() , savings.withdraw(amount)); + } + @Test + public void shouldGenerateBankStatements() { + Customer customer = new Customer("Hanna Håkansson", 1); + Account savings = new SavingsAccount(customer, 1, new BigDecimal(1000)); + + BigDecimal amount = new BigDecimal(100); + savings.deposit(amount); + savings.withdraw(amount); + + Assertions.assertEquals("date\t||\tcredit\t||\tdebit\t||\t balance\n14/01/12\t||\t100\t1100", savings.generateBankStatements()); + } + +} From ba0edfbb7148c4611076eb602b1faf37487f67b9 Mon Sep 17 00:00:00 2001 From: hannaklh Date: Wed, 20 Aug 2025 10:11:09 +0200 Subject: [PATCH 2/7] red stage --- src/Diagram.png | Bin 0 -> 42341 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/Diagram.png diff --git a/src/Diagram.png b/src/Diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..6897e18ae838ce616e42471e2bea447802a7c907 GIT binary patch literal 42341 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 Xaju3(#4i8VQ8tK<(XXX Date: Wed, 20 Aug 2025 11:06:12 +0200 Subject: [PATCH 3/7] core exercise: green stage --- src/main/java/com/booleanuk/core/Account.java | 46 +++++++++++++++---- .../com/booleanuk/core/CurrentAccount.java | 2 +- .../java/com/booleanuk/core/Customer.java | 3 +- .../com/booleanuk/core/SavingsAccount.java | 2 +- .../java/com/booleanuk/core/Transaction.java | 23 +++++----- src/main/java/com/booleanuk/core/main.java | 2 +- .../java/com/booleanuk/core/AccountTest.java | 23 +++++----- 7 files changed, 65 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Account.java b/src/main/java/com/booleanuk/core/Account.java index 4d2247232..baffcc178 100644 --- a/src/main/java/com/booleanuk/core/Account.java +++ b/src/main/java/com/booleanuk/core/Account.java @@ -1,6 +1,7 @@ package com.booleanuk.core; import java.math.BigDecimal; +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; @@ -8,14 +9,15 @@ public abstract class Account { private Customer customer; private int id; private List transactions; - private BigDecimal balance = new BigDecimal(0); + private double balance = 0; + private int transactionCount = 1; public Account(Customer customer, int id) { this.customer = customer; this.id = id; this.transactions = new ArrayList<>(); } - public Account(Customer customer, int id, BigDecimal balance) { + public Account(Customer customer, int id, double balance) { this.customer = customer; this.id = id; this.balance = balance; @@ -47,21 +49,47 @@ public void setTransactions(List transactions) { this.transactions = transactions; } - public BigDecimal getBalance() { + public double getBalance() { return balance; } - public void setBalance(BigDecimal balance) { + public void setBalance(double balance) { this.balance = balance; } - public String deposit(BigDecimal amount){ - return ""; + public String deposit(double transAmount){ + Transaction trans = new Transaction(this.transactionCount, LocalDate.now(), transAmount, "debit", this); + + this.balance +=transAmount; + trans.setBalance(this.balance); + this.transactionCount++; + this.transactions.add(trans); + return transAmount + " has been deposited to your account " + this.id; } - public String withdraw(BigDecimal amount){ - return ""; + public String withdraw(double transAmount){ + if (this.balance>transAmount) { + Transaction trans = new Transaction(this.transactionCount, LocalDate.now(), transAmount, "credit",this); + + this.balance -=transAmount; + trans.setBalance(this.balance); + this.transactionCount++; + this.transactions.add(trans); + return transAmount + " has been withdrawn from your account " + this.id; + } else + return "There are not enough funds on your account. Current balance: " +this.balance; } public String generateBankStatements() { - return ""; + + String returnString = "date\t\t||\tcredit\t||\tdebit\t||\tbalance\n"; + + for (Transaction trans : transactions) { + if (trans.getType().equals("credit")) { + returnString += trans.getDate().toString() + "\t||\t" + trans.getTransAmount()+"\t\t||\t\t||\t"+trans.getBalance()+"\n"; + } else + returnString += trans.getDate().toString() + "\t||\t\t\t||\t" + trans.getTransAmount()+"\t||\t"+trans.getBalance()+"\n"; + + + } + return returnString; } } diff --git a/src/main/java/com/booleanuk/core/CurrentAccount.java b/src/main/java/com/booleanuk/core/CurrentAccount.java index 1bdd8f6dd..ca9f90a1d 100644 --- a/src/main/java/com/booleanuk/core/CurrentAccount.java +++ b/src/main/java/com/booleanuk/core/CurrentAccount.java @@ -7,7 +7,7 @@ public CurrentAccount(Customer customer, int id) { super(customer, id); } - public CurrentAccount(Customer customer, int id, BigDecimal balance) { + public CurrentAccount(Customer customer, int id, double balance) { super(customer, id, balance); } public CurrentAccount() { diff --git a/src/main/java/com/booleanuk/core/Customer.java b/src/main/java/com/booleanuk/core/Customer.java index 0090bc06b..6b1835b20 100644 --- a/src/main/java/com/booleanuk/core/Customer.java +++ b/src/main/java/com/booleanuk/core/Customer.java @@ -31,6 +31,7 @@ public void setName(String name) { this.name = name; } public String createAccount( Account account) { - return ""; + this.accounts.add(account); + return "Account "+account.getId()+" was added to " +this.name; } } diff --git a/src/main/java/com/booleanuk/core/SavingsAccount.java b/src/main/java/com/booleanuk/core/SavingsAccount.java index c44022a40..cdca77b87 100644 --- a/src/main/java/com/booleanuk/core/SavingsAccount.java +++ b/src/main/java/com/booleanuk/core/SavingsAccount.java @@ -7,7 +7,7 @@ public SavingsAccount(Customer customer, int id) { super(customer, id); } - public SavingsAccount(Customer customer, int id, BigDecimal balance) { + public SavingsAccount(Customer customer, int id, double balance) { super(customer, id, balance); } diff --git a/src/main/java/com/booleanuk/core/Transaction.java b/src/main/java/com/booleanuk/core/Transaction.java index b9e26bce4..b4f27adad 100644 --- a/src/main/java/com/booleanuk/core/Transaction.java +++ b/src/main/java/com/booleanuk/core/Transaction.java @@ -6,17 +6,16 @@ public class Transaction { private int id; private LocalDate date; - private BigDecimal amount; + private double transAmount; private String type; - private BigDecimal balance; + private double balance; private Account account; - public Transaction(int id, LocalDate date, BigDecimal amount, String type, BigDecimal balance, Account account) { + public Transaction(int id, LocalDate date, double transAmount, String type, Account account) { this.id = id; this.date = date; - this.amount = amount; + this.transAmount = transAmount; this.type = type; - this.balance = balance; this.account = account; } public Transaction() {} @@ -29,7 +28,7 @@ public void setId(int id) { this.id = id; } - public LocalDateTime getDate() { + public LocalDate getDate() { return date; } @@ -37,12 +36,12 @@ public void setDate(LocalDate date) { this.date = date; } - public BigDecimal getAmount() { - return amount; + public double getTransAmount() { + return transAmount; } - public void setAmount(BigDecimal amount) { - this.amount = amount; + public void setTransAmount(double transAmount) { + this.transAmount = transAmount; } public String getType() { @@ -53,11 +52,11 @@ public void setType(String type) { this.type = type; } - public BigDecimal getBalance() { + public double getBalance() { return balance; } - public void setBalance(BigDecimal balance) { + public void setBalance(double balance) { this.balance = balance; } diff --git a/src/main/java/com/booleanuk/core/main.java b/src/main/java/com/booleanuk/core/main.java index 2517d5f0e..b534533ff 100644 --- a/src/main/java/com/booleanuk/core/main.java +++ b/src/main/java/com/booleanuk/core/main.java @@ -2,6 +2,6 @@ public class main { public static void main(String[] args) { - System.out.println("date\t||\tcredit\t||\tdebit\t||\t balance\n14/01/12\t||\t100\t1100"); + System.out.println("date\t\t||\tcredit\t||\tdebit\t||\tbalance\n14/01/12\t||\t100\t\t||\t\t\t||\t1100"); } } diff --git a/src/test/java/com/booleanuk/core/AccountTest.java b/src/test/java/com/booleanuk/core/AccountTest.java index cd394fa27..277e40412 100644 --- a/src/test/java/com/booleanuk/core/AccountTest.java +++ b/src/test/java/com/booleanuk/core/AccountTest.java @@ -21,37 +21,38 @@ public void shouldDeposit() { Customer customer = new Customer("Hanna Håkansson", 1); Account savings = new SavingsAccount(customer, 1); - BigDecimal amount = new BigDecimal(123); - Assertions.assertEquals(amount +" was deposited to your account" , savings.deposit(amount)); + double amount = 100; + Assertions.assertEquals(amount +" has been deposited to your account " + savings.getId() , savings.deposit(amount)); } @Test public void shouldWithdraw() { Customer customer = new Customer("Hanna Håkansson", 1); - Account savings = new SavingsAccount(customer, 1, new BigDecimal(1000)); - BigDecimal amount = new BigDecimal(100); + Account savings = new SavingsAccount(customer, 1, 1000); + double amount = 100; - Assertions.assertEquals(amount +" was withdrawn from your account" , savings.withdraw(amount)); + Assertions.assertEquals(amount +" has been withdrawn from your account "+ savings.getId() , savings.withdraw(amount)); } @Test public void shouldNotWithdraw() { Customer customer = new Customer("Hanna Håkansson", 1); - Account savings = new SavingsAccount(customer, 1, new BigDecimal(1000)); + Account savings = new SavingsAccount(customer, 1, 1000); - BigDecimal amount = new BigDecimal(100); + double amount = 11000; - Assertions.assertEquals("There is not enough balance in your account. Balance: "+savings.getBalance() , savings.withdraw(amount)); + Assertions.assertEquals("There are not enough funds on your account. Current balance: "+savings.getBalance() , savings.withdraw(amount)); } @Test public void shouldGenerateBankStatements() { Customer customer = new Customer("Hanna Håkansson", 1); - Account savings = new SavingsAccount(customer, 1, new BigDecimal(1000)); + Account savings = new SavingsAccount(customer, 1, 1000); - BigDecimal amount = new BigDecimal(100); + double amount = 100.0; savings.deposit(amount); savings.withdraw(amount); + String string = "date\t\t||\tcredit\t||\tdebit\t||\tbalance\n2025-08-20\t||\t\t\t||\t100.0\t||\t1100.0\n2025-08-20\t||\t100.0\t\t||\t\t||\t1000.0\n"; - Assertions.assertEquals("date\t||\tcredit\t||\tdebit\t||\t balance\n14/01/12\t||\t100\t1100", savings.generateBankStatements()); + Assertions.assertEquals(string, savings.generateBankStatements()); } } From 67a23de6ee4bf3c988f9d533b0d4acdde821ded9 Mon Sep 17 00:00:00 2001 From: hannaklh Date: Wed, 20 Aug 2025 12:01:23 +0200 Subject: [PATCH 4/7] extension exercise: red stage --- src/EXTENSION.md | 86 +++++++++++++++++++ src/main/java/com/booleanuk/core/Account.java | 31 ++++--- src/main/java/com/booleanuk/core/Branch.java | 41 +++++++++ .../com/booleanuk/core/CurrentAccount.java | 4 +- .../java/com/booleanuk/core/Customer.java | 25 ++---- src/main/java/com/booleanuk/core/Manager.java | 16 ++++ .../com/booleanuk/core/SavingsAccount.java | 4 +- src/main/java/com/booleanuk/core/User.java | 31 +++++++ .../java/com/booleanuk/core/AccountTest.java | 49 +++++++++-- 9 files changed, 241 insertions(+), 46 deletions(-) create mode 100644 src/EXTENSION.md create mode 100644 src/main/java/com/booleanuk/core/Branch.java create mode 100644 src/main/java/com/booleanuk/core/Manager.java create mode 100644 src/main/java/com/booleanuk/core/User.java diff --git a/src/EXTENSION.md b/src/EXTENSION.md new file mode 100644 index 000000000..18fc682b7 --- /dev/null +++ b/src/EXTENSION.md @@ -0,0 +1,86 @@ +# Bank exercise + +### Core excercise + +**User Stories** + +``` +As a customer, +So I can safely store and use my money, +I want to create a current account. + +As a customer, +So I can save for a rainy day, +I want to create a savings account. + +As a customer, +So I can keep a record of my finances, +I want to generate bank statements with transaction dates, amounts, and balance at the time of transaction. + +As a customer, +So I can use my account, +I want to deposit and withdraw funds. + +As an engineer, +So I don't need to keep track of state, +I want account balances to be calculated based on transaction history instead of stored in memory. + +As a bank manager, +So I can expand, +I want accounts to be associated with specific branches. + +As a customer, +So I have an emergency fund, +I want to be able to request an overdraft on my account. + +As a bank manager, +So I can safeguard our funds, +I want to approve or reject overdraft requests. + +As a customer, +So I can stay up to date, +I want statements to be sent as messages to my phone. +``` +**Domain Models** + +| Classes | Members | Methods | Scenario | Outputs | +|------------|-------------------|----------------------|-------------------|---------| +| `Customer` | `properties` | `getters/setters` | | | +| | `Account account` | `createAccount` | | | +| | `Account account` | `requestOverdraft()` | if it is accepted | true | +| | | | if it is rejected | | + + +| Classes | Members | Methods | Scenario | Outputs | +|-----------|--------------------------------------|-----------------------|-------------------|---------| +| `Manager` | `properties` | `getters/setters` | | | +| | `Customer customer, Account account` | `decideOnOverdraft()` | if it is accepted | true | +| | | | if it is rejected | false | + +| Classes | Members | Methods | Scenario | Outputs | +|-----------|-----------------------------------|---------------------------|------------------------------|---------| +| `Account` | `List transactions` | `generateBankStatement()` | If there are any transactions | String | +| | | | If there are no transactions | String | +| | `double amount` | `deposit()` | If amount is a valid int | String | +| | | | If amount is not a valid int | String | +| | `List ` | `calculateBalance()` | if there are no transactions | String | +| | | | if there are transactions | String | + + +| Classes | Members | Methods | Scenario | Outputs | +|-----------|-----------------|--------------|--------------------------------------------------------------------|---------| +| `Account` | `double amount` | `withdraw()` | If amount is a valid int | String | +| | | | If amount is a valid int | String | +| | | | If amount is greater than balance and overdraft has been accepted | String | +| | | | if account is greater than balance and overdraft has been rejected | String | + + +| Classes | Members | Methods | Scenario | Outputs | +|---------------|--------------|--------------------|----------|---------| +| `Transaction` | `properties` | `getters/setters` | | | + + +| Classes | Members | Methods | Scenario | Outputs | +|----------|-------------------|-------------------|----------|---------| +| `Branch` | `properties` | `getters/setters` | | | + diff --git a/src/main/java/com/booleanuk/core/Account.java b/src/main/java/com/booleanuk/core/Account.java index baffcc178..66250a188 100644 --- a/src/main/java/com/booleanuk/core/Account.java +++ b/src/main/java/com/booleanuk/core/Account.java @@ -9,18 +9,19 @@ public abstract class Account { private Customer customer; private int id; private List transactions; - private double balance = 0; private int transactionCount = 1; + private boolean canBeOverdrafted = false; + private Branch branch; public Account(Customer customer, int id) { this.customer = customer; this.id = id; this.transactions = new ArrayList<>(); } - public Account(Customer customer, int id, double balance) { + public Account(Customer customer, int id, Branch branch) { this.customer = customer; this.id = id; - this.balance = balance; + this.branch = branch; this.transactions = new ArrayList<>(); } public Account () {} @@ -49,25 +50,17 @@ public void setTransactions(List transactions) { this.transactions = transactions; } - public double getBalance() { - return balance; - } - - public void setBalance(double balance) { - this.balance = balance; - } - public String deposit(double transAmount){ Transaction trans = new Transaction(this.transactionCount, LocalDate.now(), transAmount, "debit", this); - +/* this.balance +=transAmount; trans.setBalance(this.balance); this.transactionCount++; - this.transactions.add(trans); + this.transactions.add(trans);*/ return transAmount + " has been deposited to your account " + this.id; } public String withdraw(double transAmount){ - if (this.balance>transAmount) { + /*if (this.balance>transAmount) { Transaction trans = new Transaction(this.transactionCount, LocalDate.now(), transAmount, "credit",this); this.balance -=transAmount; @@ -75,8 +68,8 @@ public String withdraw(double transAmount){ this.transactionCount++; this.transactions.add(trans); return transAmount + " has been withdrawn from your account " + this.id; - } else - return "There are not enough funds on your account. Current balance: " +this.balance; + } else*/ + return "There are not enough funds on your account. Current balance: " +this; } public String generateBankStatements() { @@ -92,4 +85,10 @@ public String generateBankStatements() { } return returnString; } + public boolean requestOverdraft() { + return false; + } + public double calculateBalance() { + return 0; + } } 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..90ff44c51 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Branch.java @@ -0,0 +1,41 @@ +package com.booleanuk.core; + +import java.util.ArrayList; +import java.util.List; + +public class Branch { + private String name; + private Manager manager; + private List accounts; + + public Branch(String name, Manager manager) { + this.name = name; + this.manager = manager; + this.accounts = new ArrayList<>(); + } + public Branch() {} + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Manager getManager() { + return manager; + } + + public void setManager(Manager manager) { + this.manager = manager; + } + + public List getAccounts() { + return accounts; + } + + public void setAccounts(List accounts) { + this.accounts = accounts; + } +} diff --git a/src/main/java/com/booleanuk/core/CurrentAccount.java b/src/main/java/com/booleanuk/core/CurrentAccount.java index ca9f90a1d..08be9d57f 100644 --- a/src/main/java/com/booleanuk/core/CurrentAccount.java +++ b/src/main/java/com/booleanuk/core/CurrentAccount.java @@ -7,8 +7,8 @@ public CurrentAccount(Customer customer, int id) { super(customer, id); } - public CurrentAccount(Customer customer, int id, double balance) { - super(customer, id, balance); + public CurrentAccount(Customer customer, int id, Branch branch) { + super(customer, id, branch); } public CurrentAccount() { } diff --git a/src/main/java/com/booleanuk/core/Customer.java b/src/main/java/com/booleanuk/core/Customer.java index 6b1835b20..8558ae2f1 100644 --- a/src/main/java/com/booleanuk/core/Customer.java +++ b/src/main/java/com/booleanuk/core/Customer.java @@ -3,35 +3,20 @@ import java.util.ArrayList; import java.util.List; -public class Customer { - private String name; - private int id; +public class Customer extends User { + private List accounts; public Customer(String name, int id) { - this.name = name; - this.id = id; + super(name, id); this.accounts = new ArrayList<>(); } public Customer() {} - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } public String createAccount( Account account) { this.accounts.add(account); - return "Account "+account.getId()+" was added to " +this.name; + return "Account "+account.getId()+" was added to " + super.getName(); } + } 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..11f8504bc --- /dev/null +++ b/src/main/java/com/booleanuk/core/Manager.java @@ -0,0 +1,16 @@ +package com.booleanuk.core; + +public class Manager extends User { + private Branch branch; + + public Manager(String name, int id, Branch branch) { + super(name, id); + this.branch = branch; + } + + public Manager() { + } + public boolean decideOnOverdraft(Customer c, Account a) { + return false; + } +} diff --git a/src/main/java/com/booleanuk/core/SavingsAccount.java b/src/main/java/com/booleanuk/core/SavingsAccount.java index cdca77b87..4a0111dc4 100644 --- a/src/main/java/com/booleanuk/core/SavingsAccount.java +++ b/src/main/java/com/booleanuk/core/SavingsAccount.java @@ -7,8 +7,8 @@ public SavingsAccount(Customer customer, int id) { super(customer, id); } - public SavingsAccount(Customer customer, int id, double balance) { - super(customer, id, balance); + public SavingsAccount(Customer customer, int id,Branch branch) { + super(customer, id, branch); } public SavingsAccount() { diff --git a/src/main/java/com/booleanuk/core/User.java b/src/main/java/com/booleanuk/core/User.java new file mode 100644 index 000000000..2aef75242 --- /dev/null +++ b/src/main/java/com/booleanuk/core/User.java @@ -0,0 +1,31 @@ +package com.booleanuk.core; + +import java.util.ArrayList; +import java.util.List; + +public abstract class User { + private String name; + private int id; + + public User(String name, int id) { + this.name = name; + this.id = id; + } + + public User() {} + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/test/java/com/booleanuk/core/AccountTest.java b/src/test/java/com/booleanuk/core/AccountTest.java index 277e40412..4b29071c4 100644 --- a/src/test/java/com/booleanuk/core/AccountTest.java +++ b/src/test/java/com/booleanuk/core/AccountTest.java @@ -27,32 +27,69 @@ public void shouldDeposit() { @Test public void shouldWithdraw() { Customer customer = new Customer("Hanna Håkansson", 1); - Account savings = new SavingsAccount(customer, 1, 1000); - double amount = 100; + Branch branch = new Branch(); + Manager manager = new Manager("Giovanni Capilletti", 1, branch); + Account savings = new SavingsAccount(customer, 1, branch); + + branch.setManager(manager); + branch.setName("Scranton"); + double amount = 1000; Assertions.assertEquals(amount +" has been withdrawn from your account "+ savings.getId() , savings.withdraw(amount)); + + savings.deposit(1000); + savings.deposit(7000); + savings.deposit(12); + boolean overdraft = savings.requestOverdraft(); + + Assertions.assertEquals(amount +" has been withdrawn from your account "+ savings.getId() , savings.withdraw(1300000)); + + } @Test public void shouldNotWithdraw() { Customer customer = new Customer("Hanna Håkansson", 1); - Account savings = new SavingsAccount(customer, 1, 1000); + Branch branch = new Branch(); + Manager manager = new Manager("Giovanni Capilletti", 1, branch); + Account savings = new SavingsAccount(customer, 1, branch); + + + branch.setManager(manager); + branch.setName("Scranton"); double amount = 11000; - Assertions.assertEquals("There are not enough funds on your account. Current balance: "+savings.getBalance() , savings.withdraw(amount)); + Assertions.assertEquals("There are not enough funds on your account. Current balance: "+savings.calculateBalance() , savings.withdraw(amount)); } @Test public void shouldGenerateBankStatements() { Customer customer = new Customer("Hanna Håkansson", 1); - Account savings = new SavingsAccount(customer, 1, 1000); + Branch branch = new Branch(); + Manager manager = new Manager("Giovanni Capilletti", 1, branch); + Account savings = new SavingsAccount(customer, 1, branch); - double amount = 100.0; + double amount = 1000; savings.deposit(amount); savings.withdraw(amount); String string = "date\t\t||\tcredit\t||\tdebit\t||\tbalance\n2025-08-20\t||\t\t\t||\t100.0\t||\t1100.0\n2025-08-20\t||\t100.0\t\t||\t\t||\t1000.0\n"; Assertions.assertEquals(string, savings.generateBankStatements()); } + @Test + public void shouldCalculateBalance() { + Customer customer = new Customer("Hanna Håkansson", 1); + Branch branch = new Branch(); + Manager manager = new Manager("Giovanni Capilletti", 1, branch); + Account savings = new SavingsAccount(customer, 1, branch); + + double amount = 100.0; + savings.deposit(amount); + savings.withdraw(amount); + Assertions.assertEquals(1100.0, savings.calculateBalance()); + } + + + } From 7191f908eeb180f82835de49b7f268498b7e5222 Mon Sep 17 00:00:00 2001 From: hannaklh Date: Wed, 20 Aug 2025 12:03:04 +0200 Subject: [PATCH 5/7] extension exercise: red stage --- src/diagram-extension.png | Bin 0 -> 50260 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/diagram-extension.png diff --git a/src/diagram-extension.png b/src/diagram-extension.png new file mode 100644 index 0000000000000000000000000000000000000000..361c596dcbb608a12a5cb49f6e56dd179a0b71d7 GIT binary patch literal 50260 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

-mwP{aWAG``y&vUf?^oZlBWDZ&wQuh{)8{s# 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�# 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 Date: Wed, 20 Aug 2025 13:12:43 +0200 Subject: [PATCH 6/7] extension exercise: green stage --- src/main/java/com/booleanuk/core/Account.java | 36 ++++++++++--------- src/main/java/com/booleanuk/core/Manager.java | 7 ++-- .../java/com/booleanuk/core/Transaction.java | 22 +----------- .../java/com/booleanuk/core/AccountTest.java | 14 ++++---- 4 files changed, 34 insertions(+), 45 deletions(-) diff --git a/src/main/java/com/booleanuk/core/Account.java b/src/main/java/com/booleanuk/core/Account.java index 66250a188..959d2ac5a 100644 --- a/src/main/java/com/booleanuk/core/Account.java +++ b/src/main/java/com/booleanuk/core/Account.java @@ -51,44 +51,48 @@ public void setTransactions(List transactions) { } public String deposit(double transAmount){ - Transaction trans = new Transaction(this.transactionCount, LocalDate.now(), transAmount, "debit", this); -/* - this.balance +=transAmount; - trans.setBalance(this.balance); + Transaction trans = new Transaction(this.transactionCount, LocalDate.now(), transAmount, this); + this.transactionCount++; - this.transactions.add(trans);*/ + this.transactions.add(trans); return transAmount + " has been deposited to your account " + this.id; } public String withdraw(double transAmount){ - /*if (this.balance>transAmount) { - Transaction trans = new Transaction(this.transactionCount, LocalDate.now(), transAmount, "credit",this); - this.balance -=transAmount; - trans.setBalance(this.balance); + if (calculateBalance()>=transAmount || canBeOverdrafted) { + Transaction trans = new Transaction(this.transactionCount, LocalDate.now(), -transAmount,this); this.transactionCount++; this.transactions.add(trans); return transAmount + " has been withdrawn from your account " + this.id; - } else*/ - return "There are not enough funds on your account. Current balance: " +this; + + } else + return "There are not enough funds on your account."; } public String generateBankStatements() { String returnString = "date\t\t||\tcredit\t||\tdebit\t||\tbalance\n"; + double currentBalance = 0; for (Transaction trans : transactions) { - if (trans.getType().equals("credit")) { - returnString += trans.getDate().toString() + "\t||\t" + trans.getTransAmount()+"\t\t||\t\t||\t"+trans.getBalance()+"\n"; + currentBalance += trans.getTransAmount(); + if (trans.getTransAmount() <0) { + returnString += trans.getDate().toString() + "\t||\t" + (trans.getTransAmount()*-1)+"\t\t||\t\t||\t"+currentBalance+"\n"; } else - returnString += trans.getDate().toString() + "\t||\t\t\t||\t" + trans.getTransAmount()+"\t||\t"+trans.getBalance()+"\n"; + returnString += trans.getDate().toString() + "\t||\t\t\t||\t" + trans.getTransAmount()+"\t||\t"+currentBalance+"\n"; } return returnString; } public boolean requestOverdraft() { - return false; + this.canBeOverdrafted = branch.getManager().decideOnOverdraft(this); + return this.canBeOverdrafted; } public double calculateBalance() { - return 0; + double totalBalance = 0; + for (Transaction trans : transactions){ + totalBalance += trans.getTransAmount(); + } + return totalBalance; } } diff --git a/src/main/java/com/booleanuk/core/Manager.java b/src/main/java/com/booleanuk/core/Manager.java index 11f8504bc..3eb2ed12a 100644 --- a/src/main/java/com/booleanuk/core/Manager.java +++ b/src/main/java/com/booleanuk/core/Manager.java @@ -10,7 +10,10 @@ public Manager(String name, int id, Branch branch) { public Manager() { } - public boolean decideOnOverdraft(Customer c, Account a) { - return false; + public boolean decideOnOverdraft(Account a) { + if (a.getTransactions().size()>3) { + return true; + } else + return false; } } diff --git a/src/main/java/com/booleanuk/core/Transaction.java b/src/main/java/com/booleanuk/core/Transaction.java index b4f27adad..72a6531d3 100644 --- a/src/main/java/com/booleanuk/core/Transaction.java +++ b/src/main/java/com/booleanuk/core/Transaction.java @@ -7,15 +7,12 @@ public class Transaction { private int id; private LocalDate date; private double transAmount; - private String type; - private double balance; private Account account; - public Transaction(int id, LocalDate date, double transAmount, String type, Account account) { + public Transaction(int id, LocalDate date, double transAmount, Account account) { this.id = id; this.date = date; this.transAmount = transAmount; - this.type = type; this.account = account; } public Transaction() {} @@ -43,23 +40,6 @@ public double getTransAmount() { public void setTransAmount(double transAmount) { this.transAmount = transAmount; } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public double getBalance() { - return balance; - } - - public void setBalance(double balance) { - this.balance = balance; - } - public Account getAccount() { return account; } diff --git a/src/test/java/com/booleanuk/core/AccountTest.java b/src/test/java/com/booleanuk/core/AccountTest.java index 4b29071c4..4717ae7ab 100644 --- a/src/test/java/com/booleanuk/core/AccountTest.java +++ b/src/test/java/com/booleanuk/core/AccountTest.java @@ -33,7 +33,7 @@ public void shouldWithdraw() { branch.setManager(manager); branch.setName("Scranton"); - + savings.deposit(1000); double amount = 1000; Assertions.assertEquals(amount +" has been withdrawn from your account "+ savings.getId() , savings.withdraw(amount)); @@ -41,9 +41,9 @@ public void shouldWithdraw() { savings.deposit(1000); savings.deposit(7000); savings.deposit(12); - boolean overdraft = savings.requestOverdraft(); + savings.requestOverdraft(); - Assertions.assertEquals(amount +" has been withdrawn from your account "+ savings.getId() , savings.withdraw(1300000)); + Assertions.assertEquals(1300000.0 +" has been withdrawn from your account "+ savings.getId() , savings.withdraw(1300000)); } @@ -60,7 +60,7 @@ public void shouldNotWithdraw() { double amount = 11000; - Assertions.assertEquals("There are not enough funds on your account. Current balance: "+savings.calculateBalance() , savings.withdraw(amount)); + Assertions.assertEquals("There are not enough funds on your account.", savings.withdraw(amount)); } @Test public void shouldGenerateBankStatements() { @@ -72,7 +72,7 @@ public void shouldGenerateBankStatements() { double amount = 1000; savings.deposit(amount); savings.withdraw(amount); - String string = "date\t\t||\tcredit\t||\tdebit\t||\tbalance\n2025-08-20\t||\t\t\t||\t100.0\t||\t1100.0\n2025-08-20\t||\t100.0\t\t||\t\t||\t1000.0\n"; + String string = "date\t\t||\tcredit\t||\tdebit\t||\tbalance\n2025-08-20\t||\t\t\t||\t1000.0\t||\t1000.0\n2025-08-20\t||\t1000.0\t\t||\t\t||\t0.0\n"; Assertions.assertEquals(string, savings.generateBankStatements()); } @@ -85,8 +85,10 @@ public void shouldCalculateBalance() { double amount = 100.0; savings.deposit(amount); + savings.deposit(amount); + savings.deposit(amount); savings.withdraw(amount); - Assertions.assertEquals(1100.0, savings.calculateBalance()); + Assertions.assertEquals(200.0, savings.calculateBalance()); } From 126909fa553a5f5bd507e5f2ef7c7ce59ccd69ab Mon Sep 17 00:00:00 2001 From: hannaklh Date: Wed, 20 Aug 2025 14:44:47 +0200 Subject: [PATCH 7/7] extension exercise: blue stage --- src/main/java/com/booleanuk/core/Account.java | 98 --------------- .../com/booleanuk/core/CurrentAccount.java | 15 --- .../com/booleanuk/core/SavingsAccount.java | 16 --- .../booleanuk/core/dto/TransactionResult.java | 18 +++ .../InsufficientFundsException.java | 7 ++ .../exceptions/InvalidAmountException.java | 7 ++ .../com/booleanuk/core/models/Account.java | 114 ++++++++++++++++++ .../booleanuk/core/models/AccountsType.java | 5 + .../booleanuk/core/{ => models}/Branch.java | 2 +- .../booleanuk/core/{ => models}/Customer.java | 2 +- .../booleanuk/core/{ => models}/Manager.java | 2 +- .../core/{ => models}/Transaction.java | 20 ++- .../core/models/TransactionType.java | 5 + .../com/booleanuk/core/{ => models}/User.java | 5 +- .../com/booleanuk/core/{ => models}/main.java | 2 +- .../java/com/booleanuk/core/AccountTest.java | 43 +++++-- 16 files changed, 208 insertions(+), 153 deletions(-) delete mode 100644 src/main/java/com/booleanuk/core/Account.java delete mode 100644 src/main/java/com/booleanuk/core/CurrentAccount.java delete mode 100644 src/main/java/com/booleanuk/core/SavingsAccount.java create mode 100644 src/main/java/com/booleanuk/core/dto/TransactionResult.java create mode 100644 src/main/java/com/booleanuk/core/exceptions/InsufficientFundsException.java create mode 100644 src/main/java/com/booleanuk/core/exceptions/InvalidAmountException.java create mode 100644 src/main/java/com/booleanuk/core/models/Account.java create mode 100644 src/main/java/com/booleanuk/core/models/AccountsType.java rename src/main/java/com/booleanuk/core/{ => models}/Branch.java (95%) rename src/main/java/com/booleanuk/core/{ => models}/Customer.java (92%) rename src/main/java/com/booleanuk/core/{ => models}/Manager.java (91%) rename src/main/java/com/booleanuk/core/{ => models}/Transaction.java (60%) create mode 100644 src/main/java/com/booleanuk/core/models/TransactionType.java rename src/main/java/com/booleanuk/core/{ => models}/User.java (84%) rename src/main/java/com/booleanuk/core/{ => models}/main.java (84%) diff --git a/src/main/java/com/booleanuk/core/Account.java b/src/main/java/com/booleanuk/core/Account.java deleted file mode 100644 index 959d2ac5a..000000000 --- a/src/main/java/com/booleanuk/core/Account.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.booleanuk.core; - -import java.math.BigDecimal; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.List; - -public abstract class Account { - private Customer customer; - private int id; - private List transactions; - private int transactionCount = 1; - private boolean canBeOverdrafted = false; - private Branch branch; - - public Account(Customer customer, int id) { - this.customer = customer; - this.id = id; - this.transactions = new ArrayList<>(); - } - public Account(Customer customer, int id, Branch branch) { - this.customer = customer; - this.id = id; - this.branch = branch; - this.transactions = new ArrayList<>(); - } - public Account () {} - - public Customer getCustomer() { - return customer; - } - - public void setCustomer(Customer customer) { - this.customer = customer; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public List getTransactions() { - return transactions; - } - - public void setTransactions(List transactions) { - this.transactions = transactions; - } - - public String deposit(double transAmount){ - Transaction trans = new Transaction(this.transactionCount, LocalDate.now(), transAmount, this); - - this.transactionCount++; - this.transactions.add(trans); - return transAmount + " has been deposited to your account " + this.id; - } - public String withdraw(double transAmount){ - - if (calculateBalance()>=transAmount || canBeOverdrafted) { - Transaction trans = new Transaction(this.transactionCount, LocalDate.now(), -transAmount,this); - this.transactionCount++; - this.transactions.add(trans); - return transAmount + " has been withdrawn from your account " + this.id; - - } else - return "There are not enough funds on your account."; - } - public String generateBankStatements() { - - String returnString = "date\t\t||\tcredit\t||\tdebit\t||\tbalance\n"; - double currentBalance = 0; - - for (Transaction trans : transactions) { - currentBalance += trans.getTransAmount(); - if (trans.getTransAmount() <0) { - returnString += trans.getDate().toString() + "\t||\t" + (trans.getTransAmount()*-1)+"\t\t||\t\t||\t"+currentBalance+"\n"; - } else - returnString += trans.getDate().toString() + "\t||\t\t\t||\t" + trans.getTransAmount()+"\t||\t"+currentBalance+"\n"; - - - } - return returnString; - } - public boolean requestOverdraft() { - this.canBeOverdrafted = branch.getManager().decideOnOverdraft(this); - return this.canBeOverdrafted; - } - public double calculateBalance() { - double totalBalance = 0; - for (Transaction trans : transactions){ - totalBalance += trans.getTransAmount(); - } - return totalBalance; - } -} diff --git a/src/main/java/com/booleanuk/core/CurrentAccount.java b/src/main/java/com/booleanuk/core/CurrentAccount.java deleted file mode 100644 index 08be9d57f..000000000 --- a/src/main/java/com/booleanuk/core/CurrentAccount.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.booleanuk.core; - -import java.math.BigDecimal; - -public class CurrentAccount extends Account{ - public CurrentAccount(Customer customer, int id) { - super(customer, id); - } - - public CurrentAccount(Customer customer, int id, Branch branch) { - super(customer, id, branch); - } - public CurrentAccount() { - } -} diff --git a/src/main/java/com/booleanuk/core/SavingsAccount.java b/src/main/java/com/booleanuk/core/SavingsAccount.java deleted file mode 100644 index 4a0111dc4..000000000 --- a/src/main/java/com/booleanuk/core/SavingsAccount.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.booleanuk.core; - -import java.math.BigDecimal; - -public class SavingsAccount extends Account{ - public SavingsAccount(Customer customer, int id) { - super(customer, id); - } - - public SavingsAccount(Customer customer, int id,Branch branch) { - super(customer, id, branch); - } - - public SavingsAccount() { - } -} diff --git a/src/main/java/com/booleanuk/core/dto/TransactionResult.java b/src/main/java/com/booleanuk/core/dto/TransactionResult.java new file mode 100644 index 000000000..97d952069 --- /dev/null +++ b/src/main/java/com/booleanuk/core/dto/TransactionResult.java @@ -0,0 +1,18 @@ +package com.booleanuk.core.dto; + +import java.math.BigDecimal; + +public class TransactionResult { + private boolean success; + private String message; + + public TransactionResult(boolean success, String message) { + this.success = success; + this.message = message; + } + + public boolean isSuccess() { return success; } + + public String getMessage() { return message; } + +} diff --git a/src/main/java/com/booleanuk/core/exceptions/InsufficientFundsException.java b/src/main/java/com/booleanuk/core/exceptions/InsufficientFundsException.java new file mode 100644 index 000000000..f80ed0cd9 --- /dev/null +++ b/src/main/java/com/booleanuk/core/exceptions/InsufficientFundsException.java @@ -0,0 +1,7 @@ +package com.booleanuk.core.exceptions; + +public class InsufficientFundsException extends Exception{ + public InsufficientFundsException(String message) { + super(message); + } +} diff --git a/src/main/java/com/booleanuk/core/exceptions/InvalidAmountException.java b/src/main/java/com/booleanuk/core/exceptions/InvalidAmountException.java new file mode 100644 index 000000000..06dbded58 --- /dev/null +++ b/src/main/java/com/booleanuk/core/exceptions/InvalidAmountException.java @@ -0,0 +1,7 @@ +package com.booleanuk.core.exceptions; + +public class InvalidAmountException extends Exception { + public InvalidAmountException(String message) { + super(message); + } +} diff --git a/src/main/java/com/booleanuk/core/models/Account.java b/src/main/java/com/booleanuk/core/models/Account.java new file mode 100644 index 000000000..6ce42473e --- /dev/null +++ b/src/main/java/com/booleanuk/core/models/Account.java @@ -0,0 +1,114 @@ +package com.booleanuk.core.models; + +import com.booleanuk.core.dto.TransactionResult; +import com.booleanuk.core.exceptions.InsufficientFundsException; +import com.booleanuk.core.exceptions.InvalidAmountException; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +public class Account { + private Customer customer; + private int id; + private List transactions; + private int transactionCount = 1; + private boolean canBeOverdrafted = false; + private Branch branch; + private AccountType accountType; + + public Account(Customer customer, int id, AccountType accountType) { + this.customer = customer; + this.id = id; + this.accountType = accountType; + this.transactions = new ArrayList<>(); + } + public Account(Customer customer, int id, Branch branch, AccountType accountType) { + this.customer = customer; + this.id = id; + this.branch = branch; + this.accountType = accountType; + this.transactions = new ArrayList<>(); + } + public Account () {} + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(Customer customer) { + this.customer = customer; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public List getTransactions() { + return transactions; + } + + public void setTransactions(List transactions) { + this.transactions = transactions; + } + + public TransactionResult deposit(BigDecimal transAmount){ + if (transAmount.compareTo(BigDecimal.ZERO) >= 0) { + return new TransactionResult(false, "Amount must be more than 0"); + } + + Transaction trans = new Transaction(this.transactionCount, LocalDate.now(), transAmount, this, TransactionType.DEPOSIT); + this.transactionCount++; + this.transactions.add(trans); + return new TransactionResult(true, "Deposit successful"); + + + } + public TransactionResult withdraw(BigDecimal transAmount){ + + if (transAmount.compareTo(BigDecimal.ZERO) <=0) { + throw new InvalidAmountException("Amount must be more than 0"); + } + if (calculateBalance().compareTo(transAmount) <0 && !canBeOverdrafted) { + throw new InsufficientFundsException("Insufficient funds. Balance is at: " +calculateBalance().toString()); + } + + Transaction trans = new Transaction(this.transactionCount, LocalDate.now(), transAmount,this, TransactionType.WITHDRAWAL); + this.transactionCount++; + this.transactions.add(trans); + return new TransactionResult(true, transAmount.toString()+ " have been withdrawn from you account"); + } + public StringBuilder generateBankStatements() { + + StringBuilder returnString = new StringBuilder("date\t\t||\tcredit\t||\tdebit\t||\tbalance\n"); + BigDecimal currentBalance = new BigDecimal("0"); + + for (Transaction trans : transactions) { + currentBalance = currentBalance.add(trans.getTransAmount()); + if (trans.getType() == TransactionType.WITHDRAWAL) + returnString.append(trans.getDate().toString() + "\t||\t" + trans.getTransAmount().toString()+"\t\t||\t\t||\t"+currentBalance+"\n"); + + if (trans.getTransAmount().compareTo(BigDecimal.ZERO) >= 0) + returnString.append(trans.getDate().toString() + "\t||\t\t\t||\t" + trans.getTransAmount()+"\t||\t"+currentBalance+"\n"); + + + } + return returnString; + } + public boolean requestOverdraft() { + this.canBeOverdrafted = branch.getManager().decideOnOverdraft(this); + return this.canBeOverdrafted; + } + public BigDecimal calculateBalance() { + BigDecimal totalBalance = new BigDecimal("0"); + for (Transaction trans : transactions){ + totalBalance = totalBalance.add(trans.getTransAmount()); + } + return totalBalance; + } +} diff --git a/src/main/java/com/booleanuk/core/models/AccountsType.java b/src/main/java/com/booleanuk/core/models/AccountsType.java new file mode 100644 index 000000000..e3d797fd8 --- /dev/null +++ b/src/main/java/com/booleanuk/core/models/AccountsType.java @@ -0,0 +1,5 @@ +package com.booleanuk.core.models; + +public enum AccountType { + SAVINGS, CURRENT +} diff --git a/src/main/java/com/booleanuk/core/Branch.java b/src/main/java/com/booleanuk/core/models/Branch.java similarity index 95% rename from src/main/java/com/booleanuk/core/Branch.java rename to src/main/java/com/booleanuk/core/models/Branch.java index 90ff44c51..d6bb0e3f6 100644 --- a/src/main/java/com/booleanuk/core/Branch.java +++ b/src/main/java/com/booleanuk/core/models/Branch.java @@ -1,4 +1,4 @@ -package com.booleanuk.core; +package com.booleanuk.core.models; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/booleanuk/core/Customer.java b/src/main/java/com/booleanuk/core/models/Customer.java similarity index 92% rename from src/main/java/com/booleanuk/core/Customer.java rename to src/main/java/com/booleanuk/core/models/Customer.java index 8558ae2f1..01c04355b 100644 --- a/src/main/java/com/booleanuk/core/Customer.java +++ b/src/main/java/com/booleanuk/core/models/Customer.java @@ -1,4 +1,4 @@ -package com.booleanuk.core; +package com.booleanuk.core.models; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/booleanuk/core/Manager.java b/src/main/java/com/booleanuk/core/models/Manager.java similarity index 91% rename from src/main/java/com/booleanuk/core/Manager.java rename to src/main/java/com/booleanuk/core/models/Manager.java index 3eb2ed12a..9260d456a 100644 --- a/src/main/java/com/booleanuk/core/Manager.java +++ b/src/main/java/com/booleanuk/core/models/Manager.java @@ -1,4 +1,4 @@ -package com.booleanuk.core; +package com.booleanuk.core.models; public class Manager extends User { private Branch branch; diff --git a/src/main/java/com/booleanuk/core/Transaction.java b/src/main/java/com/booleanuk/core/models/Transaction.java similarity index 60% rename from src/main/java/com/booleanuk/core/Transaction.java rename to src/main/java/com/booleanuk/core/models/Transaction.java index 72a6531d3..dd555972f 100644 --- a/src/main/java/com/booleanuk/core/Transaction.java +++ b/src/main/java/com/booleanuk/core/models/Transaction.java @@ -1,4 +1,4 @@ -package com.booleanuk.core; +package com.booleanuk.core.models; import java.math.BigDecimal; import java.time.LocalDate; @@ -6,14 +6,16 @@ public class Transaction { private int id; private LocalDate date; - private double transAmount; + private BigDecimal transAmount; private Account account; + private TransactionType type; - public Transaction(int id, LocalDate date, double transAmount, Account account) { + public Transaction(int id, LocalDate date, BigDecimal transAmount, Account account, TransactionType transactionType) { this.id = id; this.date = date; this.transAmount = transAmount; this.account = account; + this.type = transactionType; } public Transaction() {} @@ -33,11 +35,11 @@ public void setDate(LocalDate date) { this.date = date; } - public double getTransAmount() { + public BigDecimal getTransAmount() { return transAmount; } - public void setTransAmount(double transAmount) { + public void setTransAmount(BigDecimal transAmount) { this.transAmount = transAmount; } public Account getAccount() { @@ -47,4 +49,12 @@ public Account getAccount() { public void setAccount(Account account) { this.account = account; } + + public TransactionType getType() { + return type; + } + + public void setType(TransactionType type) { + this.type = type; + } } diff --git a/src/main/java/com/booleanuk/core/models/TransactionType.java b/src/main/java/com/booleanuk/core/models/TransactionType.java new file mode 100644 index 000000000..268a8a801 --- /dev/null +++ b/src/main/java/com/booleanuk/core/models/TransactionType.java @@ -0,0 +1,5 @@ +package com.booleanuk.core.models; + +public enum TransactionType { + DEPOSIT, WITHDRAWAL +} diff --git a/src/main/java/com/booleanuk/core/User.java b/src/main/java/com/booleanuk/core/models/User.java similarity index 84% rename from src/main/java/com/booleanuk/core/User.java rename to src/main/java/com/booleanuk/core/models/User.java index 2aef75242..7b0ecb7d2 100644 --- a/src/main/java/com/booleanuk/core/User.java +++ b/src/main/java/com/booleanuk/core/models/User.java @@ -1,7 +1,4 @@ -package com.booleanuk.core; - -import java.util.ArrayList; -import java.util.List; +package com.booleanuk.core.models; public abstract class User { private String name; diff --git a/src/main/java/com/booleanuk/core/main.java b/src/main/java/com/booleanuk/core/models/main.java similarity index 84% rename from src/main/java/com/booleanuk/core/main.java rename to src/main/java/com/booleanuk/core/models/main.java index b534533ff..b7c74ec15 100644 --- a/src/main/java/com/booleanuk/core/main.java +++ b/src/main/java/com/booleanuk/core/models/main.java @@ -1,4 +1,4 @@ -package com.booleanuk.core; +package com.booleanuk.core.models; public class main { public static void main(String[] args) { diff --git a/src/test/java/com/booleanuk/core/AccountTest.java b/src/test/java/com/booleanuk/core/AccountTest.java index 4717ae7ab..dd936e78e 100644 --- a/src/test/java/com/booleanuk/core/AccountTest.java +++ b/src/test/java/com/booleanuk/core/AccountTest.java @@ -1,18 +1,18 @@ package com.booleanuk.core; +import com.booleanuk.core.models.*; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.math.BigDecimal; - public class AccountTest { +/* + @BeforeEach @Test public void shouldCreateAccount() { Customer customer = new Customer("Hanna Håkansson", 1); - Account savings = new SavingsAccount(customer, 1); - Account current = new CurrentAccount(customer, 2); + Account savings = new Account(customer, 1, branch, AccountType.SAVINGS); Assertions.assertEquals("Account " + savings.getId()+ " was added to " + customer.getName(), customer.createAccount(savings)); - Assertions.assertEquals("Account " + current.getId()+ " was added to " + customer.getName(), customer.createAccount(current)); } @@ -25,11 +25,11 @@ public void shouldDeposit() { Assertions.assertEquals(amount +" has been deposited to your account " + savings.getId() , savings.deposit(amount)); } @Test - public void shouldWithdraw() { + public void shouldWithdrawWithSufficientFunds() { Customer customer = new Customer("Hanna Håkansson", 1); Branch branch = new Branch(); Manager manager = new Manager("Giovanni Capilletti", 1, branch); - Account savings = new SavingsAccount(customer, 1, branch); + Account savings = new Account(customer, 1, branch, AccountType.SAVINGS); branch.setManager(manager); branch.setName("Scranton"); @@ -46,13 +46,34 @@ public void shouldWithdraw() { Assertions.assertEquals(1300000.0 +" has been withdrawn from your account "+ savings.getId() , savings.withdraw(1300000)); + } + @Test + public void shouldWithdrawWithOverdraft() { + Customer customer = new Customer("Hanna Håkansson", 1); + Branch branch = new Branch(); + Manager manager = new Manager("Giovanni Capilletti", 1, branch); + Account savings = new Account(customer, 1, branch, AccountType.SAVINGS); + + branch.setManager(manager); + branch.setName("Scranton"); + savings.deposit(1000); + double amount = 1000; + + savings.deposit(1000); + savings.deposit(7000); + savings.deposit(12); + savings.requestOverdraft(); + + Assertions.assertEquals(1300000.0 +" has been withdrawn from your account "+ savings.getId() , savings.withdraw(1300000)); + + } @Test public void shouldNotWithdraw() { Customer customer = new Customer("Hanna Håkansson", 1); Branch branch = new Branch(); Manager manager = new Manager("Giovanni Capilletti", 1, branch); - Account savings = new SavingsAccount(customer, 1, branch); + Account savings = new Account(customer, 1, branch, AccountType.SAVINGS); branch.setManager(manager); @@ -67,7 +88,7 @@ public void shouldGenerateBankStatements() { Customer customer = new Customer("Hanna Håkansson", 1); Branch branch = new Branch(); Manager manager = new Manager("Giovanni Capilletti", 1, branch); - Account savings = new SavingsAccount(customer, 1, branch); + Account savings = new Account(customer, 1, branch, AccountType.SAVINGS); double amount = 1000; savings.deposit(amount); @@ -81,7 +102,7 @@ public void shouldCalculateBalance() { Customer customer = new Customer("Hanna Håkansson", 1); Branch branch = new Branch(); Manager manager = new Manager("Giovanni Capilletti", 1, branch); - Account savings = new SavingsAccount(customer, 1, branch); + Account savings = new Account(customer, 1, branch, AccountType.SAVINGS); double amount = 100.0; savings.deposit(amount); @@ -90,7 +111,7 @@ public void shouldCalculateBalance() { savings.withdraw(amount); Assertions.assertEquals(200.0, savings.calculateBalance()); } - +*/