Skip to content

Commit 97da979

Browse files
committed
feat: enhance BankAtm with money order support and multi-currency deposits
- Modified BankAtm, AuditLog, and CurrencyConverter to support new features - Added MoneyOrder class for handling money order transactions - Implemented SimpleCurrencyConverter for basic currency conversion logic - Introduced CurrencyConverterException to handle conversion errors - Updated BankAtmTest with new test cases for added functionality
1 parent 581c616 commit 97da979

File tree

7 files changed

+156
-42
lines changed

7 files changed

+156
-42
lines changed
Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
package com.codedifferently.lesson17.bank;
22

3+
import java.time.LocalDateTime;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
37
public class AuditLog {
4-
private final List<String> entries = new ArrayList<>();
58

6-
public void record(String message) {
7-
entries.add(LocalDateTime.now() + " - " + message);
8-
}
9+
private final List<String> entries = new ArrayList<>();
910

10-
public List<String> getEntries() {
11-
return entries;
12-
}
13-
}
11+
public void record(String message) {
12+
entries.add(LocalDateTime.now() + " - " + message);
13+
}
1414

15+
public List<String> getEntries() {
16+
return entries;
17+
}
1518

19+
public void printLog() {
20+
entries.forEach(System.out::println);
21+
}
22+
}

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

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,23 @@
11
package com.codedifferently.lesson17.bank;
22

3+
import com.codedifferently.lesson17.bank.exceptions.AccountNotFoundException;
34
import java.util.HashMap;
45
import java.util.Map;
56
import java.util.Set;
67
import java.util.UUID;
78

