Skip to content

feat: RMiller_lesson_17_adds moneyorder and auditlog ATM simulator #537

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
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
@@ -0,0 +1,33 @@
package com.codedifferently.lesson17.bank;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class AuditLog {

private static final AuditLog INSTANCE = new AuditLog();

private final List<String> entries;

private AuditLog() {
this.entries = new ArrayList<>();
}

public static AuditLog getInstance() {
return INSTANCE;
}

public void log(String type, String accountNumber, double amount) {
String entry = String.format("%s - Account: %s, Amount: %.2f", type, accountNumber, amount);
entries.add(entry);
}

public List<String> getEntries() {
return Collections.unmodifiableList(entries);
}

public void clear() {
entries.clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class BankAtm {

private final Map<UUID, Customer> customerById = new HashMap<>();
private final Map<String, CheckingAccount> accountByNumber = new HashMap<>();
private Map<UUID, CheckingAccount> accounts;

/**
* Adds a checking account to the bank.
Expand Down Expand Up @@ -48,6 +49,7 @@ public Set<CheckingAccount> findAccountsByCustomerId(UUID customerId) {
public void depositFunds(String accountNumber, double amount) {
CheckingAccount account = getAccountOrThrow(accountNumber);
account.deposit(amount);
AuditLog.getInstance().log("DEPOSIT", account.getAccountNumber(), amount);
}

/**
Expand All @@ -59,6 +61,13 @@ public void depositFunds(String accountNumber, double amount) {
public void depositFunds(String accountNumber, Check check) {
CheckingAccount account = getAccountOrThrow(accountNumber);
check.depositFunds(account);
AuditLog.getInstance().log("CHECK DEPOSIT", account.getAccountNumber(), check.getAmount());
}

public void depositFunds(String accountNumber, MoneyOrder mo) {
Copy link
Contributor

Choose a reason for hiding this comment

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

You were not to add any new methods.

CheckingAccount toAccount = (CheckingAccount) accounts.get(accountNumber); // ✅ must not be null
mo.depositFunds(toAccount);
AuditLog.getInstance().log("MONEY ORDER DEPOSIT", toAccount.getAccountNumber(), mo.getAmount());
}

/**
Expand All @@ -70,6 +79,7 @@ public void depositFunds(String accountNumber, Check check) {
public void withdrawFunds(String accountNumber, double amount) {
CheckingAccount account = getAccountOrThrow(accountNumber);
account.withdraw(amount);
AuditLog.getInstance().log("WITHDRAWAL", account.getAccountNumber(), amount);
}

/**
Expand All @@ -85,4 +95,9 @@ private CheckingAccount getAccountOrThrow(String accountNumber) {
}
return account;
}

public BankAtm getBank() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getBank'");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public void depositFunds(CheckingAccount toAccount) {
voidCheck();
}

public double getAmount() {
return amount;
}

@Override
public int hashCode() {
return checkNumber.hashCode();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.codedifferently.lesson17.bank;

import java.util.UUID;

public class MoneyOrder extends Check {
Copy link
Contributor

Choose a reason for hiding this comment

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

A money order is not a check.


public MoneyOrder(CheckingAccount sourceAccount, double amount) {
super("MO-" + UUID.randomUUID(), amount, sourceAccount);

sourceAccount.withdraw(amount);

AuditLog.getInstance().log("MONEY ORDER ISSUED", sourceAccount.getAccountNumber(), amount);
}

@Override
public void depositFunds(CheckingAccount toAccount) {
if (getIsVoided()) {
throw new RuntimeException("This money order has already been deposited or voided.");
}

toAccount.deposit(getAmount());
voidCheck();

AuditLog.getInstance().log("MONEY ORDER DEPOSIT", toAccount.getAccountNumber(), getAmount());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.codedifferently.lesson17.bank;

import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class AuditLogTest {

private BankAtm bankAtm;
private CheckingAccount sourceAccount;
private CheckingAccount targetAccount;

@BeforeEach
void setUp() {
AuditLog.getInstance().clear();

bankAtm = new BankAtm();

Customer alice = new Customer(UUID.randomUUID(), "Alice");
Customer bob = new Customer(UUID.randomUUID(), "Bob");

Set<Customer> owners1 = Set.of(alice);
Set<Customer> owners2 = Set.of(bob);

sourceAccount = new CheckingAccount("SRC123", owners1, 1000.0);
targetAccount = new CheckingAccount("TRG456", owners2, 500.0);

bankAtm.addAccount(sourceAccount);
bankAtm.addAccount(targetAccount);
}

@Test
void testAuditLogRecordsStandardDeposit() {
bankAtm.depositFunds(targetAccount.getAccountNumber(), 500.0);

List<String> entries = AuditLog.getInstance().getEntries();
assertTrue(entries.stream().anyMatch(e -> e.contains("DEPOSIT") && e.contains("TRG456")));
}

@Test
void testAuditLogRecordsStandardWithdrawal() {
bankAtm.depositFunds(targetAccount.getAccountNumber(), 200.0);
bankAtm.withdrawFunds(targetAccount.getAccountNumber(), 100.0);

List<String> entries = AuditLog.getInstance().getEntries();
assertTrue(entries.stream().anyMatch(e -> e.contains("WITHDRAWAL") && e.contains("TRG456")));
}

@Test
void testAuditLogRecordsCheckDeposit() {
Check check = new Check("CHK123", 100.0, sourceAccount);
bankAtm.depositFunds(targetAccount.getAccountNumber(), check);

List<String> entries = AuditLog.getInstance().getEntries();
assertTrue(entries.stream().anyMatch(e -> e.contains("CHECK DEPOSIT")));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,21 @@ class BankAtmTest {
private CheckingAccount account2;
private Customer customer1;
private Customer customer2;
private BankAtm BankAtm;

@BeforeEach
void setUp() {
classUnderTest = new BankAtm();
new BankAtm();
Copy link
Contributor

Choose a reason for hiding this comment

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

Why?


customer1 = new Customer(UUID.randomUUID(), "John Doe");
customer2 = new Customer(UUID.randomUUID(), "Jane Smith");
account1 = new CheckingAccount("123456789", Set.of(customer1), 100.0);
account2 = new CheckingAccount("987654321", Set.of(customer1, customer2), 200.0);
customer1.addAccount(account1);
customer1.addAccount(account2);
customer2.addAccount(account2);

classUnderTest.addAccount(account1);
classUnderTest.addAccount(account2);
}
Expand Down Expand Up @@ -58,10 +62,8 @@ void testFindAccountsByCustomerId() {

@Test
void testDepositFunds() {
// Act
Copy link
Contributor

Choose a reason for hiding this comment

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

Why?

classUnderTest.depositFunds(account1.getAccountNumber(), 50.0);

// Assert
assertThat(account1.getBalance()).isEqualTo(150.0);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.codedifferently.lesson17.bank;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class MoneyOrderTest {

private CheckingAccount sourceAccount;
private CheckingAccount targetAccount;

@BeforeEach
void setUp() {
Customer alice = new Customer(UUID.randomUUID(), "Alice");
Customer bob = new Customer(UUID.randomUUID(), "Bob");

sourceAccount = new CheckingAccount("SRC123", Set.of(alice), 0.0);
targetAccount = new CheckingAccount("TRG456", Set.of(bob), 0.0);

sourceAccount.deposit(1000.0);
}

@Test
void testMoneyOrderWithdrawsImmediatelyFromSource() {
double initialBalance = sourceAccount.getBalance();
double amount = 250.0;

MoneyOrder moneyOrder = new MoneyOrder(sourceAccount, amount);

assertEquals(initialBalance - amount, sourceAccount.getBalance(), 0.001);
Copy link
Contributor

Choose a reason for hiding this comment

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

Test is difficult to read. Would've been better like this:

// Arrange
var sourceAccount = new CheckingAccount("TRG456", Set.of(bob), 1000.0);

// Act
var moneyOrder = new MoneyOrder(sourceAccount, 250);

// Assert
assertEquals(750.0, sourceAccount.getBalance(), 0.001);

Remember that we prefer our tests to be DAMP, not DRY.

}

@Test
void testMoneyOrderCanBeDepositedToAnotherAccount() {
double amount = 300.0;

MoneyOrder moneyOrder = new MoneyOrder(sourceAccount, amount);
moneyOrder.depositFunds(targetAccount);

assertEquals(amount, targetAccount.getBalance(), 0.001);
}

@Test
void testMoneyOrderAmountIsCorrect() {
MoneyOrder moneyOrder = new MoneyOrder(sourceAccount, 123.45);
assertEquals(123.45, moneyOrder.getAmount(), 0.001);
}
}