A full-stack expense tracking and debt management application built with Flutter (frontend) and Node.js/Express (backend). Perfect for managing shared expenses in hostels, apartments, friend groups, or any shared living situations.
- Ledger-Based Expense Tracking: All expenses are organized in ledgers (groups)
- Flexible Expense Splitting:
- Equal split among all members
- Custom split with individual amounts
- Smart Debt Calculation: Automatic debt tracking showing who owes whom
- Settlement System: Easy debt settlement with automatic distribution
- Transaction History: Complete history with filters and CSV export
- Approval System: Smart auto-approval for expenses, manual approval for settlements
- Dashboard: Quick overview of all debts across ledgers
- Multiple Ledgers: Create and manage multiple expense groups
- Friends System: Add friends and manage connections
- Member Roles: Admin and member roles for ledger management
- Real-time Updates: See debts update immediately after recording expenses
- Auto-Approved Expenses: When you record an expense, it's approved instantly
- Custom Split Support: Specify exact amounts each person owes
- Debt Resolution: Calculates net balances to minimize transactions
- CSV Export: Download transaction history for record-keeping
- Material Design 3: Modern, beautiful UI with smooth animations
HostelMoney/
├── payn/ # Backend (Node.js + Express)
│ ├── src/
│ │ ├── index.js # Main server file
│ │ └── routes/
│ │ └── db.js # Database connection
│ └── package.json
│
├── payn_frontend/ # Frontend (Flutter)
│ ├── lib/
│ │ ├── main.dart
│ │ ├── models/ # Data models
│ │ ├── screens/ # UI screens
│ │ └── services/ # API services
│ └── pubspec.yaml
│
└── Documentation/
├── APPROVAL_SYSTEM.md
├── CUSTOM_SPLIT_FEATURE.md
├── FIX_DEBT_CALCULATION.md
└── TESTING_DEBTS.md
-
Backend:
- Node.js (v14 or higher)
- MySQL database
-
Frontend:
- Flutter SDK (3.9.2 or higher)
- Dart SDK
- Android Studio / Xcode (for mobile deployment)
- Create a MySQL database named
payn:
CREATE DATABASE payn;- Create the required tables:
-- Users table
CREATE TABLE users (
Uid INT PRIMARY KEY AUTO_INCREMENT,
Uname VARCHAR(255) NOT NULL UNIQUE,
Passhash VARCHAR(255) NOT NULL,
Money DECIMAL(10, 2) DEFAULT 0.00
);
-- Ledgers table
CREATE TABLE ledgers (
LedgerID INT PRIMARY KEY AUTO_INCREMENT,
LedgerName VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Ledger members table
CREATE TABLE ledger_members (
LedgerID INT NOT NULL,
Uid INT NOT NULL,
Role ENUM('admin', 'member') DEFAULT 'member',
joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (LedgerID, Uid),
FOREIGN KEY (LedgerID) REFERENCES ledgers(LedgerID) ON DELETE CASCADE,
FOREIGN KEY (Uid) REFERENCES users(Uid) ON DELETE CASCADE
);
-- Transactions table
CREATE TABLE transactions (
Tid INT PRIMARY KEY AUTO_INCREMENT,
`From` INT NOT NULL,
`To` INT NOT NULL,
Amount DECIMAL(10, 2) NOT NULL,
Approved ENUM('A', 'NA', 'R') DEFAULT 'NA',
Resolved ENUM('Y', 'NA') DEFAULT 'NA',
LedgerID INT,
Description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (`From`) REFERENCES users(Uid),
FOREIGN KEY (`To`) REFERENCES users(Uid),
FOREIGN KEY (LedgerID) REFERENCES ledgers(LedgerID) ON DELETE CASCADE
);
-- Friends table
CREATE TABLE friends (
Uid1 INT NOT NULL,
Uid2 INT NOT NULL,
Status ENUM('pending', 'accepted', 'rejected') DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (Uid1, Uid2),
FOREIGN KEY (Uid1) REFERENCES users(Uid) ON DELETE CASCADE,
FOREIGN KEY (Uid2) REFERENCES users(Uid) ON DELETE CASCADE
);- Navigate to the backend directory:
cd payn- Install dependencies:
npm install- Configure database connection in
src/routes/db.js:
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'your_password',
database: 'payn',
// ...
});- Start the server:
npm run start:devThe server will start on http://localhost:8080
- Navigate to the frontend directory:
cd payn_frontend- Get Flutter dependencies:
flutter pub get- Update API endpoint in
lib/services/api_service.dart:
static const String baseUrl = 'http://localhost:8080';
// For Android emulator: 'http://10.0.2.2:8080'
// For physical device: 'http://YOUR_IP:8080'- Run the app:
flutter run- Click the + button on the dashboard
- Select "I Paid for Something"
- Choose the ledger (group)
- Enter the amount and description
- Choose split type:
- Equal Split: Divides amount equally among all members
- Custom Split: Enter specific amounts for each person
- Submit
Result: Everyone immediately sees they owe you their share!
Option 1: Quick Settle from Dashboard
- See orange debt cards on dashboard
- Click "Pay Now"
- Confirm the amount
- Submit
Option 2: Manual Settlement
- Click + button
- Select "Settle Up with Someone"
- Choose ledger and recipient
- Enter amount
- Submit (requires recipient's approval)
- Create Ledger: Dashboard → Create Ledger button
- Add Members: Ledger Details → Members tab → Add Member
- View Debts: Ledger Details → Debt Tracking section
- View History: Ledger Details → Transaction History tab
- Export Data: Transaction History → Export to CSV
| From | To | Type | Meaning | Auto-Approved? |
|---|---|---|---|---|
| You | You | Expense Record | You paid for the group | Yes |
| You | Other | Debt Settlement | You're paying someone back | No (needs approval) |
Equal Split Example:
- You record: "Paid $100 for dinner" (4 people)
- System calculates: $100 ÷ 4 = $25 per person
- Result: Each friend owes you $25
Custom Split Example:
- You record: "Paid $100 for groceries"
- Custom amounts: Alice $40, Bob $35, Charlie $25
- Result: Each person owes their specified amount
Expenses (Auto-Approved):
Record expense → Transaction created with Approved='A' → Debts update immediately
Settlements (Needs Approval):
Submit settlement → Transaction created with Approved='NA' →
Recipient approves → Approved='A' → Debts update
POST /signup- Register new userPOST /login- User login
GET /ledgers/:uid- Get user's ledgersPOST /ledgers- Create ledgerGET /ledgers/:ledgerId/members- Get ledger membersPOST /ledgers/:ledgerId/members- Add memberDELETE /ledgers/:ledgerId/members/:uid- Remove member
POST /pay- Create transaction (expense or settlement)GET /ledgers/:ledgerId/transactions- Get transaction historyGET /ledgers/:ledgerId/transactions/export- Export to CSVPOST /approve- Approve/reject transaction
GET /ledgers/:ledgerId/debts- Get debt balancesPOST /ledgers/:ledgerId/settle- Settle net debt
GET /friends/:uid- Get friends listPOST /friends/add- Send friend requestPOST /friends/respond- Accept/reject request
transactions
- Stores all financial transactions
Approved: 'A' (Approved), 'NA' (Pending), 'R' (Rejected)Resolved: 'Y' (Settled), 'NA' (Unresolved)- Special case:
From = Toindicates expense record
ledgers
- Groups for expense sharing
- Can have multiple members with different roles
ledger_members
- Junction table linking users to ledgers
- Stores role (admin/member) and join date
- Dashboard: Overview of all ledgers and debts
- Ledger Details: Members, debts, and transaction history
- Pay Screen: Two-step expense recording or settlement
- Approvals: Pending transactions requiring approval
- Friends: Manage friend connections
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Detailed documentation available in the project:
- APPROVAL_SYSTEM.md: Complete explanation of the approval workflow
- CUSTOM_SPLIT_FEATURE.md: How to use and implement custom splits
- FIX_DEBT_CALCULATION.md: Technical details of debt calculation
- TESTING_DEBTS.md: Testing guide and troubleshooting
- Ensure transactions are approved (
Approved = 'A') - Check transactions are unresolved (
Resolved = 'NA') - Verify correct ledger ID
- Ensure amounts sum to total (within $0.01 tolerance)
- Check description format:
[Custom split: Name $amount, ...]
- Optimal debt resolution algorithm
- Push notifications for approvals
- Receipt image uploads
- Multiple currency support
- Recurring expenses
- Budget tracking per ledger
- Mobile app deployment (iOS & Android)
Note: This is a full-stack application requiring both backend and frontend setup. Make sure both services are running for full functionality.
Happy expense tracking! 💰✨