# 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=trading pero Docker usa trading_trading/trading_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=trading_platform, DB_PORT=5433"
          - "Credenciales: trading/trading_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"
