-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSimplified Banking System.java
More file actions
466 lines (406 loc) · 18 KB
/
Simplified Banking System.java
File metadata and controls
466 lines (406 loc) · 18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;
public class taskb {
// main where all operations with the given strings will be held
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
scanner.nextLine();
BankingFacade bankingSystem = new BankingFacade();
for (int i = 0; i < n; i++) {
String operation = scanner.nextLine();
String[] details = operation.split(" ");
String type = details[0];
String accountName;
switch (type) { // checking the possible cases and doing it
case "Create":
String accountType = details[2];
accountName = details[3];
double initialDeposit = Double.parseDouble(details[4]);
bankingSystem.createAccount(accountType, accountName, initialDeposit);
break;
case "Deposit":
accountName = details[1];
double depositAmount = Double.parseDouble(details[2]);
bankingSystem.deposit(accountName, depositAmount);
break;
case "Withdraw":
accountName=details[1];
double withdrawalAmount = Double.parseDouble(details[2]);
bankingSystem.withdraw(accountName, withdrawalAmount);
break;
case "Transfer":
accountName=details[1];
String toAccountName = details[2];
double transferAmount = Double.parseDouble(details[3]);
bankingSystem.transfer(accountName, toAccountName, transferAmount);
break;
case "View":
accountName=details[1];
bankingSystem.viewAccountDetails(accountName);
break;
case "Deactivate":
accountName=details[1];
bankingSystem.deactivateAccount(accountName);
break;
case "Activate":
accountName=details[1];
bankingSystem.activateAccount(accountName);
break;
}
}
scanner.close();
}
}
// Interface for transaction fee strategy
interface TransactionFeeStrategy {
double calculateTransactionFee(double amount);
}
// Concrete strategy for Savings Account
class SavingsTransactionFeeStrategy implements TransactionFeeStrategy {
private static final double TRANSACTION_FEE_PERCENTAGE = 1.5;
@Override
public double calculateTransactionFee(double amount) {
return amount * TRANSACTION_FEE_PERCENTAGE / 100;
}
}
// Concrete strategy for Checking Account
class CheckingTransactionFeeStrategy implements TransactionFeeStrategy {
private static final double TRANSACTION_FEE_PERCENTAGE = 2.0;
@Override
public double calculateTransactionFee(double amount) {
return amount * TRANSACTION_FEE_PERCENTAGE / 100;
}
}
// Concrete strategy for Business Account
class BusinessTransactionFeeStrategy implements TransactionFeeStrategy {
private static final double TRANSACTION_FEE_PERCENTAGE = 2.5;
@Override
public double calculateTransactionFee(double amount) {
return amount * TRANSACTION_FEE_PERCENTAGE / 100;
}
}
// Context class for transaction fee strategy
class TransactionFeeContext {
private final TransactionFeeStrategy strategy;
public TransactionFeeContext(TransactionFeeStrategy strategy) {
this.strategy = strategy;
}
public double executeStrategy(double amount) {
return strategy.calculateTransactionFee(amount);
}
}
// Interface for account state
interface AccountState {
void deposit(Account account, double amount);
String withdraw(Account account, double amount);
String transfer(Account fromAccount, Account toAccount, double amount);
}
// Concrete state for active account
class ActiveState implements AccountState {
// implementation of deposit for active account
@Override
public void deposit(Account account, double amount) {
account.setBalance(account.getBalance() + amount); // new balance after deposit
account.addTransaction("Deposit", amount); // adding deposit transaction to the transaction list of person
}
// implementation of withdraw for active account
@Override
public String withdraw(Account account, double amount) {
if (account.getBalance() >= amount) {
account.setBalance(account.getBalance() - amount); // changes the balance after withdraw
account.addTransaction("Withdrawal", amount); // adding withdraw to the transaction list of person
return "";
} else {
// error handling, if person does not have enough money to withdraw
return "Error: Insufficient funds for " + account.getName()+".";
}
}
// implementation of transfer for active account
@Override
public String transfer(Account fromAccount, Account toAccount, double amount) {
if (fromAccount.getBalance() >= amount) {
double transactionFee = fromAccount.getTransactionFeeContext().executeStrategy(amount);
// from person1 will go certain amount to the person2, but it will have some fee in relation to
// the account type. So the netAmount (that will receive person2) is the amount after deduction of fee
double netAmount = amount - transactionFee;
fromAccount.setBalance(fromAccount.getBalance() - amount); // change the balance of sender after transfer
toAccount.setBalance(toAccount.getBalance() + netAmount); // change the balance of receiver after transfer
fromAccount.addTransaction("Transfer", amount); // adding transfer to the transaction list of person
return "";
} else {
// error handling, if sender does not have enough money to transfer
return "Error: Insufficient funds for " + fromAccount.getName() + ".";
}
}
}
// Concrete state for inactive account
class InactiveState implements AccountState {
// implementation of deposit for inactive account
@Override
public void deposit(Account account, double amount) {
account.setBalance(account.getBalance() + amount);
account.addTransaction("Deposit", amount);
}
// implementation of withdraw for inactive account
@Override
public String withdraw(Account account, double amount) {
return "Error: Account " + account.getName() + " is inactive.";
}
// implementation of transfer for active account
@Override
public String transfer(Account fromAccount, Account toAccount, double amount) {
return "Error: Account " + fromAccount.getName() + " is inactive.";
}
}
// Account class
class Account {
private final String type;
private final String name;
private double balance;
private AccountState state;
private final List<String> transactions;
private final TransactionFeeContext transactionFeeContext;
public Account(String type, String name, double initialDeposit) {
this.type = type;
this.name = name;
this.balance = initialDeposit;
this.transactions = new ArrayList<>();
this.transactionFeeContext = new TransactionFeeContext(getTransactionFeeStrategy());
this.state = new ActiveState();
addTransaction("Initial Deposit", initialDeposit);
}
// process of account activation
public String activate() {
// if account is activated, it will give already activated error
if (state instanceof ActiveState) {
return "Error: Account " + name + " is already activated.";
} else {
// if account not activated it will activate it
this.state = new ActiveState();
return "";
}
}
// process of account deactivation
public String deactivate() {
// if account is deactivated, it will give already deactivated error
if (state instanceof InactiveState) {
return "Error: Account " + name + " is already deactivated.";
} else {
// if account not deactivated it will deactivate it
this.state = new InactiveState();
return "";
}
}
// deposit of an account
public void deposit(double amount) {
state.deposit(this, amount);
}
// withdraw from an account
public String withdraw(double amount) {
return state.withdraw(this, amount);
}
// transfer from one person to another
public String transfer(Account toAccount, double amount) {
return state.transfer(this, toAccount, amount);
}
// adding any possible type of transaction to transaction list
public void addTransaction(String type, double amount) {
transactions.add(type + " $" + String.format("%.3f", amount));
}
// implementation of showing details of account(type, balance, active or inactive, transactions without fees)
public void viewDetails() {
System.out.print(name + "'s Account: Type: " + type + ", Balance: $" + String.format("%.3f", balance)
+ ", State: " + (state instanceof ActiveState ? "Active" : "Inactive") + ", Transactions: [");
for (int g=0; g<transactions.size()-1; g++) {
System.out.print(transactions.get(g) + ", ");
}
System.out.println(transactions.get(transactions.size()-1)+"].");
}
public String getName() {
return name;
}
public double getBalance() {
return balance;
}
// make appropriate changes in balance
public void setBalance(double balance) {
this.balance = balance;
}
// gives the percentage of fee in relation to the account type
public double percent() {
return switch (type) {
case "Savings" -> 1.5;
case "Checking" -> 2.0;
case "Business" -> 2.5;
default -> 0.00;
};
}
// calculating fee of certain account type
public double calculateTransactionFee(double amount) {
return switch (type) {
case "Savings" -> amount * 0.015;
case "Checking" -> amount * 0.02;
case "Business" -> amount * 0.025;
default -> 0.00;
};
}
public TransactionFeeContext getTransactionFeeContext() {
return transactionFeeContext;
}
// which fee strategy to apply according to the account type
public TransactionFeeStrategy getTransactionFeeStrategy() {
return switch (type) {
case "Savings" -> new SavingsTransactionFeeStrategy();
case "Checking" -> new CheckingTransactionFeeStrategy();
case "Business" -> new BusinessTransactionFeeStrategy();
default -> null;
};
}
}
// Singleton class for Banking System
class BankingSystem {
private static BankingSystem instance;
private final HashMap<String, Account> accounts;
private BankingSystem() {
accounts = new HashMap<>();
}
// Ensuring that only a single instance of the banking system exists.
public static BankingSystem getInstance() {
if (instance == null) {
instance = new BankingSystem();
}
return instance;
}
// implementation of account creation
public void createAccount(String accountType, String accountName, double initialDeposit) {
Account account = new Account(accountType, accountName, initialDeposit);
accounts.put(accountName, account);
System.out.println("A new " + accountType + " account created for " + accountName
+ " with an initial balance of $" + String.format("%.3f", initialDeposit) + ".");
}
// processing account name and the amount of deposit and printing corresponding result
public void deposit(String accountName, double amount) {
Account account = accounts.get(accountName);
if (account != null) {
account.deposit(amount);
// printing the result of deposit
System.out.println(accountName + " successfully deposited $" + String.format("%.3f", amount)
+ ". New Balance: $" + String.format("%.3f", account.getBalance())+".");
} else {
// error handling if account does not exist
System.out.println("Error: Account " + accountName + " does not exist.");
}
}
// processing account name and the amount of withdraw and printing corresponding result
public void withdraw(String accountName, double amount) {
Account account = accounts.get(accountName);
if (account != null) {
String InsufficientFundsError = account.withdraw(amount);
// error handling if person does not have enough money to deposit
if (!InsufficientFundsError.isEmpty()) {
System.out.println(InsufficientFundsError);
return;
}
double transactionFee = account.calculateTransactionFee(amount);
amount -= transactionFee;
// printing the result of withdraw
System.out.println(accountName + " successfully withdrew $" + String.format("%.3f", amount)
+ ". New Balance: $" + String.format("%.3f", account.getBalance()) + ". Transaction Fee: $"
+ String.format("%.3f", transactionFee) + " (" + account.percent()+ "%) in the system.");
} else {
// error handling if account does not exist
System.out.println("Error: Account " + accountName + " does not exist.");
}
}
// processing account name of sender and receiver and the amount of transfer then printing corresponding result
public void transfer(String fromAccountName, String toAccountName, double amount) {
Account fromAccount = accounts.get(fromAccountName);
Account toAccount = accounts.get(toAccountName);
if (fromAccount != null && toAccount != null) {
String InsufficientFundsError = fromAccount.transfer(toAccount, amount);
if (!InsufficientFundsError.isEmpty()) {
// error handling if sender does not have enough money to transfer
System.out.println(InsufficientFundsError);
return;
}
double transactionFee = fromAccount.calculateTransactionFee(amount);
amount -= transactionFee;
// printing the result of transfer
System.out.println(fromAccountName + " successfully transferred $" + String.format("%.3f", amount) + " to "
+ toAccountName + ". New Balance: $" + String.format("%.3f", fromAccount.getBalance())
+ ". Transaction Fee: $" + String.format("%.3f", transactionFee) + " (" + fromAccount.percent()+
"%) in the system.");
}
// error handling if sender account does not exist
else if (fromAccount==null) System.out.println("Error: Account " + fromAccountName + " does not exist.");
// error handling if receiver account does not exist
else System.out.println("Error: Account " + toAccountName + " does not exist.");
}
// showing the account details
public void viewAccountDetails(String accountName) {
Account account = accounts.get(accountName);
if (account != null) {
account.viewDetails();
} else {
// error handling if account does not exist
System.out.println("Error: Account " + accountName + " does not exist.");
}
}
// process the deactivating account and printing corresponding result
public void deactivateAccount(String accountName) {
Account account = accounts.get(accountName);
if (account != null) {
if (account.deactivate().equals("Error: Account " + accountName + " is already deactivated.")){
System.out.println("Error: Account " + accountName + " is already deactivated.");
return;
}
System.out.println(accountName + "'s account is now deactivated.");
} else {
System.out.println("Error: Account " + accountName + " does not exist.");
}
}
// process the activating account and printing corresponding result
public void activateAccount(String accountName) {
Account account = accounts.get(accountName);
if (account != null) {
if (account.activate().equals("Error: Account " + accountName + " is already activated.")){
System.out.println("Error: Account " + accountName + " is already activated.");
return;
}
System.out.println(accountName + "'s account is now activated.");
} else {
System.out.println("Error: Account " + accountName + " does not exist.");
}
}
}
// Facade class for simplified interaction with BankingSystem
class BankingFacade {
private final BankingSystem bankingSystem;
public BankingFacade() {
this.bankingSystem = BankingSystem.getInstance();
}
public void createAccount(String accountType, String accountName, double initialDeposit) {
bankingSystem.createAccount(accountType, accountName, initialDeposit);
}
public void deposit(String accountName, double amount) {
bankingSystem.deposit(accountName, amount);
}
public void withdraw(String accountName, double amount) {
bankingSystem.withdraw(accountName, amount);
}
public void transfer(String fromAccountName, String toAccountName, double amount) {
bankingSystem.transfer(fromAccountName, toAccountName, amount);
}
public void viewAccountDetails(String accountName) {
bankingSystem.viewAccountDetails(accountName);
}
public void deactivateAccount(String accountName) {
bankingSystem.deactivateAccount(accountName);
}
public void activateAccount(String accountName) {
bankingSystem.activateAccount(accountName);
}
}