API Incidencias de Fichaje v2¶
Documentación de endpoints para la gestión de incidencias de fichaje (check-in incidents).
GET /api/v2/incident/¶
Obtiene el listado paginado de incidencias y estadísticas globales.
- Auth:
Authorization: Bearer <token> - Query Params:
status(opcional):"open"|"closed"- Filtra el listado por estadolimit(opcional): number - Límite de resultados (default: todos)offset(opcional): number - Offset para paginación (default: 0)schoolCourseId(opcional): number - Filtra por curso escolarsearch(opcional): string - Búsqueda por nombre/apellido de empleado o descripciónstartDate(opcional): ISO date string - Fecha de inicio para filtrar (ej:2026-01-01)endDate(opcional): ISO date string - Fecha de fin (si no se especifica, filtra desde startDate hasta hoy)incidentType(opcional): string - Tipo de incidencia (EARLY_EXIT,OUT_OF_RANGE,NO_SCHEDULE_TODAY,OUT_OF_SCHEDULE_WINDOW)
Ejemplo¶
curl -X GET "$HOST/api/v2/incident/?status=open&limit=10&offset=0&search=Juan&startDate=2026-01-01" \
-H "Authorization: Bearer $TOKEN"
Respuesta (200)¶
{
"status": "success",
"data": {
"incidents": [
{
"id": 1,
"description": "Fichaje fuera de horario",
"status": "open",
"reviewStatus": "underReview",
"incidentType": "OUT_OF_SCHEDULE_WINDOW",
"timeRecordId": 456,
"employeeId": 123,
"schoolCourseId": 1,
"createdAt": "2026-01-27T10:00:00.000Z",
"updatedAt": "2026-01-27T10:00:00.000Z",
"employee": {
"id": 123,
"name": "Juan",
"lastName": "Pérez"
}
}
]
},
"counts": {
"total": 50,
"open": 15,
"inReview": 8,
"closed": 35
},
"pagination": {
"totalItems": 15,
"limit": 10,
"offset": 0
}
}
Campos de Respuesta¶
| Campo | Descripción |
|---|---|
data.incidents |
Array de incidencias filtradas y paginadas |
counts.total |
Total de incidencias (sin filtros de estado) |
counts.open |
Incidencias con status = 'open' |
counts.inReview |
Incidencias con status = 'open' AND reviewStatus = 'underReview' |
counts.closed |
Incidencias con status = 'closed' |
pagination.totalItems |
Total de items que coinciden con el filtro actual |
pagination.limit |
Límite usado en la consulta |
pagination.offset |
Offset usado en la consulta |
Notas¶
- Los contadores (
counts) son globales y no se ven afectados por el filtrostatus. Esto permite mostrar los números de las "tabs" (Todas, Abiertas, En Revisión, Cerradas) mientras se filtra el listado. - Si se proporciona
schoolCourseId, los contadores también se filtran por ese curso. - El campo
inReviewes un subconjunto deopen(incidencias abiertas que están bajo revisión).
GET /api/v2/incident/my¶
Obtiene las incidencias del empleado autenticado.
- Auth:
Authorization: Bearer <token> - Query Params:
status(opcional):"open"|"closed"limit(opcional): numberoffset(opcional): number
Ejemplo¶
Respuesta (200)¶
{
"status": "success",
"data": {
"incidents": [...]
},
"counts": {
"total": 5,
"open": 2,
"inReview": 1,
"closed": 3
}
}
GET /api/v2/incident/:id¶
Obtiene el detalle de una incidencia por ID.
- Auth:
Authorization: Bearer <token> - Params:
id- ID de la incidencia
Ejemplo¶
Respuesta (200)¶
{
"status": "success",
"data": {
"incident": {
"id": 123,
"description": "...",
"status": "open",
"reviewStatus": "underReview",
"incidentType": "EARLY_EXIT",
"employee": {...},
"incidentThreads": [...],
"incidentFiles": [...]
}
}
}
Eventos Socket.IO¶
El backend emite un único evento global incident_notification en la sala correspondiente. El frontend distingue el tipo de notificación por el campo type en la data.
Evento: incident_notification¶
Salas de escucha:
- admins - Para administradores
- employee:{id} - Para un empleado específico
- incident_chat:{id} - Para el chat de una incidencia
Tipos de Notificación (campo type)¶
| Tipo | Destino | Descripción |
|---|---|---|
new_incident |
admins | Nueva incidencia creada |
new_message |
admins, incident_chat | Empleado envió mensaje |
incident_resolved |
admins | Incidencia cerrada |
admin_reply |
employee, incident_chat | Admin respondió al hilo |
status_changed |
employee | Cambio de estado de incidencia |
Payload¶
interface IncidentNotificationPayload {
type: "new_incident" | "new_message" | "admin_reply" | "status_changed" | "incident_resolved";
incidentId: number;
employeeId?: number;
employeeName?: string;
incidentType?: string;
message?: string; // Mensaje completo (solo en chat)
preview?: string; // Primeros 100 caracteres
senderType?: "user" | "admin";
status?: string;
reviewStatus?: string;
timestamp: Date;
data?: {
checkInType?: "start" | "end";
adminName?: string;
changedBy?: "admin" | "system";
};
}
Cómo conectarse¶
// Conectarse y unirse a salas
socket.emit("join", { employeeId: 123 }); // Auto-join a "admins" si tiene rol
// Unirse a chat de incidencia
socket.emit("join_incident_chat", { incidentId: 456 });
// Escuchar un solo evento y filtrar por type
socket.on("incident_notification", (data) => {
switch (data.type) {
case "new_incident":
console.log("Nueva incidencia:", data);
break;
case "admin_reply":
console.log("Admin respondió:", data);
break;
// ... otros tipos
}
});
Tipos de Incidencia (incidentType)¶
Los siguientes son los valores posibles para el campo incidentType, usados tanto para filtrar como para mostrar en el frontend:
Incidencias de Fichaje (creadas automáticamente al fichar con errores)¶
| Valor | Descripción (Frontend) | Cuándo se genera |
|---|---|---|
early_exit |
Salida anticipada | Empleado sale antes de que termine su última clase |
out_of_schedule |
Fuera de horario | Entrada fuera del rango de tolerancia antes de la primera clase |
no_schedule |
Sin clases programadas | No hay eventos/clases para ese día |
out_of_range |
Fuera de rango permitido | Fichaje desde una ubicación fuera del radio del centro |
Incidencias Automáticas (generadas por el cron)¶
| Valor | Descripción (Frontend) | Cuándo se genera |
|---|---|---|
missing_checkin_entry |
Falta fichaje de entrada | Empleado tenía clase pero no fichó entrada |
missing_checkin_exit |
Falta fichaje de salida | Empleado fichó entrada pero no fichó salida |
missing_checkin_both |
Falta entrada y salida | Empleado no fichó ni entrada ni salida |
no_exit_registered |
Salida no registrada | El cron cerró automáticamente un fichaje abierto |
missingClockIn |
Fichaje faltante | Verificación detectó fichaje faltante |
Otros Tipos¶
| Valor | Descripción (Frontend) | Uso |
|---|---|---|
no_events_today |
Sin eventos hoy | Incidencia manual creada por el empleado |
general_issue |
Problema general | Valor por defecto si no se especifica tipo |
Relacionado: - API Fichaje v2 - Errores de fichaje