Skip to content

Commit 1fe3735

Browse files
committed
lesson 17
1 parent ccf8696 commit 1fe3735

21 files changed

+443
-128
lines changed
Binary file not shown.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import java.util.Set;
4+
5+
/**
6+
* Interface representing a bank account. This interface defines the common operations that all
7+
* account types must support.
8+
*/
9+
public interface Account {
10+
11+
/**
12+
* Gets the account number.
13+
*
14+
* @return The account number.
15+
*/
16+
String getAccountNumber();
17+
18+
/**
19+
* Gets the owners of the account.
20+
*
21+
* @return The owners of the account.
22+
*/
23+
Set<Customer> getOwners();
24+
25+
/**
26+
* Deposits funds into the account.
27+
*
28+
* @param amount The amount to deposit.
29+
* @throws IllegalStateException if the account is closed or amount is invalid.
30+
*/
31+
void deposit(double amount);
32+
33+
/**
34+
* Withdraws funds from the account.
35+
*
36+
* @param amount The amount to withdraw.
37+
* @throws IllegalStateException if the account is closed or amount is invalid.
38+
* @throws com.codedifferently.lesson17.bank.exceptions.InsufficientFundsException if insufficient
39+
* funds.
40+
*/
41+
void withdraw(double amount);
42+
43+
/**
44+
* Gets the balance of the account.
45+
*
46+
* @return The balance of the account.
47+
*/
48+
double getBalance();
49+
50+
/**
51+
* Closes the account.
52+
*
53+
* @throws IllegalStateException if the account cannot be closed.
54+
*/
55+
void closeAccount();
56+
57+
/**
58+
* Checks if the account is closed.
59+
*
60+
* @return True if the account is closed, otherwise false.
61+
*/
62+
boolean isClosed();
63+
}
Binary file not shown.
Binary file not shown.
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import java.time.LocalDateTime;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
7+
/**
8+
* Audit log for tracking all banking transactions. Records debits and credits to accounts for
9+
* compliance and traceability.
10+
*/
11+
public class AuditLog {
12+
13+
private final List<AuditEntry> entries = new ArrayList<>();
14+
15+
/**
16+
* Records a debit transaction.
17+
*
18+
* @param accountNumber The account number.
19+
* @param amount The amount debited.
20+
* @param description Description of the transaction.
21+
*/
22+
public void recordDebit(String accountNumber, double amount, String description) {
23+
entries.add(new AuditEntry(accountNumber, TransactionType.DEBIT, amount, description));
24+
}
25+
26+
/**
27+
* Records a credit transaction.
28+
*
29+
* @param accountNumber The account number.
30+
* @param amount The amount credited.
31+
* @param description Description of the transaction.
32+
*/
33+
public void recordCredit(String accountNumber, double amount, String description) {
34+
entries.add(new AuditEntry(accountNumber, TransactionType.CREDIT, amount, description));
35+
}
36+
37+
/**
38+
* Gets all audit entries.
39+
*
40+
* @return List of all audit entries.
41+
*/
42+
public List<AuditEntry> getAllEntries() {
43+
return new ArrayList<>(entries);
44+
}
45+
46+
/**
47+
* Gets audit entries for a specific account.
48+
*
49+
* @param accountNumber The account number to filter by.
50+
* @return List of audit entries for the specified account.
51+
*/
52+
public List<AuditEntry> getEntriesForAccount(String accountNumber) {
53+
return entries.stream()
54+
.filter(entry -> entry.getAccountNumber().equals(accountNumber))
55+
.toList();
56+
}
57+
58+
/**
59+
* Gets the total number of recorded transactions.
60+
*
61+
* @return The total number of transactions.
62+
*/
63+
public int getTransactionCount() {
64+
return entries.size();
65+
}
66+
67+
/** Represents a single audit entry. */
68+
public static class AuditEntry {
69+
private final String accountNumber;
70+
private final TransactionType type;
71+
private final double amount;
72+
private final String description;
73+
private final LocalDateTime timestamp;
74+
75+
/**
76+
* Creates a new audit entry.
77+
*
78+
* @param accountNumber The account number.
79+
* @param type The transaction type.
80+
* @param amount The transaction amount.
81+
* @param description The transaction description.
82+
*/
83+
public AuditEntry(
84+
String accountNumber, TransactionType type, double amount, String description) {
85+
this.accountNumber = accountNumber;
86+
this.type = type;
87+
this.amount = amount;
88+
this.description = description;
89+
this.timestamp = LocalDateTime.now();
90+
}
91+
92+
/**
93+
* Gets the account number.
94+
*
95+
* @return The account number.
96+
*/
97+
public String getAccountNumber() {
98+
return accountNumber;
99+
}
100+
101+
/**
102+
* Gets the transaction type.
103+
*
104+
* @return The transaction type.
105+
*/
106+
public TransactionType getType() {
107+
return type;
108+
}
109+
110+
/**
111+
* Gets the transaction amount.
112+
*
113+
* @return The transaction amount.
114+
*/
115+
public double getAmount() {
116+
return amount;
117+
}
118+
119+
/**
120+
* Gets the transaction description.
121+
*
122+
* @return The transaction description.
123+
*/
124+
public String getDescription() {
125+
return description;
126+
}
127+
128+
/**
129+
* Gets the transaction timestamp.
130+
*
131+
* @return The transaction timestamp.
132+
*/
133+
public LocalDateTime getTimestamp() {
134+
return timestamp;
135+
}
136+
137+
@Override
138+
public String toString() {
139+
return String.format(
140+
"[%s] %s %s: %.2f - %s", timestamp, accountNumber, type, amount, description);
141+
}
142+
}
143+
144+
/** Enumeration for transaction types. */
145+
public enum TransactionType {
146+
CREDIT,
147+
DEBIT
148+
}
149+
}
Binary file not shown.

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

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

