11 KiB
Recurring Income Implementation
Overview
Implementation of automatic recurring income functionality that allows users to set up income entries (like salaries, freelance payments) that are automatically created based on frequency.
Date: 2024
Status: ✅ COMPLETE
Features Implemented
1. Database Schema Enhancement
File: app/models.py
Added recurring income fields to the Income model:
next_due_date(DateTime, nullable) - Next date when recurring income is duelast_created_date(DateTime, nullable) - Last date when income was auto-createdis_active(Boolean, default=True) - Whether recurring income is activeauto_create(Boolean, default=False) - Automatically create income entries
Helper Methods Added:
get_frequency_days()- Calculate days until next occurrenceis_recurring()- Check if income is recurring (frequency != 'once' and is_active)
2. Database Migration
File: migrations/add_recurring_income.py
Idempotent migration script that:
- Checks for existing columns before adding them
- Supports both
data/fina.dbandinstance/fina.dblocations - Adds all 4 recurring income fields with proper defaults
Execution: Run inside Docker container
docker compose exec web python migrations/add_recurring_income.py
3. Backend API Enhancement
File: app/routes/income.py
New Helper Function:
calculate_income_next_due_date(frequency, custom_days, from_date)- Calculates next due date based on frequency
Enhanced Endpoints:
POST /api/income/
- Now accepts
auto_createparameter - Calculates
next_due_datefor recurring income - Sets up recurring income infrastructure on creation
PUT /api/income/<id>
- Handles frequency changes
- Recalculates
next_due_datewhen frequency or auto_create changes - Clears
next_due_datewhen auto_create is disabled
PUT /api/income/<id>/toggle (NEW)
- Toggle recurring income active status (pause/resume)
- Recalculates
next_due_datewhen reactivated - Security: User-isolated via user_id check
POST /api/income/<id>/create-now (NEW)
- Manually create income entry from recurring income
- Creates one-time income entry with current date
- Updates recurring income's
last_created_dateandnext_due_date - Security: User-isolated via user_id check
4. Automatic Income Creation - Scheduler
File: app/scheduler.py
New Function: process_due_recurring_income()
- Runs every hour (5 minutes past the hour)
- Finds all active recurring income with auto_create enabled and due date <= today
- Creates new one-time income entries automatically
- Updates recurring income's
last_created_dateandnext_due_date - Prevents duplicates by checking for existing income on same day
- User isolation maintained through foreign keys
Scheduler Configuration:
scheduler.add_job(
func=process_due_recurring_income,
trigger=CronTrigger(minute=5), # Run 5 minutes past every hour
id='process_recurring_income',
name='Process due recurring income',
replace_existing=True
)
5. Frontend UI Enhancement
File: app/templates/income.html
Added to income modal form:
<!-- Auto-create recurring income -->
<div id="auto-create-container">
<label>
<input type="checkbox" id="income-auto-create">
<span>Automatically create income entries</span>
<p>When enabled, income entries will be created automatically based on the frequency.
You can edit or cancel at any time.</p>
</label>
</div>
6. Frontend JavaScript Enhancement
File: app/static/js/income.js
Enhanced Functions:
saveIncome()
- Now captures
auto_createcheckbox value - Sends to backend for processing
editIncome()
- Populates
auto_createcheckbox when editing - Shows/hides custom frequency container based on frequency value
renderIncomeTable()
- Shows recurring income badge with:
- Frequency indicator (weekly, monthly, etc.)
- Active/paused status icon
- Next due date
- Displays recurring-specific action buttons:
- Pause/Resume button (toggle active status)
- Create Now button (manually create income entry)
New Functions:
toggleRecurringIncome(id)
- Calls
/api/income/<id>/toggleendpoint - Toggles active status (pause/resume)
- Reloads income list on success
createIncomeNow(id)
- Calls
/api/income/<id>/create-nowendpoint - Creates income entry immediately
- Shows confirmation dialog
- Reloads income list and dashboard on success
7. Translation Support
File: app/static/js/i18n.js
English Translations Added:
'income.autoCreate': 'Automatically create income entries',
'income.autoCreateHelp': 'When enabled, income entries will be created automatically...',
'income.createNowConfirm': 'Create an income entry now from this recurring income?'
Romanian Translations Added:
'income.autoCreate': 'Creează automat intrări de venit',
'income.autoCreateHelp': 'Când este activat, intrările de venit vor fi create automat...',
'income.createNowConfirm': 'Creezi o intrare de venit acum din acest venit recurent?'
8. PWA Cache Update
File: app/static/sw.js
Updated cache version from fina-v2 to fina-v3 to ensure new JavaScript is loaded.
User Flow
Setting Up Recurring Income
- User clicks "Add Income" button
- Fills in income details:
- Amount: e.g., $5000
- Source: e.g., "Salary"
- Description: e.g., "Monthly Salary"
- Frequency: Select "Monthly" (or weekly, biweekly, every4weeks, custom)
- Checks "Automatically create income entries" checkbox
- Clicks "Save Income"
Backend Processing:
- Income entry created with frequency='monthly' and auto_create=True
next_due_datecalculated (e.g., 30 days from now)is_activeset to True- Entry appears in income list with recurring badge
Automatic Income Creation
Every hour (at :05 minutes):
- Scheduler checks for due recurring income
- For each due income:
- Creates new one-time income entry with current date
- Updates
last_created_dateto today - Calculates new
next_due_date(e.g., +30 days for monthly)
- Duplicate prevention: Checks if income already created today
Managing Recurring Income
Pause/Resume:
- Click pause button on recurring income entry
- Status changes to "paused",
next_due_datecleared - Click resume button to reactivate
next_due_daterecalculated from last_created_date or original date
Create Now (Manual):
- Click "Create Now" button
- Confirmation dialog appears
- Income entry created immediately
- Recurring income's
next_due_dateadvances to next period
Edit:
- Click edit button
- Modify amount, frequency, or other fields
- If frequency changes,
next_due_daterecalculated - Auto-create can be toggled on/off
Delete:
- Click delete button
- Confirmation dialog appears
- Recurring income deleted (no more auto-creation)
- Existing income entries remain
Security Considerations
User Isolation
✅ All queries filter by user_id=current_user.id
✅ Users can only access their own recurring income
✅ Scheduler maintains user isolation through foreign keys
Data Validation
✅ Amount validation (positive float) ✅ Custom frequency validation (min 1 day) ✅ Frequency enum validation (once/weekly/biweekly/every4weeks/monthly/custom)
Duplicate Prevention
✅ Scheduler checks for existing income on same day before creating ✅ Checks match on: user_id, description, source, date
Frequency Calculation
Supported Frequencies
| Frequency | Days | Calculation Method |
|---|---|---|
| once | 0 | No next_due_date (one-time) |
| weekly | 7 | from_date + 7 days |
| biweekly | 14 | from_date + 14 days |
| every4weeks | 28 | from_date + 28 days |
| monthly | ~30 | from_date + 1 month (relativedelta) |
| custom | N | from_date + N days (user-specified) |
Note: Monthly uses relativedelta(months=1) for accurate month-based calculation (handles varying month lengths).
Testing Checklist
✅ Completed Tests
-
Database Migration
- ✅ Migration runs successfully in container
- ✅ All 4 columns added (next_due_date, last_created_date, is_active, auto_create)
- ✅ Idempotent (can run multiple times)
-
API Endpoints
- ✅ Create income with auto_create=True
- ✅ Update income frequency and auto_create
- ✅ Toggle recurring income (pause/resume)
- ✅ Create income now (manual trigger)
- ✅ Delete income
-
Frontend UI
- ✅ Auto-create checkbox appears in modal
- ✅ Recurring badge shows on income table
- ✅ Action buttons (pause/resume, create now) appear
- ✅ Edit modal populates auto_create checkbox
-
Scheduler
- ⏳ Pending: Wait for next hour to verify automatic creation
- ✅ Scheduler initialized and running
-
Translations
- ✅ English translations added
- ✅ Romanian translations added
-
Security
- ✅ User isolation verified
- ✅ All queries filter by user_id
Future Enhancements (Not in Scope)
- Email notifications before income creation
- Bulk edit recurring income
- Recurring income templates
- Income forecasting/projections
- Dashboard widget showing upcoming recurring income
- Export recurring income schedule to calendar (ICS)
Technical Notes
Dependencies Added
python-dateutil- Already in requirements.txt for relativedelta
Files Modified
/home/iulian/projects/fina/app/models.py- Income model enhancement/home/iulian/projects/fina/migrations/add_recurring_income.py- New migration/home/iulian/projects/fina/app/routes/income.py- API endpoints/home/iulian/projects/fina/app/scheduler.py- Scheduler enhancement/home/iulian/projects/fina/app/templates/income.html- UI update/home/iulian/projects/fina/app/static/js/income.js- Frontend logic/home/iulian/projects/fina/app/static/js/i18n.js- Translations/home/iulian/projects/fina/app/static/sw.js- Cache version bump
Container Updates
# Migration executed inside container
docker compose exec web python migrations/add_recurring_income.py
# Container restarted to pick up changes
docker compose restart web
Conclusion
Recurring income feature is now fully implemented and operational. Users can:
- ✅ Set up automatic recurring income (salary, freelance, etc.)
- ✅ Choose frequency (weekly, monthly, every 4 weeks, custom)
- ✅ Enable/disable auto-creation
- ✅ Pause/resume recurring income
- ✅ Manually create income entries anytime
- ✅ Edit or delete recurring income
The scheduler runs hourly to automatically create income entries when due, maintaining user isolation and preventing duplicates. All features include proper security, translations, and PWA support.