mitai-jinkendo/backend/migrations/030_goal_progress_log.sql
Lars 7db98a4fa6
All checks were successful
Deploy Development / deploy (push) Successful in 44s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 13s
feat: Goal Progress Log - backend + API (v2.1)
Implemented progress tracking system for all goals.

**Backend:**
- Migration 030: goal_progress_log table with unique constraint per day
- Trigger: Auto-update goal.current_value from latest progress
- Endpoints: GET/POST/DELETE /api/goals/{id}/progress
- Pydantic Models: GoalProgressCreate, GoalProgressUpdate

**Features:**
- Manual progress tracking for custom goals (flexibility, strength, etc.)
- Full history with date, value, note
- current_value always reflects latest progress entry
- One entry per day per goal (unique constraint)
- Cascade delete when goal is deleted

**API:**
- GET /api/goals/{goal_id}/progress - List all entries
- POST /api/goals/{goal_id}/progress - Log new progress
- DELETE /api/goals/{goal_id}/progress/{progress_id} - Delete entry

**Next:** Frontend UI (progress button, modal, history list)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 13:58:14 +01:00

65 lines
2.4 KiB
PL/PgSQL

-- Migration 030: Goal Progress Log
-- Date: 2026-03-27
-- Purpose: Track progress history for all goals (especially custom goals without data source)
-- ============================================================================
-- Goal Progress Log Table
-- ============================================================================
CREATE TABLE IF NOT EXISTS goal_progress_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
goal_id UUID NOT NULL REFERENCES goals(id) ON DELETE CASCADE,
profile_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
-- Progress data
date DATE NOT NULL,
value DECIMAL(10,2) NOT NULL,
note TEXT,
-- Metadata
source VARCHAR(20) DEFAULT 'manual' CHECK (source IN ('manual', 'automatic', 'import')),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
-- Constraints
CONSTRAINT unique_progress_per_day UNIQUE(goal_id, date)
);
CREATE INDEX idx_goal_progress_goal_date ON goal_progress_log(goal_id, date DESC);
CREATE INDEX idx_goal_progress_profile ON goal_progress_log(profile_id);
COMMENT ON TABLE goal_progress_log IS 'Progress history for goals - enables manual tracking for custom goals and charts';
COMMENT ON COLUMN goal_progress_log.value IS 'Progress value in goal unit (e.g., kg, cm, points)';
COMMENT ON COLUMN goal_progress_log.source IS 'manual: user entered, automatic: computed from data source, import: CSV/API';
-- ============================================================================
-- Function: Update goal current_value from latest progress
-- ============================================================================
CREATE OR REPLACE FUNCTION update_goal_current_value()
RETURNS TRIGGER AS $$
BEGIN
-- Update current_value in goals table with latest progress entry
UPDATE goals
SET current_value = (
SELECT value
FROM goal_progress_log
WHERE goal_id = NEW.goal_id
ORDER BY date DESC
LIMIT 1
),
updated_at = NOW()
WHERE id = NEW.goal_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Trigger: Auto-update current_value when progress is added/updated
CREATE TRIGGER trigger_update_goal_current_value
AFTER INSERT OR UPDATE ON goal_progress_log
FOR EACH ROW
EXECUTE FUNCTION update_goal_current_value();
COMMENT ON FUNCTION update_goal_current_value IS 'Auto-update goal.current_value when new progress is logged';