mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-24 07:10:21 -05:00
d9dab3a49c
- Add organized screenshot sections for better visual presentation - Include all 12 available screenshots from assets/screenshots/ - Group screenshots into logical categories: * Core Application Views (Dashboard, Projects, Tasks, Clients) * Management & Analytics (Reports, Visual Analytics, Task Management, Admin) * Data Entry & Creation (Log Time, New Task, New Client, New Project) - Improve visual layout with proper spacing and responsive design - Enhance user experience by showcasing full application capabilities
359 lines
9.1 KiB
Markdown
359 lines
9.1 KiB
Markdown
# Complete Database Migration Guide
|
|
|
|
This guide covers **ALL** possible migration scenarios from any previous database state to the new Flask-Migrate system.
|
|
|
|
## 🎯 Migration Scenarios Covered
|
|
|
|
### 1. **Fresh Installation** (No existing database)
|
|
- New project setup
|
|
- First-time deployment
|
|
|
|
### 2. **Existing Database with Old Custom Migrations**
|
|
- Legacy migration scripts
|
|
- Custom Python migration files
|
|
- Manual schema changes
|
|
|
|
### 3. **Existing Database with Mixed Schema**
|
|
- Some tables exist, some missing
|
|
- Incomplete schema
|
|
- Partial migrations
|
|
|
|
### 4. **Existing Database with Data**
|
|
- Production databases with user data
|
|
- Development databases with test data
|
|
- Staging databases
|
|
|
|
### 5. **Database from Different Versions**
|
|
- Old TimeTracker versions
|
|
- Different schema versions
|
|
- Incompatible table structures
|
|
|
|
## 🚀 Migration Methods
|
|
|
|
### **Method 1: Automated Migration (Recommended)**
|
|
|
|
#### **For Any Existing Database:**
|
|
```bash
|
|
# Run the comprehensive migration script
|
|
python migrations/migrate_existing_database.py
|
|
```
|
|
|
|
This script will:
|
|
- ✅ Detect your database type (PostgreSQL/SQLite)
|
|
- ✅ Create a complete backup
|
|
- ✅ Analyze existing schema
|
|
- ✅ Create migration strategy
|
|
- ✅ Initialize Flask-Migrate
|
|
- ✅ Create baseline migration
|
|
- ✅ Preserve all existing data
|
|
- ✅ Verify migration success
|
|
|
|
#### **For Legacy Schema Migration:**
|
|
```bash
|
|
# Run the legacy schema migration script
|
|
python migrations/legacy_schema_migration.py
|
|
```
|
|
|
|
This script handles:
|
|
- ✅ Old `projects.client` → `projects.client_id` conversion
|
|
- ✅ Missing columns in settings table
|
|
- ✅ Legacy table structures
|
|
- ✅ Data preservation
|
|
|
|
### **Method 2: Manual Migration**
|
|
|
|
#### **Step-by-Step Process:**
|
|
|
|
1. **Backup Your Database**
|
|
```bash
|
|
# 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. **Initialize Flask-Migrate**
|
|
```bash
|
|
flask db init
|
|
```
|
|
|
|
3. **Create Baseline Migration**
|
|
```bash
|
|
flask db migrate -m "Baseline from existing database"
|
|
```
|
|
|
|
4. **Review Generated Migration**
|
|
```bash
|
|
# Check the generated file in migrations/versions/
|
|
cat migrations/versions/*.py
|
|
```
|
|
|
|
5. **Stamp Database as Current**
|
|
```bash
|
|
flask db stamp head
|
|
```
|
|
|
|
6. **Apply Any Pending Migrations**
|
|
```bash
|
|
flask db upgrade
|
|
```
|
|
|
|
### **Method 3: Setup Scripts**
|
|
|
|
#### **Windows:**
|
|
```bash
|
|
scripts\setup-migrations.bat
|
|
```
|
|
|
|
#### **Linux/Mac:**
|
|
```bash
|
|
scripts/setup-migrations.sh
|
|
```
|
|
|
|
#### **Python (Cross-platform):**
|
|
```bash
|
|
python migrations/manage_migrations.py
|
|
```
|
|
|
|
## 🔍 Pre-Migration Analysis
|
|
|
|
### **Check Your Current State:**
|
|
|
|
```bash
|
|
# Check if Flask-Migrate is available
|
|
python -c "import flask_migrate; print('✓ Flask-Migrate available')"
|
|
|
|
# Check database connection
|
|
python -c "from app import create_app; app = create_app(); print('✓ Database accessible')"
|
|
|
|
# Check existing tables (if any)
|
|
python -c "
|
|
from app import create_app, db
|
|
app = create_app()
|
|
with app.app_context():
|
|
inspector = db.inspect(db.engine)
|
|
tables = inspector.get_table_names()
|
|
print(f'Existing tables: {tables}')
|
|
"
|
|
```
|
|
|
|
### **Common Database States:**
|
|
|
|
| State | Description | Migration Approach |
|
|
|-------|-------------|-------------------|
|
|
| **No Database** | Fresh installation | `flask db init` → `flask db migrate` → `flask db upgrade` |
|
|
| **Empty Database** | Tables exist but no data | `flask db stamp head` → `flask db upgrade` |
|
|
| **Partial Schema** | Some tables missing | Run comprehensive migration script |
|
|
| **Legacy Schema** | Old table structures | Run legacy schema migration script |
|
|
| **Complete Schema** | All tables exist | `flask db stamp head` |
|
|
|
|
## 🛡️ Safety Measures
|
|
|
|
### **Automatic Backups:**
|
|
- ✅ Database backup before any migration
|
|
- ✅ Timestamped backup files
|
|
- ✅ Multiple backup formats (dump, copy)
|
|
- ✅ Backup verification
|
|
|
|
### **Migration Verification:**
|
|
- ✅ Schema analysis before migration
|
|
- ✅ Data integrity checks
|
|
- ✅ Rollback capability
|
|
- ✅ Migration status verification
|
|
|
|
### **Error Handling:**
|
|
- ✅ Graceful failure handling
|
|
- ✅ Detailed error messages
|
|
- ✅ Recovery instructions
|
|
- ✅ Safe fallback options
|
|
|
|
## 📋 Migration Checklist
|
|
|
|
### **Before Migration:**
|
|
- [ ] **Backup your database** (automatic with scripts)
|
|
- [ ] **Check disk space** (need space for backup + migration)
|
|
- [ ] **Stop application** (if running)
|
|
- [ ] **Verify dependencies** (Flask-Migrate installed)
|
|
- [ ] **Check permissions** (database access)
|
|
|
|
### **During Migration:**
|
|
- [ ] **Run migration script** (automatic or manual)
|
|
- [ ] **Review generated files** (check migrations/versions/)
|
|
- [ ] **Verify backup creation** (check backup files)
|
|
- [ ] **Monitor progress** (watch for errors)
|
|
|
|
### **After Migration:**
|
|
- [ ] **Test application** (start and verify functionality)
|
|
- [ ] **Check migration status** (`flask db current`)
|
|
- [ ] **Verify data integrity** (check key tables)
|
|
- [ ] **Update deployment scripts** (if using CI/CD)
|
|
|
|
## 🔧 Troubleshooting
|
|
|
|
### **Common Issues & Solutions:**
|
|
|
|
#### **1. Migration Already Applied**
|
|
```bash
|
|
# Check current status
|
|
flask db current
|
|
|
|
# If migration is already applied, stamp the database
|
|
flask db stamp head
|
|
```
|
|
|
|
#### **2. Schema Conflicts**
|
|
```bash
|
|
# Show migration heads
|
|
flask db heads
|
|
|
|
# Merge branches if needed
|
|
flask db merge -m "Merge migration branches" <revision1> <revision2>
|
|
```
|
|
|
|
#### **3. Database Out of Sync**
|
|
```bash
|
|
# Check migration history
|
|
flask db history
|
|
|
|
# Reset to specific revision
|
|
flask db stamp <revision>
|
|
```
|
|
|
|
#### **4. Permission Errors**
|
|
```bash
|
|
# Check database permissions
|
|
# Ensure user has CREATE, ALTER, INSERT privileges
|
|
# For PostgreSQL: GRANT ALL PRIVILEGES ON DATABASE timetracker TO timetracker;
|
|
```
|
|
|
|
#### **5. Connection Issues**
|
|
```bash
|
|
# Verify DATABASE_URL environment variable
|
|
echo $DATABASE_URL
|
|
|
|
# Test connection manually
|
|
python -c "from app import create_app; app = create_app(); print('Connection OK')"
|
|
```
|
|
|
|
### **Recovery Options:**
|
|
|
|
#### **If Migration Fails:**
|
|
1. **Check backup files** - your data is safe
|
|
2. **Review error logs** - identify the issue
|
|
3. **Fix the problem** - resolve conflicts/errors
|
|
4. **Restart migration** - run script again
|
|
|
|
#### **If Data is Lost:**
|
|
1. **Restore from backup** - use pg_restore or copy SQLite file
|
|
2. **Verify restoration** - check data integrity
|
|
3. **Contact support** - if issues persist
|
|
|
|
## 📚 Advanced Migration Scenarios
|
|
|
|
### **Handling Complex Schema Changes:**
|
|
|
|
#### **Custom Data Migrations:**
|
|
```python
|
|
# In your migration file
|
|
def upgrade():
|
|
# Custom data transformation
|
|
op.execute("UPDATE users SET role = 'user' WHERE role IS NULL")
|
|
|
|
# Complex table modifications
|
|
op.execute("""
|
|
INSERT INTO new_table (id, name, status)
|
|
SELECT id, name, 'active' FROM old_table
|
|
WHERE status = 'enabled'
|
|
""")
|
|
```
|
|
|
|
#### **Conditional Migrations:**
|
|
```python
|
|
def upgrade():
|
|
# Handle different database types
|
|
if op.get_bind().dialect.name == 'postgresql':
|
|
op.execute('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"')
|
|
elif op.get_bind().dialect.name == 'sqlite':
|
|
# SQLite-specific operations
|
|
pass
|
|
```
|
|
|
|
#### **Rollback Strategies:**
|
|
```python
|
|
def downgrade():
|
|
# Always provide rollback capability
|
|
op.drop_table('new_table')
|
|
op.drop_column('existing_table', 'new_column')
|
|
```
|
|
|
|
## 🚀 Post-Migration
|
|
|
|
### **Verification Steps:**
|
|
```bash
|
|
# Check migration status
|
|
flask db current
|
|
|
|
# View migration history
|
|
flask db history
|
|
|
|
# Test database connection
|
|
python -c "from app import create_app, db; app = create_app(); print('OK')"
|
|
|
|
# Verify key tables
|
|
python -c "
|
|
from app import create_app, db
|
|
from app.models import User, Project, TimeEntry
|
|
app = create_app()
|
|
with app.app_context():
|
|
users = User.query.count()
|
|
projects = Project.query.count()
|
|
entries = TimeEntry.query.count()
|
|
print(f'Users: {users}, Projects: {projects}, Entries: {entries}')
|
|
"
|
|
```
|
|
|
|
### **Future Migrations:**
|
|
```bash
|
|
# Create new migration
|
|
flask db migrate -m "Add new feature"
|
|
|
|
# Apply migration
|
|
flask db upgrade
|
|
|
|
# Rollback if needed
|
|
flask db downgrade
|
|
```
|
|
|
|
## 📞 Support & Help
|
|
|
|
### **Getting Help:**
|
|
1. **Check this guide** - covers most scenarios
|
|
2. **Review migration logs** - detailed error information
|
|
3. **Check Flask-Migrate docs** - https://flask-migrate.readthedocs.io/
|
|
4. **Check Alembic docs** - https://alembic.sqlalchemy.org/
|
|
|
|
### **Emergency Recovery:**
|
|
```bash
|
|
# If everything fails, restore from backup
|
|
# PostgreSQL:
|
|
pg_restore --clean --dbname="$DATABASE_URL" backup_file.dump
|
|
|
|
# SQLite:
|
|
cp backup_file.db instance/timetracker.db
|
|
```
|
|
|
|
## 🎉 Success Indicators
|
|
|
|
Your migration is successful when:
|
|
- ✅ `flask db current` shows a revision number
|
|
- ✅ `flask db history` shows migration timeline
|
|
- ✅ Application starts without database errors
|
|
- ✅ All existing data is accessible
|
|
- ✅ New features work correctly
|
|
- ✅ Backup files are created and accessible
|
|
|
|
---
|
|
|
|
**Remember**: The migration scripts are designed to be **safe** and **reversible**. Your data is automatically backed up, and you can always restore if needed. When in doubt, run the comprehensive migration script - it handles all scenarios automatically!
|