druvu-acc
A modular Java library for reading and writing accounting data with a clean API for double-entry bookkeeping.
Overview
druvu-acc provides a clean API for working with double-entry bookkeeping data including accounts, transactions, commodities, and prices — both reading existing files and writing changes back. It uses a pluggable architecture allowing multiple accounting file formats through ServiceLoader.
Commodity and price support makes it suitable for multi-currency books and investment tracking (securities and their price history).
Currently supports GnuCash XML files (both plain and gzip-compressed).
Reading
// Load a GnuCash file (auto-discovers implementation via ServiceLoader)
AccStore store = AccStore.load(Path.of("/path/to/book.gnucash"));
// Iterate over accounts
for (Account account : store.accounts()) {
System.out.println(account.name() + " [" + account.type() + "]");
}
// Get transactions
for (Transaction tx : store.transactions()) {
System.out.println(tx.description() + " - " + tx.datePosted());
for (Split split : tx.splits()) {
System.out.println(" " + split.accountId() + ": " + split.value());
}
}
Writing
Load a store as a WritableAccStore to add or remove entities and save the result.
Output is GnuCash-compatible (opens directly in GnuCash).
WritableAccStore store = AccStore.loadWritable(Path.of("/path/to/book.gnucash"));
String rootId = store.rootAccounts().getFirst().id();
// Add an account and a balanced transaction
store.addAccount(new Account(newGuid(), "Coffee", AccountType.EXPENSE,
Optional.empty(), Optional.empty(),
Optional.of(CommodityId.currency("EUR")), Optional.of(rootId)));
// Track an investment: define a security and record a price quote
store.addCommodity(Commodity.security("NASDAQ", "AAPL", "Apple Inc.", 10000));
store.addPrice(new Price(newGuid(),
new CommodityId("NASDAQ", "AAPL"), CommodityId.currency("USD"),
LocalDate.now().atStartOfDay(), "user:price-editor",
Optional.of("last"), new BigDecimal("212.50")));
// Persist (gzip-compressed when the path ends with .gnucash or .gz)
store.save(Path.of("/path/to/book-modified.gnucash"));
IDs are caller-supplied; use 32-character hex GUIDs for GnuCash compatibility
(newGuid() above stands for UUID.randomUUID().toString().replace("-", "")).
Supported entities
GnuCash files can hold many entity types. This table tracks what the library supports today against the GnuCash XML v2 data model. The core double-entry entities and the investment / multi-currency entities are covered; business (accounts-receivable/payable) and planning entities are not yet implemented.
| Entity | In GnuCash | druvu-acc |
|---|---|---|
| Accounts | ✓ | read + write |
| Transactions & splits | ✓ | read + write |
| Commodities (currencies & securities) | ✓ | read + write |
| Prices (price database) | ✓ | read + write |
| Scheduled (recurring) transactions | ✓ | — not yet |
| Budgets | ✓ | — not yet |
| Customers / Vendors / Employees | ✓ | — not yet |
| Invoices & bills (+ line entries) | ✓ | — not yet |
| Jobs / Orders | ✓ | — not yet |
| Billing terms / Tax tables | ✓ | — not yet |
| Lots | ✓ | — not yet |
Need one of the not yet entities? Open an issue describing your use case — prioritisation follows real demand.
Core Entities
| Entity | Description |
|---|---|
| Account | Name, type, code, description, commodity |
| Transaction | Date, description, containing splits |
| Split | Value, quantity, reconciliation state |
| Commodity | A currency or security definition (namespace, symbol, name, fraction) |
| CommodityId | Identifies currencies and securities |
| Price | Historical price data for commodities |
Account types: ASSET, LIABILITY, INCOME, EXPENSE, EQUITY, BANK, CASH, STOCK, etc.
Read access is via AccStore; mutation and persistence via WritableAccStore (AccStore.loadWritable(...)).
Module Structure
druvu-acc-parent/
├── druvu-acc-api # Core interfaces and entities
├── druvu-acc-gnucash-xml # GnuCash XML format implementation
└── druvu-acc-tests # Integration tests and examples
Full JPMS (Java Platform Module System) support with clean module boundaries.
Requirements
- Java 25+
- Maven 3.9+
License
Apache License 2.0