workspace/projects/gamilit/orchestration/analisis-teacher-portal-2025-12-18/50-GAP-CRITICO-RESPONSES-PAGE.md
rckrdmrd 5704222b85 chore: Migrar archivos desde workspace-old (2025-12-19)
Database:
- Actualizar backups de producción (usuarios, perfiles, stats)

Orchestration:
- Añadir análisis errores producción 2025-12-18
- Actualizar análisis teacher portal
- Añadir reportes de migración y producción

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 00:15:05 -06:00

13 KiB
Raw Blame History

GAP CRITICO: Responses Page No Muestra Datos Reales

Fecha: 18 Diciembre 2025 Analista: Requirements-Analyst Prioridad: P0 - CRITICO (Bloquea funcionalidad core) Estado: CORREGIDO - Implementación completada


CORRECCION APLICADA

Fecha de corrección: 19 Diciembre 2025

Archivos Modificados

Archivo Cambio
apps/backend/src/modules/teacher/dto/exercise-responses.dto.ts Agregados enums ResponseSource, SubmissionStatus y campos source, status, feedback, requires_manual_grading
apps/backend/src/modules/teacher/services/exercise-responses.service.ts Método getAttempts() ahora usa UNION de ambas tablas; getAttemptDetail() busca en ambas tablas

Cambios Clave

  1. UNION Query: El método getAttempts() ahora consulta:

    • progress_tracking.exercise_attempts (ejercicios autocorregibles)
    • progress_tracking.exercise_submissions (ejercicios de revisión manual)
  2. Nuevo campo source: Indica de qué tabla proviene cada registro (attempt o submission)

  3. Filtro por status: Excluye automáticamente submissions con status draft

  4. getAttemptDetail mejorado: Busca primero en exercise_attempts, si no encuentra busca en exercise_submissions


RESUMEN EJECUTIVO

El Teacher Portal tiene un gap critico: la pagina de Responses (/teacher/responses) NO muestra las respuestas de los estudiantes porque consulta la tabla incorrecta.

Aspecto Estado Actual Estado Esperado
Tabla consultada exercise_attempts exercise_submissions + exercise_attempts
Datos visibles 0 o datos antiguos Todas las respuestas
Funcionalidad ROTA FUNCIONAL

ANALISIS DEL PROBLEMA

Arquitectura Dual de Tablas

El sistema GAMILIT tiene dos tablas para almacenar respuestas de ejercicios:

┌─────────────────────────────────────────────────────────────────────┐
│                    FLUJO ACTUAL (ROTO)                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ESTUDIANTE                         TEACHER PORTAL                  │
│  ┌─────────────────┐               ┌─────────────────┐             │
│  │ Completa        │               │ Responses Page  │             │
│  │ Ejercicio       │               │ /teacher/       │             │
│  │                 │               │ responses       │             │
│  └────────┬────────┘               └────────┬────────┘             │
│           │                                 │                       │
│           ▼                                 ▼                       │
│  ┌─────────────────┐               ┌─────────────────┐             │
│  │ POST /progress/ │               │ GET /teacher/   │             │
│  │ submissions/    │               │ attempts        │             │
│  │ submit          │               │                 │             │
│  └────────┬────────┘               └────────┬────────┘             │
│           │                                 │                       │
│           ▼                                 ▼                       │
│  ┌─────────────────┐               ┌─────────────────┐             │
│  │ exercise_       │              │ exercise_       │             │
│  │ submissions     │─────╳─────────│ attempts        │             │
│  │ (AQUI ESTAN     │              │ (AQUI BUSCA)    │             │
│  │  LOS DATOS!)    │               │                 │             │
│  └─────────────────┘               └─────────────────┘             │
│                                                                     │
│  ❌ NO HAY CONEXION - EL TEACHER NO VE LAS RESPUESTAS              │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Tabla 1: exercise_submissions

Proposito: Ejercicios que requieren revision manual (Modulos 4 y 5)

  • Archivo DDL: apps/database/ddl/schemas/progress_tracking/tables/04-exercise_submissions.sql
  • Campo de respuestas: answer_data (JSONB)
  • Estados: draft, submitted, graded, reviewed
  • Tiene: feedback, graded_at, columnas de revision manual

Servicio que escribe: ExerciseSubmissionService.submitExercise()

  • Endpoint: POST /progress/submissions/submit
  • Usado por: Frontend de estudiantes (progressAPI.ts)

Tabla 2: exercise_attempts

Proposito: Ejercicios autocorregibles (multiples intentos)

  • Archivo DDL: apps/database/ddl/schemas/progress_tracking/tables/03-exercise_attempts.sql
  • Campo de respuestas: submitted_answers (JSONB)
  • Sin estados de workflow - solo registro de intentos

Servicio que lee: ExerciseResponsesService.getAttempts()

  • Endpoint: GET /teacher/attempts
  • Usado por: Teacher Portal Responses Page

EVIDENCIA DEL GAP

1. Frontend de Estudiantes (progressAPI.ts:384-385)

// Backend endpoint: POST /api/progress/submissions/submit
const backendPayload = {
  userId,
  exerciseId,
  answers,
};

const { data } = await apiClient.post<ApiResponse<SubmitExerciseResponse>>(
  '/progress/submissions/submit',  // <-- ESCRIBE EN exercise_submissions
  backendPayload,
);

2. Backend de Teacher Portal (exercise-responses.service.ts:186)

FROM progress_tracking.exercise_attempts attempt  -- <-- LEE DE exercise_attempts
LEFT JOIN auth_management.profiles profile ON profile.user_id = attempt.user_id
...

