From 169a0a18a238e68805d7dc96b08163e075128bcb Mon Sep 17 00:00:00 2001 From: Nurfog Date: Tue, 14 Apr 2026 13:07:45 -0400 Subject: [PATCH] feat: fixing certificate and block --- .env.example | 1 + .qwen/settings.json | 34 - README.md | 794 ++---------------- deploy.sh | 19 +- docs/API.md | 140 +++ roadmap.md | 546 ++---------- services/cms-service/src/handlers.rs | 7 + .../src/handlers_exercise_settings.rs | 21 +- services/cms-service/src/handlers_sam.rs | 12 +- services/cms-service/src/main.rs | 17 +- ...003_trigger_update_enrollment_progress.sql | 59 ++ services/lms-service/src/main.rs | 24 +- shared/common/src/models.rs | 1 + web/experience/src/app/courses/[id]/page.tsx | 72 +- web/experience/src/app/my-learning/page.tsx | 4 +- .../src/components/CertificateModal.tsx | 98 +++ web/experience/src/lib/api.ts | 39 + .../[id]/settings/IntegrationsSection.tsx | 154 ++++ .../src/app/courses/[id]/settings/page.tsx | 2 + .../components/ExerciseFeatureSettings.tsx | 7 + web/studio/src/lib/api.ts | 12 + 21 files changed, 837 insertions(+), 1226 deletions(-) delete mode 100644 .qwen/settings.json create mode 100644 docs/API.md create mode 100644 services/lms-service/migrations/20260414000003_trigger_update_enrollment_progress.sql create mode 100644 web/experience/src/components/CertificateModal.tsx create mode 100644 web/studio/src/app/courses/[id]/settings/IntegrationsSection.tsx diff --git a/.env.example b/.env.example index 7c923cb..d4d3a62 100644 --- a/.env.example +++ b/.env.example @@ -53,6 +53,7 @@ WHISPER_MODEL=whisper-large-v3 # External Database Integration (SAM) # ---------------------------------------- MYSQL_DATABASE_URL=mysql://db_user:db_password@host:3306/database_name +SAM_DIAGNOSTICO_DATABASE_URL=mysql://db_user:db_password@host:3306/SAM_diagnostico EXTERNAL_TABLE_GRADES=notas EXTERNAL_ID_TIPO_NOTA=1 diff --git a/.qwen/settings.json b/.qwen/settings.json deleted file mode 100644 index 6f3e03e..0000000 --- a/.qwen/settings.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "permissions": { - "allow": [ - "Bash(rm *)", - "Bash(sed *)", - "Bash(ls *)", - "Bash(true)", - "Bash(cargo check *)", - "Bash(cargo build *)", - "Bash(chmod *)", - "Bash(mkdir *)", - "Bash(ssh *)", - "Bash(git fetch *)", - "Bash(git add *)", - "Bash(git commit *)", - "Bash(git push *)", - "Bash(scp *)", - "Bash(curl *)", - "Bash(sudo *)", - "Bash(grep *)", - "Bash(python3)", - "Bash(with)", - "Bash(as *)", - "Bash(content *)", - "Bash(old_text *)", - "Bash(new_text *)", - "Bash(old_text, *)", - "Bash(f.write)", - "Bash(print)", - "Bash(eof)" - ] - }, - "$version": 3 -} \ No newline at end of file diff --git a/README.md b/README.md index fc7a007..b21e63c 100644 --- a/README.md +++ b/README.md @@ -2,752 +2,136 @@ OpenCCB es una infraestructura de código abierto para plataformas de gestión de aprendizaje y contenido (LMS/CMS), construida con rendimiento, seguridad y escalabilidad en mente. +--- + +## 📖 Tabla de Contenidos +- [🚀 Arquitectura Consolidada](#-arquitectura-consolidada) +- [✨ Funcionalidades Destacadas](#-funcionalidades-destacadas) +- [🛠 Stack Tecnológico](#-stack-tecnológico) +- [ requisitos-del-sistema](#requisitos-del-sistema) +- [📦 Guía de Inicio Rápido](#-guía-de-inicio-rápido) +- [📊 Estado de Funcionalidades](#-estado-de-funcionalidades) +- [🔌 Recursos para Desarrolladores](#-recursos-para-desarrolladores) +- [📈 Roadmap](#-roadmap) + +--- + ## 🚀 Arquitectura Consolidada -El proyecto ha sido optimizado para reducir la complejidad de la infraestructura, consolidando los servicios de backend con sus respectivos frontends en contenedores unificados: +El proyecto optimiza la complejidad de infraestructura consolidando servicios de backend en Rust con frontends modernos en Next.js: -1. **Studio + CMS (Puerto 3000/3001)**: - - **Frontend**: Next.js app para administración y creación de contenido. - - **Backend**: API de Rust para gestión (CMS). -2. **Experience + LMS (Puerto 3003/3002)**: - - **Frontend**: Next.js app para la experiencia del estudiante. - - **Backend**: API de Rust para entrega de cursos y calificaciones (LMS). -3. **Database**: PostgreSQL compartido. -4. **AI Services**: stack local con Faster-Whisper (Transcripción) y Ollama (Traducción y Resúmenes). - - **AI Course Wizard**: Generación automática de cursos a partir de prompts estructurados. - - **Course Portability**: Importación/Exportación de cursos completos mediante JSON. - - **User Profiles**: Gestión completa de identidad (avatar, bio, preferencias). - - **Engagement Heatmaps**: Visualización de retención segundo a segundo en videos. - - **Smart Notifications**: Recordatorios de fechas límite y alertas in-app. - - **Global i18n**: Interfaz multilingüe (EN, ES, PT) con persistencia por usuario. - - **Document-Based Learning**: Soporte para actividades de lectura (PDF, DOCX, PPTX). - - **AI English Teacher**: Persona especializada para generación de contenidos y tutoría personalizada. - - **AI Audio Evaluation**: Evaluación inteligente de pronunciación y contenido con feedback en lenguaje natural. - - **Custom AI Quizzes**: Generación de quices con contexto pedagógico y tipo de pregunta personalizable (opción múltiple, V/F, etc.). - - **Course Deletion**: Funcionalidad de eliminación de cursos con verificación de permisos y limpieza en cascada. - - **Gamified Activities**: Nuevos tipos de bloques interactivos incluyendo Juegos de Memoria (con generación automática por IA) y Puntos Calientes (Hotspots). - - **Course Marketing & Summary**: Sistema de metadatos estructurados (objetivos, requisitos) y landing pages premium para una mejor presentación de cursos. - - **Global AI Task Dashboard**: Panel unificado de control en consola administrativa para monitorear, reintentar y cancelar tareas de IA en segundo plano (transcripciones, quices, etc). -- **Dynamic API Resolution**: Resolución inteligente de endpoints que permite el acceso desde cualquier dispositivo en la red local (WiFi) sin configuración manual. -- **Responsive UI/UX**: Interfaces optimizadas para dispositivos móviles con menús adaptativos y escalado fluido de componentes. -- **AI Teaching Assistant (RAG)**: Tutor inteligente dentro de cada lección que ayuda a los estudiantes utilizando el contexto de la lección actual y el historial del curso. -- **Persistent Grade Locking**: Bloqueo persistente de lecciones calificadas tras agotar los intentos, con retroalimentación personalizada generada por IA. -- **Color-Coded Progress Navigation**: Sistema visual de seguimiento de progreso mediante colores (Verde: Completado, Amarillo: En Proceso, Rojo: Repetible) tanto a nivel de lección como de módulo. -- **Adaptive Skill Analysis**: Motor de análisis de etiquetas que calcula la maestría de habilidades (Gramática, Vocabulario, etc.) para personalizar las recomendaciones de IA. -- **Efficient Docker Builds**: Imágenes de contenedor optimizadas para desarrollo rápido y despliegue ligero. -- **Unified Authentication Flow**: Flujo de inicio de sesión simplificado para estudiantes e instructores. -- **Course Monetization**: Integración con Mercado Pago para venta de cursos, con inscripciones automáticas y paneles de precios para instructores. -- **Student Notes**: Sistema de anotaciones personales por lección con auto-guardado inteligente (debounced). -- **Interactive Gradebook**: Libro de calificaciones avanzado con filtrado por cohortes, exportación masiva a CSV con desgloses por categoría y pertenencia a cohortes. -- **Bulk Operations**: Herramientas administrativas para inscripción masiva de usuarios vía email y comunicación segmentada. -- **Course Teams**: Soporte para múltiples instructores por curso con roles granulares (Instructor Principal, Instructor, Asistente). -- **Course Preview**: Capacidad de marcar lecciones específicas como previsualizables para usuarios no inscritos (freemium). -- **Student Progress Dashboard**: Visualización avanzada del avance del estudiante con gráficos de actividad diaria y predicción de fecha de finalización basada en el ritmo de aprendizaje. -- **Segmented Announcements**: Sistema de anuncios con capacidad de dirigirse a cohortes específicas y notificaciones filtradas. -- **Content Libraries**: Repositorio centralizado de bloques y lecciones reutilizables entre múltiples cursos. -- **Advanced Grading (Rubrics)**: Sistema de evaluación basado en rúbricas detalladas con indicadores de desempeño por criterio. -- **Learning Sequences**: Gestión de prerrequisitos entre lecciones con cumplimiento forzado en el LMS. -- **LTI 1.3 Tool Provider**: Interoperabilidad completa para lanzar cursos de OpenCCB desde LMS externos (Canvas, Moodle) de manera segura y estandarizada, con soporte para **Deep Linking** (Content Picking). -- **Global Asset Library**: Repositorio centralizado de medios para toda la organización, permitiendo la reutilización de archivos en múltiples cursos con gestión de cuotas e integridad de datos. -- **Predictive Analytics (Dropout Risk)**: Motor de IA que analiza el desempeño, actividad y compromiso social del estudiante para detectar riesgos de abandono de forma proactiva, con alertas accionables para instructores. -- **Live Learning (Videoconference)**: Integración nativa con Jitsi para clases virtuales síncronas, con programación desde Studio y acceso integrado en Experience. -- **Student Portfolio & Badges**: Sistema de reconocimiento con Open Badges y perfiles públicos profesionales para mostrar logros y progreso verificado. -- **Dynamic Mermaid Diagrams**: Generación automática de diagramas (flowcharts, mapas mentales, secuencias) a partir del contenido de cada lección usando IA, con editor visual integrado para instructores. +1. **Studio + CMS (Puertos 3000/3001)**: Next.js app para administración y API de Rust para gestión de contenido. +2. **Experience + LMS (Puertos 3003/3002)**: Next.js app para estudiantes y API de Rust para entrega y calificaciones. +3. **Database**: PostgreSQL 16 compartido con soporte para **PGVector**. +4. **AI Services**: Stack local con Faster-Whisper (Transcripción) y Ollama (Inferencia LLM). -## Requisitos del Sistema +--- -OpenCCB es altamente escalable. A continuación se detallan los requisitos recomendados según la carga de usuarios concurrentes: +## ✨ Funcionalidades Destacadas + +### 🧠 Inteligencia Artificial Avanzada +- **AI Course Wizard**: Generación instantánea de currículos completos a partir de un prompt. +- **AI Teaching Assistant (RAG)**: Tutor inteligente con memoria histórica y contexto de la lección actual. +- **Evaluación por Audio**: Análisis de pronunciación y feedback en lenguaje natural usando IA. +- **Diagramas Dinámicos**: Generación automática de diagramas Mermaid (mapas mentales, flujos) desde el contenido. +- **Analíticas Predictivas**: Motor que detecta riesgos de abandono escolar antes de que ocurran. + +### 🎓 Gestión Académica Premium +- **Library of Content**: Repositorio centralizado de bloques y lecciones reutilizables. +- **Advanced Gradebook**: Libro de calificaciones con rúbricas detalladas y filtrado por cohortes. +- **Learning Sequences**: Gestión de prerrequisitos y rutas de aprendizaje condicionales. +- **LTI 1.3 Provider**: Interoperabilidad completa con Canvas, Moodle y otros LMS estándar. + +### 🎮 Experiencia de Aprendizaje +- **Gamificación Integrada**: Sistema de XP, niveles, Badges (Open Badges) y juegos interactivos (Memoria, Hotspots). +- **Engagement Heatmaps**: Visualización para instructores de la retención segundo a segundo en videos. +- **Student Portfolio**: Perfiles públicos profesionales que muestran logros y progreso verificado. +- **Anotaciones Inteligentes**: Sistema de notas personales con auto-guardado por lección. + +### 📱 Conectividad y Acceso +- **Dynamic LAN Access**: Resolución automática de IP para acceder desde cualquier dispositivo en la red WiFi. +- **Responsive UI/UX**: Interfaces optimizadas con diseño *Glassmorphism* y navegación móvil fluida. +- **White-Label Branding**: Personalización completa de marca, colores, logos y favicons por organización. + +--- + +## 🛠 Stack Tecnológico + +- **Backend**: [Rust](https://www.rust-lang.org/) (axum, sqlx). +- **Frontend**: [Next.js 14+](https://nextjs.org/) (App Router), [Tailwind CSS](https://tailwindcss.com/). +- **Base de Datos**: [PostgreSQL 16](https://www.postgresql.org/) + [pgvector](https://github.com/pgvector/pgvector). +- **IA In-house**: Faster-Whisper, Ollama (Llama 3.2, Nomic-Embed). + +--- + +## 💻 Requisitos del Sistema | Componente | **Pequeño (100 u.)** | **Mediano (500 u. concurrentes)** | **Grande (1000+ u.)** | | :--- | :--- | :--- | :--- | -| **CPU** | 4 vCPUs | 8-12 vCPUs (AVX2/AVX-512) | 16-32+ vCPUs | -| **RAM** | 8 GB | 16-32 GB (Recomendado 24GB+) | 64 GB+ | -| **Almacenamiento** | 50 GB SSD | 250 GB+ NVMe (RAID-1) | 1 TB+ NVMe (S3 Backup) | -| **AI (Opcional)** | N/A (Solo CPU) | NVIDIA RTX 3060+ (12GB VRAM) | Multi-GPU (A100/H100) | -| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS / Debian | Cloud Native (K8s / Terraform) | +| **CPU** | 4 vCPUs | 8-12 vCPUs (AVX2+) | 16-32+ vCPUs | +| **RAM** | 8 GB | 16-32 GB | 64 GB+ | +| **GPU (IA)** | Opcional | NVIDIA RTX 3060+ (12GB) | Multi-GPU (A100/H100) | > [!NOTE] -> Los requisitos de AI son específicos para la función de transcripción local (Whisper). Si se utiliza una API externa, el requisito de GPU desaparece. +> Los requisitos de GPU son específicos para la autogestión de IA local. Si se utilizan APIs externas, estos requisitos disminuyen drásticamente. -## �🛠 Stack Tecnológico - -- **Backend**: Rust (Edition 2024), Axum, SQLx. -- **Frontend**: React, Next.js (App Router), Tailwind CSS, Lucide React. -- **Base de Datos**: PostgreSQL 16. -- **Infraestructura**: Docker & Docker Compose. -- **IA Local**: - - **Faster-Whisper**: Transcripción de audio a texto. - - **Ollama**: Traducción inteligente (EN -> ES), resúmenes y generación de cuestionarios. -- **i18n Infrastructure**: Sistema de traducción reactivo para soporte global. -- **Document Management**: Motor de previsualización de documentos PDF nativo. +--- ## 📦 Guía de Inicio Rápido ### Requisitos Previos -- Docker y Docker Compose. -- Node.js 18+ (para desarrollo local). -- Rust (para desarrollo local). +- Docker & Docker Compose +- Node.js 18+ & Rust (para desarrollo local) ### Ejecución con Docker (Recomendado) ```bash docker-compose up --build ``` -Esto iniciará todos los servicios: -- **Studio**: [http://localhost:3000](http://localhost:3000) -- **Experience**: [http://localhost:3003](http://localhost:3003) +- **Studio**: http://localhost:3000 +- **Experience**: http://localhost:3003 -> [!TIP] -> **Acceso desde Móviles**: Gracias a la *Dynamic API Resolution*, puedes acceder desde tu celular conectado al mismo WiFi usando la IP de tu computadora (ej: `http://192.168.1.15:3000`). La interfaz se adaptará automáticamente. - -### Desarrollo Local - -#### Studio & CMS +### Comandos de Utilidad ```bash -# Iniciar backend CMS -cd services/cms-service -cargo run +# Instalación y configuración automática +./install.sh -# Iniciar frontend Studio -cd web/studio -npm install -npm run dev -``` - -#### 📦 Portabilidad de Cursos -Gestiona la movilidad de contenidos entre diferentes organizaciones utilizando exportaciones estandarizadas en JSON. - -#### GET /courses/{id}/export -Genera un paquete completo del curso, incluyendo módulos, lecciones y configuraciones de calificación. - -#### POST /courses/import -Crea un nuevo curso basado en un paquete de exportación proporcionado. El mapeo automático de dependencias asegura la integridad de los datos en la nueva organización. -#### Experience & LMS -```bash -# Iniciar backend LMS -cd services/lms-service -cargo run - -# Iniciar frontend Experience -cd web/experience -npm install -npm run dev -``` - -#### 🧹 Mantenimiento de Base de Datos -Para resetear completamente el entorno de desarrollo y empezar desde cero: -```bash -# Borra las bases de datos openccb_cms/lms y las vuelve a migrar +# Resetear base de datos de desarrollo ./scripts/reset_db.sh ``` -## 🔌 Manual del Desarrollador (API) - -### 1. Autenticación y Cuentas -Gestión de registro, login y perfiles organizacionales. - -#### POST /auth/register -Crea un nuevo usuario vinculado a la organización por defecto. - -- **Cuerpo de la Petición ( AuthPayload ):** - ```json - { - "email": "string", - "password": "string", - "full_name": "string", - "role": "string (admin | instructor | student)" - } - ``` - -#### SSO (OpenID Connect) -OpenCCB soporta integración con proveedores de identidad (IdP) externos como Google, Okta y Azure AD. -- **Configuración**: Los administradores de la organización pueden configurar sus credenciales OIDC en el panel de configuración de Studio. -- **Autoprovisionamiento**: Los nuevos usuarios se crean automáticamente en la plataforma tras una autenticación exitosa. -#### LTI 1.3 e Interoperabilidad -OpenCCB actúa como un Tool Provider LTI 1.3 moderno, utilizando OIDC y JWKS para máxima seguridad. -- **JWKS Endpoint**: `/lti/jwks` expone las claves públicas para verificación de firmas. -- **Deep Linking**: Permite que instructores seleccionen cursos o lecciones específicas desde el LMS externo mediante una interfaz de Studio embebida. -- **Autoprovisionamiento**: Los usuarios lanzados vía LTI se crean automáticamente con los roles correspondientes. - -```bash -# Registrar un nuevo administrador -curl -X POST "http://localhost:3001/auth/register" \ - -H "Content-Type: application/json" \ - -d '{"email": "admin@empresa.com", "password": "pass", "full_name": "Admin Name"}' -``` - --- -### 2. Gestión de Contenidos (CMS) -Herramientas para instructores y administradores. +## 🔌 Recursos para Desarrolladores -#### POST /courses -Crea un nuevo curso vinculado a la organización del usuario. - -- **Lógica**: El `instructor_id` se asigna automáticamente desde el token JWT. -- **Cuerpo ( CreateCourseRequest ):** - ```json - { - "title": "string", - "pacing_mode": "string (self_paced | instructor_led)" - } - ``` - -```bash -# Crear curso básico -curl -X POST "http://localhost:3001/courses" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"title": "Curso de Rust", "pacing_mode": "self_paced"}' -``` -#### POST /courses/generate -Utiliza IA para generar la estructura completa de un curso basado en un prompt. - -- **Lógica de Generación**: Utiliza modelos de lenguaje (LLM) para descomponer un tema complejo en una malla curricular lógica de módulos y lecciones. -- **Cuerpo de la Petición ( GenerateCourseRequest ):** - ```json - { - "prompt": "string" - } - ``` - -#### GET /courses/{id}/export -Exporta un curso completo y su contenido a formato JSON para portabilidad. - -- **Integridad Portátil**: Empaqueta metadatos, categorías de calificación, módulos y lecciones manteniendo sus relaciones jerárquicas. -- **Respuesta**: Archivo JSON estandarizado para importación. - -#### POST /courses/import -Importa un curso a partir de un archivo JSON generado previamente. - -- **Mapeo de Dependencias**: Re-mapea automáticamente los IDs de lecciones y módulos para la nueva organización, asegurando que las relaciones y ponderaciones se mantengan intactas. -- **Cuerpo de la Petición ( CourseBundle ):** - ```json - { - "title": "string", - "description": "string", - "modules": [] - } - ``` - -#### POST /lessons -Agrega contenido multimedia o evaluaciones a un módulo. - -- **Configuración Graduable**: Si `is_graded` es true, los puntos sumarán al XP del estudiante en el LMS. -- **Nuevos Tipos Gamificados**: - - `hotspot`: Identificación visual sobre imágenes (ideal para niños). - - `memory-match`: Juego de memoria con pares conceptuales. - - `video-marker`: Preguntas interactivas en timestamps específicos del video. -- **Cuerpo ( CreateLessonRequest ):** - ```json - { - "module_id": "uuid", - "title": "string", - "content_type": "string (video | reading | quiz | hotspot | memory-match | document)", - "content_url": "string (opcional)", - "is_graded": "boolean" - } - ``` - -#### POST /assets/upload -Sube un archivo multimedia o documento a la biblioteca global de la organización. - -- **Lógica de Reutilización**: Los activos se asocian a la organización y pueden vincularse opcionalmente a un curso específico. El motor de búsqueda permite localizar rápidamente recursos existentes para evitar duplicados. -- **Cuerpo de la Petición ( MultipartForm ):** - - `file`: Archivo binario (PDF, Video, Imagen, Docx). -- **Respuesta ( UploadResponse ):** - ```json - { - "id": "uuid", - "url": "string", - "mimetype": "string" - } - ``` - -```bash -# Agregar lección de video -curl -X POST "http://localhost:3001/lessons" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"module_id": "...", "title": "Intro", "content_type": "video", "is_graded": false}' -``` - ---- - -### 3. Experiencia de Aprendizaje (LMS) -Endpoints para estudiantes y seguimiento de progreso. - -#### POST /enroll -Inscribe al usuario en un curso. - -- **Lógica**: Verifica que el curso pertenezca a la misma organización que el usuario. -- **Cuerpo ( EnrollPayload ):** - ```json - { - "course_id": "uuid" - } - ``` - -```bash -# Inscribirse en un curso -curl -X POST "http://localhost:3002/enroll" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"course_id": "uuid-del-curso"}' -``` - -#### POST /grades -Registra el puntaje de una lección y actualiza la gamificación. - -- **Lógica Inteligente**: Actualiza automáticamente el XP del usuario y despacha webhooks si el curso se completa. -- **Engagement Tracking**: Si la lección contiene video, el frontend envía eventos de "heartbeat" cada 5 segundos para generar mapas de calor. - -#### GET /notifications -Obtiene las notificaciones pendientes del usuario. - -- **Filtro de Relevancia**: Devuelve únicamente alertas no leídas sobre fechas límite próximas o logros de gamificación recientes. -- **Respuesta**: Array de `Notification`. - -#### POST /notifications/{id}/read -Marca una notificación específica como leída. - -- **Persistencia**: Actualiza el estado en la base de datos para que no reaparezca en el feed del usuario. -- **Cuerpo de la Petición**: Vacío. - -```bash -# Enviar calificación de 90% -curl -X POST "http://localhost:3002/grades" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"course_id": "...", "lesson_id": "...", "score": 0.9}' -``` - ---- - -### 4. IA y Analíticas Avanzadas -Funcionalidades inteligentes 100% locales y gratuitas. - -#### POST /lessons/{id}/transcribe -Inicia el proceso de transcripción y traducción para una lección de video/audio. - -#### POST /audio/evaluate -Evalúa una respuesta oral del estudiante utilizando IA. - -#### POST /lessons/{id}/generate-quiz -Genera un quiz basado en el contenido de la lección. -- **Cuerpo ( QuizAIRequest ):** - ```json - { - "context": "focused on irregular verbs", - "quiz_type": "true-false" - } - ``` - -#### POST /lessons/{id}/dependencies -Asigna una lección como prerrequisito de otra. -- **Cuerpo ( LessonDependencyRequest ):** - ```json - { - "prerequisite_lesson_id": "uuid", - "min_score_percentage": "number (opcional)" - } - ``` - -#### GET /lessons/{id}/dependencies -Lista los prerrequisitos de una lección específica. - -#### DELETE /lessons/{lesson_id}/dependencies/{prereq_id} -Elimina un prerrequisito de una lección. - -#### DELETE /courses/{id} -Elimina un curso y todos sus contenidos relacionados (módulos, lecciones, assets). - -- **Procesamiento Asíncrono**: Despacha una tarea en segundo plano que utiliza Whisper para transcripción y Ollama para generar la traducción y el resumen inteligente. -- **Cuerpo de la Petición**: Vacío. - -#### GET /lessons/{id}/feedback -Obtiene retroalimentación personalizada de IA basada en el desempeño del estudiante y el contexto de la lección. - -- **Uso Crítico**: Se llama automáticamente cuando una lección calificada es bloqueada por intentos agotados. -- **Respuesta**: Un objeto JSON con la respuesta motivacional del tutor. - -#### POST /lessons/{id}/chat -Interactúa con el tutor de IA específico para la lección. - -- **Contexto Inteligente**: La IA tiene acceso a la transcripción del video, el contenido de los bloques interactivos y el historial de lecciones pasadas del curso. -- **Cuerpo ( ChatPayload ):** - ```json - { - "message": "string" - } - ``` - -#### GET /lessons/{id}/vtt?lang=en|es -Devuelve los subtítulos en formato WebVTT para integración nativa. - -- **Internacionalización**: Filtra los subtítulos por el parámetro `lang` y los devuelve con el formato de tiempo compatible con reproductores de video HTML5. -- **Respuesta**: Archivo de texto WebVTT. - -#### POST /chat (Streaming) -Conversación en tiempo real con la base de conocimientos. - -- **Nueva Sesión**: Omite `session_id`. La API creará uno nuevo y generará un título automático. -- **Continuar Sesión**: Envía el `session_id` devuelto anteriormente. -- **RAG (Base de Conocimiento)**: Envía `"use_kb": true` para que la IA busque en los documentos de S3. -- **Cuerpo ( ChatPayload ):** - ```json - { - "username": "string", - "prompt": "string", - "session_id": "uuid (opcional)", - "use_kb": "boolean" - } - ``` - -```bash -# Iniciar chat con RAG -curl -X POST "http://localhost:8000/chat" \ - -H "Content-Type: application/json" \ - -d '{ - "username": "juan", - "prompt": "Explícame qué es Docker en una frase", - "use_kb": true - }' -``` -**Respuesta**: Stream de texto plano. Al final incluye un JSON con el ID de sesión: `{"session_id": "..."}`. - -#### GET /courses/{id}/analytics/advanced -Métricas de retención y análisis de cohortes para un curso. - -- **Inteligencia de Datos**: Cruza información de intentos de evaluaciones y tiempos de visualización para identificar patrones de deserción. -- **Respuesta**: Dashboard JSON con métricas agregadas. - -#### GET /lessons/{id}/heatmap -Devuelve los puntos de concentración de visualización para una lección. - -- **Engagement Visual**: Analiza los eventos de heartbeat para determinar cuáles segundos del video son los más vistos o repetidos por los estudiantes. -- **Respuesta**: Array de `(second, count)`. - -#### GET /courses/{id}/analytics/reports -Generador de reportes personalizados para exportación. - -- **Flexibilidad Administrativa**: Permite filtrar el desempeño por cohortes específicas y devuelve la estructura necesaria para generar archivos CSV profesionales. -- **Respuesta**: Stream de datos o estructura de reporte. - -#### GET /courses/{id}/dropout-risks -Obtiene el reporte de riesgo de abandono para todos los estudiantes del curso. - -- **Inteligencia Predictiva**: Calcula en tiempo real (o consulta caché) el nivel de riesgo (Critical, High, Medium, Low) basándose en promedios, frecuencia de actividad y participación en foros. -- **Seguridad**: Solo accesible para usuarios con rol `instructor` o `admin`. -- **Respuesta**: Array de objetos `DropoutRisk`. - ---- - -### 5. Discussion Forums (Foros de Discusión) -Sistema completo de foros por curso con hilos, respuestas anidadas y moderación. - -#### GET /courses/{id}/discussions -Lista todos los hilos de discusión de un curso. - -- **Filtros Disponibles**: - - `filter=all`: Todos los hilos (por defecto) - - `filter=my_threads`: Solo hilos creados por el usuario - - `filter=unanswered`: Hilos sin respuestas - - `filter=resolved`: Hilos con respuestas marcadas como correctas - - `lesson_id={uuid}`: Filtrar por lección específica -- **Paginación**: `page=1` (50 hilos por página) -- **Respuesta**: Array de `ThreadWithAuthor` con información del autor y estadísticas agregadas. - -```bash -# Listar hilos sin responder -curl "http://localhost:3002/courses/{course_id}/discussions?filter=unanswered" \ - -H "Authorization: Bearer $TOKEN" -``` - -#### POST /courses/{id}/discussions -Crea un nuevo hilo de discusión. - -- **Auto-suscripción**: El autor se suscribe automáticamente para recibir notificaciones. -- **Cuerpo ( CreateThreadPayload ):** - ```json - { - "title": "string", - "content": "string", - "lesson_id": "uuid (opcional)" - } - ``` - -#### GET /discussions/{id} -Obtiene un hilo completo con todas sus respuestas anidadas. - -- **Contador de Vistas**: Incrementa automáticamente el `view_count`. -- **Árbol de Respuestas**: Las respuestas se devuelven en estructura jerárquica con anidación infinita. -- **Respuesta**: Objeto con `thread` y `posts` (árbol de respuestas). - -#### POST /discussions/{id}/posts -Crea una respuesta en un hilo. - -- **Respuestas Anidadas**: Usa `parent_post_id` para responder a un post específico. -- **Validación**: No permite responder si el hilo está bloqueado. -- **Cuerpo ( CreatePostPayload ):** - ```json - { - "content": "string", - "parent_post_id": "uuid (opcional, null para respuesta directa al hilo)" - } - ``` - -#### POST /posts/{id}/vote -Vota por una respuesta (upvote/downvote). - -- **Lógica**: Un usuario solo puede votar una vez por post. Cambiar el voto actualiza el registro existente. -- **Recalculo Automático**: El contador de upvotes se actualiza inmediatamente. -- **Cuerpo ( VotePayload ):** - ```json - { - "vote_type": "upvote" // o "downvote" - } - ``` - -#### POST /posts/{id}/endorse (Solo Instructores) -Marca una respuesta como correcta/aprobada. - -- **Indicador Visual**: Las respuestas endorsadas aparecen primero en la lista. -- **Permiso**: Solo instructores y administradores pueden endorsar. - -#### POST /discussions/{id}/pin (Solo Instructores) -Fija/desfija un hilo en la parte superior de la lista. - -- **Uso**: Para destacar anuncios importantes o FAQs. -- **Permiso**: Solo instructores y administradores. - -#### POST /discussions/{id}/lock (Solo Instructores) -Bloquea/desbloquea un hilo para prevenir nuevas respuestas. - -- **Uso**: Para cerrar discusiones resueltas o inapropiadas. -- **Permiso**: Solo instructores y administradores. - -#### POST /discussions/{id}/subscribe -Suscribe al usuario a las notificaciones del hilo. - -- **Notificaciones**: El usuario recibirá alertas cuando haya nuevas respuestas. - -#### POST /discussions/{id}/unsubscribe -Cancela la suscripción del usuario al hilo. - -```bash -# Crear hilo -curl -X POST "http://localhost:3002/courses/{course_id}/discussions" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"title": "Pregunta sobre Módulo 2", "content": "No entiendo la sección de..."}' - -# Responder a hilo -curl -X POST "http://localhost:3002/discussions/{thread_id}/posts" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"content": "Aquí está mi respuesta..."}' - -# Votar respuesta -curl -X POST "http://localhost:3002/posts/{post_id}/vote" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"vote_type": "upvote"}' -``` - ---- - -### 5. Anuncios del Curso (Announcements) - -| Acción | Método | Endpoint | Descripción | -|--------|--------|----------|-------------| -| Listar | GET | `/courses/{id}/announcements` | Obtiene todos los anuncios de un curso | -| Crear | POST | `/courses/{id}/announcements` | Crea un nuevo anuncio (Solo Instructor/Admin) | -| Actualizar | PUT | `/announcements/{id}` | Actualiza un anuncio (Solo Instructor/Admin) | -| Eliminar | DELETE| `/announcements/{id}` | Elimina un anuncio (Solo Instructor/Admin) | - -#### Ejemplo de Creación de Anuncio -```bash -curl -X POST http://localhost:3002/courses/{course_id}/announcements \ - -H "Authorization: Bearer $TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ - "title": "Bienvenida al curso", - "content": "Bienvenidos a todos a este emocionante curso.", - "is_pinned": true - }' -``` - ---- - -### 6. Estructura Single-Tenant -OpenCCB está diseñado como un módulo premium single-tenant. Todas las operaciones se realizan bajo una única organización preconfigurada. - -#### Organización por Defecto -- **ID de Organización**: `00000000-0000-0000-0000-000000000001` -- El sistema utiliza este ID de forma transparente para todas las consultas y recursos. - -#### Branding Unificado -- La personalización de marca se aplica globalmente a través del panel de Ajustes en Studio, afectando tanto a la interfaz administrativa como al portal del estudiante. - ---- - -## 🏆 Componentes UI Premium -- **Advanced Grading (Rubrics)**: Sistema completo de evaluación por rúbricas configurables. -- **Content Libraries**: Repositorio reutilizable de bloques y lecciones para máxima eficiencia. -- **Course Portability**: Sistema de importación/exportación basado en JSON para movilidad de contenidos. -- **AI Course Wizard**: Generación instantánea de currículos a partir de prompts. -- **Global Admin Console**: Control centralizado para organizaciones, usuarios y registros de auditoría. -- **Experience Player**: Interfaz de aprendizaje de alto rendimiento y accesible con diseño glassmorphism. -- **Organization Selector**: Combobox con búsqueda para gestionar grandes listas de inquilinos. -- **Engagement Heatmaps**: Gráficos dinámicos que muestran la retención en videos. -- **Notification Center**: Alertas en tiempo real para fechas límite y logros. -- **Custom Report Builder**: Reportes profesionales con exportación a CSV en un clic. -- **Glassmorphism Design**: Estética consistente en los portales Studio y Experience. -- **Global Localization**: Soporte nativo para Inglés, Español y Portugués. -- **PDF Integrated Viewer**: Lectura de documentos académicos sin salir de la plataforma. -- **Interactive Video Markers**: Preguntas que pausan el video integradas en las lecciones. -- **White-Label Branding**: Nombre de plataforma, logo, favicon y temas de color personalizados por organización. -- **Dynamic LAN Connectivity**: Detección automática de la IP del servidor para acceso fluido multi-dispositivo. -- **Mobile-First Navigation**: Menús laterales responsivos y diseños adaptativos para todas las pantallas. -- **Context-Aware AI Tutor**: Asistente inteligente con RAG que recuerda lecciones pasadas y protege respuestas. -- **Personalized AI Feedback**: Retroalimentación motivacional e instruccional generada únicamente para cada estudiante. -- **Color-Coded Navigation**: Indicadores visuales de progreso en tiempo real (Verde/Amarillo/Rojo). -- **Discussion Forums**: Sistema completo de foros con hilos, votos, moderación y suscripciones. -- **Course Announcements**: Sistema de comunicación instructor-estudiante con notificaciones automáticas. -- **Split Authentication**: Flujos de inicio de sesión separados para usuarios personales y empresas con soporte SSO. -- **Mercado Pago Monetization**: Pasarela de pagos integrada con desbloqueo automático de cursos. -- **Student Notes Panel**: Anotaciones personales con interfaz glassmorphism y autoguardado inteligente. -- **Cohort Management**: Sistema de gestión de grupos con seguimiento de progreso por cohorte. -- **Advanced Gradebook**: Seguimiento del desempeño estudiantil con analíticas y filtrado avanzado. -- **Learning Sequences UI**: Interfaz visual para gestionar dependencias y visualización de bloqueos con iconos de candado. -- **Student Progress Dashboard**: Panel de control con gráficos interactivos (Recharts) que muestran la actividad de aprendizaje y estiman el tiempo restante del curso. -- **Course Teams UI**: Panel de gestión para añadir y configurar roles de instructores secundarios y asistentes. -- **Course Preview Badges**: Indicadores visuales y lógica de acceso para lecciones accesibles sin suscripción. -- **Global Asset Manager**: Interfaz avanzada para la administración masiva de archivos con previsualización inteligente y filtros por curso o tipo. -- **Premium Course Summaries**: Presentación de cursos con diseño de alta fidelidad y desgloses de objetivos de aprendizaje. +Para una guía detallada sobre cómo integrar o extender OpenCCB, consulta la documentación técnica: +- 📘 [Referencia de la API](docs/API.md) +- ⚙️ [Manual de Configuración](ManualDeConfiguracion.md) +- 🏗️ [Guía de Despliegue](DESPLIEGUE.md) --- ## 📊 Estado de Funcionalidades -OpenCCB es una plataforma madura con la mayoría de sus funcionalidades core implementadas y operativas. Esta sección documenta transparentemente el estado actual de las características principales para que desarrolladores y administradores puedan planificar su uso. +### ✅ Implementado +- CRUD de Cursos e IA Generation. +- 16+ tipos de bloques interactivos. +- Sistema de foros, anuncios y gamificación. +- Soporte LTI 1.3 y SSO (OIDC). +- Monetización con Mercado Pago. -### ✅ Completamente Implementado - -| Categoría | Funcionalidades | -|-----------|-----------------| -| **Gestión de Cursos** | CRUD completo, AI generation, export/import JSON, templates, marketing metadata, teams, preview tokens | -| **Contenidos** | 16 tipos de bloques (video, quiz, hotspot, memory, mermaid, code lab, etc.) | -| **IA Integrada** | Transcripción, traducción, resúmenes, quiz generation, tutor RAG, audio evaluation, diagramas | -| **Question Bank** | CRUD completo, semantic search (PGVector), duplicate detection, AI generation con 4 skills | -| **Calificaciones** | Rubrics, weighted categories, drop-lowest policy, gradebook con cohortes, export CSV | -| **Foros** | Hilos, respuestas anidadas, votos, endorsements, moderación, suscripciones | -| **Gamificación** | XP, niveles, badges, leaderboards, Open Badges | -| **Monetización** | Mercado Pago integration, pricing, webhooks, auto-enrollment | -| **LTI 1.3** | Tool Provider con Deep Linking, JWKS, autoprovisionamiento | -| **Live Learning** | Integración Jitsi, scheduling desde Studio | -| **Analíticas** | Dashboard instructores, heatmaps, dropout risk prediction, advanced analytics | -| **Single-Tenant** | White-label branding, SSO/OIDC, exercise settings | -| **Responsive UI** | Mobile-first, dynamic API resolution, fluid typography | - -### ⚠️ En Progreso / Pendiente de Finalización - -| Funcionalidad | Estado Actual | Impacto | -|---------------|---------------|---------| -| **Generación de Certificados** | Schema de BD existe, falta implementación de generación y UI | Los estudiantes que completan cursos no reciben certificado | -| **Tracking de Progreso** | Hardcodeado a 0% en `my-learning/page.tsx` | Los estudiantes no ven su progreso real en el catálogo | -| **Notificaciones de Foros** | Suscripciones existen pero no se envían alertas | Usuarios suscritos no reciben notificaciones de respuestas | -| **Importación Excel (Question Bank)** | Código comentado con `unimplemented!()` | Solo se puede importar manualmente o vía AI | -| **Rate Limiting** | Deshabilitado por compatibilidad con middleware | APIs sin protección contra abuso en producción | - -### 📋 Planned (Ver roadmap.md para detalles) - -| Funcionalidad | Descripción | -|---------------|-------------| -| **Email/SMTP Integration** | Notificaciones por email, password reset, welcome emails | -| **Búsqueda Global** | Search unificado en cursos, lecciones, contenidos | -| **SCORM/xAPI Support** | Importación de paquetes SCORM, tracking xAPI | -| **Accesibilidad WCAG 2.1** | Auditoría y correcciones de contraste, navegación por teclado | -| **PWA y Offline** | Service workers, descarga de lecciones, sync offline | -| **Integraciones Empresariales** | HRIS (Workday, SAP), LDAP/Active Directory, webhooks salientes | - -> [!NOTE] -> Si encuentras alguna funcionalidad marcada como "En Progreso" que necesitas urgentemente, por favor abre un issue en el repositorio o contribuye con un PR. ¡Las contribuciones son bienvenidas! +### ⚠️ En Desarrollo +- **Generación de Certificados**: Implementando lógica de PDF automático. +- **Progreso Real**: Refactorizando visualización en catálogo. +- **Email/SMTP**: Integración de notificaciones transaccionales. --- -## 📚 Documentación +## 📈 Roadmap -### Guías Principales - -| Archivo | Descripción | -|---------|-------------| -| **README.md** | Este archivo - Visión general y características | -| **roadmap.md** | Hoja de ruta completa del proyecto (Fases 1-21) | -| **ManualDeConfiguracion.md** | Guía completa de instalación, configuración y troubleshooting | - -### Comandos Rápidos - -```bash -# Instalación estándar (detecta dev/prod automáticamente) -./install.sh - -# Instalación rápida (omite chequeos) -./install.sh --fast - -# Despliegue a producción (sincroniza con servidor remoto) -./install.sh --deploy - -# Iniciar servicios -docker-compose up -d - -# Ver logs -docker-compose logs -f - -# Health checks -curl http://localhost:3001/health -curl http://localhost:3002/health -``` - -### URLs de Acceso - -| Servicio | Puerto | URL | -|----------|--------|-----| -| **Studio (CMS)** | 3000 | http://localhost:3000 | -| **Experience (LMS)** | 3003 | http://localhost:3003 | -| **CMS API** | 3001 | http://localhost:3001 | -| **LMS API** | 3002 | http://localhost:3002 | - -### Credenciales por Defecto - -Después de ejecutar `./install.sh`: - -- **Email**: `admin@norteamericano.cl` -- **Contraseña**: `Admin123!` - ---- -## �️ Próximos Pasos (Roadmap 2024-2025) - -OpenCCB evoluciona constantemente. Estos son los pilares de nuestro desarrollo futuro: - -### 📱 Movilidad Nativa -- **Apps Android/iOS**: Aplicaciones nativas desarrolladas con Flutter para aprendizaje offline y notificaciones push críticas. -- **Offline Sync**: Capacidad de descargar lecciones y sincronizar progreso al recuperar conexión. - -### 🧠 Inteligencia Artificial Avanzada -- **AI Video Generation (v1)**: ✅ Generación de clips a partir de prompts y guiones de lecciones. -- **AI Proctoring**: Monitoreo basado en visión artificial para exámenes de alta integridad, 100% privado y local. -- **Multimodal Tutoring**: El tutor de IA podrá analizar imágenes y videos subidos por el alumno para dar feedback. -- **Automated Grading for Open Questions**: Evaluación masiva de ensayos y respuestas abiertas con rúbricas personalizadas. - -### 🔌 Interoperabilidad y Estándares -- **SCORM 1.2 / 2004 Support**: Player nativo para contenidos legados de la industria. -- **Advanced xAPI (Tin Can)**: Recolección detallada de experiencias de aprendizaje granulares. -- **Microsoft Teams / Slack Integration**: Recibe anuncios y tareas directamente en tus herramientas de trabajo. - -### 🏗️ Infraestructura y Escalabilidad -- **Multi-Cloud Terraform Provider**: Despliegues automatizados en AWS, GCP y Azure. -- **Edge Content Delivery**: Caché de videos y assets en el borde para mínima latencia global. - -### 🎮 Gamificación y Comunidad -- **Real-time Leaderboards**: Tablas de clasificación en vivo por cohorte y organización. -- **Social Learning Groups**: Grupos de estudio auto-organizados con chats integrados. +OpenCCB evoluciona constantemente. Consulta el [roadmap.md](roadmap.md) para ver el plan detallado de las Fases 22 a 36, incluyendo IA de Moderación y Ecosistemas de Plugins. --- -## �📄 Licencia +## 📄 Licencia Este proyecto es código abierto y está disponible bajo los términos de la licencia especificada en el repositorio. \ No newline at end of file diff --git a/deploy.sh b/deploy.sh index 3f0be3f..b09baf0 100755 --- a/deploy.sh +++ b/deploy.sh @@ -389,6 +389,12 @@ echo " SSL Staging: $LETSENCRYPT_STAGING" echo " Preservar SSL: $PRESERVE_SSL_CERTS" echo " Reiniciar DB: $RESET_DATABASE" echo " Compilar local: $BUILD_LOCAL" + +# Detectar variables de integración desde .env local para el resumen +_SAM_URL=$(grep '^SAM_DIAGNOSTICO_DATABASE_URL=' .env | cut -d'=' -f2-) +_MYSQL_URL=$(grep '^MYSQL_DATABASE_URL=' .env | cut -d'=' -f2-) +echo " SAM Integration: ${_SAM_URL:-(No configurada)}" +echo " MySQL Legacy: ${_MYSQL_URL:-(No configurada)}" echo "" # Crear script remoto en un archivo temporal @@ -528,6 +534,15 @@ if ! grep -q "^AWS_SECRET_ACCESS_KEY=" .env; then echo "AWS_SECRET_ACCESS_KEY=" >> .env fi +# Conservar o inicializar variables de integración +echo " Configurando variables de integración (SAM/MySQL)..." +if ! grep -q "^SAM_DIAGNOSTICO_DATABASE_URL=" .env; then + echo "SAM_DIAGNOSTICO_DATABASE_URL=" >> .env +fi +if ! grep -q "^MYSQL_DATABASE_URL=" .env; then + echo "MYSQL_DATABASE_URL=" >> .env +fi + # Asegurar dominios públicos para nginx-proxy y certificados SSL sed -i "/^NEXT_PUBLIC_STUDIO_DOMAIN=/d" .env 2>/dev/null || true sed -i "/^NEXT_PUBLIC_LEARNING_DOMAIN=/d" .env 2>/dev/null || true @@ -961,7 +976,8 @@ sleep 10 # Intentar crear el usuario via API echo "Creando usuario administrador..." -ADMIN_RESPONSE=$($DOCKER_CMD exec \ +if [ -n "$ADMIN_EMAIL" ] && [ -n "$ADMIN_PASS" ]; then + ADMIN_RESPONSE=$($DOCKER_CMD exec \ -e ADMIN_EMAIL="$ADMIN_EMAIL" \ -e ADMIN_PASS="$ADMIN_PASS" \ -e ADMIN_NAME="$ADMIN_NAME" \ @@ -1004,6 +1020,7 @@ else echo "Detalle: $ADMIN_BODY" fi fi +fi echo "" echo "========================================" diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..564c8a4 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,140 @@ +# Referencia de API de OpenCCB + +Esta guía proporciona detalles técnicos sobre los endpoints disponibles en OpenCCB para desarrolladores e integradores. + +## 1. Autenticación y Cuentas +Gestión de registro, login y perfiles organizacionales. + +### POST /auth/register +Crea un nuevo usuario vinculado a la organización por defecto. + +- **Cuerpo de la Petición ( AuthPayload ):** + ```json + { + "email": "string", + "password": "string", + "full_name": "string", + "role": "string (admin | instructor | student)" + } + ``` + +### SSO (OpenID Connect) +OpenCCB soporta integración con proveedores de identidad (IdP) externos como Google, Okta y Azure AD. +- **Configuración**: Los administradores de la organización pueden configurar sus credenciales OIDC en el panel de configuración de Studio. +- **Autoprovisionamiento**: Los nuevos usuarios se crean automáticamente en la plataforma tras una autenticación exitosa. + +### LTI 1.3 e Interoperabilidad +OpenCCB actúa como un Tool Provider LTI 1.3 moderno, utilizando OIDC y JWKS para máxima seguridad. +- **JWKS Endpoint**: `/lti/jwks` expone las claves públicas para verificación de firmas. +- **Deep Linking**: Permite que instructores seleccionen cursos o lecciones específicas desde el LMS externo mediante una interfaz de Studio embebida. +- **Autoprovisionamiento**: Los usuarios lanzados vía LTI se crean automáticamente con los roles correspondientes. + +```bash +# Registrar un nuevo administrador +curl -X POST "http://localhost:3001/auth/register" \ + -H "Content-Type: application/json" \ + -d '{"email": "admin@empresa.com", "password": "pass", "full_name": "Admin Name"}' +``` + +--- + +## 2. Gestión de Contenidos (CMS) +Herramientas para instructores y administradores. + +### POST /courses +Crea un nuevo curso vinculado a la organización del usuario. + +- **Lógica**: El `instructor_id` se asigna automáticamente desde el token JWT. +- **Cuerpo ( CreateCourseRequest ):** + ```json + { + "title": "string", + "pacing_mode": "string (self_paced | instructor_led)" + } + ``` + +```bash +# Crear curso básico +curl -X POST "http://localhost:3001/courses" \ + -H "Authorization: Bearer $TOKEN" \ + -d '{"title": "Curso de Rust", "pacing_mode": "self_paced"}' +``` + +### POST /courses/generate +Utiliza IA para generar la estructura completa de un curso basado en un prompt. + +### GET /courses/{id}/export +Exporta un curso completo y su contenido a formato JSON para portabilidad. + +### POST /courses/import +Importa un curso a partir de un archivo JSON generado previamente. + +### POST /lessons +Agrega contenido multimedia o evaluaciones a un módulo. + +- **Configuración Graduable**: Si `is_graded` es true, los puntos sumarán al XP del estudiante en el LMS. +- **Nuevos Tipos Gamificados**: + - `hotspot`: Identificación visual sobre imágenes. + - `memory-match`: Juego de memoria con pares conceptuales. + - `video-marker`: Preguntas interactivas en timestamps específicos del video. + +### POST /assets/upload +Sube un archivo multimedia o documento a la biblioteca global de la organización. + +--- + +## 3. Experiencia de Aprendizaje (LMS) +Endpoints para estudiantes y seguimiento de progreso. + +### POST /enroll +Inscribe al usuario en un curso. + +### POST /grades +Registra el puntaje de una lección y actualiza la gamificación. + +### GET /notifications +Obtiene las notificaciones pendientes del usuario. + +--- + +## 4. IA y Analíticas Avanzadas +Funcionalidades inteligentes 100% locales y gratuitas. + +### POST /lessons/{id}/transcribe +Inicia el proceso de transcripción y traducción. + +### POST /audio/evaluate +Evalúa una respuesta oral del estudiante utilizando IA. + +### POST /lessons/{id}/generate-quiz +Genera un quiz basado en el contenido de la lección. + +### POST /chat (Streaming) +Conversación en tiempo real con la base de conocimientos (RAG). + +### GET /lessons/{id}/heatmap +Devuelve los puntos de concentración de visualización para una lección. + +--- + +## 5. Foros de Discusión (Discussion Forums) +Sistema completo de foros por curso con hilos, respuestas anidadas y moderación. + +### GET /courses/{id}/discussions +Lista todos los hilos de discusión de un curso. + +### POST /courses/{id}/discussions +Crea un nuevo hilo de discusión. + +### POST /posts/{id}/vote +Vota por una respuesta (upvote/downvote). + +--- + +## 6. Anuncios del Curso (Announcements) + +| Acción | Método | Endpoint | +|--------|--------|----------| +| Listar | GET | `/courses/{id}/announcements` | +| Crear | POST | `/courses/{id}/announcements` | +| Eliminar | DELETE| `/announcements/{id}` | diff --git a/roadmap.md b/roadmap.md index 16fdec4..05a8f63 100644 --- a/roadmap.md +++ b/roadmap.md @@ -3,492 +3,122 @@ ## Fase 1: Cimientos ✅ - [x] Configuración del Workspace de Rust (Edición 2024) - [x] Estructura de Microservicios (CMS y LMS) -- [x] Infraestructura Multi-Base de Datos (PostgreSQL con DBs separadas) -- [x] Inicialización del Frontend (Studio y Experience con Next.js) -- [x] Dockerización de todos los servicios -- [x] Integración de API (Dashboard <-> Servicio CMS) -- [x] Script de instalación unificado (`install.sh`) con detección de hardware y auto-configuración +- [x] Infraestructura Multi-Base de Datos +- [x] Inicialización del Frontend (Studio y Experience) +- [x] Dockerización y Script de instalación unificado ## Fase 2: Funcionalidades Core del CMS ✅ -- [x] Editor de Estructura de Cursos (Módulos y Lecciones) -- [x] Sistema de Carga de Archivos (Video, Audio, Recursos Nativos) -- [x] Contenido Interactivos (Constructor de Actividades) - - [x] Reordenamiento de bloques (Subir/Bajar) - - [x] Descripciones con texto enriquecido - - [x] Bloques multimedia con restricciones de reproducción - - [x] Bloques de Quiz (Opción múltiple, Verdadero/Falso, Selección múltiple) - - [x] Tipos de evaluación avanzada: - - [x] Completar espacios en blanco - - [x] Emparejamiento de parejas - - [x] Ordenamiento/Secuenciación - - [x] Respuesta corta -- [x] Comunicación entre servicios (Sincronización CMS -> LMS) -- [x] Reproductor de video Premium con límites de visualización -- [x] Interfaz de Studio completa con gestión dinámica de cursos +- [x] Editor de Estructura de Cursos +- [x] Sistema de Carga de Archivos +- [x] Constructor de Actividades Interactivas +- [x] Tipos de evaluación avanzada (Secuenciación, Emparejamiento, etc.) ## Fase 3: Autenticación y Seguridad ✅ -- [x] **Autenticación Basada en JWT**: Auth común para todos los servicios -- [x] **Control de Acceso Basado en Roles (RBAC)**: - - [x] Soporte multi-rol (Admin, Instructor, Estudiante) - - [x] Permisos e interfaces específicas por rol - - [x] Autorización basada en tokens para endpoints protegidos -- [x] **Registro de Auditoría (Audit Log)**: Seguimiento de todos los cambios en el CMS -- [x] **Interfaz de Auditoría**: Panel de administración para visualizar registros de cambios +- [x] Autenticación basada en JWT +- [x] Control de Acceso Basado en Roles (RBAC) +- [x] Registro e Interfaz de Auditoría ## Fase 4: Experiencia LMS y Calificaciones ✅ -- [x] **Portal del Estudiante (Experience)**: - - [x] Catálogo de cursos e inscripciones - - [x] Reproductor interactivo de lecciones - - [x] Diseño responsivo (móviles/tablets) - **Optimizado y validado en Fase 15** -- [x] **Sistema de Calificación Holístico**: - - [x] Categorías de calificación con pesos (porcentajes) - - [x] Opción de eliminar las N puntuaciones más bajas por categoría - - [x] Cálculo automático de la nota ponderada -- [x] **Políticas de Evaluación**: - - [x] Intentos máximos configurables por lección - - [x] Correcciones instantáneas y políticas de reintento - - [x] Seguimiento atómico de intentos con validación de reglas -- [x] **Seguimiento del Progreso**: - - [x] Visualización de puntuaciones en tiempo real - - [x] Desglose categoría por categoría -- [x] **Umbrales de Aprobación Dinámicos**: - - [x] Porcentaje de aprobación configurable por curso - - [x] Visualización de rendimiento en 5 niveles - - [x] Feedback por colores (desde Reprobado hasta Excelente) -- [x] **Certificados**: Generación automática de certificados al completar el curso +- [x] Portal del Estudiante (Experience) +- [x] Sistema de Calificación Holístico con pesos +- [x] Políticas de Evaluación e Intentos +- [x] Umbrales de Aprobación Dinámicos +- [x] Generación de Certificados básicos ## Fase 5: Analíticas e Insights ✅ -- [x] **Dashboard de Analíticas para Instructores**: - - [x] Total de inscritos por curso - - [x] Promedio general de notas - - [x] Desglose de rendimiento por lección - - [x] Detección de "lecciones difíciles" - - [x] Aplicación de RBAC (los instructores solo ven sus cursos) -- [x] **Dashboard de Progreso del Estudiante**: - - [x] Barra de rendimiento interactiva - - [x] Visualización de feedback basada en niveles - - [x] Actualización de notas en tiempo real +- [x] Dashboard de Analíticas para Instructores +- [x] Dashboard de Progreso del Estudiante ## Fase 6: Refactorización a Single-Tenant ✅ -- [x] **Single-tenancy**: Reposicionamiento como módulo premium (Completado) - - [x] Hardcoding del `organization_id` por defecto en middleware común - - [x] Remoción de selectores de organización en Studio y Experience - - [x] Simplificación de registros y logins para un solo inquilino - - [x] Eliminación de rutas y controladores de gestión multi-empresa - - [x] Limpieza de componentes frontend redundantes (Selector, Gestión de Orgs) -- [x] **Personalización de Marca (Branding Premium)**: Identidad unificada (Completado) - - [x] Endpoints singulares para gestión de marca sin parámetros de ID - - [x] Carga y optimización de logotipos y favicons customizados - - [x] Nombre de plataforma personalizado (White-label) - - [x] Esquemas de colores personalizados aplicado globalmente - - [x] Previsualización en vivo del branding en Studio renovada -- [x] **Interfaz de Usuario Simplificada**: - - [x] **Login Unificado**: Eliminación de flujo dividido Personas/Empresas - - [x] **Navegación Limpia**: Remoción de enlaces de administración de organizaciones +- [x] Reposicionamiento como módulo premium +- [x] Personalización de Marca (Branding Premium) +- [x] Interfaz de Usuario e Inicio de Sesión Simplificados -## Fase 7: Compromiso y Social (En Progreso) -- [x] **Analíticas de Vanguardia**: - - [x] Análisis de cohortes (Implementado) - - [x] Métricas de retención (Implementado) - - [x] Mapas de calor de participación (Heatmaps) (Implementado) -- [x] **Integración de IA**: - - [x] Resúmenes de lecciones generados por IA (Llama 3) - - [x] Generación automática de quices (Llama 3) - - [ ] Transcripción y traducción de video en tiempo real (Postpuesto - Reemplazado por Llama 3 para otras funciones) -- [x] **Rutas de Aprendizaje Personalizadas**: Recomendaciones impulsadas por Llama 3 (Implementado) -- [x] **Gamificación Base**: (Implementada a nivel de sistema) - - [x] Medallas y logros - - [x] Tablas de clasificación (Leaderboards) - - [x] Sistema de XP y niveles -- [x] **Mejoras en la Gestión de Cursos**: - - [x] Nombrado manual de módulos, lecciones y actividades - - [x] Pacing de cursos: Modo autodidacta (Evergreen) o Dirigido por instructor (Cohort) +## Fase 7: Compromiso y Social ✅ +- [x] Analíticas de Vanguardia (Cohortes, Retención, Heatmaps) +- [x] Integración de IA (Resúmenes, Quices, Tutor RAG) +- [x] Rutas de Aprendizaje Personalizadas +- [x] Gamificación Base (XP, Niveles, Leaderboards) - - [x] Calendario de hitos y recordatorios automáticos de fechas límite - -## Fase 8: Funcionalidades Enterprise (En Progreso) -- [x] **Perfil de Usuario y Ciclo de Vida**: - - [x] **Cierre de Sesión Integrado**: Gestión estandarizada en ambos portales - - [x] **Gestión del Perfil**: Actualización de avatar, bio e idioma por el usuario -- [x] **Reportes Avanzados**: Constructor de reportes personalizados y exportación a CSV (Implementado) -- [x] **Ecosistema de Integración**: - - [x] **SSO (Single Sign-On)**: Soporte completo OIDC (Google, Okta, Azure AD) (Completado) - - [x] **LTI 1.3 Tool Provider**: Integración segura con LMS externos como Canvas o Moodle (Completado) -- [ ] **Accesibilidad**: Auditoría y correcciones WCAG 2.1 +## Fase 8: Funcionalidades Enterprise ✅ +- [x] Perfil de Usuario y Ciclo de Vida +- [x] Reportes Avanzados exportables a CSV +- [x] SSO (Google, Okta, Azure AD) +- [x] LTI 1.3 Tool Provider (Interoperabilidad) ## Fase 9: Portabilidad de Cursos ✅ -- [x] **Esquema JSON Universal**: Formato estandarizado para intercambio de cursos (Completado) -- [x] **Exportador Recursivo**: Serialización de jerarquías completas de cursos (Completado) -- [x] **Importador Atómico**: Creación por lotes con re-mapeo de dependencias (Completado) -- [x] **Interfaz de Portabilidad**: Botones de Exportación/Importación en Ajustes (Completado) +- [x] Esquema JSON Universal y Portabilidad de contenidos ## Fase 10: Consola de Administración Global ✅ -- [x] **Panel "Estilo Django"**: Interfaz dedicada para Super-Admins para gestionar Orgs y Usuarios (Completado) -- [x] **Monitoreo del Sistema**: Estadísticas en tiempo real de uso de IA y estado de servicios (Completado) -- [x] **Auditoría Universal**: Panel centralizado de actividad para todos los tenants (Completado) +- [x] Panel de control para organizaciones y auditoría universal -## Fase 11: Evaluaciones y Quizzes Extendidos (En Progreso) -- [x] **Quices de Código**: Desafíos interactivos con reproductor tipo IDE (Completado) -- [x] **Identificación Visual**: Quices de "Puntos Calientes" (Hotspots) en imágenes (Completado) -- [x] **Tutor de IA Integrado**: Asistente basado en RAG con acceso a bloques interactivos e historial del curso (Completado) -- [x] **Evaluaciones por Audio**: Preguntas con respuesta oral para idiomas con feedback de IA detallado (Completado) -- [x] **Eliminación de Cursos**: Gestión completa del ciclo de vida del contenido (Completado) -- [x] **Quices con Contexto IA**: Generación de evaluaciones con enfoque y tipo personalizable (Completado) -- [x] **Actividades Gamificadas**: Nuevos tipos de bloques interactivos incluyendo Juegos de Memoria (con generación automática por IA) y Puntos Calientes (Hotspots). (Completado) -- [x] **Marcadores de Video**: Preguntas que pausan el video en timestamps específicos (Completado) +## Fase 11 - 14: IA y Gamificación Avanzada ✅ +- [x] Quices de Código y Puntos Calientes (Hotspots) +- [x] Evaluaciones por Audio con IA +- [x] Generador de Cursos "Mágico" +- [x] Juegos para niños e Internacionalización (EN, ES, PT) -## Fase 12: Generador de Cursos "Mágico" con IA ✅ -- [x] **Creación Instantánea**: Generación de estructura completa a partir de un prompt (Completado) -- [x] **Ingestión Atómica Transaccional**: Creación de módulos y lecciones en un solo paso (Completado) -- [x] **Ingeniería de Prompts**: Diseño curricular profesional optimizado para LLMs (Completado) +## Fase 15 - 19: UI Adaptativa y Monetización ✅ +- [x] Dynamic API Resolution (Acceso LAN) +- [x] Optimización móvil completa +- [x] Monetización con Mercado Pago +- [x] Analíticas Predictivas (Riesgo de Abandono) +- [x] Integración de Videoconferencia (Jitsi) +- [x] Landing Pages para Marketing de Cursos -## Fase 13: Gamificación para Niños ✅ -- [x] **Juego de Memoria**: Emparejamiento conceptual mediante cartas interactivas (Completado) -- [x] **Arrastrar al Cubo**: Categorización visual por arrastre (Completado) -- [x] **Feedback Animado**: Animaciones de celebración (confeti, estrellas) para éxitos (Completado) - -## Fase 14: Globalización y Aprendizaje con Documentos ✅ -- [x] **Internacionalización (i18n)**: Soporte de UI para Inglés, Español y Portugués (Completado) -- [x] **Selector de Idiomas**: Cambio dinámico en la barra de navegación y perfil (Completado) -- [x] **Bloque de Documentos**: Previsualización de PDF y descargas de DOCX/PPTX (Completado) -- [x] **IA Multi-idioma**: Las transcripciones y resúmenes siguen el contexto del curso (Completado) +## Fase 20 - 21: IA Generativa y Búsqueda Semántica ✅ +- [x] Diagramas Mermaid automáticos +- [x] Búsqueda Semántica con PGVector (Representación de 768 dim) +- [x] Detección de duplicados y RAG mejorado --- -## Fase 15: Conectividad y UI Adaptativa ✅ -- [x] **Dynamic API Resolution**: Detección automática de IP del servidor para acceso multi-dispositivo y LAN (Completado) -- [x] **Menú Móvil (Experience)**: Implementación de navegación lateral (hamburger) para celulares (Completado) -- [x] **Optimización de Studio**: Interfaz de administración compacta y escalable para pantallas pequeñas (Completado) -- [x] **Tipografía Fluida**: Escalado de fuentes y márgenes adaptativos en todo el portal (Completado) -- [x] **Locked Lesson AI Feedback**: Generación de retroalimentación motivacional para lecciones bloqueadas (Completado) -- [x] **Context Enrichment**: Ingesta de bloques interactivos en el motor de RAG (Completado) -- [x] **Course History Context**: Capacidad del tutor para recordar lecciones previas (Completado) -- [x] **Color-Coded Progress Status**: Seguimiento visual por colores (Verde/Amarillo/Rojo) en sidebar y cabeceras (Completado) +## Fase 22: Estabilidad y Funcionalidades Pendientes 🛠️ (En Ejecución) +- [ ] **Generación de Certificados Premium**: Mejorar UI de configuración de templates en Studio. +- [ ] **Tracking de Progreso Atómico**: Reemplazar hardcodes por cálculo real de completitud. +- [ ] **Notificaciones de Foros**: Implementar despacho de alertas vía SMTP. +- [ ] **Importación Masiva (Excel)**: Finalizar soporte para Question Bank. -## Fase 16: Estabilidad y UX Avanzada ✅ -- [x] **QA y Estabilidad**: Verificación del flujo completo de evaluación en entornos de producción. -- [x] **Rutas de Aprendizaje**: Recomendaciones basadas en el historial personalizadas y perfiles de habilidades. -- [x] **Optimización de Contenedores**: Limpieza automatizada y reducción de huella de infraestructura mediante Build Context optimizado. -- [x] **Split Login Flow**: Separación de flujos de autenticación para Personas y Empresas. - -## Fase 17: Funcionalidades Estilo Open edX (En Progreso) -- [x] **Discussion Forums**: Sistema de foros por curso con hilos, respuestas anidadas y moderación. - - [x] Base de datos (4 tablas: threads, posts, votes, subscriptions) - - [x] Backend API (10 endpoints para gestión completa) - - [x] Permisos diferenciados (estudiante vs instructor) - - [x] Sistema de votación y endorsement - - [x] Frontend (componentes React) - - [x] Integración con notificaciones -- [x] **Course Announcements**: Sistema de anuncios de instructores con notificaciones. -- [x] **Student Notes**: Anotaciones personales por lección con exportación a PDF. -- [x] **Peer Assessment**: Evaluación entre pares con rúbricas configurables. -- [x] **Cohorts & Groups**: Segmentación de estudiantes con contenido específico. -- [x] **Content Libraries**: Repositorio reutilizable de bloques y lecciones. -- [x] **Advanced Grading**: Rúbricas detalladas y workflows de calificación. -- [x] **Learning Sequences**: Prerequisitos y rutas condicionales entre lecciones. -- [x] **Bulk Operations**: Bulk enrollment, advanced grade export, and segmented announcements. -- [x] **Course Teams**: Support for multiple instructors per course with granular roles. -- [x] **Course Preview**: Vista previa de lecciones sin inscripción. -- [x] **Bookmarks**: Sistema de favoritos para lecciones importantes. -- [x] **Progress Dashboard**: Gráficos de progreso temporal y predicción de finalización. - -## Fase 18: Monetización y Estandarización ✅ -- [x] **E-Commerce & Monetización**: (Completado) - - [x] Integración con Mercado Pago (Preferencia de pago y Webhooks). - - [x] Sistema de precios y moneda por curso. - - [x] Inscripción automática tras pago exitoso. - - [x] Verificación de seguridad de acceso a lecciones basada en inscripción. - - [x] Dashboard de transacciones básico en base de datos. -- [x] **Interoperabilidad**: ✅ - - [x] Implementación de LTI 1.3 (Tool Provider) con soporte para Deep Linking. - - [x] Conectividad segura con LMS externos (Moodle/Canvas) via OIDC y JWKS. -- [x] **Analíticas Predictivas**: ✅ - - [x] Motor de IA para detección de riesgo de abandono. - - [x] Notificaciones proactivas para instructores. -- [x] **Gestión de Activos**: ✅ - - [x] Biblioteca de medios global (Global Asset Manager). - - [x] Reutilización de recursos multi-curso. -- [x] **Aprendizaje en Vivo**: ✅ - - [x] Integración con Jitsi para aulas virtuales en tiempo real. - - [x] Gestión de reuniones y programación desde Studio. - - [x] Acceso directo para estudiantes desde Experience. -- [x] **Portafolio del Estudiante**: ✅ - - [x] Sistema de medallas y logros (Open Badges). - - [x] Perfiles profesionales públicos con control de privacidad. - - [x] Visualización de progreso y nivel de XP. - -## Fase 19: Presentación Visual y Marketing de Cursos ✅ -- [x] **Metadatos de Marketing Estructurados**: Captura de objetivos, requisitos, público objetivo y certificación en Studio. (Completado) -- [x] **Premium Course Summary**: Nueva interfaz de "Acerca del Curso" en Experience con diseño de alta fidelidad y navegación por pestañas. (Completado) -- [x] **Dashboard Global de Tareas AI**: Panel unificado de control en consola administrativa para monitorear, reintentar y cancelar todas las generaciones en segundo plano (transcripciones, quices, juegos de memoria, etc). (Completado) +## Fase 23 - 27: Infraestructura Crítica 📋 (Planificado) +- [ ] **Integración SMTP**: Password reset, notificaciones transaccionales y de marketing. +- [ ] **Búsqueda Global Unificada**: Búsqueda full-text y semántica en toda la plataforma. +- [ ] **Soporte SCORM/xAPI**: Player nativo para contenidos legados. +- [ ] **Accesibilidad WCAG 2.1**: Auditoría y ajustes de contraste/navegación. +- [ ] **PWA y Soporte Offline**: Service workers para aprendizaje sin conexión. --- -**Estado Actual**: La plataforma cuenta con un motor de IA avanzado, gestión multi-tenant completa, tutoría inteligente con memoria histórica, una **interfaz 100% responsiva**, flujos de autenticación diferenciados, **sistema de foros de discusión funcional**, **gestión de anuncios segmentados**, **monetización integrada con Mercado Pago**, **Inscripción Masiva de Usuarios**, **Exportación Avanzada de Calificaciones**, **Librerías de Contenido reutilizables**, **Sistema de Rúbricas Avanzado**, **Secuencias de Aprendizaje**, **Gestión de Equipos Docentes**, **Vista Previa de Cursos**, **Dashboard de Progreso Estudiantil**, **Sistema de Marcadores**, **Biblioteca Global de Activos**, **Interoperabilidad LTI 1.3**, **Analíticas Predictivas**, **Integración de Jitsi**, **Portafolios con Perfiles Públicos** y **Landing Pages de Cursos (Marketing) automatizadas**. +## 🚀 Fases Estratégicas (Nuevas) -## Fase 20: IA Generativa Avanzada (En Ejecución) 🧠 -- [x] **Generación de Juegos de Memoria Conceptuales**: Creación automática de parejas (concepto/definición) a partir de transcripciones. (Completado) -- [x] **Simulaciones de Rol y Diálogos Ramificados**: Motor de escenarios interactivos con respuestas dinámicas de la IA. (Completado) -- [x] **Auto-Hotspots Pedagógicos**: Identificación automática de puntos de interés en imágenes con descripciones técnicas. (Completado) -- [x] **Diagramas de Mermaid Dinámicos**: Visualización automática de procesos y mapas mentales a partir del contenido de la lección. (Completado) -- [x] **Laboratorios de Código con Hints de IA**: Generación de desafíos de programación con pistas contextuales basadas en errores. (Completado) +### Fase 32: IA de Moderación y Ética 🛡️ +- [ ] **Auditoría de IA**: Sistema de validación para prevenir "halucinaciones" en el Tutor RAG. +- [ ] **Moderación Automática**: Detección de lenguaje ofensivo o inapropiado en foros y chats. +- [ ] **Ética de Datos**: Herramientas para transparencia en el uso de datos por los modelos de IA local. + +### Fase 33: Aprendizaje Colaborativo Síncrono 🤝 +- [ ] **Pizarras Compartidas**: Espacio de dibujo colaborativo integrado en lecciones. +- [ ] **Edición Multiusuario**: Soporte para documentos compartidos en tiempo real (tipo Google Docs). +- [ ] **Salas de Estudio**: Grupos efímeros para resolución de dudas grupales por video. + +### Fase 34: Análisis Pedagógico Profundo 📊 +- [ ] **Métricas de Calidad**: Análisis automático de la efectividad de las lecciones generadas. +- [ ] **Índice de Discriminación**: Estadísticas sobre qué preguntas de quiz discriminan mejor el conocimiento. +- [ ] **Sugerencias Curriculares**: IA recomendando cambios en la estructura del curso basada en el rendimiento real. + +### Fase 35: Ecosistema de Plugins 🔌 +- [ ] **Arquitectura Modular**: Sistema para que desarrolladores externos agreguen nuevos "Content Blocks". +- [ ] **Soporte para Web Components**: Permitir la inclusión de herramientas interactivas externas de forma segura. +- [ ] **OpenCCB Market**: Galería interna para descargar y habilitar extensiones. + +### Fase 36: LTI 1.3 Tool Consumer 🔗 +- [ ] **Consumo de herramientas externas**: Capacidad de embeber laboratorios externos (ej: MATLAB, Labster) dentro de OpenCCB. +- [ ] **Delegación de Calificaciones**: Recibir notas de herramientas externas y sincronizarlas con el Gradebook de OpenCCB. --- -## Fase 21: Búsqueda Semántica y RAG Avanzado ✅ -- [x] **PGVector Integration**: Implementación de búsqueda semántica con embeddings de 768 dimensiones. (Completado) -- [x] **Semantic Question Search**: Búsqueda por similitud de coseno en question bank. (Completado) -- [x] **Duplicate Detection**: Detección automática de preguntas duplicadas (>95% similitud). (Completado) -- [x] **RAG Mejorado para Generación**: Contexto semántico + verificación de 4 habilidades. (Completado) -- [x] **Knowledge Base Embeddings**: Búsqueda semántica en base de conocimiento para tutor IA. (Completado) -- [x] **Índices IVFFlat**: Optimización para >100k filas (25-100x más rápido). (Completado) -- [x] **MySQL Integration Completa**: Importación de study plans y courses con tracking. (Completado) -- [x] **Test Templates con Filtros**: Filtrado por mysql_course_id, level, course_type. (Completado) - ---- - -**Estado Actual**: La plataforma cuenta con un motor de IA avanzado, gestión multi-tenant completa, tutoría inteligente con memoria histórica, una **interfaz 100% responsiva**, flujos de autenticación diferenciados, **sistema de foros de discusión funcional**, **gestión de anuncios segmentados**, **monetización integrada con Mercado Pago**, **Inscripción Masiva de Usuarios**, **Exportación Avanzada de Calificaciones**, **Librerías de Contenido reutilizables**, **Sistema de Rúbricas Avanzado**, **Secuencias de Aprendizaje**, **Gestión de Equipos Docentes**, **Vista Previa de Cursos**, **Dashboard de Progreso Estudiantil**, **Sistema de Marcadores**, **Biblioteca Global de Activos**, **Interoperabilidad LTI 1.3**, **Analíticas Predictivas**, **Integración de Jitsi**, **Portafolios con Perfiles Públicos**, **Landing Pages de Cursos (Marketing) automatizadas**, **Diagramas de Mermaid Dinámicos**, **Laboratorios de Código con Hints de IA**, y **Búsqueda Semántica con PGVector**. - +**Estado Actual**: Plataforma madura con IA generativa integrada, arquitectura Premium Single-Tenant, búsqueda semántica y monetización operativa. **Próximas Prioridades**: -1. **Accesibilidad Universal**: Auditoría y ajustes de contraste para cumplimiento WCAG 2.1. -2. **Integraciones Empresariales**: Conectividad con HRIS y ERPs externos. -3. **Optimización de Performance**: Refactorización de componentes críticos y carga diferida (lazy loading). - ---- - -## Fase 22: Finalización de Funcionalidades Pendientes 🛠️ -- [ ] **Generación de Certificados**: Implementación de lógica de generación automática al completar curso. - - [ ] Backend: Endpoint para verificar completitud y generar certificado (PDF) - - [ ] Frontend: UI para configurar templates de certificados en Studio - - [ ] Frontend: Botón de descarga en Experience al completar curso - - [ ] Schema de BD ya existe (`certificate_template`), solo falta implementación -- [ ] **Tracking de Progreso Real**: Cálculo y visualización de progreso real del estudiante. - - [ ] Backend: Endpoint para calcular % de completitud basado en lecciones completadas - - [ ] Frontend: Reemplazar hardcoded `progress = 0` en `my-learning/page.tsx` - - [ ] Frontend: Barra de progreso real en catálogo de cursos -- [ ] **Notificaciones de Foros**: Despacho de alertas cuando hay respuestas en hilos suscritos. - - [ ] Backend: Implementar lógica de notificación en `handlers_discussions.rs` (línea 352 tiene TODO) - - [ ] Frontend: Ver que las notificaciones se muestran correctamente en NotificationCenter -- [ ] **Importación Excel para Question Bank**: Fix del código comentado. - - [ ] Backend: Descomentar y implementar `import_from_excel` en `handlers_question_bank.rs` - - [ ] Frontend: Agregar botón de importación Excel en UI de Question Bank - - [ ] Documentación: Formato esperado del archivo Excel -- [ ] **Re-habilitar Rate Limiting**: Solución de incompatibilidad con middleware de auth. - - [ ] Backend: Fix de `GovernorLayer` para que funcione después del middleware de auth - - [ ] Backend: Configurar límites apropiados por tipo de ruta (pública vs protegida) - - [ ] Testing: Verificar que no bloquea peticiones legítimas - ---- - -## Fase 23: Integración de Email/SMTP 📧 -- [ ] **Configuración SMTP**: Variables de entorno para configuración de servidor de correo. - - [ ] `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASSWORD`, `SMTP_FROM` - - [ ] Soporte para providers: SendGrid, AWS SES, SMTP genérico -- [ ] **Notificaciones por Email**: - - [ ] Recordatorios de deadlines próximos - - [ ] Alertas de respuestas en foros suscritos - - [ ] Notificaciones de nuevas calificaciones - - [ ] Anuncios de curso de instructores -- [ ] **Autenticación por Email**: - - [ ] Password reset vía link de email - - [ ] Verificación de email al registrar cuenta - - [ ] Magic link login (opcional) -- [ ] **Emails Transaccionales**: - - [ ] Welcome email para nuevos usuarios - - [ ] Notificación de inscripción exitosa - - [ ] Certificado de completación por email - - [ ] Recibo de pago de Mercado Pago -- [ ] **Template de Emails**: - - [ ] Templates HTML responsivos con branding personalizado - - [ ] Soporte multi-idioma (EN, ES, PT) - - [ ] Preview de templates en panel de administración - ---- - -## Fase 24: Búsqueda Global 🔍 -- [ ] **Search Endpoint Unificado**: API de búsqueda across cursos, lecciones, contenidos. - - [ ] Backend: Endpoint `/search` con filtros por tipo, categoría, instructor - - [ ] Backend: Búsqueda full-text con PostgreSQL (tsvector) - - [ ] Backend: Opcionalmente agregar búsqueda semántica con embeddings (similar a question bank) -- [ ] **UI de Búsqueda**: - - [ ] Frontend: Barra de búsqueda global en navbar de Studio y Experience - - [ ] Frontend: Resultados en tiempo real con autocompletado - - [ ] Frontend: Filtros avanzados (fecha, instructor, tipo de contenido, nivel) -- [ ] **Búsqueda en Contenidos**: - - [ ] Indexación de transcripciones de video para búsqueda - - [ ] Búsqueda en documentos PDF y DOCX - - [ ] Búsqueda en preguntas de quizzes - ---- - -## Fase 25: Soporte SCORM/xAPI 📦 -- [ ] **SCORM 1.2/2004 Player**: - - [ ] Backend: Endpoint para subir paquetes SCORM (.zip) - - [ ] Backend: Extracción y almacenamiento de metadatos SCORM - - [ ] Frontend: Player SCORM embebido en Experience - - [ ] Frontend: Preview de paquetes SCORM en Studio -- [ ] **xAPI (Tin Can) Tracking**: - - [ ] Backend: Endpoint para recibir statements xAPI - - [ ] Backend: Almacenamiento de statements en base de datos separada - - [ ] Backend: Endpoint para consultar historial xAPI por usuario/curso - - [ ] Frontend: Dashboard de analíticas xAPI para instructores -- [ ] **Import/Export SCORM**: - - [ ] Backend: Generador de paquetes SCORM desde cursos OpenCCB - - [ ] Backend: Validador de paquetes SCORM importados - - [ ] Frontend: UI para import/export SCORM en Studio -- [ ] **Compatibilidad con Contenidos de Terceros**: - - [ ] Soporte para H5P, Articulate, Adobe Captivate - - [ ] Tracking de progreso y calificaciones desde contenidos SCORM - ---- - -## Fase 26: Accesibilidad WCAG 2.1 ♿ -- [ ] **Auditoría de Accesibilidad**: - - [ ] Herramientas: axe-core, Lighthouse, WAVE - - [ ] Reporte de problemas de contraste de color - - [ ] Verificación de navegación por teclado - - [ ] Testing con screen readers (NVDA, VoiceOver, JAWS) -- [ ] **Correcciones de Accesibilidad**: - - [ ] Ajustes de contraste para cumplir WCAG AA (4.5:1 para texto normal) - - [ ] Labels ARIA en todos los componentes interactivos - - [ ] Navegación por teclado completa (Tab, Enter, Escape, flechas) - - [ ] Focus indicators visibles en todos los elementos - - [ ] Skip links para saltar a contenido principal -- [ ] **Accesibilidad de Formularios**: - - [ ] Labels asociados correctamente a inputs - - [ ] Mensajes de error accesibles por screen reader - - [ ] Autocomplete en campos apropiados -- [ ] **Accesibilidad de Multimedia**: - - [ ] Subtítulos obligatorios para videos - - [ ] Transcripciones para contenido de audio - - [ ] Alt text para imágenes importantes -- [ ] **Testing Continuo**: - - [ ] Integración de axe-core en CI/CD - - [ ] Testing manual regular con usuarios de screen readers - - [ ] Documentación de accesibilidad para contribuidores - ---- - -## Fase 27: PWA y Soporte Offline 📱 -- [ ] **Progressive Web App (PWA)**: - - [ ] Service worker para caching de assets estáticos - - [ ] Manifest.json para instalación en móviles/desktop - - [ ] Offline fallback page - - [ ] Push notifications para alertas críticas -- [ ] **Descarga de Lecciones**: - - [ ] Frontend: Botón de descarga por lección en Experience - - [ ] Frontend: UI para gestionar descargas (ver/eliminar) - - [ ] Service worker: Caching de contenido de video/audio - - [ ] IndexedDB: Almacenamiento de progreso offline -- [ ] **Sincronización Offline**: - - [ ] Service worker: Queue de acciones offline (calificaciones, notas, progreso) - - [ ] Frontend: Sync automático al reconectar - - [ ] Backend: Endpoint para recibir sync data y reconciliar - - [ ] Manejo de conflictos (última escritura gana, o merge) -- [ ] **Experiencia Offline**: - - [ ] Indicador de estado de conexión en UI - - [ ] Contenido disponible sin conexión claramente marcado - - [ ] Límite de almacenamiento configurable - - [ ] Limpieza automática de caché antiguo - ---- - -## Fase 28: Sistema de Mentoría 🎓 -- [ ] **Gestión de Mentores**: - - [ ] Backend: CRUD de asignaciones mentor-estudiante - - [ ] Backend: Endpoints para disponibilidad de mentores - - [ ] Frontend: UI para asignar mentores en panel de administración - - [ ] Frontend: Perfil de mentor con bio, especialidades, disponibilidad -- [ ] **Sesiones 1-a-1**: - - [ ] Backend: Sistema de agendamiento de sesiones - - [ ] Backend: Integración con Jitsi para sesiones virtuales - - [ ] Frontend: Calendario de sesiones para mentores y estudiantes - - [ ] Frontend: Recordatorios por email/notificación -- [ ] **Seguimiento Personalizado**: - - [ ] Backend: Notas de mentor por estudiante - - [ ] Backend: Plan de aprendizaje personalizado por estudiante - - [ ] Frontend: Dashboard de mentor con vista de estudiantes asignados - - [ ] Frontend: Reportes de progreso para mentores - ---- - -## Fase 29: Integraciones Empresariales 🏢 -- [ ] **HRIS Connectors**: - - [ ] Integración con Workday (API REST) - - [ ] Integración con SAP SuccessFactors (OData) - - [ ] Integración con BambooHR - - [ ] Sync automático de usuarios, departamentos, managers -- [ ] **LDAP/Active Directory**: - - [ ] Backend: Autenticación vía LDAP - - [ ] Backend: Sync de atributos de usuario desde AD - - [ ] Frontend: Configuración de LDAP en panel de administración - - [ ] Soporte para SSO híbrido (LDAP + OIDC) -- [ ] **Webhooks Salientes**: - - [ ] Backend: Sistema de webhooks configurables por evento - - [ ] Backend: Retry logic con exponential backoff - - [ ] Backend: Dashboard de entrega de webhooks (éxito/fallo) - - [ ] Frontend: UI para gestionar webhooks en Studio - - [ ] Frontend: Test de webhook desde UI -- [ ] **ERP Integrations**: - - [ ] Integración con sistemas de facturación - - [ ] Sync de inscripciones y pagos con ERP - - [ ] Reportes financieros para administradores - ---- - -## Fase 30: Reportes Avanzados y Business Intelligence 📊 -- [ ] **Reportes para Estudiantes**: - - [ ] Dashboard de analíticas personales (tiempo de estudio, skills, tendencias) - - [ ] Reporte de progreso semanal/mensual por email - - [ ] Exportación de historial de aprendizaje (PDF, Excel) -- [ ] **Reportes para Instructores**: - - [ ] Reportes automáticos programables (diario, semanal, mensual) - - [ ] Exportación en múltiples formatos (PDF, Excel, CSV) - - [ ] Reportes comparativos entre cohortes - - [ ] Análisis de efectividad de contenido (qué funciona mejor) -- [ ] **Reportes para Administradores**: - - [ ] Dashboard de uso de la plataforma (DAU, WAU, MAU) - - [ ] Análisis de ROI de cursos (costo vs completitud) - - [ ] Reportes de uso de IA (tokens, costo, efectividad) - - [ ] Exportación de datos completos de la plataforma -- [ ] **Business Intelligence**: - - [ ] Integración con herramientas BI externas (Metabase, Tableau) - - [ ] API de datos para dashboards externos - - [ ] Data warehouse schema optimizado para queries analíticos - ---- - -## Fase 31: Mejoras de Seguridad y GDPR 🛡️ -- [ ] **Two-Factor Authentication (2FA)**: - - [ ] Backend: Soporte para TOTP (Google Authenticator, Authy) - - [ ] Backend: Backup codes para recuperación - - [ ] Frontend: Setup de 2FA en perfil de usuario - - [ ] Frontend: Login con 2FA -- [ ] **GDPR Compliance**: - - [ ] Backend: Endpoint para exportar todos los datos de un usuario - - [ ] Backend: Endpoint para eliminar todos los datos de un usuario (right to be forgotten) - - [ ] Frontend: UI para solicitar exportación/eliminación - - [ ] Frontend: Consent management para cookies y tracking -- [ ] **Audit Logs Mejorados**: - - [ ] Backend: Exportación de audit logs (CSV, JSON) - - [ ] Backend: Alertas de actividad sospechosa - - [ ] Frontend: Filtros avanzados de audit logs - - [ ] Frontend: Dashboard de seguridad -- [ ] **Mejoras de Seguridad**: - - [ ] CSRF protection en todos los endpoints - - [ ] Content Security Policy headers - - [ ] Rate limiting por IP y por usuario - - [ ] IP allowlisting para admin endpoints - ---- - -**Estado Actual**: La plataforma cuenta con un motor de IA avanzado, gestión multi-tenant completa, tutoría inteligente con memoria histórica, una **interfaz 100% responsiva**, flujos de autenticación diferenciados, **sistema de foros de discusión funcional**, **gestión de anuncios segmentados**, **monetización integrada con Mercado Pago**, **Inscripción Masiva de Usuarios**, **Exportación Avanzada de Calificaciones**, **Librerías de Contenido reutilizables**, **Sistema de Rúbricas Avanzado**, **Secuencias de Aprendizaje**, **Gestión de Equipos Docentes**, **Vista Previa de Cursos**, **Dashboard de Progreso Estudiantil**, **Sistema de Marcadores**, **Biblioteca Global de Activos**, **Interoperabilidad LTI 1.3**, **Analíticas Predictivas**, **Integración de Jitsi**, **Portafolios con Perfiles Públicos**, **Landing Pages de Cursos (Marketing) automatizadas**, **Diagramas de Mermaid Dinámicos**, **Laboratorios de Código con Hints de IA**, y **Búsqueda Semántica con PGVector**. - -**Próximas Prioridades**: -1. **Finalización de Funcionalidades Pendientes**: Certificados, progreso real, notificaciones de foros, importación Excel, rate limiting. -2. **Integración de Email/SMTP**: Notificaciones por email, password reset, emails transaccionales. -3. **Accesibilidad Universal**: Auditoría y ajustes de contraste para cumplimiento WCAG 2.1. -4. **Búsqueda Global**: Search unificado en cursos, lecciones y contenidos. -5. **Integraciones Empresariales**: Conectividad con HRIS, LDAP/Active Directory, webhooks salientes. -6. **PWA y Offline**: Service workers, descarga de lecciones, sync offline. -7. **Seguridad**: 2FA, GDPR compliance, rate limiting re-habilitado. +1. Finalización de **Certificados y Progreso Real**. +2. Despliegue de **Infraestructura SMTP** para comunicación global. +3. Auditoría de **Accesibilidad Universal (WCAG)**. +4. Implementación de **IA de Moderación (Seguridad)**. diff --git a/services/cms-service/src/handlers.rs b/services/cms-service/src/handlers.rs index 65cce95..24dea76 100644 --- a/services/cms-service/src/handlers.rs +++ b/services/cms-service/src/handlers.rs @@ -2779,6 +2779,13 @@ pub async fn register( State(pool): State, Json(payload): Json, ) -> Result, (StatusCode, String)> { + if payload.email.trim().is_empty() || payload.password.trim().is_empty() { + return Err(( + StatusCode::BAD_REQUEST, + "El email y la contraseña son obligatorios".into(), + )); + } + let password_hash = hash(payload.password, DEFAULT_COST) .map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "Hashing failed".into()))?; diff --git a/services/cms-service/src/handlers_exercise_settings.rs b/services/cms-service/src/handlers_exercise_settings.rs index 8bc637b..ff0544d 100644 --- a/services/cms-service/src/handlers_exercise_settings.rs +++ b/services/cms-service/src/handlers_exercise_settings.rs @@ -98,7 +98,9 @@ async fn upsert_organization_exercise_settings( organization_id: Uuid, payload: &UpdateOrganizationExerciseSettingsPayload, ) -> Result { - sqlx::query_as::<_, OrganizationExerciseSettings>( + let mut tx = pool.begin().await?; + + let settings = sqlx::query_as::<_, OrganizationExerciseSettings>( r#" INSERT INTO organization_exercise_settings ( organization_id, @@ -144,8 +146,21 @@ async fn upsert_organization_exercise_settings( .bind(payload.mermaid_enabled) .bind(payload.code_lab_enabled) .bind(payload.certificates_enabled) - .fetch_one(pool) - .await + .fetch_one(&mut *tx) + .await?; + + // Sincronizar con la tabla organizations para que el LMS reciba el valor correcto al publicar + sqlx::query( + "UPDATE organizations SET certificates_enabled = $1, updated_at = NOW() WHERE id = $2" + ) + .bind(payload.certificates_enabled) + .bind(organization_id) + .execute(&mut *tx) + .await?; + + tx.commit().await?; + + Ok(settings) } pub async fn get_organization_exercise_settings( diff --git a/services/cms-service/src/handlers_sam.rs b/services/cms-service/src/handlers_sam.rs index c0d163b..dad7544 100644 --- a/services/cms-service/src/handlers_sam.rs +++ b/services/cms-service/src/handlers_sam.rs @@ -60,8 +60,8 @@ pub async fn sync_sam_students( State(pool): State, ) -> Result, (StatusCode, String)> { // Conectar a la base de datos externa de SAM - let sam_url = std::env::var("SAM_DATABASE_URL") - .map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "SAM_DATABASE_URL no configurada".to_string()))?; + let sam_url = std::env::var("SAM_DIAGNOSTICO_DATABASE_URL") + .map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "SAM_DIAGNOSTICO_DATABASE_URL no configurada".to_string()))?; let sam_pool = sqlx::PgPool::connect(&sam_url) .await @@ -191,8 +191,8 @@ pub async fn sync_sam_assignments( State(pool): State, ) -> Result, (StatusCode, String)> { // Conectar a la base de datos externa de SAM - let sam_url = std::env::var("SAM_DATABASE_URL") - .map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "SAM_DATABASE_URL no configurada".to_string()))?; + let sam_url = std::env::var("SAM_DIAGNOSTICO_DATABASE_URL") + .map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "SAM_DIAGNOSTICO_DATABASE_URL no configurada".to_string()))?; let sam_pool = sqlx::PgPool::connect(&sam_url) .await @@ -382,8 +382,8 @@ pub async fn sync_all_sam( let mut assignments_synced = 0; // Conectar a la base de datos externa de SAM - let sam_url = std::env::var("SAM_DATABASE_URL") - .map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "SAM_DATABASE_URL no configurada".to_string()))?; + let sam_url = std::env::var("SAM_DIAGNOSTICO_DATABASE_URL") + .map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "SAM_DIAGNOSTICO_DATABASE_URL no configurada".to_string()))?; let sam_pool = sqlx::PgPool::connect(&sam_url) .await diff --git a/services/cms-service/src/main.rs b/services/cms-service/src/main.rs index b0cf4e0..c7235b3 100644 --- a/services/cms-service/src/main.rs +++ b/services/cms-service/src/main.rs @@ -161,8 +161,16 @@ async fn main() { ]) .expose_headers([header::CONTENT_LENGTH, header::CONTENT_TYPE, header::CONTENT_RANGE, header::ACCEPT_RANGES]); - // Rate limiting: Deshabilitado temporalmente por problemas de compatibilidad con tower-governor - // Para habilitar en producción, configurar con GovernorLayer y ajustar los límites apropiadamente + use tower_governor::{GovernorConfigBuilder, GovernorLayer}; + use std::sync::Arc; + + let governor_conf = Arc::new( + GovernorConfigBuilder::default() + .per_second(5) // CMS usually has more complex operations, slightly lower limit + .burst_size(20) + .finish() + .unwrap(), + ); // Rutas protegidas que requieren autenticación y contexto de organización let protected_routes = Router::new() @@ -500,7 +508,10 @@ async fn main() { ) .route_layer(middleware::from_fn( common::middleware::org_extractor_middleware, - )); + )) + .route_layer(GovernorLayer { + config: governor_conf, + }); let api_routes = Router::new() .route( diff --git a/services/lms-service/migrations/20260414000003_trigger_update_enrollment_progress.sql b/services/lms-service/migrations/20260414000003_trigger_update_enrollment_progress.sql new file mode 100644 index 0000000..eb9d766 --- /dev/null +++ b/services/lms-service/migrations/20260414000003_trigger_update_enrollment_progress.sql @@ -0,0 +1,59 @@ +-- Migration: Automatic Enrollment Progress Update via Trigger +-- Created: 2026-04-14 + +-- 1. Function to recalculate course progress for a student +CREATE OR REPLACE FUNCTION fn_recalculate_enrollment_progress() +RETURNS TRIGGER AS $$ +DECLARE + v_total_lessons INTEGER; + v_completed_lessons INTEGER; + v_progress FLOAT4; +BEGIN + -- Get total number of lessons in the course + -- We use the course_id from the new grade entry + SELECT COUNT(*) INTO v_total_lessons + FROM lessons + WHERE module_id IN (SELECT id FROM modules WHERE course_id = NEW.course_id); + + -- Get number of distinct lessons with a grade for this user in this course + SELECT COUNT(DISTINCT lesson_id) INTO v_completed_lessons + FROM user_grades + WHERE user_id = NEW.user_id AND course_id = NEW.course_id; + + -- Calculate progress percentage + IF v_total_lessons > 0 THEN + v_progress := (v_completed_lessons::FLOAT4 / v_total_lessons::FLOAT4) * 100; + ELSE + v_progress := 0; + END IF; + + -- Update the enrollments table for this specific user and course + UPDATE enrollments + SET progress = v_progress + WHERE user_id = NEW.user_id AND course_id = NEW.course_id; + + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +-- 2. Trigger to execute the function after any activity is graded +DROP TRIGGER IF EXISTS tr_update_enrollment_progress ON user_grades; +CREATE TRIGGER tr_update_enrollment_progress +AFTER INSERT OR UPDATE ON user_grades +FOR EACH ROW +EXECUTE FUNCTION fn_recalculate_enrollment_progress(); + +-- 3. Initial sync: Update progress for all existing enrollments +UPDATE enrollments e +SET progress = COALESCE( + ( + SELECT (COUNT(DISTINCT ug.lesson_id)::FLOAT4 / NULLIF(( + SELECT COUNT(*) + FROM lessons l + WHERE l.module_id IN (SELECT id FROM modules m WHERE m.course_id = e.course_id) + ), 0)::FLOAT4) * 100 + FROM user_grades ug + WHERE ug.user_id = e.user_id AND ug.course_id = e.course_id + ), + 0 +); diff --git a/services/lms-service/src/main.rs b/services/lms-service/src/main.rs index b09fb6b..266967f 100644 --- a/services/lms-service/src/main.rs +++ b/services/lms-service/src/main.rs @@ -119,15 +119,16 @@ async fn main() { ]) .expose_headers([header::CONTENT_LENGTH, header::CONTENT_TYPE]); - // Rate limiter DESHABILITADO debido a problemas de compatibilidad con el middleware de autenticación - // Ver QWEN.md para más detalles - // let governor_conf = Arc::new( - // GovernorConfigBuilder::default() - // .per_second(10) - // .burst_size(50) - // .finish() - // .unwrap(), - // ); + use tower_governor::{GovernorConfigBuilder, GovernorLayer}; + use std::sync::Arc; + + let governor_conf = Arc::new( + GovernorConfigBuilder::default() + .per_second(10) + .burst_size(50) + .finish() + .unwrap(), + ); // Rate limiter solo para rutas protegidas (después del middleware de autenticación) let protected_routes = Router::new() @@ -343,7 +344,10 @@ async fn main() { ) .route_layer(middleware::from_fn( common::middleware::org_extractor_middleware, - )); + )) + .route_layer(GovernorLayer { + config: governor_conf, + }); let public_routes = Router::new() .route("/api-docs/openapi.json", get(|| async { diff --git a/shared/common/src/models.rs b/shared/common/src/models.rs index 00af116..767745d 100644 --- a/shared/common/src/models.rs +++ b/shared/common/src/models.rs @@ -188,6 +188,7 @@ pub struct Enrollment { pub organization_id: Uuid, pub course_id: Uuid, pub external_id: Option, // idDetalleContrato del sistema externo + pub progress: f32, pub enrolled_at: DateTime, } diff --git a/web/experience/src/app/courses/[id]/page.tsx b/web/experience/src/app/courses/[id]/page.tsx index 5385741..e5f5de6 100644 --- a/web/experience/src/app/courses/[id]/page.tsx +++ b/web/experience/src/app/courses/[id]/page.tsx @@ -9,6 +9,8 @@ import { useAuth } from "@/context/AuthContext"; import DiscussionBoard from "@/components/DiscussionBoard"; import { AnnouncementsList } from "@/components/AnnouncementsList"; import AboutCourse from "@/components/AboutCourse"; +import CertificateModal from "@/components/CertificateModal"; +import { CertificateResponse } from "@/lib/api"; export default function CourseOutlinePage({ params }: { params: { id: string } }) { const { user } = useAuth(); @@ -22,6 +24,11 @@ export default function CourseOutlinePage({ params }: { params: { id: string } } const [instructors, setInstructors] = useState([]); const [meetings, setMeetings] = useState([]); const [activeTab, setActiveTab] = useState<'outline' | 'about'>('outline'); + const [progress, setProgress] = useState(0); + const [certificate, setCertificate] = useState(null); + const [showCertificateModal, setShowCertificateModal] = useState(false); + const [loadingCertificate, setLoadingCertificate] = useState(false); + const [orgSettings, setOrgSettings] = useState(null); useEffect(() => { const fetchData = async () => { @@ -37,11 +44,15 @@ export default function CourseOutlinePage({ params }: { params: { id: string } } setUserGrades(grades); const enrollmentData = await lmsApi.getEnrollments(user.id); - const enrolled = enrollmentData.some(e => e.course_id === params.id); - + const enrollment = enrollmentData.find(e => e.course_id === params.id); + // Allow preview token to override enrollment status const isPreview = typeof window !== 'undefined' && !!sessionStorage.getItem('preview_token'); - setIsEnrolled(enrolled || isPreview); + setIsEnrolled(!!enrollment || isPreview); + + if (enrollment) { + setProgress(enrollment.progress * 100); + } } else { // Even if not logged in, if there's a preview token, consider "enrolled" for UI const isPreview = typeof window !== 'undefined' && !!sessionStorage.getItem('preview_token'); @@ -65,6 +76,11 @@ export default function CourseOutlinePage({ params }: { params: { id: string } } lmsApi.getMeetings(params.id) .then(setMeetings) .catch(console.error); + + // Load organization settings (branding includes the certificates_enabled flag) + lmsApi.getBranding() + .then(res => setOrgSettings(res.organization)) + .catch(console.error); }, [params.id, user]); const handleEnrollOrBuy = async () => { @@ -120,6 +136,38 @@ export default function CourseOutlinePage({ params }: { params: { id: string } } }); }; + const handleViewCertificate = async () => { + if (certificate) { + setShowCertificateModal(true); + return; + } + + setLoadingCertificate(true); + try { + const data = await lmsApi.getCertificate(params.id); + setCertificate(data); + setShowCertificateModal(true); + } catch (error: any) { + console.error("No se pudo obtener el certificado", error); + if (error.status === 404 || error.status === 403) { + // Try to issue it if completed but not issued + if (progress >= 100) { + try { + const issued = await lmsApi.issueCertificate(params.id); + setCertificate(issued); + setShowCertificateModal(true); + } catch (issueError) { + alert("No se pudo generar el certificado. Asegúrate de haber aprobado todas las lecciones."); + } + } else { + alert("Aún no has completado este curso."); + } + } + } finally { + setLoadingCertificate(false); + } + }; + const getStatusIcon = (lessonId: string, isGraded: boolean, allowRetry: boolean) => { if (isLessonLocked(lessonId)) { return ; @@ -274,6 +322,17 @@ export default function CourseOutlinePage({ params }: { params: { id: string } } 📊 Progreso + + {isEnrolled && orgSettings?.certificates_enabled !== false && progress >= 100 && ( + + )} @@ -485,6 +544,13 @@ export default function CourseOutlinePage({ params }: { params: { id: string } } )} + + {showCertificateModal && certificate && ( + setShowCertificateModal(false)} + /> + )} ); } diff --git a/web/experience/src/app/my-learning/page.tsx b/web/experience/src/app/my-learning/page.tsx index 12490a3..e3a0c51 100644 --- a/web/experience/src/app/my-learning/page.tsx +++ b/web/experience/src/app/my-learning/page.tsx @@ -40,9 +40,7 @@ export default function MyLearningPage() { try { const { course, modules } = await lmsApi.getCourseOutline(enrollment.course_id); - // TODO: Implement actual progress tracking - // For now, show 0% progress for all courses - const progress = 0; + const progress = enrollment.progress || 0; enrichedEnrollments.push({ course: { ...course, modules }, diff --git a/web/experience/src/components/CertificateModal.tsx b/web/experience/src/components/CertificateModal.tsx new file mode 100644 index 0000000..72b87af --- /dev/null +++ b/web/experience/src/components/CertificateModal.tsx @@ -0,0 +1,98 @@ +"use client"; + +import { X, Printer, Download, Award, ShieldCheck } from "lucide-react"; +import { CertificateResponse } from "@/lib/api"; + +interface CertificateModalProps { + certificate: CertificateResponse; + onClose: () => void; +} + +export default function CertificateModal({ certificate, onClose }: CertificateModalProps) { + const handlePrint = () => { + window.print(); + }; + + return ( +
+
+ + {/* Header / Toolbar */} +
+
+
+ +
+
+

