Expense Splitter Pro is a sophisticated desktop application designed to take the headache out of group finances. Whether it's a weekend trip, a shared apartment, or a dinner with friends, this tool ensures everyone pays their fair share with minimal friction.
Experience the precision of our multicurrency reporting with these sample exports from an international trip:
Organize your social circles. Create custom groups for different occasions and manage members seamlessly with automatic user profile setup.
Log expenses as they happen with flexible split types:
- Equal
- Exact Amount
- Percentage
- Shares
Record expenses in any currency (INR, USD, EUR, etc.) and let the app handle the math.
- Smart Currency Selection: A powerful searchable modal allows you to pick from 100+ global currencies by name or country.
- Advanced Financial Formatting: Automatically applies Western, Indian (3-2), or East Asian (Myriad) digit grouping based on the currency.
- Live Exchange Rates: Real-time conversion using the Currency API.
- Persistent Offline Cache: Rates and currency metadata are cached locally (
exchange_rates.json,currency_names.json) for seamless offline operation. - Global Normalization: All statistics and settlements are automatically normalized to your primary currency.
A single expense can be split among multiple payers. The system tracks partial payments and contributions meticulously.
Our Smart Settle Up feature uses a greedy optimization algorithm to minimize the number of transactions needed to settle all debts across multiple currencies.
Generate detailed reports with smart naming:
- PDF Reports (iText): Styled summaries with charts. (Default:
GroupName_ExpenseReport) - CSV Data Export: Raw transaction data for Excel/Sheets. (Default:
GroupName_ExpenseReport) - JSON Backup: Full database portable export for migration. (Default:
GroupName_Backup)
Enable family-based expense tracking to aggregate spending by household while maintaining individual member records.
Built with JavaFX + AtlantaFX (Primer Dark) for a modern dark-mode experience.
Uses Spring Data JPA with an embedded H2 database for reliable local storage and automatic data migration.
| Layer | Technology |
|---|---|
| Core Framework | Spring Boot 3 |
| UI Framework | JavaFX 21 + FXML |
| Styling | AtlantaFX |
| Persistence | Spring Data JPA / Hibernate |
| Database | H2 Embedded Database |
| JSON Processing | Jackson Databind |
| PDF Generation | iText PDF Core |
| Data Export | CSV Writer |
| Build Tool | Maven |
- Java JDK 17+
- Maven 3.6+
git clone https://github.com/malcolm-cephas/Expense_Splitter.git
cd Expense_Splitter/expense-splitterTo set up the environment and build the project for the first time:
./setup.batOnce setup is complete, run the application:
./start.batNote
Detailed system dependencies are listed in requirements.txt.
The project includes a robust GitHub Actions workflow (build.yml) that:
- Automatically builds and tests the application on every push to
main. - Generates an executable JAR as a build artifact.
- Enables seamless release management via GitHub Releases.
mvn clean install -DskipTests
mvn javafx:runThe application runs as a single JVM desktop application combining JavaFX UI with a Spring Boot backend and external Currency API integration.
flowchart TD
subgraph External
API["Currency API\n(Exchange Rates)"]
end
subgraph System_Context
U[End User]
APP["Expense Splitter Pro\n(JavaFX + Spring Boot)"]
FS[(Local Filesystem)]
H2[(Embedded H2 Database)]
CACHE["exchange_rates.json\n(Offline Cache)"]
BKUP["Exported Backups\n(.json / .csv / .pdf)"]
end
U -->|uses| APP
APP -->|fetches| API
APP -->|reads/writes| H2
APP -->|persist| CACHE
APP -->|exports/imports| BKUP
APP -->|renders| FS
subgraph JVM_Process
BOOT[Application Bootstrap]
CFG[Spring Configuration]
subgraph JavaFX_UI
FXML[FXML Views]
CTRLS[Controllers]
end
subgraph Spring_Backend
SRV[Business Services]
EXSRV[Exchange Rate Service]
REPO[Repositories]
JPA[JPA Hibernate]
end
end
BOOT --> CFG
BOOT --> FXML
BOOT --> SRV
FXML --> CTRLS
CTRLS --> SRV
SRV --> EXSRV
SRV --> REPO
REPO --> JPA
JPA --> H2
SRV --> FS
The application uses an embedded relational model with support for currency preferences.
erDiagram
GROUP ||--o{ EXPENSE : has
GROUP }o--o{ USER : members
EXPENSE ||--o{ EXPENSE_PAYMENT : has
EXPENSE ||--o{ EXPENSE_SPLIT : has
USER ||--o{ EXPENSE_PAYMENT : pays
USER ||--o{ EXPENSE_SPLIT : owes
GROUP {
UUID id
string name
string description
decimal budget
string budgetCurrency
boolean familyGroupingEnabled
}
USER {
UUID id
string name
string email
string currencyPreference
string familyName
}
EXPENSE {
UUID id
string description
decimal amount
string currency
string splitType
string category
LocalDate expenseDate
}
EXPENSE_PAYMENT {
UUID id
decimal amount
}
EXPENSE_SPLIT {
UUID id
decimal owedAmount
decimal paidAmount
boolean isPaid
}
The app fetches live rates (or uses cache) to ensure correct conversion if the expense currency differs from the group base.
sequenceDiagram
actor User
participant UI as AddExpenseController
participant EX as ExchangeRateService
participant Service as ExpenseService
participant DB as H2 Database
User ->> UI: Select Currency & Payers
UI ->> EX: getExchangeRate()
EX -->> UI: Rate (Cached/Live)
UI ->> Service: addExpense(multiple_payers)
Service ->> Service: compute multi-payer splits
Service ->> Service: normalize to base currency
Service ->> DB: save Expense + Payments
DB -->> Service: OK
Service -->> UI: success
UI -->> User: UI updated
Debts are simplified globally by converting all individual expense balances into the user's primary currency first.
sequenceDiagram
actor User
participant UI as SettleUpController
participant EX as ExchangeRateService
participant Service as SettlementService
participant DB as H2 Database
User ->> UI: Smart Settle Up
UI ->> Service: computeSettlements()
Service ->> DB: load expenses
DB -->> Service: expenses
loop For each Expense
Service ->> EX: convert to base currency
EX -->> Service: normalized amount
end
opt Family Grouping Enabled
Service ->> Service: Aggregate by Family Name
end
Service ->> Service: greedy debt algorithm
Service -->> UI: simplified settlement list
UI -->> User: show suggestions
Generate reports that preserve both the original currency and the normalized totals.
sequenceDiagram
actor User
participant UI as GroupViewController
participant Service as ExportService
participant PDF as iText
participant CSV as CSV Writer
participant JSON as Jackson
participant FS as Filesystem
User ->> UI: Export (Choose Type)
UI ->> Service: export()
alt PDF/CSV Report
Service ->> PDF: generate (GroupName_ExpenseReport)
PDF -->> Service: file
else JSON Backup
Service ->> JSON: serialize (GroupName_Backup)
JSON -->> Service: file
end
Service ->> FS: write file
Service -->> UI: path
UI -->> User: success success
src/main/java/com/malcolm/expensesplitter
│
├── config
│ └── AppConfig (Global Settings & Currency Symbols)
│
├── controllers
│ ├── DashboardController (Setup & Navigation)
│ ├── GroupViewController (Expense List)
│ ├── AddExpenseController (Multi-Currency Entry)
│ ├── ExpenseDetailsController (Split Breakdown)
│ └── StatisticsController (Normalized spending charts)
│
├── services
│ ├── ExpenseService (Split Logic)
│ ├── SettlementService (Debt Simplification)
│ ├── ExchangeRateService (API & Offline Cache)
│ └── ExportService (PDF/CSV Generation)
│
├── repositories
│ └── ... (JPA Data Access)
│
└── models
└── ... (Domain Entities)
Contributions are welcome!
- Fork the repository
- Create a feature branch
- Commit your changes
- Push to your branch
- Open a Pull Request
This project is licensed under the MIT License. See the LICENSE file for details.
Malcolm Cephas
- GitHub: @Malcolm Cephas
Marcus Franklin J
- GitHub: @Marcus Franklin J