3. Validacion en ExerciseSubmissionService (linea 227)

// Este servicio es SOLO para ejercicios que requieren revisión manual
// Los ejercicios autocorregibles deben usar ExerciseAttemptService
if (!exercise.requires_manual_grading) {
  throw new BadRequestException(
    'This exercise is auto-graded and allows multiple attempts...'
  );
}

Esto confirma la arquitectura dual, pero el Teacher Portal solo lee de una tabla.


IMPACTO

Impacto Descripcion
Funcionalidad Teacher no puede ver respuestas de estudiantes
Calificacion No puede calificar ejercicios de Modulos 4-5
Monitoreo No puede monitorear progreso real de estudiantes
Datos Los datos existen en BD pero son invisibles al teacher

SOLUCION PROPUESTA

Opcion A: Modificar ExerciseResponsesService para consultar AMBAS tablas (RECOMENDADO)

Complejidad: Media Riesgo: Bajo Tiempo estimado: 4-6 horas

// exercise-responses.service.ts

async getAttempts(userId: string, query: GetAttemptsQueryDto): Promise<AttemptsListResponseDto> {
  // Query UNION de ambas tablas
  const sql = `
    -- Ejercicios autocorregibles (exercise_attempts)
    SELECT
      'attempt' as source,
      attempt.id AS id,
      attempt.user_id AS student_id,
      attempt.submitted_answers AS answers,
      attempt.score,
      attempt.is_correct,
      attempt.submitted_at,
      ...
    FROM progress_tracking.exercise_attempts attempt
    ...

    UNION ALL

    -- Ejercicios de revision manual (exercise_submissions)
    SELECT
      'submission' as source,
      sub.id AS id,
      sub.user_id AS student_id,
      sub.answer_data AS answers,
      sub.score,
      sub.is_correct,
      sub.submitted_at,
      ...
    FROM progress_tracking.exercise_submissions sub
    ...
    WHERE sub.status != 'draft'

    ORDER BY submitted_at DESC
    LIMIT $X OFFSET $Y
  `;
}

Opcion B: Crear endpoint separado para submissions

Complejidad: Baja Riesgo: Bajo Tiempo estimado: 2-3 horas

Crear un nuevo endpoint /teacher/submissions que consulte exercise_submissions y agregar una tab en el frontend para mostrar ambos tipos.

Opcion C: Migrar datos a una sola tabla (NO RECOMENDADO)

Complejidad: Alta Riesgo: Alto (podria romper otras partes del sistema) Tiempo estimado: 2-3 dias


ARCHIVOS A MODIFICAR

Opcion A (Recomendada)

Archivo Cambio
apps/backend/src/modules/teacher/services/exercise-responses.service.ts Modificar query para UNION de ambas tablas
apps/backend/src/modules/teacher/dto/exercise-responses.dto.ts Agregar campo source: 'attempt' | 'submission'
apps/frontend/src/apps/teacher/components/responses/ResponsesTable.tsx (Opcional) Mostrar indicador de tipo

VALIDACION POST-IMPLEMENTACION

Pasos de Verificación

  1. Compilar backend:

    cd apps/backend && npm run build
    
  2. Test manual: Como estudiante, completar un ejercicio de Modulo 4 o 5

  3. Verificar BD:

    SELECT * FROM progress_tracking.exercise_submissions
    WHERE status != 'draft'
    ORDER BY submitted_at DESC LIMIT 5;
    
  4. Verificar Teacher Portal: Navegar a /teacher/responses y confirmar que aparece el ejercicio

  5. Test de detalle: Click en "Ver" y confirmar que muestra las respuestas correctamente

  6. Test de filtros:

    • Filtrar por source=submission para ver solo ejercicios de revisión manual
    • Filtrar por status=submitted para ver ejercicios pendientes de calificación

Nuevo Flujo Corregido

┌─────────────────────────────────────────────────────────────┐
│                     FLUJO CORREGIDO ✅                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ESTUDIANTE                       TEACHER PORTAL            │
│  ┌────────────┐                  ┌────────────┐            │
│  │ Submit     │                  │ Responses  │            │
│  │ Ejercicio  │                  │ Page       │            │
│  └─────┬──────┘                  └──────┬─────┘            │
│        │                                │                   │
│        ▼                                ▼                   │
│  ┌────────────────┐          ┌────────────────┐            │
│  │ exercise_      │          │ UNION QUERY    │            │
│  │ SUBMISSIONS    │◄─────────│ attempts +     │            │
│  │ (M4-M5)        │          │ submissions    │            │
│  └────────────────┘          └────────────────┘            │
│        │                                ▲                   │
│        │                                │                   │
│  ┌────────────────┐                     │                   │
│  │ exercise_      │─────────────────────┘                   │
│  │ ATTEMPTS       │                                         │
│  │ (M1-M3)        │                                         │
│  └────────────────┘                                         │
│                                                             │
│  ✅ CONEXION COMPLETA - Teacher VE todas las respuestas    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

DEPENDENCIAS

  • RLS policies ya existen para exercise_submissions (linea 168 del DDL)
  • El frontend ya maneja el formato de respuesta (no requiere cambios mayores)

SIGUIENTE PASO

ACCION INMEDIATA: Implementar Opcion A - Modificar ExerciseResponsesService para consultar ambas tablas con UNION.


Analisis realizado: 2025-12-18 Proyecto: GAMILIT - Portal Teacher Gap ID: G-RESPONSES-001