mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-01-05 19:20:21 -06:00
320 lines
7.9 KiB
Markdown
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
|
|
|