-- name: MarkVideoCompleted :one INSERT INTO user_sub_course_video_progress ( user_id, sub_course_id, video_id, completed_at, updated_at ) SELECT @user_id::BIGINT, v.sub_course_id, v.id, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP FROM sub_course_videos v WHERE v.id = @video_id::BIGINT AND v.status = 'PUBLISHED' ON CONFLICT (user_id, video_id) DO UPDATE SET completed_at = CURRENT_TIMESTAMP, updated_at = CURRENT_TIMESTAMP RETURNING *; -- name: GetFirstIncompletePreviousVideo :one SELECT v.id, v.title, v.display_order FROM sub_course_videos target JOIN sub_course_videos v ON v.sub_course_id = target.sub_course_id AND v.status = 'PUBLISHED' AND ( v.display_order < target.display_order OR (v.display_order = target.display_order AND v.id < target.id) ) LEFT JOIN user_sub_course_video_progress p ON p.video_id = v.id AND p.user_id = @user_id::BIGINT AND p.completed_at IS NOT NULL WHERE target.id = @video_id::BIGINT AND p.video_id IS NULL ORDER BY v.display_order ASC, v.id ASC LIMIT 1;