Skip to content

Commit 28d2adb

Browse files
committed
feat: adds 2 feats to BankATM: todo: remove comments
1 parent 1c93014 commit 28d2adb

File tree

8 files changed

+145
-6
lines changed

8 files changed

+145
-6
lines changed

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class BankAtm {
1111

1212
private final Map<UUID, Customer> customerById = new HashMap<>();
1313
private final Map<String, CheckingAccount> accountByNumber = new HashMap<>();
14+
private final CurrencyConverter currencyConverter = new FixedRateCurrencyConverter();
1415

1516
/**
1617
* Adds a checking account to the bank.
@@ -40,14 +41,20 @@ public Set<CheckingAccount> findAccountsByCustomerId(UUID customerId) {
4041
}
4142

4243
/**
43-
* Deposits funds into an account.
44+
* Deposits funds into an account in a given currency. Non-USD is converted to USD using a
45+
* fixed-rate converter. Rounds to 2 decimals, half-up. Throws AccountNotFoundException if account
46+
* is missing or closed, IllegalArgumentException for non-positive amounts, and
47+
* UnsupportedOperationException for unsupported currencies.
4448
*
4549
* @param accountNumber The account number.
4650
* @param amount The amount to deposit.
51+
* @param currency The currency type.
4752
*/
48-
public void depositFunds(String accountNumber, double amount) {
53+
public void depositFunds(String accountNumber, double amount, Currency currency) {
4954
CheckingAccount account = getAccountOrThrow(accountNumber);
50-
account.deposit(amount);
55+
double usdAmount =
56+
(currency == Currency.USD) ? amount : currencyConverter.convertToUsd(amount, currency);
57+
account.deposit(usdAmount);
5158
}
5259

5360
/**
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+
import java.util.Set;
4+
5+
/**
6+
* A business checking account. Requires at least one business owner. Throws
7+
* IllegalArgumentException if no owners are businesses.
8+
*/
9+
public class BusinessCheckingAccount extends CheckingAccount {
10+
public BusinessCheckingAccount(
11+
String accountNumber, Set<Customer> owners, double initialBalance) {
12+
super(accountNumber, owners, initialBalance);
13+
boolean hasBusiness = owners.stream().anyMatch(Customer::isBusiness);
14+
if (!hasBusiness) {
15+
throw new IllegalArgumentException(
16+
"BusinessCheckingAccount requires at least one business owner");
17+
}
18+
}
19+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
/** Supported currencies for deposit. */
4+
public enum Currency {
5+
USD,
6+
EUR,
7+
GBP
8+
}
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+
/** Converts an amount in a given currency to USD. */
4+
public interface CurrencyConverter {
5+
/**
6+
* Converts the given amount in the given currency to USD.
7+
*
8+
* @param amount The amount in the original currency.
9+
* @param currency The currency type.
10+
* @return The equivalent amount in USD, rounded to 2 decimals (half-up).
11+
* @throws UnsupportedOperationException if the currency is not supported.
12+
*/
13+
double convertToUsd(double amount, Currency currency);
14+
}

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

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

1415
/**
15-
* Creates a new customer.
16+
* Creates a new customer (individual).
1617
*
1718
* @param id The ID of the customer.
1819
* @param name The name of the customer.
1920
*/
2021
public Customer(UUID id, String name) {
22+
this(id, name, false);
23+
}
24+
25+
/**
26+
* Creates a new customer (individual or business).
27+
*
28+
* @param id The ID of the customer.
29+
* @param name The name of the customer.
30+
* @param isBusiness True if this customer is a business, false if an individual.
31+
*/
32+
public Customer(UUID id, String name, boolean isBusiness) {
2133
this.id = id;
2234
this.name = name;
35+
this.isBusiness = isBusiness;
2336
}
2437

2538
/**
@@ -58,6 +71,11 @@ public Set<CheckingAccount> getAccounts() {
5871
return accounts;
5972
}
6073

74+
/** Returns true if this customer is a business. */
75+
public boolean isBusiness() {
76+
return isBusiness;
77+
}
78+
6179
@Override
6280
public int hashCode() {
6381
return id.hashCode();
@@ -73,6 +91,6 @@ public boolean equals(Object obj) {
7391

7492
@Override
7593
public String toString() {
76-
return "Customer{" + "id=" + id + ", name='" + name + '\'' + '}';
94+
return "Customer{" + "id=" + id + ", name='" + name + '\'' + ", isBusiness=" + isBusiness + '}';
7795
}
7896
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import java.math.BigDecimal;
4+
import java.math.RoundingMode;
5+
import java.util.Map;
6+
7+
/** Fixed-rate currency converter for supported currencies to USD. */
8+
public class FixedRateCurrencyConverter implements CurrencyConverter {
9+
private static final Map<Currency, Double> RATES =
10+
Map.of(
11+
Currency.USD, 1.0,
12+
Currency.EUR, 1.08,
13+
Currency.GBP, 1.25);
14+
15+
@Override
16+
public double convertToUsd(double amount, Currency currency) {
17+
if (currency == null) {
18+
throw new UnsupportedOperationException("Unsupported currency: null");
19+
}
20+
Double rate = RATES.get(currency);
21+
if (rate == null) {
22+
throw new UnsupportedOperationException("Unsupported currency: " + currency);
23+
}
24+
double usd = amount * rate;
25+
return BigDecimal.valueOf(usd).setScale(2, RoundingMode.HALF_UP).doubleValue();
26+
}
27+
}

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void testFindAccountsByCustomerId() {
5959
@Test
6060
void testDepositFunds() {
6161
// Act
62-
classUnderTest.depositFunds(account1.getAccountNumber(), 50.0);
62+
classUnderTest.depositFunds(account1.getAccountNumber(), 50.0, Currency.USD);
6363

6464
// Assert
6565
assertThat(account1.getBalance()).isEqualTo(150.0);
@@ -107,4 +107,24 @@ void testWithdrawFunds_AccountNotFound() {
107107
.isThrownBy(() -> classUnderTest.withdrawFunds(nonExistingAccountNumber, 50.0))
108108
.withMessage("Account not found");
109109
}
110+
111+
@Test
112+
void testDepositFunds_EUR() {
113+
// Arrange: 100 EUR at 1.08 = 108.00 USD
114+
double eurAmount = 100.0;
115+
double expectedUsd = 108.00;
116+
// Act
117+
classUnderTest.depositFunds(account1.getAccountNumber(), eurAmount, Currency.EUR);
118+
// Assert
119+
assertThat(account1.getBalance()).isEqualTo(100.0 + expectedUsd);
120+
}
121+
122+
@Test
123+
void testDepositFunds_UnsupportedCurrency() {
124+
// Arrange: Use a fake currency
125+
Currency unsupported = null;
126+
// Act & Assert
127+
assertThatExceptionOfType(UnsupportedOperationException.class)
128+
.isThrownBy(() -> classUnderTest.depositFunds(account1.getAccountNumber(), 100.0, null));
129+
}
110130
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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+
@Test
12+
void testValidBusinessOwner() {
13+
Customer business = new Customer(UUID.randomUUID(), "Biz LLC", true);
14+
BusinessCheckingAccount acct = new BusinessCheckingAccount("BIZ123", Set.of(business), 100.0);
15+
assertThat(acct.getBalance()).isEqualTo(100.0);
16+
}
17+
18+
@Test
19+
void testInvalidBusinessOwner() {
20+
Customer person1 = new Customer(UUID.randomUUID(), "Alice");
21+
Customer person2 = new Customer(UUID.randomUUID(), "Bob");
22+
assertThatExceptionOfType(IllegalArgumentException.class)
23+
.isThrownBy(() -> new BusinessCheckingAccount("BIZ124", Set.of(person1, person2), 100.0))
24+
.withMessage("BusinessCheckingAccount requires at least one business owner");
25+
}
26+
}

0 commit comments

Comments
 (0)