# TRACEABILITY.yml - OQI-002 Módulo Educativo # Mapeo de requerimientos a implementación version: "1.1.0" epic: OQI-002 name: "Módulo Educativo - Cursos de Trading" updated: "2026-01-04" status: in_progress # Resumen de trazabilidad summary: total_requirements: 6 total_specs: 6 total_user_stories: 8 total_files_to_implement: 35 test_coverage: "TBD" story_points: 45 # Mapeo de Requerimientos Funcionales requirements: RF-EDU-001: name: "Catálogo de Cursos" status: pending specs: - ET-EDU-001 - ET-EDU-002 - ET-EDU-003 user_stories: - US-EDU-001 - US-EDU-002 implementation: backend: - path: apps/backend/src/modules/education/services/course.service.ts description: "Servicio de gestión de cursos" methods: - getCourses - getCourseBySlug - getCourseById - searchCourses - getCoursesbyCategory - path: apps/backend/src/modules/education/controllers/education.controller.ts methods: - listCourses - getCourse - path: apps/backend/src/modules/education/education.routes.ts routes: - "GET /education/courses" - "GET /education/courses/:slug" - "GET /education/categories" frontend: - path: apps/frontend/src/modules/education/pages/Courses.tsx description: "Página de catálogo de cursos" - path: apps/frontend/src/modules/education/pages/CourseDetail.tsx description: "Página de detalle de curso" - path: apps/frontend/src/modules/education/components/CourseCard.tsx description: "Tarjeta de curso" - path: apps/frontend/src/modules/education/components/CourseFilters.tsx description: "Filtros de búsqueda" database: - path: apps/database/schemas/02_education_schema.sql tables: - courses - course_categories - course_tags enums: - course_level_enum - course_status_enum tests: - path: apps/backend/tests/education/course.service.test.ts status: pending RF-EDU-002: name: "Sistema de Lecciones" status: implemented implementation_notes: - date: "2026-01-04" changes: - "Creado Lesson.tsx para visualización de lecciones con video player" - "Soporte para contenido: video, article, text, quiz, exercise" - "Navegación entre lecciones con sidebar de progreso" - "Integrado en App.tsx con rutas /education/courses/:courseSlug/lesson/:lessonId" specs: - ET-EDU-001 - ET-EDU-004 user_stories: - US-EDU-003 - US-EDU-004 implementation: backend: - path: apps/backend/src/modules/education/services/lesson.service.ts description: "Servicio de lecciones" methods: - getLessonsByCourse - getLessonById - getNextLesson - getPreviousLesson - path: apps/backend/src/modules/education/controllers/education.controller.ts methods: - getLessons - getLesson - path: apps/backend/src/modules/education/education.routes.ts routes: - "GET /education/courses/:id/lessons" - "GET /education/lessons/:id" frontend: - path: apps/frontend/src/modules/education/pages/LessonViewer.tsx description: "Visor de lecciones" - path: apps/frontend/src/modules/education/components/LessonList.tsx description: "Lista de lecciones del curso" - path: apps/frontend/src/modules/education/components/LessonNavigation.tsx description: "Navegación entre lecciones" - path: apps/frontend/src/modules/education/components/VideoPlayer.tsx description: "Reproductor de video" database: - path: apps/database/schemas/02_education_schema.sql tables: - lessons - lesson_resources enums: - lesson_type_enum - resource_type_enum tests: - path: apps/backend/tests/education/lesson.service.test.ts status: pending RF-EDU-003: name: "Tracking de Progreso" status: pending specs: - ET-EDU-001 - ET-EDU-003 user_stories: - US-EDU-005 - US-EDU-007 implementation: backend: - path: apps/backend/src/modules/education/services/progress.service.ts description: "Servicio de progreso" methods: - getProgress - updateLessonProgress - completeCourse - getEnrolledCourses - calculateCourseProgress - path: apps/backend/src/modules/education/controllers/education.controller.ts methods: - getMyProgress - markLessonComplete - enrollInCourse - path: apps/backend/src/modules/education/education.routes.ts routes: - "POST /education/courses/:id/enroll" - "GET /education/my-courses" - "POST /education/lessons/:id/progress" - "GET /education/courses/:id/progress" frontend: - path: apps/frontend/src/modules/education/pages/MyLearning.tsx description: "Página de mis cursos" - path: apps/frontend/src/modules/education/components/ProgressBar.tsx description: "Barra de progreso" - path: apps/frontend/src/modules/education/components/ProgressSummary.tsx description: "Resumen de progreso" database: - path: apps/database/schemas/02_education_schema.sql tables: - enrollments - lesson_progress tests: - path: apps/backend/tests/education/progress.service.test.ts status: pending RF-EDU-004: name: "Sistema de Quizzes" status: implemented implementation_notes: - date: "2026-01-04" changes: - "Creado Quiz.tsx con estados: intro, in_progress, submitted" - "Timer de cuenta regresiva para quizzes con límite de tiempo" - "Soporte para tipos: multiple_choice, true_false, multi_select" - "Sistema de puntos y XP integrado" - "Ruta: /education/courses/:courseSlug/lesson/:lessonId/quiz" specs: - ET-EDU-005 user_stories: - US-EDU-006 implementation: backend: - path: apps/backend/src/modules/education/services/quiz.service.ts description: "Servicio de quizzes" methods: - getQuiz - submitQuiz - getQuizResults - calculateScore - getQuizAttempts - path: apps/backend/src/modules/education/controllers/education.controller.ts methods: - getQuiz - submitQuizAnswers - getQuizResults - path: apps/backend/src/modules/education/education.routes.ts routes: - "GET /education/quizzes/:id" - "POST /education/quizzes/:id/submit" - "GET /education/quizzes/:id/results" frontend: - path: apps/frontend/src/modules/education/pages/QuizPage.tsx description: "Página de quiz" - path: apps/frontend/src/modules/education/components/QuizForm.tsx description: "Formulario de quiz" - path: apps/frontend/src/modules/education/components/QuizResults.tsx description: "Resultados de quiz" - path: apps/frontend/src/modules/education/components/QuizQuestion.tsx description: "Componente de pregunta" database: - path: apps/database/schemas/02_education_schema.sql tables: - quizzes - quiz_questions - quiz_answers - quiz_attempts enums: - question_type_enum tests: - path: apps/backend/tests/education/quiz.service.test.ts status: pending RF-EDU-005: name: "Certificados" status: pending specs: - ET-EDU-003 user_stories: - US-EDU-008 implementation: backend: - path: apps/backend/src/modules/education/services/certificate.service.ts description: "Servicio de certificados" methods: - generateCertificate - getCertificates - verifyCertificate - downloadCertificate - path: apps/backend/src/modules/education/controllers/education.controller.ts methods: - getMyCertificates - downloadCertificate - verifyCertificate - path: apps/backend/src/modules/education/education.routes.ts routes: - "GET /education/certificates" - "GET /education/certificates/:id/download" - "GET /education/certificates/verify/:code" frontend: - path: apps/frontend/src/modules/education/pages/Certificates.tsx description: "Página de certificados" - path: apps/frontend/src/modules/education/components/CertificateCard.tsx description: "Tarjeta de certificado" - path: apps/frontend/src/modules/education/components/CertificateModal.tsx description: "Modal de certificado" database: - path: apps/database/schemas/02_education_schema.sql tables: - certificates tests: - path: apps/backend/tests/education/certificate.service.test.ts status: pending RF-EDU-006: name: "Gamificación" status: pending specs: - ET-EDU-006 user_stories: [] implementation: backend: - path: apps/backend/src/modules/education/services/gamification.service.ts description: "Servicio de gamificación" methods: - awardPoints - getLeaderboard - getBadges - checkAchievements - getStreak - path: apps/backend/src/modules/education/controllers/education.controller.ts methods: - getLeaderboard - getMyAchievements - getMyBadges - path: apps/backend/src/modules/education/education.routes.ts routes: - "GET /education/leaderboard" - "GET /education/achievements" - "GET /education/badges" frontend: - path: apps/frontend/src/modules/education/components/Leaderboard.tsx description: "Tabla de clasificación" - path: apps/frontend/src/modules/education/components/AchievementBadge.tsx description: "Badge de logro" - path: apps/frontend/src/modules/education/components/StreakCounter.tsx description: "Contador de racha" database: - path: apps/database/schemas/02_education_schema.sql tables: - achievements - user_achievements - badges - user_badges - learning_streaks tests: - path: apps/backend/tests/education/gamification.service.test.ts status: pending # Mapeo de archivos de configuración config_files: backend: - path: apps/backend/src/modules/education/education.module.ts description: "Módulo de educación" - path: apps/backend/src/modules/education/validators/education.validators.ts description: "Validadores Zod" - path: apps/backend/src/modules/education/types/education.types.ts description: "Tipos TypeScript" frontend: - path: apps/frontend/src/modules/education/stores/education.store.ts description: "Store de educación Zustand" - path: apps/frontend/src/modules/education/hooks/useEducation.ts description: "Hook principal de educación" - path: apps/frontend/src/modules/education/services/education.api.ts description: "Cliente API de educación" # Dependencias externas external_dependencies: npm_backend: - name: pdfkit version: "^0.14.0" usage: "Generación de certificados PDF" - name: qrcode version: "^1.5.3" usage: "QR en certificados" - name: sharp version: "^0.33.0" usage: "Procesamiento de imágenes" npm_frontend: - name: react-player version: "^2.13.0" usage: "Reproductor de video" - name: "@tanstack/react-query" version: "^5.0.0" usage: "Data fetching" services: - name: Cloudflare Stream purpose: "Video hosting y streaming" alternative: "Vimeo OTT" - name: AWS S3 purpose: "Almacenamiento de recursos" # APIs de terceros third_party_apis: - name: Cloudflare Stream API docs: https://developers.cloudflare.com/stream/ usage: - Upload de videos - Signed URLs - Analytics de reproducciones - name: AWS S3 docs: https://docs.aws.amazon.com/s3/ usage: - Almacenamiento de recursos - Certificados PDF # Endpoints API api_endpoints: base_path: /api/v1/education endpoints: # Cursos - method: GET path: /courses requirement: RF-EDU-001 auth: false description: "Listar catálogo de cursos" - method: GET path: /courses/:slug requirement: RF-EDU-001 auth: false description: "Detalle de curso por slug" - method: GET path: /categories requirement: RF-EDU-001 auth: false description: "Listar categorías" # Inscripción - method: POST path: /courses/:id/enroll requirement: RF-EDU-003 auth: true description: "Inscribirse a un curso" - method: GET path: /my-courses requirement: RF-EDU-003 auth: true description: "Mis cursos inscritos" # Lecciones - method: GET path: /courses/:id/lessons requirement: RF-EDU-002 auth: true description: "Lecciones de un curso" - method: GET path: /lessons/:id requirement: RF-EDU-002 auth: true description: "Detalle de lección" - method: POST path: /lessons/:id/progress requirement: RF-EDU-003 auth: true description: "Actualizar progreso" # Quizzes - method: GET path: /quizzes/:id requirement: RF-EDU-004 auth: true description: "Obtener quiz" - method: POST path: /quizzes/:id/submit requirement: RF-EDU-004 auth: true description: "Enviar respuestas" - method: GET path: /quizzes/:id/results requirement: RF-EDU-004 auth: true description: "Ver resultados" # Certificados - method: GET path: /certificates requirement: RF-EDU-005 auth: true description: "Mis certificados" - method: GET path: /certificates/:id/download requirement: RF-EDU-005 auth: true description: "Descargar certificado" - method: GET path: /certificates/verify/:code requirement: RF-EDU-005 auth: false description: "Verificar certificado" # Gamificación - method: GET path: /leaderboard requirement: RF-EDU-006 auth: true description: "Ver clasificación" - method: GET path: /achievements requirement: RF-EDU-006 auth: true description: "Mis logros" # Dependencias de épicas dependencies: blocks: [] blocked_by: - epic: OQI-001 reason: "Requiere autenticación de usuarios" - epic: OQI-005 reason: "Compra de cursos requiere sistema de pagos" type: partial # Notas y decisiones notes: - "Videos almacenados en Cloudflare Stream con URLs firmadas" - "Progreso guardado automáticamente cada 30 segundos" - "Certificados con QR de verificación único" - "Quizzes con intentos ilimitados pero score máximo registrado" - "Sistema de puntos: 10 por lección, 50 por quiz aprobado, 100 por certificado" # Implementación 2026-01-04 recent_changes: - date: "2026-01-04" developer: "Claude Code" session: 1 changes: - type: frontend files: - apps/frontend/src/modules/education/pages/Lesson.tsx - apps/frontend/src/modules/education/pages/Quiz.tsx - apps/frontend/src/App.tsx (rutas añadidas) - apps/frontend/src/types/education.types.ts (props añadidas) description: "Páginas de lección y quiz implementadas" - type: database files: - apps/database/seeds/prod/education/01-education-courses.sql description: "Seeds de cursos ICT/IPDA con 1 curso, 7 módulos, 28 lecciones, 5 quizzes" issues_found: - "DDL loader no carga 00-extensions.sql ni 01-enums.sql correctamente" - "Script usa DB_NAME=orbiquant pero Docker usa orbiquant_trading/orbiquant_platform" - date: "2026-01-04" developer: "Claude Code" session: 2 changes: - type: database_scripts files: - apps/database/scripts/create-database.sh description: "Correcciones críticas al DDL loader" fixes: - "Agregada carga de 00-extensions.sql antes de enums" - "Búsqueda de enums en 00-enums.sql y 01-enums.sql" - "Defaults unificados: DB_NAME=orbiquantia_platform, DB_PORT=5433" - "Credenciales: orbiquantia/orbiquantia_dev_2025" - type: database_ddl files: - apps/database/ddl/schemas/auth/tables/01-users.sql - apps/database/ddl/schemas/auth/tables/99-deferred-constraints.sql (nuevo) description: "Resolución de dependencia circular en auth.users" fixes: - "Removido constraint password_or_oauth (PostgreSQL no soporta subqueries en CHECK)" - "Documentado en 99-deferred-constraints.sql con alternativa de trigger" - type: database_seeds files: - apps/database/seeds/prod/education/01-education-courses.sql description: "Correcciones de columnas en seeds de educación" fixes: - "Lecciones: removido duration_minutes (28 filas corregidas)" - "Quizzes: passing_score → passing_score_percentage" - "Questions: single_choice → multiple_choice" - "Questions: correct_answers removido (respuesta en options.isCorrect)" - "Questions: formato options actualizado a [{id,text,isCorrect}]" validation: status: passed database_recreated: true counts: categories: 5 courses: 1 modules: 7 lessons: 28 quizzes: 5 questions: 14 command: "DB_PORT=5433 ./drop-and-recreate-database.sh"