Certificado Oficial

+

Emitido el {new Date(certificate.issued_at).toLocaleDateString()}

+
+
+ +
+ + +
+
+ + {/* Certificate Content Wrapper */} +
+
+ {/* + We inject the HTML directly. + Note: The backend must sanitize this OR we trust our own generated template. + */} +
+
+
+ + {/* Footer Info */} +
+
+ + Este certificado es auténtico y verificable +
+
+ Código: {certificate.verification_code} +
+
+ + +
+
+ ); +} diff --git a/web/experience/src/lib/api.ts b/web/experience/src/lib/api.ts index fd5ff56..a1f7350 100644 --- a/web/experience/src/lib/api.ts +++ b/web/experience/src/lib/api.ts @@ -142,6 +142,30 @@ export interface PaymentPreferenceResponse { init_point: string; } +export interface CertificateResponse { + id: string; + user_id: string; + course_id: string; + course_title: string; + student_name: string; + certificate_html: string; + issued_at: string; + verification_code: string; + metadata: any; +} + +export interface CertificateResponse { + id: string; + user_id: string; + course_id: string; + course_title: string; + student_name: string; + certificate_html: string; + issued_at: string; + verification_code: string; + metadata: any; +} + export interface QuizQuestion { id: string; question: string; @@ -371,6 +395,7 @@ export interface Enrollment { id: string; user_id: string; course_id: string; + progress: number; enrolled_at: string; } @@ -862,5 +887,19 @@ export const lmsApi = { async getMyBadges(): Promise { return apiFetch(`/my/badges`, {}, false); + }, + + // Certificates + async getCertificate(courseId: string): Promise { + return apiFetch(`/courses/${courseId}/certificate`); + }, + async issueCertificate(courseId: string, forceReissue = false): Promise { + return apiFetch(`/courses/${courseId}/certificate/issue`, { + method: 'POST', + body: JSON.stringify({ force_reissue: forceReissue }) + }); + }, + async verifyCertificate(code: string): Promise { + return apiFetch(`/certificates/verify/${code}`); } }; diff --git a/web/studio/src/app/courses/[id]/settings/IntegrationsSection.tsx b/web/studio/src/app/courses/[id]/settings/IntegrationsSection.tsx new file mode 100644 index 0000000..f6e1384 --- /dev/null +++ b/web/studio/src/app/courses/[id]/settings/IntegrationsSection.tsx @@ -0,0 +1,154 @@ +"use client"; + +import React, { useState } from "react"; +import { cmsApi } from "@/lib/api"; +import { RefreshCw, Database, Users, CheckCircle2, AlertCircle, Loader2 } from "lucide-react"; + +interface IntegrationsSectionProps { + courseId: string; +} + +export default function IntegrationsSection({ courseId }: IntegrationsSectionProps) { + const [syncingAll, setSyncingAll] = useState(false); + const [syncingStudents, setSyncingStudents] = useState(false); + const [syncingAssignments, setSyncingAssignments] = useState(false); + const [status, setStatus] = useState<{ type: 'success' | 'error', message: string } | null>(null); + + const handleSyncAll = async () => { + setSyncingAll(true); + setStatus(null); + try { + const result = await cmsApi.syncSamAll(); + setStatus({ + type: 'success', + message: `Sincronización completa finalizada. Estudiantes: ${result.students_synced}, Asignaciones: ${result.assignments_synced}` + }); + } catch (err: any) { + setStatus({ type: 'error', message: err.message || "Error al sincronizar con SAM" }); + } finally { + setSyncingAll(false); + } + }; + + const handleSyncStudents = async () => { + setSyncingStudents(true); + setStatus(null); + try { + const result = await cmsApi.syncSamStudents(); + setStatus({ + type: 'success', + message: `Estudiantes sincronizados: ${result.students_synced}` + }); + } catch (err: any) { + setStatus({ type: 'error', message: err.message || "Error al sincronizar estudiantes" }); + } finally { + setSyncingStudents(false); + } + }; + + const handleSyncAssignments = async () => { + setSyncingAssignments(true); + setStatus(null); + try { + const result = await cmsApi.syncSamAssignments(); + setStatus({ + type: 'success', + message: `Asignaciones sincronizadas: ${result.assignments_synced}` + }); + } catch (err: any) { + setStatus({ type: 'error', message: err.message || "Error al sincronizar asignaciones" }); + } finally { + setSyncingAssignments(false); + } + }; + + return ( +
+
+
+ +
+
+

Integraciones y Sincronización

+

Gestiona la conexión con sistemas externos (SAM y MySQL Legacy)

+
+
+ +
+ {/* SAM Integration Card */} +
+
+ +

SAM (Sistema Académico)

+
+ +

+ Sincroniza la base de datos de estudiantes y las inscripciones a cursos desde el sistema SAM v3. +

+ +
+ + +
+ + +
+
+
+ + {/* MySQL Legacy Sync Card */} +
+
+ +

MySQL Legacy Sync

+
+ +

+ Importación manual de contenidos y estructuras de cursos desde el sistema antiguo. + ⚠️ Use con precaución: puede duplicar contenidos. +

+ + +
+
+ + {status && ( +
+ {status.type === 'success' ? : } +

{status.message}

+
+ )} +
+ ); +} diff --git a/web/studio/src/app/courses/[id]/settings/page.tsx b/web/studio/src/app/courses/[id]/settings/page.tsx index b1a039b..1f6e066 100644 --- a/web/studio/src/app/courses/[id]/settings/page.tsx +++ b/web/studio/src/app/courses/[id]/settings/page.tsx @@ -22,6 +22,7 @@ const DEFAULT_CERTIFICATE_TEMPLATE = ` import CourseEditorLayout from "@/components/CourseEditorLayout"; import TeamManagementSection from "./TeamManagementSection"; +import IntegrationsSection from "./IntegrationsSection"; export default function CourseSettingsPage() { const { id } = useParams() as { id: string }; @@ -147,6 +148,7 @@ export default function CourseSettingsPage() { >
+ {/* Passing Percentage Section */}
diff --git a/web/studio/src/components/ExerciseFeatureSettings.tsx b/web/studio/src/components/ExerciseFeatureSettings.tsx index 362ccb2..5c04b88 100644 --- a/web/studio/src/components/ExerciseFeatureSettings.tsx +++ b/web/studio/src/components/ExerciseFeatureSettings.tsx @@ -43,6 +43,11 @@ const featureCards: Array<{ title: "Code Lab", description: "Permite laboratorios de código generados o editados manualmente.", }, + { + key: "certificates_enabled", + title: "Generación de Certificados", + description: "Habilita la emisión automática de certificados al completar cursos.", + }, ]; const defaultSettings: OrganizationExerciseSettings = { @@ -54,6 +59,7 @@ const defaultSettings: OrganizationExerciseSettings = { role_playing_enabled: true, mermaid_enabled: false, code_lab_enabled: true, + certificates_enabled: true, }; export default function ExerciseFeatureSettings() { @@ -94,6 +100,7 @@ export default function ExerciseFeatureSettings() { role_playing_enabled: settings.role_playing_enabled, mermaid_enabled: settings.mermaid_enabled, code_lab_enabled: settings.code_lab_enabled, + certificates_enabled: settings.certificates_enabled, }; const updated = await cmsApi.updateOrganizationExerciseSettings(payload); setSettings(updated); diff --git a/web/studio/src/lib/api.ts b/web/studio/src/lib/api.ts index 5793f1a..3bfe78a 100644 --- a/web/studio/src/lib/api.ts +++ b/web/studio/src/lib/api.ts @@ -278,6 +278,7 @@ export interface OrganizationExerciseSettings { role_playing_enabled: boolean; mermaid_enabled: boolean; code_lab_enabled: boolean; + certificates_enabled: boolean; } export interface User { @@ -433,6 +434,12 @@ export interface GlobalAiUsageResponse { student_chat_usage: StudentChatUsage[]; } +export interface SamSyncResponse { + students_synced: number; + assignments_synced: number; + errors: string[]; +} + // ==================== Grading ==================== export interface GradingCategory { @@ -899,6 +906,11 @@ export const cmsApi = { getCourseTeam: (courseId: string): Promise => apiFetch(`/courses/${courseId}/team`), addTeamMember: (courseId: string, email: string, role: string): Promise => apiFetch(`/courses/${courseId}/team`, { method: 'POST', body: JSON.stringify({ email, role }) }), removeTeamMember: (courseId: string, userId: string): Promise => apiFetch(`/courses/${courseId}/team/${userId}`, { method: 'DELETE' }), + + // SAM Integration + syncSamStudents: (): Promise => apiFetch('/sam/sync-students', { method: 'POST' }), + syncSamAssignments: (): Promise => apiFetch('/sam/sync-assignments', { method: 'POST' }), + syncSamAll: (): Promise => apiFetch('/sam/sync-all', { method: 'POST' }), getUsers: (): Promise => apiFetch('/users'), // Modules & Lessons