## New Features
### Import/Export System
- Add DataImport and DataExport models for tracking operations
- Implement CSV import for bulk time entry data
- Add support for importing from Toggl and Harvest (placeholder)
- Implement GDPR-compliant full data export (JSON format)
- Add filtered export functionality with date/project filters
- Create backup/restore functionality for database migrations
- Build migration wizard UI for seamless data transitions
- Add comprehensive test coverage (unit and integration tests)
- Create user documentation (IMPORT_EXPORT_GUIDE.md)
### Database Changes
- Add migration 040: Create data_imports and data_exports tables
- Track import/export operations with status, logs, and file paths
- Support automatic file expiration for temporary downloads
## UI/UX Improvements
### Navigation Menu Restructure
- Rename "Work" to "Time Tracking" for clarity
- Rename "Finance" to "Finance & Expenses"
- Add "Tools & Data" submenu with Import/Export and Saved Filters
- Reorganize Time Tracking submenu: prioritize Log Time, add icons to all items
- Expand Finance submenu: add Mileage, Per Diem, and Budget Alerts
- Add icons to all Admin submenu items for better visual scanning
- Fix Weekly Goals not keeping Time Tracking menu open
### Standardized Page Headers
Apply consistent page_header macro across 26+ pages:
- **Time Tracking**: Tasks, Projects, Clients, Kanban, Weekly Goals, Templates, Manual Entry
- **Finance**: Invoices, Payments, Expenses, Mileage, Per Diem, Budget Alerts, Reports
- **Admin**: Dashboard, Users, Roles, Permissions, Settings, API Tokens, Backups, System Info, OIDC
- **Tools**: Import/Export, Saved Filters, Calendar
- **Analytics**: Dashboard
Each page now includes:
- Descriptive icon (Font Awesome)
- Clear title and subtitle
- Breadcrumb navigation
- Consistent action button placement
- Responsive design with dark mode support
## Bug Fixes
### Routing Errors
- Fix endpoint name: `per_diem.list_per_diems` → `per_diem.list_per_diem`
- Fix endpoint name: `reports.index` → `reports.reports`
- Fix endpoint name: `timer.timer` → `timer.manual_entry`
- Add missing route registration for import_export blueprint
### User Experience
- Remove duplicate "Test Configuration" button from OIDC debug page
- Clean up user dropdown menu (remove redundant Import/Export link)
- Improve menu item naming ("Profile" → "My Profile", "Settings" → "My Settings")
## Technical Details
### New Files
- `app/models/import_export.py` - Import/Export models
- `app/utils/data_import.py` - Import business logic
- `app/utils/data_export.py` - Export business logic
- `app/routes/import_export.py` - API endpoints
- `app/templates/import_export/index.html` - User interface
- `tests/test_import_export.py` - Integration tests
- `tests/models/test_import_export_models.py` - Model tests
- `docs/IMPORT_EXPORT_GUIDE.md` - User documentation
- `docs/import_export/README.md` - Quick reference
- `migrations/versions/040_add_import_export_tables.py` - Database migration
### Modified Files
- `app/__init__.py` - Register import_export blueprint
- `app/models/__init__.py` - Export new models
- `app/templates/base.html` - Restructure navigation menu
- 26+ template files - Standardize headers with page_header macro
## Breaking Changes
None. All changes are backward compatible.
## Testing
- All existing tests pass
- New test coverage for import/export functionality
- Manual testing of navigation menu changes
- Verified consistent UI across all updated pages
Database Migrations with Flask-Migrate
This directory contains the database migration system for TimeTracker, now standardized on Flask-Migrate with proper versioning.
Overview
The migration system has been updated from custom Python scripts to use Flask-Migrate, which provides:
- Standardized migrations using Alembic
- Version tracking for all database changes
- Rollback capabilities to previous versions
- Automatic schema detection from SQLAlchemy models
- Cross-database compatibility (PostgreSQL, SQLite)
Quick Start
1. Initialize Migrations (First Time Only)
flask db init
2. Create Your First Migration
flask db migrate -m "Initial database schema"
3. Apply Migrations
flask db upgrade
Migration Commands
Basic Commands
flask db init- Initialize migrations directoryflask db migrate -m "Description"- Create a new migrationflask db upgrade- Apply pending migrationsflask db downgrade- Rollback last migrationflask db current- Show current migration versionflask db history- Show migration history
Advanced Commands
flask db show <revision>- Show specific migration detailsflask db stamp <revision>- Mark database as being at specific revisionflask db heads- Show current heads (for branched migrations)
Migration Workflow
1. Make Model Changes
Edit your SQLAlchemy models in app/models/:
# Example: Add a new column
class User(db.Model):
# ... existing fields ...
phone_number = db.Column(db.String(20), nullable=True)
2. Generate Migration
flask db migrate -m "Add phone number to users"
3. Review Generated Migration
Check the generated migration file in migrations/versions/:
def upgrade():
op.add_column('users', sa.Column('phone_number', sa.String(length=20), nullable=True))
def downgrade():
op.drop_column('users', 'phone_number')
4. Apply Migration
flask db upgrade
5. Verify Changes
Check the migration status:
flask db current
Migration Files Structure
migrations/
├── versions/ # Migration files
│ ├── 001_initial_schema.py
│ ├── 002_add_phone_number.py
│ └── ...
├── env.py # Migration environment
├── script.py.mako # Migration template
├── alembic.ini # Alembic configuration
└── README.md # This file
Transition from Old System
If you're migrating from the old custom migration system:
1. Backup Your Database
# PostgreSQL
pg_dump --format=custom --dbname="$DATABASE_URL" --file=backup_$(date +%Y%m%d_%H%M%S).dump
# SQLite
cp instance/timetracker.db backup_timetracker_$(date +%Y%m%d_%H%M%S).db
2. Use Migration Management Script
python migrations/manage_migrations.py
3. Or Manual Migration
# Initialize Flask-Migrate
flask db init
# Create initial migration (captures current schema)
flask db migrate -m "Initial schema from existing database"
# Apply migration
flask db upgrade
Best Practices
1. Migration Naming
Use descriptive names for migrations:
flask db migrate -m "Add user profile fields"
flask db migrate -m "Create project categories table"
flask db migrate -m "Add invoice payment tracking"
2. Testing Migrations
Always test migrations on a copy of your production data:
# Test upgrade
flask db upgrade
# Test downgrade
flask db downgrade
# Verify data integrity
3. Backup Before Migrations
# Always backup before major migrations
flask db backup # Custom command
# or
pg_dump --format=custom --dbname="$DATABASE_URL" --file=pre_migration_backup.dump
4. Review Generated Code
Always review auto-generated migrations before applying:
- Check the
upgrade()function - Verify the
downgrade()function - Ensure data types and constraints are correct
Troubleshooting
Common Issues
1. Migration Already Applied
# Check current status
flask db current
# If migration is already applied, stamp the database
flask db stamp <revision>
2. Migration Conflicts
# Show migration heads
flask db heads
# Merge branches if needed
flask db merge -m "Merge migration branches" <revision1> <revision2>
3. Database Out of Sync
# Check migration history
flask db history
# Reset to specific revision
flask db stamp <revision>
4. Model Import Errors
Ensure all models are imported in your application:
# In app/__init__.py or similar
from app.models import User, Project, TimeEntry, Task, Settings, Invoice, Client
Getting Help
- Check the migration status:
flask db current - Review migration history:
flask db history - Check Alembic logs for detailed error messages
- Verify database connection and permissions
Advanced Features
Custom Migration Operations
You can add custom operations in your migrations:
def upgrade():
# Custom data migration
op.execute("UPDATE users SET role = 'user' WHERE role IS NULL")
# Custom table operations
op.create_index('custom_idx', 'table_name', ['column_name'])
Data Migrations
For complex data migrations, use the op.execute() method:
def upgrade():
# Migrate existing data
op.execute("""
INSERT INTO new_table (id, name)
SELECT id, name FROM old_table
""")
Conditional Migrations
Handle different database types:
def upgrade():
# PostgreSQL-specific operations
if op.get_bind().dialect.name == 'postgresql':
op.execute('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"')
Environment Variables
Ensure these environment variables are set:
export FLASK_APP=app.py
export DATABASE_URL="postgresql://user:pass@localhost/dbname"
# or
export DATABASE_URL="sqlite:///instance/timetracker.db"
CI/CD Integration
For automated deployments, include migration steps:
# Example GitHub Actions step
- name: Run database migrations
run: |
flask db upgrade
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
Support
For migration-related issues:
- Check this README
- Review Flask-Migrate documentation: https://flask-migrate.readthedocs.io/
- Check Alembic documentation: https://alembic.sqlalchemy.org/
- Review generated migration files for errors