Skip to content

feat: implemented SavingsAccount and BusinessCheckingAccount classes #551

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you add this? This was not in the requirements.

throw new IllegalArgumentException(
"Business checking account balance must remain greater than $10,000");
}
}
account.withdraw(amount);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>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<Customer> 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.
*
* <p>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<Customer> owners) {
return getOwners().stream()
.anyMatch(
owner ->
owner.getName().toUpperCase().contains("INC")
|| owner.getName().toUpperCase().contains("LLC"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.codedifferently.lesson17.bank;

import java.util.Set;

public class SavingsAccount extends CheckingAccount {

public SavingsAccount(String accountNumber, Set<Customer> owners, double initialBalance) {
super(accountNumber, owners, initialBalance);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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");
}
}
Original file line number Diff line number Diff line change
@@ -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<Customer> 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.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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<Customer> owners;

@BeforeEach
void setUp() {
owners = new HashSet<>();
owners.add(new Customer(UUID.randomUUID(), "Bob Smith"));
savingsAccount = new SavingsAccount("12345", owners, 500);
}
}