Double-entry accounting system.
To read a journal form a file, we first need to create a LedgerReader
object. If we use the LedgerReader
constructor without arguments, it would use the default locale
from the operating system:
var reader = new LedgerReader();
var filename = "src/main/resources/example.ledger";
var file = Path.of(filename);
var ledger = reader.readJournal(file);
But we can also use a specific locale
whe creating a LedgerReader
object. For example, to read a journal file using the default China locale
(amounts in yuans, and points as decimal separators), we could use:
var reader = new LedgerReader(Locale.CHINA);
var filename = "src/main/resources/yuan.ledger";
var file = Path.of(filename);
var ledger = reader.readJournal(file);
Once we have read a journal file into a ledger
object, we can print the journal to the standard output using a LedgerWriter
object. That LedgerWriter
object will use the same locale
as the one we used to read the Ledger
object.
For the first example, where we used the default locale
from the operating system (in my case, es-ES
), when we run:
var journal = ledger.getJournal();
var writer = new LedgerWriter();
writer.writeJournal(journal);
We’ll get:
2023/03/06 * Opening Balance Assets:Cash 500,00 € Assets:Debit Card 500,00 € Equity:Opening Balances -1.000,00 € 2023/03/07 Moe's restaurant Expenses:Restaurant:Food 20,00 € Expenses:Restaurant:Tips 2,00 € Assets:Cash -12,00 € Assets:Debit Card -10,00 € 2023/03/07 Mike's convenience store Expenses:Groceries 35,95 € Assets:Cash -35,95 €
For the second example, where we used the Locale.CHINA
locale, we’ll get:
2023/03/06 * Opening Balance Assets:Cash 500.00 CNY Assets:Debit Card 500.00 CNY Equity:Opening Balances -1,000.00 CNY 2023/03/07 Moe's restaurant Expenses:Restaurant:Food 20.00 CNY Expenses:Restaurant:Tips 2.00 CNY Assets:Cash -12.00 CNY Assets:Debit Card -10.00 CNY 2023/03/07 Mike's convenience store Expenses:Groceries 35.95 CNY Assets:Cash -35.95 CNY
We can also write a journal to a file using the following code:
var journal = ledger.getJournal();
var writer = new LedgerWriter();
var outputFilename = "src/main/resources/output.ledger";
var outputFile = Path.of(outputFilename);
try {
writer.writeJournal(journal, outputFile);
} catch (IOException e) {
System.out.println("Error writing the journal to a file. Cause: " + e);
}
And we’ll get the same output as before but written to a file instead of printed to the standard output.
Given a Journal
object, we can get the balance of an Account
using the getBalanceAsString(...)
method, which supports the following options:
- string balance representation by account name:
String getBalanceAsString(String accountName)
. - string balance representation by account:
String getBalanceAsString(Account account)
. - string balance representation by account name, between dates:
String getBalanceAsString(String accountName, String startDate, String endDate)
. - balance by account, between dates:
String getBalanceAsString(Account account, String startDate, String endDate)
.
For example:
System.out.println("Balance for Assets: " + journal.getBalanceAsString("Assets"));
var start = "2023/03/05";
var end = "2023/03/07";
System.out.println("Balance for Cash between " + start + " and " + end + ": " +
journal.getBalanceAsString("Cash", start, end));
Output:
Balance for Assets: 942,05 € Balance for Cash between 2023/03/05 and 2023/03/07: 452,05 €
There’s also a method to get the balance of an Account
as a Money
object: getBalance(...)
. That method supports the same options as before:
- balance by account name:
Money getBalance(String accountName)
. - balance by account:
Money getBalance(Account account)
. - balance by account name, between dates:
Money getBalance(String accountName, String startDate, String endDate)
. - balance by account, between dates:
Money getBalance(Account account, String startDate, String endDate)
.
Given a Journal
object, we can get the balance report of an Account
using the getBalanceReport(...)
method, which supports the following options:
- balance by account name:
String getBalanceReport(String accountName)
. - balance by account:
String getBalanceReport(Account account)
. - balance by account name, between dates:
String getBalanceReport(String accountName, String startDate, String endDate)
. - balance by account, between dates:
String getBalanceReport(Account account, String startDate, String endDate)
.
For example, using:
System.out.println("\n--- Balance Report for Assets ---");
System.out.println(journal.getBalanceReport("Assets"));
var start = "2023/03/05";
var end = "2023/03/07";
System.out.println("\n--- Balance Report for Cash between " + start + " and " + end + " ---");
System.out.println(journal.getBalanceReport("Cash", start, end));
We get this output:
--- Balance Report for Assets --- 500,00 € Assets:Cash 500,00 € Assets:Debit Card -12,00 € Assets:Cash -10,00 € Assets:Debit Card -35,95 € Assets:Cash ----------------------------------------------------- 942,05 € --- Balance Report for Cash between 2023/03/05 and 2023/03/07 --- 500,00 € Assets:Cash -12,00 € Assets:Cash -35,95 € Assets:Cash ----------------------------------------------------- 452,05 €
Given a Journal
object, we can use the getTransactionReport(...)
method to get some transaction reports, which supports the following options:
- transaction report by account:
String getTransactionReport(Account account)
. - transaction report by list of accounts:
String getTransactionReport(List<Account> accounts)
. - transaction report by payee:
String getTransactionReport(Payee payee)
. - transaction report between dates:
String getTransactionReport(String startDate, String endDate)
.
For example:
System.out.println("--- Transaction report for account Assets:Cash ---");
System.out.println(journal.getTransactionReport(new Account("Assets:Cash")));
System.out.println("--- Transaction report for accounts Assets:Debit Card and Equity:Opening Balances ---");
System.out.println(journal.getTransactionReport(List.of(new Account("Assets:Debit Card"), new Account("Equity:Opening Balances"))));
System.out.println("--- Transaction report for payee Moe's restaurant ---");
System.out.println(journal.getTransactionReport(new Payee("Moe's restaurant")));
System.out.println("--- Transaction report for all transactions between 2023/03/01 and 2023/03/06 ---");
System.out.println(journal.getTransactionReport("2023/03/01", "2023/03/06"));
System.out.println("--- Transaction report for all transactions between 2023/03/01 and 2023/03/31 ---");
System.out.println(journal.getTransactionReport("2023/03/01", "2023/03/31"));
Output:
--- Transaction report for account Assets:Cash --- 2023/03/07 Moe's restaurant Expenses:Restaurant:Food 20,00 € 20,00 € Expenses:Restaurant:Tips 2,00 € 22,00 € Assets:Cash -12,00 € 10,00 € Assets:Debit Card -10,00 € 0,00 € 2023/03/06 Opening Balance Assets:Cash 500,00 € 500,00 € Assets:Debit Card 500,00 € 1.000,00 € Equity:Opening Balances -1.000,00 € 0,00 € 2023/03/07 Mike's convenience store Expenses:Groceries 35,95 € 35,95 € Assets:Cash -35,95 € 0,00 € --- Transaction report for accounts Assets:Debit Card and Equity:Opening Balances --- 2023/03/07 Moe's restaurant Expenses:Restaurant:Food 20,00 € 20,00 € Expenses:Restaurant:Tips 2,00 € 22,00 € Assets:Cash -12,00 € 10,00 € Assets:Debit Card -10,00 € 0,00 € 2023/03/06 Opening Balance Assets:Cash 500,00 € 500,00 € Assets:Debit Card 500,00 € 1.000,00 € Equity:Opening Balances -1.000,00 € 0,00 € --- Transaction report for payee Moe's restaurant --- 2023/03/07 Moe's restaurant Expenses:Restaurant:Food 20,00 € 20,00 € Expenses:Restaurant:Tips 2,00 € 22,00 € Assets:Cash -12,00 € 10,00 € Assets:Debit Card -10,00 € 0,00 € --- Transaction report for all transactions between 2023/03/01 and 2023/03/06 --- 2023/03/06 Opening Balance Assets:Cash 500,00 € 500,00 € Assets:Debit Card 500,00 € 1.000,00 € Equity:Opening Balances -1.000,00 € 0,00 € --- Transaction report for all transactions between 2023/03/01 and 2023/03/31 --- 2023/03/07 Moe's restaurant Expenses:Restaurant:Food 20,00 € 20,00 € Expenses:Restaurant:Tips 2,00 € 22,00 € Assets:Cash -12,00 € 10,00 € Assets:Debit Card -10,00 € 0,00 € 2023/03/06 Opening Balance Assets:Cash 500,00 € 500,00 € Assets:Debit Card 500,00 € 1.000,00 € Equity:Opening Balances -1.000,00 € 0,00 € 2023/03/07 Mike's convenience store Expenses:Groceries 35,95 € 35,95 € Assets:Cash -35,95 € 0,00 €