A comprehensive Django-based personal finance tracking application with multi-currency support, expense management, income tracking, loan management, and advanced analytics.
Location: expenses/models.py
class UserProfile(models.Model):
user = OneToOneField(User)
currency = CharField(default='₹') # Base currency
language = CharField(choices=['en', 'hi', 'mr']) # Multi-language
has_seen_tutorial = BooleanField()
# Subscription fields
tier = CharField(choices=['FREE', 'PLUS', 'PRO'])
subscription_end_date = DateTimeField(null=True)
is_lifetime = BooleanField()
# Push notification preferences
daily_reminder = BooleanField(default=True)Key Properties:
is_pro- Check if user has active Pro subscriptionis_plus- Check if user has Plus or higher tieractive_tier- Returns actual active tier respecting subscription expirycan_add_account(),can_add_expense(),can_add_recurring()- Tier-based limits
View: expenses/views/settings.py - ProfileUpdateView
- Template: templates/expenses/profile_settings.html
- Form: expenses/forms.py -
ProfileUpdateForm
Current Fields Managed:
- First Name / Last Name
- Email Address
- Daily Expense Reminder (toggle)
- Social login detection
Related Settings Views:
CurrencyUpdateView- UpdatesUserProfile.currencyLanguageUpdateView- UpdatesUserProfile.language
Location: expenses/models.py
class Expense(models.Model):
user = ForeignKey(User)
date = DateField()
amount = DecimalField(max_digits=10, decimal_places=2)
description = TextField()
category = CharField(max_length=255)
payment_method = CharField(choices=['Cash', 'Credit Card', 'Debit Card', 'UPI', 'NetBanking'])
account = ForeignKey(Account, null=True, blank=True)
currency = CharField(max_length=5, default='₹')
exchange_rate = DecimalField()
base_amount = DecimalField() # Amount in user's base currencyLocation: expenses/models.py
class Income(models.Model):
user = ForeignKey(User)
date = DateField()
amount = DecimalField(max_digits=10, decimal_places=2)
source = CharField(max_length=255) # e.g., "Salary", "Freelance", "Dividend"
description = TextField()
account = ForeignKey(Account, null=True, blank=True)
currency = CharField(max_length=5, default='₹')
exchange_rate = DecimalField()
base_amount = DecimalField()Location: expenses/models.py
class Account(models.Model):
user = ForeignKey(User)
name = CharField(max_length=100)
account_type = CharField(choices=['CASH', 'BANK', 'CREDIT_CARD', 'INVESTMENT', 'FIXED_DEPOSIT', 'OTHER'])
balance = DecimalField()
currency = CharField(max_length=5, default='₹')
is_active = BooleanField(default=True)Location: expenses/models.py
class RecurringTransaction(models.Model):
user = ForeignKey(User)
transaction_type = CharField(choices=['EXPENSE', 'INCOME', 'TRANSFER', 'LOAN'])
amount = DecimalField()
description = TextField()
frequency = CharField(choices=['DAILY', 'WEEKLY', 'MONTHLY', 'YEARLY'])
start_date = DateField()
last_processed_date = DateField()
is_active = BooleanField(default=True)
# Source/Category fields for different transaction types
category = CharField() # For EXPENSE
source = CharField() # For INCOME
account = ForeignKey(Account)
from_account = ForeignKey(Account) # For TRANSFER
to_account = ForeignKey(Account) # For TRANSFER
loan = ForeignKey('Loan') # For LOAN repaymentLocation: expenses/models.py
class Category(models.Model):
user = ForeignKey(User)
name = CharField(max_length=255)
icon = CharField(max_length=50, default='bi-tag')
limit = DecimalField(null=True, blank=True) # Monthly budget limitLocation: expenses/views/dashboard.py
1. Net Worth History
net_worth_history = FinancialService.get_monthly_history(request.user, 6)
# Returns: [{'month': date, 'income': float, 'expense': float, 'savings': float}]2. Expense Analysis
- Category Breakdown: Group expenses by category, calculate % of total, project month-end
- Time Trends: Daily or Monthly aggregation with 7-day rolling average
- Top Expenses: Top 5 expenses by amount
- Budget Status: Compare category spending vs monthly limits
3. Income vs Expense Trend
# Merged view of income, expenses, and loan interest over time
ie_income_data = [income for each period]
ie_expense_data = [expenses + loan_interest for each period]
ie_savings_data = [income - expenses - loan_principal for each period]4. Salary Breakdown Analysis ("Where Did My Salary Go?") Location: expenses/views/dashboard.py
The dashboard calculates:
- Total Income - Sum of all income transactions
- Total Expenses - Sum of all expense transactions
- Savings Rate - (Savings / Total Income) × 100
- Daily Burn Rate - Total Expenses / Days Elapsed in month
- Top Categories - Top 3 spending categories
- Spending Pace - Projected month-end spending vs budget
salary_breakdown = {
'income': total_income,
'expenses': total_expenses,
'savings': savings,
'savings_rate': savings_rate,
'daily_burn': daily_burn,
'top_categories': category_limits[:3],
'month_name': display_month,
'spending_pace': {
'daily_spending_pace': daily_burn,
'projected_month_spend': daily_burn * num_days,
'spent_percent': (total_expenses / total_monthly_budget) * 100,
'ideal_percent': (days_elapsed / num_days) * 100,
}
}Users can filter by:
- Date Range: Custom start/end dates
- Year/Month: Single or multiple months
- Category: Single or multiple expense categories
- Budget breach warnings
- Category overspending alerts
- 3-month average spending comparisons
- "Relatable metrics" (e.g., "equivalent to X Netflix subscriptions")
1. Income Model has source field
- Text field for income source (e.g., "Salary", "Freelance", "Dividend")
- Used to identify salary income but not to automate salary date logic
2. RecurringTransaction Model
- Already supports MONTHLY frequency for recurring income
- Has
start_dateandlast_processed_datefields - Example: Salary could be set as recurring monthly income
- Code location: expenses/models.py
# Example: Salary can be tracked as recurring transaction
RecurringTransaction.objects.create(
user=user,
transaction_type='INCOME',
amount=Decimal('5000'),
source='Salary',
frequency='MONTHLY',
start_date=date(2026, 5, 25), # Salary date each month
)3. Income Forecasting Service Location: expenses/services.py
Current FinancialService provides:
get_monthly_history()- Aggregates income/expense by monthget_categorical_spending()- Breaks down spending by categoryget_spending_streak()- Calculates consecutive overspend days
- ✅ expenses/models.py - UserProfile (add salary_date field)
- ✅ expenses/models.py - Income (already has source)
- ✅ expenses/views/settings.py - ProfileUpdateView & CurrencyUpdateView
- ✅ expenses/views/dashboard.py - Dashboard salary breakdown logic
- ✅ expenses/forms.py - ProfileUpdateForm
- ✅ expenses/services.py - Add salary-based analysis methods
class UserProfile(models.Model):
# ... existing fields ...
salary_date = IntegerField(null=True, blank=True) # Day of month (1-31)
salary_source = CharField(max_length=255, blank=True) # e.g., "Salary", "Freelance"- Filter dashboard to show spending between salary dates
- "Salary Cycle" view: Show spending from salary_date to salary_date
- Alerts: Warn if spending exceeds salary before next salary date
- Add "Salary Date" field to Profile Settings
- Add "Salary Source" field (for identifying salary income)
- Example: "I receive salary on 25th of each month"
- "Income vs Expense per Salary Cycle" (not calendar month)
- "Savings % of salary" (more actionable than % of total income)
- "Days until next salary" indicator
- ✅ Multi-currency - User base currency stored in UserProfile
- ✅ Exchange rates - get_exchange_rate() utility converts transactions
- ✅ Currency choices - ₹,
$, €, £, ¥, A$ , C$, CHF, 元, ₩ - ✅ Multi-language - en, hi (Hindi), mr (Marathi)
- expenses/utils.py -
get_exchange_rate()function - expenses/models.py - CURRENCY_CHOICES
- expenses/context_processors.py - Currency formatting for templates
Add salary_date and salary_source to UserProfile
- Update ProfileUpdateForm
- Update ProfileUpdateView
- Add salary settings section to profile_settings.html
- Add salary cycle calculations
- Update salary breakdown logic
- Add salary-based insights
- Create
SalaryAnalysisServicein services.py - Methods for salary cycle aggregation and forecasting
| Component | File Path |
|---|---|
| User Profile Model | expenses/models.py |
| Income Model | expenses/models.py |
| Expense Model | expenses/models.py |
| RecurringTransaction Model | expenses/models.py |
| Dashboard View | expenses/views/dashboard.py |
| Settings View | expenses/views/settings.py |
| Profile Update Form | expenses/forms.py |
| Profile Settings Template | templates/expenses/profile_settings.html |
| Financial Services | expenses/services.py |
| Utilities | expenses/utils.py |
✅ Expense Tracking - By date, category, amount, payment method
✅ Income Tracking - By source, date, amount
✅ Budget Management - Category-wise monthly limits
✅ Account Management - Multiple accounts with currency support
✅ Recurring Transactions - Daily, Weekly, Monthly, Yearly
✅ Loan Tracking - EMI calculations with interest tracking
✅ AI Insights - Category trends, budget alerts, savings goals
✅ Net Worth Tracking - 6-month history
✅ Multi-currency Support - Currency conversion with exchange rates
✅ Advanced Filters - By date range, year/month, category
✅ Salary Breakdown Analysis - "Where Did My Salary Go?" visualization
- Add
salary_datefield to UserProfile model - Create migration for database schema change
- Update ProfileUpdateForm to include salary date input
- Enhance ProfileUpdateView to handle salary date
- Update profile_settings.html template
- Create SalaryAnalysisService in services.py
- Update dashboard.py to use salary date for period calculations
- Add salary cycle visualizations to dashboard templates