Date: October 26, 2025 Status: ✅ Complete
Added a complete CSV import system for categories, allowing users to bulk import categories, groups, and types from a CSV file.
- Auto-creates categories_type and categories_group if they don't exist
- Skips duplicates - won't create duplicate categories
- Validates CSV format and provides clear error messages
- Session-based - automatically associates with logged-in user
- Drag and drop file upload
- Browse button for traditional file selection
- Progress indicator during upload
- Detailed results showing:
- Categories created
- Duplicates skipped
- Groups processed
- Types processed
Expected format:
categories,categories_group,categories_type
Groceries,Food & Dining,Expense
Salary,Income,Income
Gas & Fuel,Auto & Transportation,ExpenseAdded:
- New endpoint:
/api/categories/csv_import(POST) - Imports:
os,csv,session,secure_filename,Config - Full CSV processing logic with validation
Features:
- Validates CSV headers
- Creates types and groups automatically
- Checks for duplicate categories
- Returns detailed import statistics
- Cleans up uploaded file after processing
Added:
- New route:
/categories/import(GET) - Renders the import page
Created new file:
- Beautiful upload interface with drag & drop
- Clear instructions and CSV format examples
- Progress bar during upload
- Detailed success/error messages
- Statistics display after import
Created new file:
- Drag and drop file handling
- File validation (CSV only)
- AJAX upload to API
- Progress tracking
- Result display with statistics
Modified:
- Added import button (upload icon) next to add category button
- Links to
/categories/import
-
Navigate to Categories
- Go to
/categories - Click the upload icon button
- Go to
-
Upload CSV
- Drag and drop your CSV file OR
- Click "Browse File" to select
-
Review Results
- See how many categories were created
- See how many duplicates were skipped
- See groups and types processed
API Endpoint:
POST /api/categories/csv_import
Content-Type: multipart/form-data
# Form data:
file: <CSV file>Response:
{
"message": "Categories imported successfully",
"categories_created": 131,
"categories_skipped": 0,
"types_processed": 3,
"groups_processed": 25
}The repository includes a sample file at /data/categories_data.csv with:
- 131 categories
- 25 groups (Food & Dining, Auto & Transportation, Bills & Utilities, etc.)
- 3 types (Income, Expense, Transfer)
- Validate user is authenticated
- Check file is provided and is CSV
- Save file to uploads folder temporarily
- Parse CSV and validate headers
- For each row:
- Get or create categories_type
- Get or create categories_group
- Check if category exists (by name + group + type)
- Skip if exists, create if new
- Clean up - delete uploaded file
- Return statistics
- Uses
query.filter_by().first()to check existing records - Caches type and group IDs in dictionaries during import
- Only one query per unique type/group name
- Prevents N+1 query problems
- ✅ Session-based authentication required
- ✅ File extension validation (.csv only)
- ✅ Secure filename handling with
secure_filename() - ✅ Temporary file cleanup after processing
- ✅ User ID from session (can't import for other users)
- Restart Flask app to load new endpoints
- Navigate to http://localhost:5000/categories
- Click upload icon button
- Upload the file
/data/categories_data.csv - Verify results show imported categories
With the sample categories_data.csv:
- ✅ 131 categories created
- ✅ 0 duplicates skipped (first import)
- ✅ 25 groups processed
- ✅ 3 types processed
Second import:
- ✅ 0 categories created
- ✅ 131 duplicates skipped
- ✅ 25 groups processed
- ✅ 3 types processed
The system handles:
| Error | Response |
|---|---|
| No file uploaded | 400: No file provided |
| Empty filename | 400: No file selected |
| Non-CSV file | 400: File must be a CSV |
| Missing CSV headers | 400: CSV must have headers: ... |
| Invalid CSV format | 500: Error processing CSV: ... |
| Not authenticated | 401: User not authenticated |
Potential improvements:
- Bulk Edit - Update existing categories from CSV
- Export - Download current categories as CSV
- Template - Download blank CSV template
- Preview - Show preview before importing
- Validation - Client-side CSV validation before upload
- Mapping - Allow custom column mapping
- Undo - Ability to undo an import
Description: Import categories from CSV file
Authentication: Required (session-based)
Content-Type: multipart/form-data
Parameters:
file(required): CSV file with headers: categories, categories_group, categories_type
Success Response (201):
{
"message": "Categories imported successfully",
"categories_created": 131,
"categories_skipped": 0,
"types_processed": 3,
"groups_processed": 25
}Error Responses:
400: Invalid request (missing file, wrong format, invalid CSV)401: Not authenticated500: Server error during processing
✅ Complete CSV import system
- Backend API endpoint
- Frontend upload interface
- Drag & drop support
- Smart duplicate handling
- Auto-creation of types and groups
- Detailed import statistics
- User-friendly interface
The feature is ready to use! Just restart your Flask application and navigate to /categories to see the new upload button.