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>
13 KiB
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
-
UNION Query: El método
getAttempts()ahora consulta:progress_tracking.exercise_attempts(ejercicios autocorregibles)progress_tracking.exercise_submissions(ejercicios de revisión manual)
-
Nuevo campo
source: Indica de qué tabla proviene cada registro (attemptosubmission) -
Filtro por status: Excluye automáticamente submissions con status
draft -
getAttemptDetail mejorado: Busca primero en
exercise_attempts, si no encuentra busca enexercise_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
-
Compilar backend:
cd apps/backend && npm run build -
Test manual: Como estudiante, completar un ejercicio de Modulo 4 o 5
-
Verificar BD:
SELECT * FROM progress_tracking.exercise_submissions WHERE status != 'draft' ORDER BY submitted_at DESC LIMIT 5; -
Verificar Teacher Portal: Navegar a
/teacher/responsesy confirmar que aparece el ejercicio -
Test de detalle: Click en "Ver" y confirmar que muestra las respuestas correctamente
-
Test de filtros:
- Filtrar por
source=submissionpara ver solo ejercicios de revisión manual - Filtrar por
status=submittedpara ver ejercicios pendientes de calificación
- Filtrar por
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