7.9 KiB
Project Costs Migration Instructions
Overview
This document provides instructions for migrating the database to add the project_costs table using Alembic.
Migration File
Location: migrations/versions/018_add_project_costs_table.py
Revision: 018
Previous Revision: 017
Description: Adds project_costs table for tracking project expenses beyond hourly work
Pre-Migration Checklist
Before running the migration:
-
✅ Backup your database
# PostgreSQL backup example pg_dump -U timetracker timetracker > backup_before_project_costs_$(date +%Y%m%d).sql -
✅ Check current migration status
# In your project directory with Flask app context flask db current # Or using alembic directly alembic currentExpected output:
017 (head)or similar -
✅ Review the migration
cat migrations/versions/018_add_project_costs_table.py
Running the Migration
Method 1: Using Flask-Migrate (Recommended)
# Navigate to project directory
cd /path/to/TimeTracker
# Activate virtual environment if needed
source venv/bin/activate # Linux/Mac
# or
.\venv\Scripts\activate # Windows
# Run the migration
flask db upgrade
# Verify the migration
flask db current
Expected output after upgrade:
INFO [alembic.runtime.migration] Running upgrade 017 -> 018, Add project costs table for tracking expenses
Method 2: Using Alembic Directly
# Navigate to project directory
cd /path/to/TimeTracker
# Run the migration
alembic upgrade head
# Verify
alembic current
Method 3: Using Docker
# If running in Docker
docker-compose exec app flask db upgrade
# Or restart the container (if auto-migration is enabled)
docker-compose restart app
Method 4: Python Script (Docker Environments)
# If you prefer the standalone script
python docker/migrate-add-project-costs.py
Method 5: Raw SQL (Manual)
# Only if Alembic is not available
psql -U timetracker -d timetracker -f migrations/add_project_costs.sql
Verification Steps
After running the migration, verify it was successful:
1. Check Migration Status
flask db current
# Should show: 018 (head)
2. Verify Table Creation
psql -U timetracker -d timetracker -c "\d project_costs"
Expected output should show:
- Columns: id, project_id, user_id, description, category, amount, etc.
- Indexes: ix_project_costs_project_id, ix_project_costs_user_id, etc.
- Foreign keys: fk_project_costs_project_id, fk_project_costs_user_id, etc.
3. Check Application Logs
tail -f logs/timetracker.log
Look for any errors related to project_costs
4. Test in Application
- Log in to TimeTracker
- Navigate to any project
- Look for "Project Costs & Expenses" section
- Try adding a test cost
Rollback (If Needed)
If you need to rollback the migration:
# Using Flask-Migrate
flask db downgrade
# Or using Alembic
alembic downgrade -1
# To downgrade to a specific revision
flask db downgrade 017
# or
alembic downgrade 017
Warning: Rolling back will delete the project_costs table and all data in it!
Troubleshooting
Issue: "Table already exists"
Problem: The migration script tries to create a table that already exists.
Solution: The migration includes a check for table existence. If you see this error:
- Verify the table actually exists:
\d project_costsin psql - If it exists and is correct, manually mark the migration as complete:
alembic stamp 018
Issue: "Cannot find revision 017"
Problem: The previous migration (017) doesn't exist or wasn't run.
Solution:
- Check current revision:
flask db current - Upgrade to 017 first:
flask db upgrade 017 - Then upgrade to 018:
flask db upgrade
Issue: Foreign key constraint fails
Problem: Referenced tables (projects, users, invoices) don't exist.
Solution:
- Ensure you're at migration 017 before running this
- The migration checks for invoices table existence before creating that FK
- Run previous migrations first:
flask db upgrade
Issue: "Cannot connect to database"
Problem: Database connection parameters are incorrect.
Solution:
- Check your
.envfile or environment variables - Verify database is running:
docker-compose psorsystemctl status postgresql - Test connection:
psql -U timetracker -d timetracker
Issue: Permission denied
Problem: Database user doesn't have permission to create tables.
Solution:
-- Grant necessary permissions (run as postgres superuser)
GRANT CREATE ON DATABASE timetracker TO timetracker;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO timetracker;
Post-Migration
After successful migration:
-
✅ Restart Application
# Docker docker-compose restart app # Systemd sudo systemctl restart timetracker # Manual # Stop and start your Flask application -
✅ Clear Application Cache
# If using Redis redis-cli FLUSHALL # Browser cache # Hard refresh: Ctrl+Shift+R (or Cmd+Shift+R on Mac) -
✅ Test Core Functionality
- View a project
- Add a cost
- Edit a cost
- Delete a cost
- Generate an invoice with costs
- View project reports
-
✅ Update Documentation
- Inform team about new feature
- Share
PROJECT_COSTS_FEATURE.mdwith users - Update internal wiki/docs if applicable
Migration Details
What Gets Created
Table: project_costs
- Primary key:
id - Foreign keys:
project_id,user_id,invoice_id - Indexes: On project_id, user_id, cost_date, invoice_id
Columns:
id: Integer, Primary Keyproject_id: Integer, NOT NULL, Foreign Key to projectsuser_id: Integer, NOT NULL, Foreign Key to usersdescription: String(500), NOT NULLcategory: String(50), NOT NULLamount: Numeric(10,2), NOT NULLcurrency_code: String(3), NOT NULL, Default 'EUR'billable: Boolean, NOT NULL, Default TRUEinvoiced: Boolean, NOT NULL, Default FALSEinvoice_id: Integer, NULL, Foreign Key to invoicescost_date: Date, NOT NULLnotes: Text, NULLreceipt_path: String(500), NULLcreated_at: DateTime, NOT NULL, Default CURRENT_TIMESTAMPupdated_at: DateTime, NOT NULL, Default CURRENT_TIMESTAMP
Database Size Impact
Estimated size per cost entry: ~300 bytes
Example capacity:
- 1,000 costs ≈ 300 KB
- 10,000 costs ≈ 3 MB
- 100,000 costs ≈ 30 MB
Support
For issues or questions:
- Check
PROJECT_COSTS_FEATURE.mdfor feature documentation - Review
PROJECT_COSTS_IMPLEMENTATION_SUMMARY.mdfor technical details - Check application logs:
logs/timetracker.log - Verify database state:
psql -U timetracker -d timetracker
Emergency Rollback Script
If you need to manually remove the table:
-- WARNING: This will delete all project cost data!
-- Only use if rollback through Alembic fails
-- Drop foreign keys first
ALTER TABLE project_costs DROP CONSTRAINT IF EXISTS fk_project_costs_invoice_id;
ALTER TABLE project_costs DROP CONSTRAINT IF EXISTS fk_project_costs_user_id;
ALTER TABLE project_costs DROP CONSTRAINT IF EXISTS fk_project_costs_project_id;
-- Drop indexes
DROP INDEX IF EXISTS ix_project_costs_invoice_id;
DROP INDEX IF EXISTS ix_project_costs_cost_date;
DROP INDEX IF EXISTS ix_project_costs_user_id;
DROP INDEX IF EXISTS ix_project_costs_project_id;
-- Drop table
DROP TABLE IF EXISTS project_costs;
-- Mark migration as rolled back
-- (Run this through Alembic, not SQL)
-- alembic downgrade 017
Next Steps
After successful migration:
- Read:
QUICK_START_PROJECT_COSTS.mdfor usage guide - Read:
PROJECT_COSTS_FEATURE.mdfor full feature documentation - Train users on the new functionality
- Monitor application performance
- Set up any necessary backups for the new data