3-
import com.codedifferently.lesson17.bank.exceptions.AccountNotFoundException;
43
import java.util.HashMap;
54
import java.util.Map;
65
import java.util.Set;
76
import java.util.UUID;
87

9-
/** Represents a bank ATM. */
8+
import com.codedifferently.lesson17.bank.exceptions.AccountNotFoundException;
9+
10+
/** Represents a bank ATM with audit logging capabilities. */
1011
public class BankAtm {
1112

1213
private final Map<UUID, Customer> customerById = new HashMap<>();
13-
private final Map<String, CheckingAccount> accountByNumber = new HashMap<>();
14+
private final Map<String, Account> accountByNumber = new HashMap<>();
15+
private final AuditLog auditLog = new AuditLog();
1416

1517
/**
1618
* Adds a checking account to the bank.
1719
*
1820
* @param account The account to add.
1921
*/
2022
public void addAccount(CheckingAccount account) {
23+
addAccountInternal(account);
24+
}
25+
26+
/**
27+
* Adds a savings account to the bank.
28+
*
29+
* @param account The savings account to add.
30+
*/
31+
public void addAccount(SavingsAccount account) {
32+
addAccountInternal(account);
33+
}
34+
35+
/**
36+
* Internal method to add any type of account.
37+
*
38+
* @param account The account to add.
39+
*/
40+
private void addAccountInternal(Account account) {
2141
accountByNumber.put(account.getAccountNumber(), account);
2242
account
2343
.getOwners()
@@ -46,30 +66,55 @@ public Set<CheckingAccount> findAccountsByCustomerId(UUID customerId) {
4666
* @param amount The amount to deposit.
4767
*/
4868
public void depositFunds(String accountNumber, double amount) {
49-
CheckingAccount account = getAccountOrThrow(accountNumber);
69+
Account account = getAccountOrThrow(accountNumber);
5070
account.deposit(amount);
71+
auditLog.recordCredit(accountNumber, amount, "Cash deposit");
5172
}
5273

5374
/**
54-
* Deposits funds into an account using a check.
75+
* Deposits funds into an account using a check. Note: Only checking accounts support check
76+
* deposits.
5577
*
5678
* @param accountNumber The account number.
5779
* @param check The check to deposit.
80+
* @throws IllegalArgumentException if trying to deposit a check to a savings account.
5881
*/
5982
public void depositFunds(String accountNumber, Check check) {
60-
CheckingAccount account = getAccountOrThrow(accountNumber);
61-
check.depositFunds(account);
83+
Account account = getAccountOrThrow(accountNumber);
84+
85+
// Only checking accounts can accept check deposits
86+
if (!(account instanceof CheckingAccount)) {
87+
throw new IllegalArgumentException("Cannot deposit checks to savings accounts");
88+
}
89+
90+
CheckingAccount checkingAccount = (CheckingAccount) account;
91+
check.depositFunds(checkingAccount);
92+
auditLog.recordCredit(
93+
accountNumber,
94+
check.getAmount(),
95+
String.format(
96+
"Check deposit from account %s", check.getSourceAccount().getAccountNumber()));
6297
}
6398

6499
/**
65100
* Withdraws funds from an account.
66101
*
67-
* @param accountNumber
68-
* @param amount
102+
* @param accountNumber The account number.
103+
* @param amount The amount to withdraw.
69104
*/
70105
public void withdrawFunds(String accountNumber, double amount) {
71-
CheckingAccount account = getAccountOrThrow(accountNumber);
106+
Account account = getAccountOrThrow(accountNumber);
72107
account.withdraw(amount);
108+
auditLog.recordDebit(accountNumber, amount, "Cash withdrawal");
109+
}
110+
111+
/**
112+
* Gets the audit log for transaction tracking.
113+
*
114+
* @return The audit log instance.
115+
*/
116+
public AuditLog getAuditLog() {
117+
return auditLog;
73118
}
74119

75120
/**
@@ -78,8 +123,8 @@ public void withdrawFunds(String accountNumber, double amount) {
78123
* @param accountNumber The account number.
79124
* @return The account.
80125
*/
81-
private CheckingAccount getAccountOrThrow(String accountNumber) {
82-
CheckingAccount account = accountByNumber.get(accountNumber);
126+
private Account getAccountOrThrow(String accountNumber) {
127+
Account account = accountByNumber.get(accountNumber);
83128
if (account == null || account.isClosed()) {
84129
throw new AccountNotFoundException("Account not found");
85130
}
Binary file not shown.

0 commit comments

Comments
 (0)