Skip to content

Commit 3abf8cd

Browse files
committed
feat: added Functional Requirements to 'BankAtm' class
1 parent a3a21bb commit 3abf8cd

File tree

13 files changed

+340
-6
lines changed

13 files changed

+340
-6
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
public class AuditLog {
7+
8+
private final List<String> logEntries = new ArrayList<>();
9+
10+
public void logAccountAddition(String accountNumber) {
11+
logEntries.add("Account added: " + accountNumber);
12+
}
13+
14+
public List<String> getLogEntries() {
15+
return new ArrayList<>(logEntries);
16+
}
17+
18+
public String getLastEntry() {
19+
if (logEntries.isEmpty()) {
20+
return null; // Or throw an exception if preferred
21+
}
22+
return logEntries.get(logEntries.size() - 1);
23+
}
24+
}

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.codedifferently.lesson17.bank;
22

33
import com.codedifferently.lesson17.bank.exceptions.AccountNotFoundException;
4+
import java.util.Currency;
45
import java.util.HashMap;
6+
import java.util.List;
57
import java.util.Map;
68
import java.util.Set;
79
import java.util.UUID;
@@ -11,6 +13,7 @@ public class BankAtm {
1113

1214
private final Map<UUID, Customer> customerById = new HashMap<>();
1315
private final Map<String, CheckingAccount> accountByNumber = new HashMap<>();
16+
private final AuditLog auditLog = new AuditLog();
1417

1518
/**
1619
* Adds a checking account to the bank.
@@ -25,6 +28,7 @@ public void addAccount(CheckingAccount account) {
2528
owner -> {
2629
customerById.put(owner.getId(), owner);
2730
});
31+
auditLog.logAccountAddition(account.getAccountNumber());
2832
}
2933

3034
/**
@@ -61,6 +65,33 @@ public void depositFunds(String accountNumber, Check check) {
6165
check.depositFunds(account);
6266
}
6367

68+
public void depositFunds(String accountNumber, double amount, Currency currency) {
69+
CheckingAccount account = getAccountOrThrow(accountNumber);
70+
71+
// Validate the currency
72+
if (currency == null || !isValidCurrency(currency)) {
73+
throw new IllegalArgumentException("Invalid currency provided");
74+
}
75+
76+
// Convert the amount to the account's currency
77+
Currency accountCurrency =
78+
Currency.getInstance("USD"); // Replace with account's actual currency
79+
double convertedAmount = CurrencyConverter.convert(amount, currency, accountCurrency);
80+
81+
account.deposit(convertedAmount);
82+
}
83+
84+
private boolean isValidCurrency(Currency currency) {
85+
// You can add additional logic here to define valid currencies if needed
86+
return currency.getCurrencyCode().equals("USD")
87+
|| currency.getCurrencyCode().equals("GBP")
88+
|| currency.getCurrencyCode().equals("CAD");
89+
}
90+
91+
public List<String> getAuditLogEntries() {
92+
return auditLog.getLogEntries();
93+
}
94+
6495
/**
6596
* Withdraws funds from an account.
6697
*
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import java.util.Set;
4+
5+
public class BusinessCheckingAccount extends CheckingAccount {
6+
7+
public BusinessCheckingAccount(
8+
String accountNumber, Set<Customer> owners, double initialBalance) {
9+
super(accountNumber, owners, initialBalance);
10+
if (!owners.stream().anyMatch(Customer::isBusiness)) {
11+
throw new IllegalArgumentException("At least one owner must be a business");
12+
}
13+
}
14+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import java.util.Currency;
4+
5+
public class CurrencyConverter {
6+
public static double convert(double amount, Currency fromCurrency, Currency toCurrency) {
7+
if (fromCurrency.equals(toCurrency)) {
8+
return amount; // No conversion needed
9+
}
10+
11+
double exchangeRate = getExchangeRate(fromCurrency, toCurrency);
12+
return amount * exchangeRate;
13+
}
14+
15+
private static double getExchangeRate(Currency fromCurrency, Currency toCurrency) {
16+
// Example exchange rates
17+
if (fromCurrency.getCurrencyCode().equals("USD")
18+
&& toCurrency.getCurrencyCode().equals("EUR")) {
19+
return 0.85; // USD to EUR
20+
} else if (fromCurrency.getCurrencyCode().equals("EUR")
21+
&& toCurrency.getCurrencyCode().equals("USD")) {
22+
return 1.18; // EUR to USD
23+
} else if (fromCurrency.getCurrencyCode().equals("USD")
24+
&& toCurrency.getCurrencyCode().equals("GBP")) {
25+
return 0.75; // USD to GBP
26+
} else if (fromCurrency.getCurrencyCode().equals("GBP")
27+
&& toCurrency.getCurrencyCode().equals("USD")) {
28+
return 1.33; // GBP to USD
29+
} else if (fromCurrency.getCurrencyCode().equals("EUR")
30+
&& toCurrency.getCurrencyCode().equals("GBP")) {
31+
return 0.88; // EUR to GBP
32+
} else if (fromCurrency.getCurrencyCode().equals("GBP")
33+
&& toCurrency.getCurrencyCode().equals("EUR")) {
34+
return 1.14; // GBP to EUR
35+
} else if (fromCurrency.getCurrencyCode().equals("USD")
36+
&& toCurrency.getCurrencyCode().equals("CAD")) {
37+
return 1.25; // USD to CAD
38+
} else if (fromCurrency.getCurrencyCode().equals("CAD")
39+
&& toCurrency.getCurrencyCode().equals("USD")) {
40+
return 0.80; // CAD to USD
41+
} else if (fromCurrency.getCurrencyCode().equals("EUR")
42+
&& toCurrency.getCurrencyCode().equals("CAD")) {
43+
return 1.50; // EUR to CAD
44+
} else if (fromCurrency.getCurrencyCode().equals("CAD")
45+
&& toCurrency.getCurrencyCode().equals("EUR")) {
46+
return 0.67; // CAD to EUR
47+
} else if (fromCurrency.getCurrencyCode().equals("GBP")
48+
&& toCurrency.getCurrencyCode().equals("CAD")) {
49+
return 1.75; // GBP to CAD
50+
} else if (fromCurrency.getCurrencyCode().equals("CAD")
51+
&& toCurrency.getCurrencyCode().equals("GBP")) {
52+
return 0.57; // CAD to GBP
53+
}
54+
// Add other currency pairs as needed
55+
return 1.0; // Default to 1.0 if no conversion is defined
56+
}
57+
}

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@ public class Customer {
1010
private final UUID id;
1111
private final String name;
1212
private final Set<CheckingAccount> accounts = new HashSet<>();
13+
private boolean isBusiness;
1314

1415
/**
1516
* Creates a new customer.
1617
*
1718
* @param id The ID of the customer.
1819
* @param name The name of the customer.
1920
*/
20-
public Customer(UUID id, String name) {
21+
public Customer(UUID id, String name, boolean isBusiness) {
2122
this.id = id;
2223
this.name = name;
24+
this.isBusiness = isBusiness;
2325
}
2426

2527
/**
@@ -40,6 +42,10 @@ public String getName() {
4042
return name;
4143
}
4244

45+
public boolean isBusiness() { // Add this method
46+
return isBusiness;
47+
}
48+
4349
/**
4450
* Adds a checking account to the customer.
4551
*
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
public class MoneyOrder {
4+
private final double amount;
5+
private final String sourceAccountNumber;
6+
7+
public MoneyOrder(double amount, String sourceAccountNumber) {
8+
this.amount = amount;
9+
this.sourceAccountNumber = sourceAccountNumber;
10+
}
11+
12+
public double getAmount() {
13+
return amount;
14+
}
15+
16+
public String getSourceAccountNumber() {
17+
return sourceAccountNumber;
18+
}
19+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import java.util.Set;
4+
5+
public class SavingsAccount extends CheckingAccount {
6+
7+
public SavingsAccount(String accountNumber, Set<Customer> owners, double initialBalance) {
8+
super(accountNumber, owners, initialBalance);
9+
}
10+
11+
@Override
12+
public void deposit(double amount) {
13+
super.deposit(amount);
14+
}
15+
}

lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/BankAtmTest.java

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
import com.codedifferently.lesson17.bank.exceptions.AccountNotFoundException;
77
import com.codedifferently.lesson17.bank.exceptions.CheckVoidedException;
8+
import com.codedifferently.lesson17.bank.exceptions.InsufficientFundsException;
9+
import java.util.Currency;
10+
import java.util.List;
811
import java.util.Set;
912
import java.util.UUID;
1013
import org.junit.jupiter.api.BeforeEach;
@@ -21,8 +24,8 @@ class BankAtmTest {
2124
@BeforeEach
2225
void setUp() {
2326
classUnderTest = new BankAtm();
24-
customer1 = new Customer(UUID.randomUUID(), "John Doe");
25-
customer2 = new Customer(UUID.randomUUID(), "Jane Smith");
27+
customer1 = new Customer(UUID.randomUUID(), "John Doe", false);
28+
customer2 = new Customer(UUID.randomUUID(), "Jane Smith", false);
2629
account1 = new CheckingAccount("123456789", Set.of(customer1), 100.0);
2730
account2 = new CheckingAccount("987654321", Set.of(customer1, customer2), 200.0);
2831
customer1.addAccount(account1);
@@ -35,7 +38,7 @@ void setUp() {
3538
@Test
3639
void testAddAccount() {
3740
// Arrange
38-
Customer customer3 = new Customer(UUID.randomUUID(), "Alice Johnson");
41+
Customer customer3 = new Customer(UUID.randomUUID(), "Tech Labs", true);
3942
CheckingAccount account3 = new CheckingAccount("555555555", Set.of(customer3), 300.0);
4043
customer3.addAccount(account3);
4144

@@ -107,4 +110,78 @@ void testWithdrawFunds_AccountNotFound() {
107110
.isThrownBy(() -> classUnderTest.withdrawFunds(nonExistingAccountNumber, 50.0))
108111
.withMessage("Account not found");
109112
}
113+
114+
@Test
115+
void testDepositFunds_WithCurrency_GBP() {
116+
// Arrange
117+
Currency gbp = Currency.getInstance("GBP");
118+
account1.deposit(100.0); // Reset balance for testing
119+
double initialBalance = account1.getBalance();
120+
121+
// Act
122+
classUnderTest.depositFunds(account1.getAccountNumber(), 100.0, gbp);
123+
124+
// Assert
125+
double expectedBalance =
126+
initialBalance + CurrencyConverter.convert(100.0, gbp, Currency.getInstance("USD"));
127+
assertThat(account1.getBalance()).isEqualTo(expectedBalance);
128+
}
129+
130+
@Test
131+
void testDepositFunds_WithCurrency_CAD() {
132+
// Arrange
133+
Currency cad = Currency.getInstance("CAD");
134+
account2.deposit(200.0);
135+
double initialBalance = account2.getBalance();
136+
137+
// Act
138+
classUnderTest.depositFunds(account2.getAccountNumber(), 100.0, cad);
139+
140+
// Assert
141+
double expectedBalance =
142+
initialBalance + CurrencyConverter.convert(100.0, cad, Currency.getInstance("USD"));
143+
assertThat(account2.getBalance()).isEqualTo(expectedBalance);
144+
}
145+
146+
@Test
147+
void testDepositFunds_AccountNotFound() {
148+
// Arrange
149+
String nonExistingAccountNumber = "999999999";
150+
151+
// Act & Assert
152+
assertThatExceptionOfType(AccountNotFoundException.class)
153+
.isThrownBy(
154+
() ->
155+
classUnderTest.depositFunds(
156+
nonExistingAccountNumber, 50.0, Currency.getInstance("USD")))
157+
.withMessage("Account not found");
158+
}
159+
160+
@Test
161+
void testWithdrawFunds_InsufficientFunds() {
162+
// Arrange
163+
double amountToWithdraw = 200.0; // More than the balance
164+
165+
// Act & Assert
166+
assertThatExceptionOfType(InsufficientFundsException.class)
167+
.isThrownBy(
168+
() -> classUnderTest.withdrawFunds(account1.getAccountNumber(), amountToWithdraw))
169+
.withMessage("Account does not have enough funds for withdrawal");
170+
}
171+
172+
@Test
173+
void testAddAccountLogsCorrectly() {
174+
// Arrange
175+
String accountNumber = "555555555";
176+
Customer customer = new Customer(UUID.randomUUID(), "New Customer", true);
177+
CheckingAccount newAccount = new CheckingAccount(accountNumber, Set.of(customer), 300.0);
178+
customer.addAccount(newAccount);
179+
180+
// Act
181+
classUnderTest.addAccount(newAccount);
182+
183+
// Assert
184+
List<String> logEntries = classUnderTest.getAuditLogEntries();
185+
assertThat(logEntries).contains("Account added: " + accountNumber);
186+
}
110187
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
5+
6+
import java.util.Set;
7+
import java.util.UUID;
8+
import org.junit.jupiter.api.Test;
9+
10+
class BusinessCheckingAccountTest {
11+
12+
@Test
13+
void testConstructor_ThrowsException_NoBusinessOwner() {
14+
Customer individualOwner = new Customer(UUID.randomUUID(), "John Doe", false);
15+
Set<Customer> owners = Set.of(individualOwner);
16+
assertThatExceptionOfType(IllegalArgumentException.class)
17+
.isThrownBy(() -> new BusinessCheckingAccount("123456789", owners, 100.0))
18+
.withMessage("At least one owner must be a business");
19+
}
20+
21+
@Test
22+
void testConstructor_Success_WithBusinessOwner() {
23+
Customer businessOwner = new Customer(UUID.randomUUID(), "Tech Labs", true);
24+
Set<Customer> owners = Set.of(businessOwner);
25+
BusinessCheckingAccount account = new BusinessCheckingAccount("123456789", owners, 100.0);
26+
assertThat(account).isNotNull();
27+
assertThat(account.getBalance()).isEqualTo(100.0);
28+
}
29+
}

lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/CheckingAccountTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ class CheckingAccountTest {
2020
@BeforeEach
2121
void setUp() {
2222
owners = new HashSet<>();
23-
owners.add(new Customer(UUID.randomUUID(), "John Doe"));
24-
owners.add(new Customer(UUID.randomUUID(), "Jane Smith"));
23+
owners.add(new Customer(UUID.randomUUID(), "John Doe", false));
24+
owners.add(new Customer(UUID.randomUUID(), "Tech Corp", true));
2525
classUnderTest = new CheckingAccount("123456789", owners, 100.0);
2626
}
2727

0 commit comments

Comments
 (0)