New achievements table: stage_completed/curriculum_completed/assessment_completed/ capstone_completed, idempotent (WHERE NOT EXISTS guard, not a unique-index dance — simple and correct at this write volume). Not a certificate — a durable internal record Phase 4/5 can render one from later. recordAssessmentAchievement only fires on an actual pass, defensively, even though today's only completion_rule already guarantees that.
20 lines
1.1 KiB
SQL
20 lines
1.1 KiB
SQL
-- Persistent completion records — stage/curriculum/assessment/capstone. Not a certificate
|
|
-- (Phase 4/5 territory, see docs/PHASE3B_LEARNING_AND_ASSESSMENT.md): just the durable fact
|
|
-- that something was achieved, with enough context to render a certificate from later without
|
|
-- re-deriving it from raw attempt history.
|
|
|
|
CREATE TABLE IF NOT EXISTS achievements (
|
|
achievement_id BIGSERIAL PRIMARY KEY,
|
|
student_id TEXT NOT NULL REFERENCES students(student_id),
|
|
achievement_type TEXT NOT NULL CHECK (achievement_type IN
|
|
('stage_completed', 'curriculum_completed', 'assessment_completed', 'capstone_completed')),
|
|
curriculum_path_id TEXT,
|
|
curriculum_version INTEGER,
|
|
stage_id TEXT,
|
|
assessment_session_id UUID REFERENCES assessment_sessions(assessment_session_id),
|
|
achieved_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
metadata JSONB
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_achievements_student ON achievements(student_id, achievement_type);
|