kristofer revisó este gist . Ir a la revisión
1 file changed, 504 insertions
MediciBankingSystem.java(archivo creado)
@@ -0,0 +1,504 @@ | |||
1 | + | /** | |
2 | + | ||
3 | + | This Java implementation showcases the core principles of double-entry accounting, using ducats as | |
4 | + | the currency in honor of the Medici banking dynasty. Here's what the code demonstrates: | |
5 | + | ||
6 | + | 1. **The Fundamental Principle**: Every transaction affects at least two accounts | |
7 | + | (the double-entry principle), and the sum of debits must always equal the sum of credits. | |
8 | + | ||
9 | + | 2. **Five Main Account Types**: | |
10 | + | - Assets: Resources owned by the business | |
11 | + | - Liabilities: Debts owed by the business | |
12 | + | - Equity: Owner's interest in the business | |
13 | + | - Revenue: Income earned by the business | |
14 | + | - Expenses: Costs incurred by the business | |
15 | + | ||
16 | + | 3. **Account Balance Rules**: | |
17 | + | - Assets and Expenses: Increased by debits, decreased by credits | |
18 | + | - Liabilities, Equity, and Revenue: Increased by credits, decreased by debits | |
19 | + | ||
20 | + | 4. **Key Financial Reports**: | |
21 | + | - Trial Balance: Verifies that total debits equal total credits | |
22 | + | - Balance Sheet: Shows Assets = Liabilities + Equity | |
23 | + | - Income Statement: Shows Revenue - Expenses = Net Income | |
24 | + | ||
25 | + | The example simulates transactions for the Medici Bank in the year 1397, | |
26 | + | including initial capitalization, loans with interest (a key banking activity), | |
27 | + | property acquisition, and operating expenses. | |
28 | + | ||
29 | + | */ | |
30 | + | import java.math.BigDecimal; | |
31 | + | import java.math.RoundingMode; | |
32 | + | import java.time.LocalDate; | |
33 | + | import java.util.*; | |
34 | + | ||
35 | + | /** | |
36 | + | * A double-entry accounting system implementation inspired by the | |
37 | + | * Florentine banking practices of the deMedici family. | |
38 | + | */ | |
39 | + | public class MediciBankingSystem { | |
40 | + | ||
41 | + | public static void main(String[] args) { | |
42 | + | // Create a new ledger for our banking operations | |
43 | + | Ledger mediciLedger = new Ledger("Medici Family Bank"); | |
44 | + | ||
45 | + | // Define our chart of accounts | |
46 | + | Account cash = mediciLedger.createAccount("Cash", AccountType.ASSET); | |
47 | + | Account accounts_receivable = mediciLedger.createAccount("Accounts Receivable", AccountType.ASSET); | |
48 | + | Account inventory = mediciLedger.createAccount("Inventory", AccountType.ASSET); | |
49 | + | Account land = mediciLedger.createAccount("Land", AccountType.ASSET); | |
50 | + | ||
51 | + | Account accounts_payable = mediciLedger.createAccount("Accounts Payable", AccountType.LIABILITY); | |
52 | + | Account loans = mediciLedger.createAccount("Loans", AccountType.LIABILITY); | |
53 | + | ||
54 | + | Account capital = mediciLedger.createAccount("Owner's Capital", AccountType.EQUITY); | |
55 | + | Account retained_earnings = mediciLedger.createAccount("Retained Earnings", AccountType.EQUITY); | |
56 | + | ||
57 | + | Account revenue = mediciLedger.createAccount("Revenue", AccountType.REVENUE); | |
58 | + | Account interest_income = mediciLedger.createAccount("Interest Income", AccountType.REVENUE); | |
59 | + | ||
60 | + | Account expenses = mediciLedger.createAccount("Expenses", AccountType.EXPENSE); | |
61 | + | Account wages = mediciLedger.createAccount("Wages", AccountType.EXPENSE); | |
62 | + | ||
63 | + | // Starting our banking operations with initial capital | |
64 | + | System.out.println("=== STARTING THE MEDICI BANK ==="); | |
65 | + | mediciLedger.recordTransaction( | |
66 | + | LocalDate.of(1397, 1, 1), | |
67 | + | "Initial investment from Giovanni de' Medici", | |
68 | + | new TransactionEntry(cash, new BigDecimal("10000.00")), | |
69 | + | new TransactionEntry(capital, new BigDecimal("10000.00")) | |
70 | + | ); | |
71 | + | ||
72 | + | // Recording a loan to a wool merchant | |
73 | + | mediciLedger.recordTransaction( | |
74 | + | LocalDate.of(1397, 2, 15), | |
75 | + | "Loan to Wool Merchant", | |
76 | + | new TransactionEntry(accounts_receivable, new BigDecimal("2000.00")), | |
77 | + | new TransactionEntry(cash, new BigDecimal("2000.00")) | |
78 | + | ); | |
79 | + | ||
80 | + | // Receiving partial payment with interest | |
81 | + | mediciLedger.recordTransaction( | |
82 | + | LocalDate.of(1397, 8, 10), | |
83 | + | "Partial loan repayment from Wool Merchant with interest", | |
84 | + | new TransactionEntry(cash, new BigDecimal("1200.00")), | |
85 | + | new TransactionEntry(accounts_receivable, new BigDecimal("1000.00")), | |
86 | + | new TransactionEntry(interest_income, new BigDecimal("200.00")) | |
87 | + | ); | |
88 | + | ||
89 | + | // Purchasing land for a new banking house | |
90 | + | mediciLedger.recordTransaction( | |
91 | + | LocalDate.of(1397, 9, 5), | |
92 | + | "Purchase of land for new Medici banking house", | |
93 | + | new TransactionEntry(land, new BigDecimal("3000.00")), | |
94 | + | new TransactionEntry(cash, new BigDecimal("3000.00")) | |
95 | + | ); | |
96 | + | ||
97 | + | // Paying wages to bank employees | |
98 | + | mediciLedger.recordTransaction( | |
99 | + | LocalDate.of(1397, 12, 1), | |
100 | + | "Quarterly wages for bank employees", | |
101 | + | new TransactionEntry(wages, new BigDecimal("800.00")), | |
102 | + | new TransactionEntry(cash, new BigDecimal("800.00")) | |
103 | + | ); | |
104 | + | ||
105 | + | // Print the trial balance to verify our accounting is balanced | |
106 | + | System.out.println("\n=== MEDICI BANK TRIAL BALANCE (Year 1397) ==="); | |
107 | + | mediciLedger.printTrialBalance(); | |
108 | + | ||
109 | + | // Print the balance sheet | |
110 | + | System.out.println("\n=== MEDICI BANK BALANCE SHEET (Year 1397) ==="); | |
111 | + | mediciLedger.printBalanceSheet(); | |
112 | + | ||
113 | + | // Print the income statement | |
114 | + | System.out.println("\n=== MEDICI BANK INCOME STATEMENT (Year 1397) ==="); | |
115 | + | mediciLedger.printIncomeStatement(); | |
116 | + | } | |
117 | + | } | |
118 | + | ||
119 | + | /** | |
120 | + | * Represents a financial account in the double-entry system | |
121 | + | */ | |
122 | + | class Account { | |
123 | + | private String name; | |
124 | + | private AccountType type; | |
125 | + | private BigDecimal balance; | |
126 | + | ||
127 | + | public Account(String name, AccountType type) { | |
128 | + | this.name = name; | |
129 | + | this.type = type; | |
130 | + | this.balance = BigDecimal.ZERO; | |
131 | + | } | |
132 | + | ||
133 | + | public String getName() { | |
134 | + | return name; | |
135 | + | } | |
136 | + | ||
137 | + | public AccountType getType() { | |
138 | + | return type; | |
139 | + | } | |
140 | + | ||
141 | + | public BigDecimal getBalance() { | |
142 | + | return balance; | |
143 | + | } | |
144 | + | ||
145 | + | /** | |
146 | + | * Debits increase ASSET and EXPENSE accounts | |
147 | + | * Debits decrease LIABILITY, EQUITY, and REVENUE accounts | |
148 | + | */ | |
149 | + | public void debit(BigDecimal amount) { | |
150 | + | if (type == AccountType.ASSET || type == AccountType.EXPENSE) { | |
151 | + | balance = balance.add(amount); | |
152 | + | } else { | |
153 | + | balance = balance.subtract(amount); | |
154 | + | } | |
155 | + | } | |
156 | + | ||
157 | + | /** | |
158 | + | * Credits decrease ASSET and EXPENSE accounts | |
159 | + | * Credits increase LIABILITY, EQUITY, and REVENUE accounts | |
160 | + | */ | |
161 | + | public void credit(BigDecimal amount) { | |
162 | + | if (type == AccountType.ASSET || type == AccountType.EXPENSE) { | |
163 | + | balance = balance.subtract(amount); | |
164 | + | } else { | |
165 | + | balance = balance.add(amount); | |
166 | + | } | |
167 | + | } | |
168 | + | ||
169 | + | @Override | |
170 | + | public String toString() { | |
171 | + | return name + " (" + type + "): " + balance + " ducats"; | |
172 | + | } | |
173 | + | } | |
174 | + | ||
175 | + | /** | |
176 | + | * The different types of accounts in double-entry accounting | |
177 | + | */ | |
178 | + | enum AccountType { | |
179 | + | ASSET, // Resources owned by the business | |
180 | + | LIABILITY, // Debts owed by the business | |
181 | + | EQUITY, // Owner's interest in the business | |
182 | + | REVENUE, // Income earned by the business | |
183 | + | EXPENSE // Costs incurred by the business | |
184 | + | } | |
185 | + | ||
186 | + | /** | |
187 | + | * Represents a single entry in a transaction | |
188 | + | */ | |
189 | + | class TransactionEntry { | |
190 | + | private Account account; | |
191 | + | private BigDecimal amount; | |
192 | + | ||
193 | + | public TransactionEntry(Account account, BigDecimal amount) { | |
194 | + | this.account = account; | |
195 | + | this.amount = amount; | |
196 | + | } | |
197 | + | ||
198 | + | public Account getAccount() { | |
199 | + | return account; | |
200 | + | } | |
201 | + | ||
202 | + | public BigDecimal getAmount() { | |
203 | + | return amount; | |
204 | + | } | |
205 | + | } | |
206 | + | ||
207 | + | /** | |
208 | + | * Represents a complete financial transaction in the double-entry system | |
209 | + | */ | |
210 | + | class Transaction { | |
211 | + | private String description; | |
212 | + | private LocalDate date; | |
213 | + | private List<TransactionEntry> debits; | |
214 | + | private List<TransactionEntry> credits; | |
215 | + | ||
216 | + | public Transaction(LocalDate date, String description) { | |
217 | + | this.date = date; | |
218 | + | this.description = description; | |
219 | + | this.debits = new ArrayList<>(); | |
220 | + | this.credits = new ArrayList<>(); | |
221 | + | } | |
222 | + | ||
223 | + | public void addDebit(TransactionEntry entry) { | |
224 | + | debits.add(entry); | |
225 | + | } | |
226 | + | ||
227 | + | public void addCredit(TransactionEntry entry) { | |
228 | + | credits.add(entry); | |
229 | + | } | |
230 | + | ||
231 | + | public boolean isBalanced() { | |
232 | + | BigDecimal totalDebits = debits.stream() | |
233 | + | .map(TransactionEntry::getAmount) | |
234 | + | .reduce(BigDecimal.ZERO, BigDecimal::add); | |
235 | + | ||
236 | + | BigDecimal totalCredits = credits.stream() | |
237 | + | .map(TransactionEntry::getAmount) | |
238 | + | .reduce(BigDecimal.ZERO, BigDecimal::add); | |
239 | + | ||
240 | + | return totalDebits.compareTo(totalCredits) == 0; | |
241 | + | } | |
242 | + | ||
243 | + | public void post() { | |
244 | + | // Apply all debits | |
245 | + | for (TransactionEntry entry : debits) { | |
246 | + | entry.getAccount().debit(entry.getAmount()); | |
247 | + | } | |
248 | + | ||
249 | + | // Apply all credits | |
250 | + | for (TransactionEntry entry : credits) { | |
251 | + | entry.getAccount().credit(entry.getAmount()); | |
252 | + | } | |
253 | + | } | |
254 | + | ||
255 | + | @Override | |
256 | + | public String toString() { | |
257 | + | StringBuilder sb = new StringBuilder(); | |
258 | + | sb.append("Transaction: ").append(date).append(" - ").append(description).append("\n"); | |
259 | + | ||
260 | + | sb.append(" Debits:\n"); | |
261 | + | for (TransactionEntry entry : debits) { | |
262 | + | sb.append(" ").append(entry.getAccount().getName()) | |
263 | + | .append(": ").append(entry.getAmount()).append(" ducats\n"); | |
264 | + | } | |
265 | + | ||
266 | + | sb.append(" Credits:\n"); | |
267 | + | for (TransactionEntry entry : credits) { | |
268 | + | sb.append(" ").append(entry.getAccount().getName()) | |
269 | + | .append(": ").append(entry.getAmount()).append(" ducats\n"); | |
270 | + | } | |
271 | + | ||
272 | + | return sb.toString(); | |
273 | + | } | |
274 | + | } | |
275 | + | ||
276 | + | /** | |
277 | + | * The main ledger that keeps track of all accounts and transactions | |
278 | + | */ | |
279 | + | class Ledger { | |
280 | + | private String name; | |
281 | + | private List<Account> accounts; | |
282 | + | private List<Transaction> transactions; | |
283 | + | ||
284 | + | public Ledger(String name) { | |
285 | + | this.name = name; | |
286 | + | this.accounts = new ArrayList<>(); | |
287 | + | this.transactions = new ArrayList<>(); | |
288 | + | } | |
289 | + | ||
290 | + | public Account createAccount(String name, AccountType type) { | |
291 | + | Account account = new Account(name, type); | |
292 | + | accounts.add(account); | |
293 | + | return account; | |
294 | + | } | |
295 | + | ||
296 | + | /** | |
297 | + | * Records a transaction with any number of debits and credits, | |
298 | + | * ensuring that debits = credits (the fundamental principle of double-entry) | |
299 | + | */ | |
300 | + | public void recordTransaction(LocalDate date, String description, | |
301 | + | TransactionEntry... entries) { | |
302 | + | Transaction transaction = new Transaction(date, description); | |
303 | + | ||
304 | + | // Separate entries into debits and credits based on account type | |
305 | + | for (TransactionEntry entry : entries) { | |
306 | + | Account account = entry.getAccount(); | |
307 | + | AccountType type = account.getType(); | |
308 | + | ||
309 | + | // For asset and expense accounts, positive amounts are debits | |
310 | + | // For liability, equity, and revenue accounts, positive amounts are credits | |
311 | + | if (type == AccountType.ASSET || type == AccountType.EXPENSE) { | |
312 | + | if (entry.getAmount().compareTo(BigDecimal.ZERO) >= 0) { | |
313 | + | transaction.addDebit(entry); | |
314 | + | } else { | |
315 | + | // Negative amount means we're crediting the account | |
316 | + | transaction.addCredit(new TransactionEntry( | |
317 | + | account, entry.getAmount().abs())); | |
318 | + | } | |
319 | + | } else { | |
320 | + | if (entry.getAmount().compareTo(BigDecimal.ZERO) >= 0) { | |
321 | + | transaction.addCredit(entry); | |
322 | + | } else { | |
323 | + | // Negative amount means we're debiting the account | |
324 | + | transaction.addDebit(new TransactionEntry( | |
325 | + | account, entry.getAmount().abs())); | |
326 | + | } | |
327 | + | } | |
328 | + | } | |
329 | + | ||
330 | + | // Verify that the transaction is balanced | |
331 | + | if (!transaction.isBalanced()) { | |
332 | + | throw new IllegalArgumentException("Transaction is not balanced: debits must equal credits"); | |
333 | + | } | |
334 | + | ||
335 | + | // Post the transaction to update account balances | |
336 | + | transaction.post(); | |
337 | + | ||
338 | + | // Record the transaction in the ledger | |
339 | + | transactions.add(transaction); | |
340 | + | System.out.println(transaction); | |
341 | + | } | |
342 | + | ||
343 | + | /** | |
344 | + | * Prints a trial balance to verify that debits = credits across all accounts | |
345 | + | */ | |
346 | + | public void printTrialBalance() { | |
347 | + | BigDecimal totalDebits = BigDecimal.ZERO; | |
348 | + | BigDecimal totalCredits = BigDecimal.ZERO; | |
349 | + | ||
350 | + | System.out.printf("%-30s %-15s %-15s%n", "Account", "Debit (Ducats)", "Credit (Ducats)"); | |
351 | + | System.out.println("-".repeat(60)); | |
352 | + | ||
353 | + | for (Account account : accounts) { | |
354 | + | BigDecimal balance = account.getBalance(); | |
355 | + | ||
356 | + | // For the trial balance, we show positive balances in their normal position | |
357 | + | // Assets and Expenses with positive balances are shown as debits | |
358 | + | // Liabilities, Equity, and Revenue with positive balances are shown as credits | |
359 | + | if (account.getType() == AccountType.ASSET || | |
360 | + | account.getType() == AccountType.EXPENSE) { | |
361 | + | if (balance.compareTo(BigDecimal.ZERO) > 0) { | |
362 | + | System.out.printf("%-30s %-15s %-15s%n", | |
363 | + | account.getName(), balance.setScale(2, RoundingMode.HALF_UP), ""); | |
364 | + | totalDebits = totalDebits.add(balance); | |
365 | + | } else if (balance.compareTo(BigDecimal.ZERO) < 0) { | |
366 | + | System.out.printf("%-30s %-15s %-15s%n", | |
367 | + | account.getName(), "", balance.abs().setScale(2, RoundingMode.HALF_UP)); | |
368 | + | totalCredits = totalCredits.add(balance.abs()); | |
369 | + | } | |
370 | + | } else { | |
371 | + | if (balance.compareTo(BigDecimal.ZERO) > 0) { | |
372 | + | System.out.printf("%-30s %-15s %-15s%n", | |
373 | + | account.getName(), "", balance.setScale(2, RoundingMode.HALF_UP)); | |
374 | + | totalCredits = totalCredits.add(balance); | |
375 | + | } else if (balance.compareTo(BigDecimal.ZERO) < 0) { | |
376 | + | System.out.printf("%-30s %-15s %-15s%n", | |
377 | + | account.getName(), balance.abs().setScale(2, RoundingMode.HALF_UP), ""); | |
378 | + | totalDebits = totalDebits.add(balance.abs()); | |
379 | + | } | |
380 | + | } | |
381 | + | } | |
382 | + | ||
383 | + | System.out.println("-".repeat(60)); | |
384 | + | System.out.printf("%-30s %-15s %-15s%n", | |
385 | + | "TOTAL", totalDebits.setScale(2, RoundingMode.HALF_UP), | |
386 | + | totalCredits.setScale(2, RoundingMode.HALF_UP)); | |
387 | + | ||
388 | + | if (totalDebits.compareTo(totalCredits) == 0) { | |
389 | + | System.out.println("\nThe books are balanced! ✓"); | |
390 | + | } else { | |
391 | + | System.out.println("\nWARNING: The books are NOT balanced! ✗"); | |
392 | + | } | |
393 | + | } | |
394 | + | ||
395 | + | /** | |
396 | + | * Prints a balance sheet (Assets = Liabilities + Equity) | |
397 | + | */ | |
398 | + | public void printBalanceSheet() { | |
399 | + | BigDecimal totalAssets = BigDecimal.ZERO; | |
400 | + | BigDecimal totalLiabilities = BigDecimal.ZERO; | |
401 | + | BigDecimal totalEquity = BigDecimal.ZERO; | |
402 | + | ||
403 | + | // Print Assets | |
404 | + | System.out.println("ASSETS"); | |
405 | + | System.out.println("-".repeat(40)); | |
406 | + | for (Account account : accounts) { | |
407 | + | if (account.getType() == AccountType.ASSET && account.getBalance().compareTo(BigDecimal.ZERO) != 0) { | |
408 | + | System.out.printf("%-30s %10s%n", | |
409 | + | account.getName(), account.getBalance().setScale(2, RoundingMode.HALF_UP)); | |
410 | + | totalAssets = totalAssets.add(account.getBalance()); | |
411 | + | } | |
412 | + | } | |
413 | + | System.out.println("-".repeat(40)); | |
414 | + | System.out.printf("%-30s %10s%n", "TOTAL ASSETS", totalAssets.setScale(2, RoundingMode.HALF_UP)); | |
415 | + | System.out.println(); | |
416 | + | ||
417 | + | // Print Liabilities | |
418 | + | System.out.println("LIABILITIES"); | |
419 | + | System.out.println("-".repeat(40)); | |
420 | + | for (Account account : accounts) { | |
421 | + | if (account.getType() == AccountType.LIABILITY && account.getBalance().compareTo(BigDecimal.ZERO) != 0) { | |
422 | + | System.out.printf("%-30s %10s%n", | |
423 | + | account.getName(), account.getBalance().setScale(2, RoundingMode.HALF_UP)); | |
424 | + | totalLiabilities = totalLiabilities.add(account.getBalance()); | |
425 | + | } | |
426 | + | } | |
427 | + | System.out.println("-".repeat(40)); | |
428 | + | System.out.printf("%-30s %10s%n", "TOTAL LIABILITIES", totalLiabilities.setScale(2, RoundingMode.HALF_UP)); | |
429 | + | System.out.println(); | |
430 | + | ||
431 | + | // Print Equity | |
432 | + | System.out.println("EQUITY"); | |
433 | + | System.out.println("-".repeat(40)); | |
434 | + | for (Account account : accounts) { | |
435 | + | if (account.getType() == AccountType.EQUITY && account.getBalance().compareTo(BigDecimal.ZERO) != 0) { | |
436 | + | System.out.printf("%-30s %10s%n", | |
437 | + | account.getName(), account.getBalance().setScale(2, RoundingMode.HALF_UP)); | |
438 | + | totalEquity = totalEquity.add(account.getBalance()); | |
439 | + | } | |
440 | + | } | |
441 | + | System.out.println("-".repeat(40)); | |
442 | + | System.out.printf("%-30s %10s%n", "TOTAL EQUITY", totalEquity.setScale(2, RoundingMode.HALF_UP)); | |
443 | + | System.out.println(); | |
444 | + | ||
445 | + | // Verify the accounting equation: Assets = Liabilities + Equity | |
446 | + | System.out.println("ACCOUNTING EQUATION"); | |
447 | + | System.out.println("-".repeat(40)); | |
448 | + | System.out.printf("%-30s %10s%n", "Total Assets", totalAssets.setScale(2, RoundingMode.HALF_UP)); | |
449 | + | System.out.printf("%-30s %10s%n", "Total Liabilities + Equity", | |
450 | + | totalLiabilities.add(totalEquity).setScale(2, RoundingMode.HALF_UP)); | |
451 | + | ||
452 | + | if (totalAssets.compareTo(totalLiabilities.add(totalEquity)) == 0) { | |
453 | + | System.out.println("\nThe accounting equation is balanced! ✓"); | |
454 | + | } else { | |
455 | + | System.out.println("\nWARNING: The accounting equation is NOT balanced! ✗"); | |
456 | + | } | |
457 | + | } | |
458 | + | ||
459 | + | /** | |
460 | + | * Prints an income statement (Revenue - Expenses = Net Income) | |
461 | + | */ | |
462 | + | public void printIncomeStatement() { | |
463 | + | BigDecimal totalRevenue = BigDecimal.ZERO; | |
464 | + | BigDecimal totalExpenses = BigDecimal.ZERO; | |
465 | + | ||
466 | + | // Print Revenue | |
467 | + | System.out.println("REVENUE"); | |
468 | + | System.out.println("-".repeat(40)); | |
469 | + | for (Account account : accounts) { | |
470 | + | if (account.getType() == AccountType.REVENUE && account.getBalance().compareTo(BigDecimal.ZERO) != 0) { | |
471 | + | System.out.printf("%-30s %10s%n", | |
472 | + | account.getName(), account.getBalance().setScale(2, RoundingMode.HALF_UP)); | |
473 | + | totalRevenue = totalRevenue.add(account.getBalance()); | |
474 | + | } | |
475 | + | } | |
476 | + | System.out.println("-".repeat(40)); | |
477 | + | System.out.printf("%-30s %10s%n", "TOTAL REVENUE", totalRevenue.setScale(2, RoundingMode.HALF_UP)); | |
478 | + | System.out.println(); | |
479 | + | ||
480 | + | // Print Expenses | |
481 | + | System.out.println("EXPENSES"); | |
482 | + | System.out.println("-".repeat(40)); | |
483 | + | for (Account account : accounts) { | |
484 | + | if (account.getType() == AccountType.EXPENSE && account.getBalance().compareTo(BigDecimal.ZERO) != 0) { | |
485 | + | System.out.printf("%-30s %10s%n", | |
486 | + | account.getName(), account.getBalance().setScale(2, RoundingMode.HALF_UP)); | |
487 | + | totalExpenses = totalExpenses.add(account.getBalance()); | |
488 | + | } | |
489 | + | } | |
490 | + | System.out.println("-".repeat(40)); | |
491 | + | System.out.printf("%-30s %10s%n", "TOTAL EXPENSES", totalExpenses.setScale(2, RoundingMode.HALF_UP)); | |
492 | + | System.out.println(); | |
493 | + | ||
494 | + | // Calculate Net Income | |
495 | + | BigDecimal netIncome = totalRevenue.subtract(totalExpenses); | |
496 | + | System.out.println("SUMMARY"); | |
497 | + | System.out.println("-".repeat(40)); | |
498 | + | System.out.printf("%-30s %10s%n", "Total Revenue", totalRevenue.setScale(2, RoundingMode.HALF_UP)); | |
499 | + | System.out.printf("%-30s %10s%n", "Total Expenses", totalExpenses.setScale(2, RoundingMode.HALF_UP)); | |
500 | + | System.out.println("-".repeat(40)); | |
501 | + | System.out.printf("%-30s %10s%n", "NET INCOME", netIncome.setScale(2, RoundingMode.HALF_UP)); | |
502 | + | } | |
503 | + | } | |
504 | + |
Siguiente
Anterior