Skip to content

Commit 090fc63

Browse files
committed
feat: completed bankATM simulator with full test coverage
1 parent 3a0b4fa commit 090fc63

File tree

11 files changed

+297
-168
lines changed

11 files changed

+297
-168
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
public enum CustomerType {
4+
INDIVIDUAL,
5+
BUSINESS
6+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import com.codedifferently.lesson17.bank.exceptions.InsufficientFundsException;
4+
import java.util.Set;
5+
import lombok.Getter;
6+
import lombok.Setter;
7+
8+
/** Abstract base class for all bank accounts. */
9+
@Getter
10+
@Setter
11+
public abstract class Account {
12+
private final Set<Customer> owners;
13+
private final String accountNumber;
14+
private double balance;
15+
private boolean isActive;
16+
17+
/**
18+
* Creates a new account.
19+
*
20+
* @param accountNumber The account number.
21+
* @param owners The owners of the account.
22+
* @param initalBalance The inital balance of the account.
23+
*/
24+
public Account(String accountNumber, Set<Customer> owners, double initalBalance) {
25+
this.accountNumber = accountNumber;
26+
this.owners = owners;
27+
this.balance = initalBalance;
28+
this.isActive = true;
29+
}
30+
31+
/**
32+
* Deposits funds into the account.
33+
*
34+
* @param amount The amount to deposit.
35+
*/
36+
public void deposit(double amount) throws IllegalStateException {
37+
if (isClosed()) {
38+
throw new IllegalStateException("Cannot deposit to a closed account");
39+
}
40+
if (amount <= 0) {
41+
throw new IllegalArgumentException("Deposit amount must be positive");
42+
}
43+
balance += amount;
44+
}
45+
46+
/**
47+
* Withdraws funds from the account.
48+
*
49+
* @param amount
50+
* @throws InsufficientFundsException
51+
*/
52+
public void withdraw(double amount) throws InsufficientFundsException {
53+
if (isClosed()) {
54+
throw new IllegalStateException("Cannot withdraw from a closed account");
55+
}
56+
if (amount <= 0) {
57+
throw new IllegalStateException("Withdrawal amount must be positive");
58+
}
59+
if (balance < amount) {
60+
throw new InsufficientFundsException("Account does not have enough funds for withdrawal");
61+
}
62+
balance -= amount;
63+
}
64+
65+
/** Closes the account. */
66+
public void closeAccount() throws IllegalStateException {
67+
if (balance > 0) {
68+
throw new IllegalStateException("Cannot close account with a positive balance");
69+
}
70+
isActive = false;
71+
}
72+
73+
/**
74+
* Checks if the account is closed.
75+
*
76+
* @return True if the account is closed, otherwise false.
77+
*/
78+
public boolean isClosed() {
79+
return !isActive;
80+
}
81+
82+
@Override
83+
public int hashCode() {
84+
return accountNumber.hashCode();
85+
}
86+
87+
@Override
88+
public boolean equals(Object obj) {
89+
if (obj instanceof CheckingAccount other) {
90+
return accountNumber.equals(other.getAccountNumber());
91+
}
92+
return false;
93+
}
94+
}

lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/BankAtm.java

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,11 @@
66
import java.util.Set;
77
import java.util.UUID;
88

9-
public class AuditLog {
10-
private static List<String> logEntries = new ArrayList<>();
11-
12-
public static void record(String message) {
13-
logEntries.add(message);
14-
System.out.println("LOG: " + message);
15-
}
16-
17-
public static List<String> getLog() {
18-
return logEntries;
19-
}
20-
}
21-
229
/** Represents a bank ATM. */
2310
public class BankAtm {
2411

2512
private final Map<UUID, Customer> customerById = new HashMap<>();
26-
private final Map<String, CheckingAccount> accountByNumber = new HashMap<>();
13+
private final Map<String, Account> accountByNumber = new HashMap<>();
2714

2815
/**
2916
* Adds a checking account to the bank.
@@ -46,7 +33,7 @@ public void addAccount(CheckingAccount account) {
4633
* @param customerId The ID of the customer.
4734
* @return The unique set of accounts owned by the customer.
4835
*/
49-
public Set<CheckingAccount> findAccountsByCustomerId(UUID customerId) {
36+
public Set<Account> findAccountsByCustomerId(UUID customerId) {
5037
return customerById.containsKey(customerId)
5138
? customerById.get(customerId).getAccounts()
5239
: Set.of();
@@ -59,7 +46,7 @@ public Set<CheckingAccount> findAccountsByCustomerId(UUID customerId) {
5946
* @param amount The amount to deposit.
6047
*/
6148
public void depositFunds(String accountNumber, double amount) {
62-
CheckingAccount account = getAccountOrThrow(accountNumber);
49+
Account account = getAccountOrThrow(accountNumber);
6350
account.deposit(amount);
6451
}
6552

@@ -70,18 +57,22 @@ public void depositFunds(String accountNumber, double amount) {
7057
* @param check The check to deposit.
7158
*/
7259
public void depositFunds(String accountNumber, Check check) {
73-
CheckingAccount account = getAccountOrThrow(accountNumber);
74-
check.depositFunds(account);
60+
Account account = getAccountOrThrow(accountNumber);
61+
if (account instanceof Account) {
62+
check.depositFunds((Account) account);
63+
} else {
64+
throw new UnsupportedOperationException("This account does not support check deposits.");
65+
}
7566
}
7667

7768
/**
7869
* Withdraws funds from an account.
7970
*
80-
* @param accountNumber
81-
* @param amount
71+
* @param accountNumber The account number.
72+
* @param amount The amount to withdraw.
8273
*/
8374
public void withdrawFunds(String accountNumber, double amount) {
84-
CheckingAccount account = getAccountOrThrow(accountNumber);
75+
Account account = getAccountOrThrow(accountNumber);
8576
account.withdraw(amount);
8677
}
8778

@@ -91,12 +82,11 @@ public void withdrawFunds(String accountNumber, double amount) {
9182
* @param accountNumber The account number.
9283
* @return The account.
9384
*/
94-
private CheckingAccount getAccountOrThrow(String accountNumber) {
95-
CheckingAccount account = accountByNumber.get(accountNumber);
85+
private Account getAccountOrThrow(String accountNumber) {
86+
Account account = accountByNumber.get(accountNumber);
9687
if (account == null || account.isClosed()) {
9788
throw new AccountNotFoundException("Account not found");
9889
}
9990
return account;
10091
}
10192
}
102-
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import java.util.Set;
4+
5+
/** Represents a business checking account */
6+
public class BusinessCheckingAccount extends CheckingAccount {
7+
8+
/**
9+
* Creates a new business checking account
10+
*
11+
* @param accountNumber The accounnt number.
12+
* @param owners The owners of the account.
13+
* @param initialBalance The initial balance of the account.
14+
*/
15+
public BusinessCheckingAccount(
16+
String accountNumber, Set<Customer> owners, double initialBalance) {
17+
super(accountNumber, owners, initialBalance);
18+
}
19+
20+
/**
21+
* Checks if at least one owner is a business.
22+
*
23+
* @param owners The owers of the account.
24+
* @throws IllegalArgumentEception If no business owner is found.
25+
*/
26+
private void validateBusinessOwner(Set<Customer> owners) {
27+
boolean hasBusinessOwner = owners.stream().anyMatch(Customer::isBusiness);
28+
if (!hasBusinessOwner) {
29+
throw new IllegalArgumentException(
30+
"Business Checking Account must have at least one business owner");
31+
}
32+
}
33+
34+
@Override
35+
public String toString() {
36+
return "BusinessCheckingAccount{"
37+
+ "accountNumber='"
38+
+ getAccountNumber()
39+
+ '\''
40+
+ ", balance="
41+
+ getBalance()
42+
+ ", isActive="
43+
+ isActive()
44+
+ '}';
45+
}
46+
}

lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/Check.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public void voidCheck() {
4545
*
4646
* @param toAccount The account to deposit the check into.
4747
*/
48-
public void depositFunds(CheckingAccount toAccount) {
48+
public void depositFunds(Account toAccount) {
4949
if (isVoided) {
5050
throw new CheckVoidedException("Check is voided");
5151
}
Lines changed: 7 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
package com.codedifferently.lesson17.bank;
22

3-
import com.codedifferently.lesson17.bank.exceptions.InsufficientFundsException;
43
import java.util.Set;
54

65
/** Represents a checking account. */
7-
public class CheckingAccount {
8-
9-
private final Set<Customer> owners;
10-
private final String accountNumber;
11-
private double balance;
12-
private boolean isActive;
6+
public class CheckingAccount extends Account {
137

148
/**
159
* Creates a new checking account.
@@ -19,113 +13,17 @@ public class CheckingAccount {
1913
* @param initialBalance The initial balance of the account.
2014
*/
2115
public CheckingAccount(String accountNumber, Set<Customer> owners, double initialBalance) {
22-
this.accountNumber = accountNumber;
23-
this.owners = owners;
24-
this.balance = initialBalance;
25-
isActive = true;
26-
}
27-
28-
/**
29-
* Gets the account number.
30-
*
31-
* @return The account number.
32-
*/
33-
public String getAccountNumber() {
34-
return accountNumber;
35-
}
36-
37-
/**
38-
* Gets the owners of the account.
39-
*
40-
* @return The owners of the account.
41-
*/
42-
public Set<Customer> getOwners() {
43-
return owners;
44-
}
45-
46-
/**
47-
* Deposits funds into the account.
48-
*
49-
* @param amount The amount to deposit.
50-
*/
51-
public void deposit(double amount) throws IllegalStateException {
52-
if (isClosed()) {
53-
throw new IllegalStateException("Cannot deposit to a closed account");
54-
}
55-
if (amount <= 0) {
56-
throw new IllegalArgumentException("Deposit amount must be positive");
57-
}
58-
balance += amount;
59-
}
60-
61-
/**
62-
* Withdraws funds from the account.
63-
*
64-
* @param amount
65-
* @throws InsufficientFundsException
66-
*/
67-
public void withdraw(double amount) throws InsufficientFundsException {
68-
if (isClosed()) {
69-
throw new IllegalStateException("Cannot withdraw from a closed account");
70-
}
71-
if (amount <= 0) {
72-
throw new IllegalStateException("Withdrawal amount must be positive");
73-
}
74-
if (balance < amount) {
75-
throw new InsufficientFundsException("Account does not have enough funds for withdrawal");
76-
}
77-
balance -= amount;
78-
}
79-
80-
/**
81-
* Gets the balance of the account.
82-
*
83-
* @return The balance of the account.
84-
*/
85-
public double getBalance() {
86-
return balance;
87-
}
88-
89-
/** Closes the account. */
90-
public void closeAccount() throws IllegalStateException {
91-
if (balance > 0) {
92-
throw new IllegalStateException("Cannot close account with a positive balance");
93-
}
94-
isActive = false;
95-
}
96-
97-
/**
98-
* Checks if the account is closed.
99-
*
100-
* @return True if the account is closed, otherwise false.
101-
*/
102-
public boolean isClosed() {
103-
return !isActive;
104-
}
105-
106-
@Override
107-
public int hashCode() {
108-
return accountNumber.hashCode();
109-
}
110-
111-
@Override
112-
public boolean equals(Object obj) {
113-
if (obj instanceof CheckingAccount other) {
114-
return accountNumber.equals(other.accountNumber);
115-
}
116-
return false;
16+
super(accountNumber, owners, initialBalance);
11717
}
11818

11919
@Override
12020
public String toString() {
121-
return "CheckingAccount{"
122-
+ "accountNumber='"
123-
+ accountNumber
124-
+ '\''
125-
+ ", balance="
126-
+ balance
21+
return "CheckingAccount{accountNumber='"
22+
+ getAccountNumber()
23+
+ "', balance="
24+
+ getBalance()
12725
+ ", isActive="
128-
+ isActive
26+
+ isActive()
12927
+ '}';
13028
}
13129
}

0 commit comments

Comments
 (0)