Saltar a contenido

API Frontend – Cierre de Bloque

Esta guía explica cómo el frontend debe cerrar un bloque. El cierre requiere 2 pasos:

1) Preview: calcula la nota sugerida y habilita una ventana temporal para poder confirmar. 2) Confirmación: cierra el bloque (pasa el estado a pending para revisión).

El sistema obliga a realizar el preview inmediatamente antes de la confirmación. Si intentas confirmar sin un preview válido, fallará con PREVIEW_REQUIRED.


Endpoint

POST /api/v2/blocks/:blockId/close
  • Modo preview: usar query preview=true
  • Modo confirmación: no enviar preview o preview=false

Autenticación

Requiere token JWT. Enviar Authorization: Bearer <JWT>

Parámetros

Parámetro Ubicación Requerido Descripción
blockId path ID del bloque a cerrar
preview query No true para preview; omitido/false para confirmar
studentId query/body ID del alumno con el que se evalúa el bloque
schoolCourseId query/body No Curso escolar. Si no se envía, usa el último curso
grade body Solo en confirmación Nota final del bloque. DECIMAL(4,2)

Flujo Recomendado (Frontend)

┌──────────────────┐
│ 1. Llamar PREVIEW │
└────────┬─────────┘
┌──────────────────────────────────────┐
│ 2. Mostrar resumen y nota sugerida   │
│    - suggestedGrade                  │
│    - counts (contenidos evaluados)   │
└────────┬─────────────────────────────┘
┌──────────────────────────────────────┐
│ 3. Profesor acepta o modifica nota   │
└────────┬─────────────────────────────┘
┌──────────────────────────────────────┐
│ 4. Llamar CONFIRMACIÓN (antes TTL)   │
│    - Enviar grade en body            │
│    - Estado cambia a "pending"       │
└──────────────────────────────────────┘

Importante: La confirmación valida que existe un preview vigente para el mismo employeeId y blockId. Si el TTL expiró o no hiciste preview, devuelve error PREVIEW_REQUIRED.


Ejemplos

Preview (curl)

curl -X POST \
  "https://<host>/api/v2/blocks/123/close?preview=true&studentId=456&schoolCourseId=2025" \
  -H "Authorization: Bearer <token>"

Respuesta:

{
  "ok": true,
  "mode": "preview",
  "expiresInSeconds": 600,
  "counts": {
    "contentScores": 5,
    "personalizedScores": 2,
    "total": 7
  },
  "suggestedGrade": 7.85
}

Confirmación (curl)

curl -X POST \
  "https://<host>/api/v2/blocks/123/close?studentId=456" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"grade": 7.5}'

Respuesta:

{
  "ok": true,
  "message": "Block closed successfully. Status set to pending.",
  "block": { /* entidad actualizada */ },
  "status": "pending",
  "grade": 7.5
}

Preview (TypeScript/fetch)

const response = await fetch(
  `/api/v2/blocks/${blockId}/close?preview=true&studentId=${studentId}&schoolCourseId=${courseId ?? ''}`,
  {
    method: 'POST',
    headers: { Authorization: `Bearer ${token}` },
  }
);
const data = await response.json();
// data.suggestedGrade, data.counts, data.expiresInSeconds

Confirmación (TypeScript/fetch)

const response = await fetch(
  `/api/v2/blocks/${blockId}/close?studentId=${studentId}&schoolCourseId=${courseId ?? ''}`,
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${token}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ grade: finalGrade }),
  }
);

Respuestas

Preview exitoso

{
  "ok": true,
  "mode": "preview",
  "expiresInSeconds": 600,
  "counts": {
    "contentScores": 5,
    "personalizedScores": 2,
    "total": 7
  },
  "suggestedGrade": 7.85
}

Confirmación exitosa

{
  "ok": true,
  "message": "Block closed successfully. Status set to pending.",
  "status": "pending",
  "grade": 7.5,
  "studentBlockId": 42
}

Nota: El studentBlockId es el ID del registro en la tabla student_blocks que almacena el estado del bloque para este estudiante específico.


Errores Comunes

Código Error Descripción
400 PREVIEW_REQUIRED Intentaste confirmar sin preview vigente (o expirado)
400 INVALID_STATUS El bloque no está en estado open
400 STUDENT_ID_REQUIRED Falta studentId o no es numérico
400 BLOCK_ID_REQUIRED blockId inválido
400 GRADE_REQUIRED Falta grade en confirmación
404 BLOCK_NOT_FOUND blockId no existe
401 UNAUTHORIZED Falta/expiró token

Notificación a Administradores

Al confirmar el cierre de un bloque, se envía automáticamente un email a los administradores configurados en ADMIN_EMAILS con:

  • Nombre del bloque (ej: "Bloque 1")
  • Asignatura
  • Nombre completo del estudiante
  • Nombre completo del profesor
  • Nota asignada
  • Fecha de cierre

Notas Técnicas

  • El preview marca una llave temporal en Redis blockClosePreview:{blockId}:{employeeId} con TTL configurable (BLOCK_CLOSE_PREVIEW_TTL, default 600s = 10 min).
  • La confirmación exige que exista esa marca (mismo usuario) y la consume al cerrar.
  • Si no envías schoolCourseId, el backend usa el último curso automáticamente.
  • Al confirmar, el bloque pasa a pending para revisión administrativa.