Files
TimeTracker/docs/features/MIGRATION_INSTRUCTIONS.md
2025-10-09 13:48:03 +02:00

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:

  1. Backup your database

    # PostgreSQL backup example
    pg_dump -U timetracker timetracker > backup_before_project_costs_$(date +%Y%m%d).sql
    
  2. Check current migration status

    # In your project directory with Flask app context
    flask db current
    # Or using alembic directly
    alembic current
    

    Expected output: 017 (head) or similar

  3. Review the migration

    cat migrations/versions/018_add_project_costs_table.py
    

Running the Migration

# 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

  1. Log in to TimeTracker
  2. Navigate to any project
  3. Look for "Project Costs & Expenses" section
  4. 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:

  1. Verify the table actually exists: \d project_costs in psql
  2. 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:

  1. Check current revision: flask db current
  2. Upgrade to 017 first: flask db upgrade 017
  3. Then upgrade to 018: flask db upgrade

Issue: Foreign key constraint fails

Problem: Referenced tables (projects, users, invoices) don't exist.

Solution:

  1. Ensure you're at migration 017 before running this
  2. The migration checks for invoices table existence before creating that FK
  3. Run previous migrations first: flask db upgrade

Issue: "Cannot connect to database"

Problem: Database connection parameters are incorrect.

Solution:

  1. Check your .env file or environment variables
  2. Verify database is running: docker-compose ps or systemctl status postgresql
  3. 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:

  1. Restart Application

    # Docker
    docker-compose restart app
    
    # Systemd
    sudo systemctl restart timetracker
    
    # Manual
    # Stop and start your Flask application
    
  2. Clear Application Cache

    # If using Redis
    redis-cli FLUSHALL
    
    # Browser cache
    # Hard refresh: Ctrl+Shift+R (or Cmd+Shift+R on Mac)
    
  3. Test Core Functionality

    • View a project
    • Add a cost
    • Edit a cost
    • Delete a cost
    • Generate an invoice with costs
    • View project reports
  4. Update Documentation

    • Inform team about new feature
    • Share PROJECT_COSTS_FEATURE.md with 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 Key
  • project_id: Integer, NOT NULL, Foreign Key to projects
  • user_id: Integer, NOT NULL, Foreign Key to users
  • description: String(500), NOT NULL
  • category: String(50), NOT NULL
  • amount: Numeric(10,2), NOT NULL
  • currency_code: String(3), NOT NULL, Default 'EUR'
  • billable: Boolean, NOT NULL, Default TRUE
  • invoiced: Boolean, NOT NULL, Default FALSE
  • invoice_id: Integer, NULL, Foreign Key to invoices
  • cost_date: Date, NOT NULL
  • notes: Text, NULL
  • receipt_path: String(500), NULL
  • created_at: DateTime, NOT NULL, Default CURRENT_TIMESTAMP
  • updated_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:

  1. Check PROJECT_COSTS_FEATURE.md for feature documentation
  2. Review PROJECT_COSTS_IMPLEMENTATION_SUMMARY.md for technical details
  3. Check application logs: logs/timetracker.log
  4. 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.md for usage guide
  • Read: PROJECT_COSTS_FEATURE.md for full feature documentation
  • Train users on the new functionality
  • Monitor application performance
  • Set up any necessary backups for the new data