8-
import com.codedifferently.lesson17.bank.exceptions.AccountNotFoundException;
9-
109
/** Represents a bank ATM. */
1110
public class BankAtm {
1211

13-
1412
private final Map<UUID, Customer> customerById = new HashMap<>();
1513
private final Map<String, CheckingAccount> accountByNumber = new HashMap<>();
16-
private final AuditLog auditLog();
17-
private final CurrencyConverter currencyConverter();
14+
private final AuditLog auditLog;
1815

19-
public BankAtm(AuditLog auditLog, CurrencyConverter currencyConverter){
16+
public BankAtm(AuditLog auditLog) {
2017

21-
this.auditLog() = auditLog;
22-
this.currencyConverter() = currencyConverter;
18+
this.auditLog = auditLog;
2319
}
24-
2520

26-
27-
}
2821
/**
2922
* Adds a checking account to the bank.
3023
*
@@ -53,14 +46,35 @@ public Set<CheckingAccount> findAccountsByCustomerId(UUID customerId) {
5346
}
5447

5548
/**
56-
* Deposits funds into an account.
49+
* Deposits funds into the specified account. This method supports both cash (Double) and
50+
* MoneyOrder objects as deposit sources.
5751
*
58-
* @param accountNumber The account number.
59-
* @param amount The amount to deposit.
52+
* @param accountNumber the account to deposit into
53+
* @param source the deposit source; must be a Double (cash) or MoneyOrder
6054
*/
61-
public void depositFunds(String accountNumber, double amount) {
62-
CheckingAccount account = getAccountOrThrow(accountNumber);
63-
account.deposit(amount);
55+
public void depositFunds(String accountNumber, Object source) {
56+
// Retrieve the target account using the provided account number
57+
CheckingAccount targetAccount = (CheckingAccount) accountByNumber.get(accountNumber);
58+
59+
// If the deposit source is a MoneyOrder, extract the amount and deposit it
60+
if (source instanceof MoneyOrder newMoneyOrder) {
61+
if (targetAccount != null) {
62+
double amount = newMoneyOrder.getAmount();
63+
targetAccount.deposit(amount);
64+
auditLog.record("Deposited $" + amount + " via MoneyOrder to account " + accountNumber);
65+
}
66+
}
67+
// If the deposit source is cash (Double), proceed with a standard deposit
68+
else if (source instanceof Double amount) {
69+
if (targetAccount != null) {
70+
targetAccount.deposit(amount);
71+
auditLog.record("Deposited $" + amount + " in cash to account " + accountNumber);
72+
}
73+
}
74+
// If the source type is unsupported, throw an exception
75+
else {
76+
throw new IllegalArgumentException("Unsupported deposit type");
77+
}
6478
}
6579

6680
/**
@@ -72,6 +86,11 @@ public void depositFunds(String accountNumber, double amount) {
7286
public void depositFunds(String accountNumber, Check check) {
7387
CheckingAccount account = getAccountOrThrow(accountNumber);
7488
check.depositFunds(account);
89+
auditLog.record("Deposited check" + check + "into account" + accountNumber);
90+
}
91+
92+
public void printAuditLog() {
93+
auditLog.printLog();
7594
}
7695

7796
/**
@@ -83,6 +102,7 @@ public void depositFunds(String accountNumber, Check check) {
83102
public void withdrawFunds(String accountNumber, double amount) {
84103
CheckingAccount account = getAccountOrThrow(accountNumber);
85104
account.withdraw(amount);
105+
auditLog.record("Withdrew $" + amount + "from account" + accountNumber);
86106
}
87107

88108
/**
@@ -98,4 +118,4 @@ private CheckingAccount getAccountOrThrow(String accountNumber) {
98118
}
99119
return account;
100120
}
101-
121+
}
Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,5 @@
11
package com.codedifferently.lesson17.bank;
22

3-
public class CurrencyConverter {
4-
private final Map<Currency, Double> exchangeRates;
5-
6-
public CurrencyConverter() {
7-
exchangeRates = new HashMap<>();
8-
exchangeRates.put(Currency.USD, 1.0);
9-
exchangeRates.put(Currency.EUR, 1.1);
10-
exchangeRates.put(Currency.GBP, 1.3);
11-
12-
}
13-
14-
public double convert(double amount, Currency from, Currency to) {
15-
double usd = amount / exchangeRates.get(from);
16-
return usd * exchangeRates.get(to);
17-
}
3+
public interface CurrencyConverter {
4+
double convert(double amount, String fromCurrency, String toCurrency);
185
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
public class CurrencyConverterException extends RuntimeException {
4+
public CurrencyConverterException(String fromCurrency, String toCurrency) {
5+
super("Unsupported conversion from " + fromCurrency + " to " + toCurrency);
6+
}
7+
}
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+
public class MoneyOrder {
4+
private final double amount;
5+
private final String sourceAccountNumber;
6+
7+
public MoneyOrder(CheckingAccount sourceAccount, double amount) {
8+
this.amount = amount;
9+
this.sourceAccountNumber = sourceAccount.getAccountNumber();
10+
sourceAccount.withdraw(amount); // Withdraw immediately
11+
}
12+
13+
public double getAmount() {
14+
return amount;
15+
}
16+
17+
public String getSourceAccountNumber() {
18+
return sourceAccountNumber;
19+
}
20+
21+
public void depositTo(CheckingAccount destinationAccount) {
22+
destinationAccount.deposit(amount);
23+
}
24+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import java.util.Map;
4+
5+
public class SimpleCurrencyConverter implements CurrencyConverter {
6+
private final Map<String, Double> exchangeRates;
7+
8+
public SimpleCurrencyConverter(Map<String, Double> exchangeRates) {
9+
this.exchangeRates = exchangeRates;
10+
}
11+
12+
@Override
13+
public double convert(double amount, String fromCurrency, String toCurrency) {
14+
if (fromCurrency.equals(toCurrency)) return amount;
15+
16+
String key = fromCurrency + "_TO_" + toCurrency;
17+
Double rate = exchangeRates.get(key);
18+
19+
if (rate == null) {
20+
throw new CurrencyConverterException(fromCurrency, toCurrency);
21+
}
22+
23+
return amount * rate;
24+
}
25+
}

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

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22

33
import static org.assertj.core.api.Assertions.assertThat;
44
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
5+
import static org.junit.jupiter.api.Assertions.assertEquals;
6+
import static org.junit.jupiter.api.Assertions.assertThrows;
7+
import static org.junit.jupiter.api.Assertions.assertTrue;
58

69
import com.codedifferently.lesson17.bank.exceptions.AccountNotFoundException;
710
import com.codedifferently.lesson17.bank.exceptions.CheckVoidedException;
11+
import java.util.Map;
812
import java.util.Set;
913
import java.util.UUID;
1014
import org.junit.jupiter.api.BeforeEach;
@@ -18,16 +22,26 @@ class BankAtmTest {
1822
private Customer customer1;
1923
private Customer customer2;
2024

25+
Map<String, Double> rates =
26+
Map.of(
27+
"USD_TO_EUR", 0.85,
28+
"EUR_TO_USD", 1.18);
29+
SimpleCurrencyConverter converter = new SimpleCurrencyConverter(rates);
30+
2131
@BeforeEach
2232
void setUp() {
23-
classUnderTest = new BankAtm();
33+
AuditLog auditLog = new AuditLog();
34+
classUnderTest = new BankAtm(auditLog);
2435
customer1 = new Customer(UUID.randomUUID(), "John Doe");
2536
customer2 = new Customer(UUID.randomUUID(), "Jane Smith");
37+
2638
account1 = new CheckingAccount("123456789", Set.of(customer1), 100.0);
2739
account2 = new CheckingAccount("987654321", Set.of(customer1, customer2), 200.0);
40+
2841
customer1.addAccount(account1);
2942
customer1.addAccount(account2);
3043
customer2.addAccount(account2);
44+
3145
classUnderTest.addAccount(account1);
3246
classUnderTest.addAccount(account2);
3347
}
@@ -107,4 +121,34 @@ void testWithdrawFunds_AccountNotFound() {
107121
.isThrownBy(() -> classUnderTest.withdrawFunds(nonExistingAccountNumber, 50.0))
108122
.withMessage("Account not found");
109123
}
124+
125+
@Test
126+
void testDeposit_LogsToConsole() {
127+
classUnderTest.depositFunds(account1.getAccountNumber(), 50.0);
128+
129+
assertThat(account1.getBalance()).isEqualTo(150.0);
130+
131+
System.out.println("🧾 Audit Log:");
132+
classUnderTest.printAuditLog();
133+
}
134+
135+
@Test
136+
public void testConvert_USDToEUR() {
137+
double result = converter.convert(100.0, "USD", "EUR");
138+
assertEquals(85.0, result, 0.001);
139+
}
140+
141+
@Test
142+
public void testConvert_SameCurrency() {
143+
double result = converter.convert(100.0, "USD", "USD");
144+
assertEquals(100.0, result, 0.001);
145+
}
146+
147+
@Test
148+
public void testUnsupportedConversion_ThrowsException() {
149+
Exception exception =
150+
assertThrows(
151+
CurrencyConverterException.class, () -> converter.convert(100.0, "USD", "JPY"));
152+
assertTrue(exception.getMessage().contains("Unsupported conversion"));
153+
}
110154
}

0 commit comments

Comments
 (0)