-- ===================================================== -- TABLE: education.lessons -- ===================================================== -- Proyecto: OrbiQuant IA (Trading Platform) -- Módulo: OQI-002 - Education -- Especificación: ET-EDU-001-database.md -- ===================================================== CREATE TABLE education.lessons ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- Relación con módulo module_id UUID NOT NULL REFERENCES education.modules(id) ON DELETE CASCADE, -- Información básica title VARCHAR(200) NOT NULL, description TEXT, -- Tipo de contenido content_type education.lesson_content_type NOT NULL DEFAULT 'video', -- Contenido video video_url VARCHAR(500), -- URL de Vimeo/S3 video_duration_seconds INTEGER, video_provider VARCHAR(50), -- 'vimeo', 's3', etc. video_id VARCHAR(200), -- ID del video en el provider -- Contenido texto/article article_content TEXT, -- Recursos adicionales attachments JSONB, -- [{name, url, type, size}] -- Ordenamiento display_order INTEGER NOT NULL DEFAULT 0, -- Configuración is_preview BOOLEAN DEFAULT false, -- Puede verse sin enrollment is_mandatory BOOLEAN DEFAULT true, -- Requerido para completar el curso -- Gamificación xp_reward INTEGER DEFAULT 10, -- XP al completar la lección -- Metadata created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT unique_module_order UNIQUE(module_id, display_order), CONSTRAINT video_fields_required CHECK ( (content_type != 'video') OR (video_url IS NOT NULL AND video_duration_seconds IS NOT NULL) ) ); -- Índices CREATE INDEX idx_lessons_module ON education.lessons(module_id); CREATE INDEX idx_lessons_order ON education.lessons(module_id, display_order); CREATE INDEX idx_lessons_type ON education.lessons(content_type); CREATE INDEX idx_lessons_preview ON education.lessons(is_preview) WHERE is_preview = true; -- Comentarios COMMENT ON TABLE education.lessons IS 'Lecciones individuales dentro de módulos'; COMMENT ON COLUMN education.lessons.attachments IS 'Archivos adjuntos en formato JSON: [{name, url, type, size}]'; COMMENT ON COLUMN education.lessons.is_preview IS 'Puede verse sin enrollment (preview gratuito)'; COMMENT ON COLUMN education.lessons.is_mandatory IS 'Requerido para completar el curso'; COMMENT ON COLUMN education.lessons.xp_reward IS 'XP otorgado al completar la lección';