From 224ce5ec1a8033853eefbfb67c362dc79edc313d Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 2 Jan 2026 13:03:55 +0100 Subject: [PATCH] feat: Add timetracking approval columns migration (v1.3.84) - Add migration 053 for approval columns - Checks if columns exist before adding (safe) - Adds: approved_hours, rounded_to, approval_note, billable, is_travel, approved_at, approved_by - Adds indexes for status and approved_at - Required for production deployment --- RELEASE_NOTES_v1.3.84.md | 90 ++++++++++++++ VERSION | 2 +- .../053_timetracking_approval_columns.sql | 111 ++++++++++++++++++ 3 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 RELEASE_NOTES_v1.3.84.md create mode 100644 migrations/053_timetracking_approval_columns.sql diff --git a/RELEASE_NOTES_v1.3.84.md b/RELEASE_NOTES_v1.3.84.md new file mode 100644 index 0000000..747db6a --- /dev/null +++ b/RELEASE_NOTES_v1.3.84.md @@ -0,0 +1,90 @@ +# Release Notes - v1.3.84 + +**Release Date:** 2. januar 2026 + +## 🔧 Database Migration + +### Timetracking Approval Columns +- **Added migration** for missing approval columns in `tmodule_times` table +- **Required for production** - local development already has these columns + +### Columns Added (if missing): +- `approved_hours` DECIMAL(10,2) - Godkendte timer +- `rounded_to` DECIMAL(10,2) - Afrundingsinterval brugt +- `approval_note` TEXT - Godkendelsesnote +- `billable` BOOLEAN DEFAULT TRUE - Skal faktureres +- `is_travel` BOOLEAN DEFAULT FALSE - Indeholder kørsel +- `approved_at` TIMESTAMP - Tidspunkt for godkendelse +- `approved_by` INTEGER - Bruger der godkendte + +### Indexes Added: +- `idx_tmodule_times_status` - For hurtigere status queries +- `idx_tmodule_times_approved_at` - For hurtigere approval queries + +## 📝 Files Changed + +- `migrations/053_timetracking_approval_columns.sql` - New migration file + +## 🚀 Deployment Instructions + +### CRITICAL - Run Migration First! + +**På produktionsserveren:** + +1. **SSH til serveren:** + ```bash + ssh bmcadmin@172.16.31.183 + ``` + +2. **Naviger til projekt:** + ```bash + cd /opt/bmc_hub + git fetch --tags + git checkout v1.3.84 + ``` + +3. **Kør migration (VIGTIGT!):** + ```bash + docker-compose exec postgres psql -U bmcnetworks -d bmc_hub -f /app/migrations/053_timetracking_approval_columns.sql + ``` + + **ELLER via docker cp hvis mounted wrong:** + ```bash + docker cp migrations/053_timetracking_approval_columns.sql bmc-hub-postgres:/tmp/ + docker-compose exec postgres psql -U bmcnetworks -d bmc_hub -f /tmp/053_timetracking_approval_columns.sql + ``` + +4. **Genstart API:** + ```bash + docker-compose restart api + ``` + +5. **Verificer:** + ```bash + # Test godkendelse i wizard + # Tjek logs for fejl + docker-compose logs -f api | grep -E "(Error|✅|❌)" + ``` + +## ⚠️ Breaking Changes + +None - backwards compatible migration + +## 📊 Impact + +- Fixes approval failures on production +- Safe to run - checks if columns exist before adding +- No data loss risk + +## 🔍 Why This Was Needed + +Production database was missing approval columns that exist in development: +- Local dev had columns from previous migrations +- Production was created before these columns were added +- This migration ensures both environments have same schema + +--- + +**Git Tag:** v1.3.84 +**Previous Version:** v1.3.83 +**Migration:** 053_timetracking_approval_columns.sql diff --git a/VERSION b/VERSION index d00cda9..2c5c5a5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.83 \ No newline at end of file +1.3.84 \ No newline at end of file diff --git a/migrations/053_timetracking_approval_columns.sql b/migrations/053_timetracking_approval_columns.sql new file mode 100644 index 0000000..0ff173b --- /dev/null +++ b/migrations/053_timetracking_approval_columns.sql @@ -0,0 +1,111 @@ +-- Migration: Add approval columns to tmodule_times if they don't exist +-- Version: 1.3.83+ +-- Date: 2026-01-02 + +-- Add approved_hours column if it doesn't exist +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'tmodule_times' AND column_name = 'approved_hours' + ) THEN + ALTER TABLE tmodule_times ADD COLUMN approved_hours DECIMAL(10,2); + RAISE NOTICE 'Added column approved_hours'; + END IF; +END $$; + +-- Add rounded_to column if it doesn't exist +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'tmodule_times' AND column_name = 'rounded_to' + ) THEN + ALTER TABLE tmodule_times ADD COLUMN rounded_to DECIMAL(10,2); + RAISE NOTICE 'Added column rounded_to'; + END IF; +END $$; + +-- Add approval_note column if it doesn't exist +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'tmodule_times' AND column_name = 'approval_note' + ) THEN + ALTER TABLE tmodule_times ADD COLUMN approval_note TEXT; + RAISE NOTICE 'Added column approval_note'; + END IF; +END $$; + +-- Add billable column if it doesn't exist +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'tmodule_times' AND column_name = 'billable' + ) THEN + ALTER TABLE tmodule_times ADD COLUMN billable BOOLEAN DEFAULT TRUE; + RAISE NOTICE 'Added column billable'; + END IF; +END $$; + +-- Add is_travel column if it doesn't exist +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'tmodule_times' AND column_name = 'is_travel' + ) THEN + ALTER TABLE tmodule_times ADD COLUMN is_travel BOOLEAN DEFAULT FALSE; + RAISE NOTICE 'Added column is_travel'; + END IF; +END $$; + +-- Add approved_at column if it doesn't exist +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'tmodule_times' AND column_name = 'approved_at' + ) THEN + ALTER TABLE tmodule_times ADD COLUMN approved_at TIMESTAMP; + RAISE NOTICE 'Added column approved_at'; + END IF; +END $$; + +-- Add approved_by column if it doesn't exist +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'tmodule_times' AND column_name = 'approved_by' + ) THEN + ALTER TABLE tmodule_times ADD COLUMN approved_by INTEGER; + RAISE NOTICE 'Added column approved_by'; + END IF; +END $$; + +-- Create index on status if it doesn't exist +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_indexes + WHERE tablename = 'tmodule_times' AND indexname = 'idx_tmodule_times_status' + ) THEN + CREATE INDEX idx_tmodule_times_status ON tmodule_times(status); + RAISE NOTICE 'Created index idx_tmodule_times_status'; + END IF; +END $$; + +-- Create index on approved_at if it doesn't exist +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_indexes + WHERE tablename = 'tmodule_times' AND indexname = 'idx_tmodule_times_approved_at' + ) THEN + CREATE INDEX idx_tmodule_times_approved_at ON tmodule_times(approved_at); + RAISE NOTICE 'Created index idx_tmodule_times_approved_at'; + END IF; +END $$;