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

320 lines
7.9 KiB
Markdown

# 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**
```bash
# PostgreSQL backup example
pg_dump -U timetracker timetracker > backup_before_project_costs_$(date +%Y%m%d).sql
```
2. ✅ **Check current migration status**
```bash
# 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**
```bash
cat migrations/versions/018_add_project_costs_table.py
```
## Running the Migration
### Method 1: Using Flask-Migrate (Recommended)
```bash
# 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
```bash
# Navigate to project directory
cd /path/to/TimeTracker
# Run the migration
alembic upgrade head
# Verify
alembic current
```
### Method 3: Using Docker
```bash
# 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)
```bash
# If you prefer the standalone script
python docker/migrate-add-project-costs.py
```
### Method 5: Raw SQL (Manual)
```bash
# 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
```bash
flask db current
# Should show: 018 (head)
```
### 2. Verify Table Creation
```bash
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
```bash
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:
```bash
# 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:
```bash
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:**
```sql
-- 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**
```bash
# Docker
docker-compose restart app
# Systemd
sudo systemctl restart timetracker
# Manual
# Stop and start your Flask application
```
2. ✅ **Clear Application Cache**
```bash
# 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:
```sql
-- 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