7.1 KiB
Alembic Migration for Project Costs - README
✅ Migration is Ready!
The Alembic migration for the Project Costs feature has been properly configured and is ready to run.
Migration Details
File: migrations/versions/018_add_project_costs_table.py
Revision: 018
Previous Revision: 017
Status: ✅ Ready to execute
Quick Start
Step 1: Backup Database (CRITICAL!)
# PostgreSQL
pg_dump -U timetracker timetracker > backup_$(date +%Y%m%d).sql
# Or if using Docker
docker-compose exec db pg_dump -U timetracker timetracker > backup_$(date +%Y%m%d).sql
Step 2: Check Current Migration Status
# Using Flask-Migrate
flask db current
# Expected output: 017 (or similar)
Step 3: Run the Migration
# Using Flask-Migrate (recommended)
flask db upgrade
# Or using Alembic directly
alembic upgrade head
Step 4: Verify Success
# Check migration status
flask db current
# Expected output: 018 (head)
# Verify table was created
psql -U timetracker -d timetracker -c "\d project_costs"
Step 5: Restart Application
# Docker
docker-compose restart app
# Or restart your Flask application server
What the Migration Does
Creates Table: project_costs
Columns:
id- Primary key (Integer)project_id- Foreign key to projects (Integer, NOT NULL)user_id- Foreign key to users (Integer, NOT NULL)description- Cost description (String 500, NOT NULL)category- Cost category (String 50, NOT NULL)amount- Cost amount (Numeric 10,2, NOT NULL)currency_code- Currency (String 3, default 'EUR')billable- Whether billable (Boolean, default TRUE)invoiced- Whether invoiced (Boolean, default FALSE)invoice_id- Foreign key to invoices (Integer, NULL)cost_date- Date of cost (Date, NOT NULL)notes- Additional notes (Text, NULL)receipt_path- Path to receipt (String 500, NULL)created_at- Creation timestamp (DateTime)updated_at- Update timestamp (DateTime)
Indexes:
ix_project_costs_project_idonproject_idix_project_costs_user_idonuser_idix_project_costs_cost_dateoncost_dateix_project_costs_invoice_idoninvoice_id
Foreign Keys:
fk_project_costs_project_id→projects(id)ON DELETE CASCADEfk_project_costs_user_id→users(id)ON DELETE CASCADEfk_project_costs_invoice_id→invoices(id)ON DELETE SET NULL
Safety Features
The migration includes:
- ✅ Table existence check (won't fail if table exists)
- ✅ Proper foreign key constraints
- ✅ Indexes for performance
- ✅ Safe rollback capability
- ✅ Follows existing migration chain (017 → 018)
Alternative Migration Methods
If Alembic/Flask-Migrate is not available:
Method 1: Direct SQL
psql -U timetracker -d timetracker -f migrations/add_project_costs.sql
Method 2: Python Script (Docker)
python docker/migrate-add-project-costs.py
Rollback (If Needed)
To rollback the migration:
# Using Flask-Migrate
flask db downgrade
# Or to specific revision
flask db downgrade 017
# Using Alembic
alembic downgrade -1
# or
alembic downgrade 017
⚠️ WARNING: Rollback will delete the project_costs table and all data!
Verification Checklist
After migration, verify:
- Migration status shows 018
- Table
project_costsexists - All columns are present
- Indexes are created
- Foreign keys are in place
- Application starts without errors
- Can view project page
- Can add a test cost
- Can edit the test cost
- Can delete the test cost
Expected Output
Successful Migration
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade 017 -> 018, Add project costs table for tracking expenses
Verification Query
-- Run this to verify table structure
\d project_costs
-- Expected output shows:
-- Table "public.project_costs"
-- Column, Type, Collation, Nullable, Default
-- (all columns listed)
-- Indexes: (4 indexes listed)
-- Foreign-key constraints: (3 constraints listed)
Troubleshooting
"Table already exists"
The migration has safety checks. If you see this error:
# Mark migration as complete
alembic stamp 018
"Cannot find revision 017"
Ensure previous migrations are run:
flask db upgrade 017
"Foreign key constraint violation"
Ensure tables projects, users, and invoices exist:
psql -U timetracker -d timetracker -c "\dt"
"Permission denied"
Grant necessary permissions:
GRANT CREATE ON DATABASE timetracker TO timetracker;
Post-Migration Steps
-
Restart Application
docker-compose restart app -
Clear Cache (if applicable)
redis-cli FLUSHALL # if using Redis -
Test in Browser
- Navigate to a project
- Look for "Project Costs & Expenses" section
- Add a test cost
-
Monitor Logs
tail -f logs/timetracker.log
Migration Files Structure
TimeTracker/
├── migrations/
│ ├── versions/
│ │ ├── 001_initial_schema.py
│ │ ├── ...
│ │ ├── 017_reporting_invoicing_extensions.py
│ │ └── 018_add_project_costs_table.py ← NEW
│ ├── add_project_costs.sql ← Alternative
│ └── alembic.ini
├── docker/
│ └── migrate-add-project-costs.py ← Alternative
└── MIGRATION_INSTRUCTIONS.md ← Detailed guide
Support & Documentation
- Detailed Instructions:
MIGRATION_INSTRUCTIONS.md - Feature Documentation:
PROJECT_COSTS_FEATURE.md - Implementation Details:
PROJECT_COSTS_IMPLEMENTATION_SUMMARY.md - Quick Start:
QUICK_START_PROJECT_COSTS.md
Migration Revision Chain
... → 016 → 017 → 018 (head)
↑ ↑
Previous Current
(project_costs)
Testing the Migration
If you want to test before running on production:
-
Create test database:
CREATE DATABASE timetracker_test; -
Restore backup to test database:
pg_restore -U timetracker -d timetracker_test backup.sql -
Run migration on test:
DB_NAME=timetracker_test flask db upgrade -
Verify on test:
psql -U timetracker -d timetracker_test -c "\d project_costs" -
If successful, run on production
Success Criteria
Migration is successful when:
- ✅ No error messages during upgrade
- ✅ Current revision is 018
- ✅ Table
project_costsexists with all columns - ✅ All 4 indexes are created
- ✅ All 3 foreign keys are in place
- ✅ Application starts without errors
- ✅ Project page shows costs section
- ✅ Can perform CRUD operations on costs
Questions?
If you encounter issues:
- Check logs:
logs/timetracker.log - Verify database connection
- Review
MIGRATION_INSTRUCTIONS.md - Check database state:
\d project_costs
Ready to migrate? Follow the Quick Start steps above!