diff --git a/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/BankAtm.java b/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/BankAtm.java
index 8cbcd3cc0..25e481ded 100644
--- a/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/BankAtm.java
+++ b/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/BankAtm.java
@@ -58,17 +58,28 @@ public void depositFunds(String accountNumber, double amount) {
*/
public void depositFunds(String accountNumber, Check check) {
CheckingAccount account = getAccountOrThrow(accountNumber);
+ if ((account instanceof SavingsAccount)) {
+ throw new IllegalArgumentException("Only checking accounts can make checks");
+ }
check.depositFunds(account);
}
/**
- * Withdraws funds from an account.
+ * Withdraws funds from a specified account.
*
- * @param accountNumber
- * @param amount
+ * @param accountNumber The unique identifier of the account.
+ * @param amount The amount to withdraw from the account.
+ * @throws IllegalArgumentException if the account is not found or if the withdrawal would result
+ * in a balance below $10,000 for a BusinessCheckingAccount.
*/
public void withdrawFunds(String accountNumber, double amount) {
CheckingAccount account = getAccountOrThrow(accountNumber);
+ if ((account instanceof BusinessCheckingAccount)) {
+ if (account.getBalance() - amount < 10000) {
+ throw new IllegalArgumentException(
+ "Business checking account balance must remain greater than $10,000");
+ }
+ }
account.withdraw(amount);
}
diff --git a/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/BusinessCheckingAccount.java b/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/BusinessCheckingAccount.java
new file mode 100644
index 000000000..0f35bb23c
--- /dev/null
+++ b/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/BusinessCheckingAccount.java
@@ -0,0 +1,53 @@
+package com.codedifferently.lesson17.bank;
+
+import java.util.Set;
+
+public class BusinessCheckingAccount extends CheckingAccount {
+
+ /**
+ * Creates a new BusinessCheckingAccount with the specified account number, owners, and initial
+ * balance.
+ *
+ *
This constructor ensures that the account meets the minimum requirements for a business
+ * checking account, including a minimum initial balance of $10,000 and at least one business
+ * owner in the provided set of owners. If these requirements are not met, an {@link
+ * IllegalArgumentException} is thrown.
+ *
+ * @param accountNumber The unique identifier for the account.
+ * @param owners A set of {@link Customer} objects representing the owners of the account.
+ * @param initialBalance The initial balance of the account, which must be at least $10,000.
+ * @throws IllegalArgumentException If the initial balance is less than $10,000 or if none of the
+ * owners meet the criteria to be considered a business owner.
+ */
+ public BusinessCheckingAccount(
+ String accountNumber, Set owners, double initialBalance) {
+ super(accountNumber, owners, initialBalance);
+
+ // Business Account Logic
+ if (initialBalance < 10000) {
+ throw new IllegalArgumentException("Business accounts require a minimum balance of $10,000.");
+ }
+ if (!hasBusinessOwner(owners)) {
+ throw new IllegalArgumentException(
+ "A business checking account must have at least one business owner.");
+ }
+ }
+
+ /**
+ * Checks if at least one owner of the account is a business.
+ *
+ * This method examines each owner in the "owners" set and returns true if any owner's name
+ * contains "INC" or "LLC" (case-insensitive), which are used as indicators of a business owning
+ * the account.
+ *
+ * @param owners The set of account owners to check.
+ * @return true if the account has at least one business owner; false otherwise.
+ */
+ public boolean hasBusinessOwner(Set owners) {
+ return getOwners().stream()
+ .anyMatch(
+ owner ->
+ owner.getName().toUpperCase().contains("INC")
+ || owner.getName().toUpperCase().contains("LLC"));
+ }
+}
diff --git a/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/Check.java b/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/Check.java
index 061fa4a5c..74814a69e 100644
--- a/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/Check.java
+++ b/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/Check.java
@@ -16,8 +16,13 @@ public class Check {
* @param checkNumber The check number.
* @param amount The amount of the check.
* @param account The account the check is drawn on.
+ * @throws IllegalArgumentException if the amount is negative or the account is not a
+ * `CheckingAccount` or `BusinessCheckingAccount` instance.
*/
public Check(String checkNumber, double amount, CheckingAccount account) {
+ if ((account instanceof SavingsAccount)) {
+ throw new IllegalArgumentException("Only checking accounts can make checks");
+ }
if (amount < 0) {
throw new IllegalArgumentException("Check amount must be positive");
}
diff --git a/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/SavingsAccount.java b/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/SavingsAccount.java
new file mode 100644
index 000000000..266f8fdc1
--- /dev/null
+++ b/lesson_17/bank/bank_app/src/main/java/com/codedifferently/lesson17/bank/SavingsAccount.java
@@ -0,0 +1,10 @@
+package com.codedifferently.lesson17.bank;
+
+import java.util.Set;
+
+public class SavingsAccount extends CheckingAccount {
+
+ public SavingsAccount(String accountNumber, Set owners, double initialBalance) {
+ super(accountNumber, owners, initialBalance);
+ }
+}
diff --git a/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/BankAtmTest.java b/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/BankAtmTest.java
index fa4a913a2..eb2774265 100644
--- a/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/BankAtmTest.java
+++ b/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/BankAtmTest.java
@@ -15,21 +15,26 @@ class BankAtmTest {
private BankAtm classUnderTest;
private CheckingAccount account1;
private CheckingAccount account2;
+ private BusinessCheckingAccount account3;
private Customer customer1;
private Customer customer2;
+ private Customer customer3;
@BeforeEach
void setUp() {
classUnderTest = new BankAtm();
customer1 = new Customer(UUID.randomUUID(), "John Doe");
customer2 = new Customer(UUID.randomUUID(), "Jane Smith");
+ customer3 = new Customer(UUID.randomUUID(), "Doodle-Bob INC.");
account1 = new CheckingAccount("123456789", Set.of(customer1), 100.0);
account2 = new CheckingAccount("987654321", Set.of(customer1, customer2), 200.0);
+ account3 = new BusinessCheckingAccount("102938475", Set.of(customer3), 10000.0);
customer1.addAccount(account1);
customer1.addAccount(account2);
customer2.addAccount(account2);
classUnderTest.addAccount(account1);
classUnderTest.addAccount(account2);
+ classUnderTest.addAccount(account3);
}
@Test
@@ -107,4 +112,11 @@ void testWithdrawFunds_AccountNotFound() {
.isThrownBy(() -> classUnderTest.withdrawFunds(nonExistingAccountNumber, 50.0))
.withMessage("Account not found");
}
+
+ @Test
+ void testWithdrawFunds_BusinessAccountBalanceBelowMinimum() {
+ assertThatExceptionOfType(IllegalArgumentException.class)
+ .isThrownBy(() -> classUnderTest.withdrawFunds(account3.getAccountNumber(), 200.0))
+ .withMessage("Business checking account balance must remain greater than $10,000");
+ }
}
diff --git a/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/BusinessCheckingAccountTest.java b/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/BusinessCheckingAccountTest.java
new file mode 100644
index 000000000..e3bc9e154
--- /dev/null
+++ b/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/BusinessCheckingAccountTest.java
@@ -0,0 +1,79 @@
+package com.codedifferently.lesson17.bank;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class BusinessCheckingAccountTest {
+ private Set owners;
+
+ @BeforeEach
+ public void setUp() {
+ owners = new HashSet<>();
+ }
+
+ @Test
+ public void testBusinessCheckingAccount_HasBusinessOwner_WithIncInName() {
+ UUID id = UUID.randomUUID();
+ Customer businesserOwner = new Customer(id, "Bob INC.");
+
+ owners.add(businesserOwner);
+
+ BusinessCheckingAccount account = new BusinessCheckingAccount("12345", owners, 15000);
+ assertNotNull(account);
+ assertEquals(15000, account.getBalance());
+ assertEquals("12345", account.getAccountNumber());
+ }
+
+ @Test
+ public void testBusinessCheckingAccount_HasBusinessOwner_WithLlcInName() {
+ UUID id = UUID.randomUUID();
+ Customer businesserOwner = new Customer(id, "Bob LLC.");
+
+ owners.add(businesserOwner);
+
+ BusinessCheckingAccount account = new BusinessCheckingAccount("12345", owners, 15000);
+ assertNotNull(account);
+ assertEquals(15000, account.getBalance());
+ assertEquals("12345", account.getAccountNumber());
+ }
+
+ @Test
+ public void testBusinessCheckingAccount_WithoutBusinessOwner() {
+ UUID individualId = UUID.randomUUID();
+ Customer individualOwner =
+ new Customer(individualId, "John Doe"); // Example customer without business designation
+
+ owners.add(individualOwner); // Add the individual owner to the set
+
+ assertThatThrownBy(
+ () -> {
+ new BusinessCheckingAccount("12345", owners, 15000);
+ })
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("A business checking account must have at least one business owner.");
+ }
+
+ @Test
+ public void testBusinessCheckingAccount_BelowMinimumBalance() {
+ UUID businessId = UUID.randomUUID();
+ Customer businessOwner =
+ new Customer(businessId, "ABC LLC"); // Create a customer with a valid business name
+
+ owners.add(businessOwner); // Add the business owner to the set
+
+ assertThatThrownBy(
+ () -> {
+ new BusinessCheckingAccount(
+ "12345", owners, 5000); // Attempt to create with a balance below 10,000
+ })
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("Business accounts require a minimum balance of $10,000.");
+ }
+}
diff --git a/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/CheckTest.java b/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/CheckTest.java
index 6b62d39ba..280bc2176 100644
--- a/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/CheckTest.java
+++ b/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/CheckTest.java
@@ -2,6 +2,8 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import com.codedifferently.lesson17.bank.exceptions.CheckVoidedException;
import org.junit.jupiter.api.BeforeEach;
@@ -49,6 +51,18 @@ void testConstructor_CantCreateCheckWithNegativeAmount() {
.withMessage("Check amount must be positive");
}
+ @Test
+ void testConstructor_CantCreateCheckWithSavingsAccount() {
+ SavingsAccount savingsAccount = new SavingsAccount("12345", null, 500.0);
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> {
+ new Check("123", 100, savingsAccount);
+ });
+ assertEquals("Only checking accounts can make checks", exception.getMessage());
+ }
+
@Test
void testHashCode() {
// Arrange
diff --git a/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/SavingsAccountTest.java b/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/SavingsAccountTest.java
new file mode 100644
index 000000000..81f0d7fec
--- /dev/null
+++ b/lesson_17/bank/bank_app/src/test/java/com/codedifferently/lesson17/bank/SavingsAccountTest.java
@@ -0,0 +1,18 @@
+package com.codedifferently.lesson17.bank;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+import org.junit.jupiter.api.BeforeEach;
+
+public class SavingsAccountTest {
+ private SavingsAccount savingsAccount;
+ private Set owners;
+
+ @BeforeEach
+ void setUp() {
+ owners = new HashSet<>();
+ owners.add(new Customer(UUID.randomUUID(), "Bob Smith"));
+ savingsAccount = new SavingsAccount("12345", owners, 500);
+ }
+}