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>
65 lines
2.4 KiB
PL/PgSQL
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';
|