Skip to content

Incidentes

Incidentes

Prefijo: /api/incidentes
Requiere Auth:
Permiso requerido: incidentes, *

Módulo de gestión de incidentes del sistema. Cada incidente representa un evento anómalo o error ocurrido durante la operación del POS (ej: error de sincronización, fallo de integración DIAN, producto sin stock crítico, etc.).

Arquitectura: Los incidentes se almacenan en la tabla movimientos_log con tipo_movimiento = 'INCIDENTE', extendiendo el modelo de auditoría existente con campos adicionales (severidad, resuelto, resuelto_por, resuelto_at, notas_resolucion, accion, datos_extra).

Severidades válidas: CRITICO, ALTO, MEDIO (default), BAJO

Contexto de uso: Los incidentes pueden ser generados automáticamente por el sistema (sync errors, fallos de conexión) o manualmente desde el panel de administración. El equipo de soporte puede consultarlos, filtrarlos por severidad/módulo, resolverlos individualmente o en批量, y agruparlos por módulo para identificar patrones.


CRUD Incidentes

<MethodBadge method="GET" /> /api/incidentes/ [NUEVO]

Descripción: Lista todos los incidentes del tenant con paginación y filtros
Requiere Auth:
Permiso requerido: incidentes, leer

Parámetros query:

ParámetroTipoObligatorioDescripción
skipintNúmero de registros a saltar (default 0)
limitintMáximo de registros a retornar (default 100)
resueltoboolFiltrar por estado: true (solo resueltos), false (solo abiertos)
severidadstringFiltrar por severidad: CRITICO, ALTO, MEDIO, BAJO
modulostringFiltrar por módulo del sistema (ej: sync, ventas, dian)

Respuesta exitosa: 200 OK

Response:

[
{
"id": 1,
"tenant_id": "uuid-tenant",
"tipo_movimiento": "INCIDENTE",
"tabla_afectada": "sync",
"id_referencia": null,
"descripcion": "Error de sincronización con el cloud: timeout",
"usuario": "sistema",
"origen": "API",
"fecha": "2026-07-29",
"hora": "10:30:00",
"severidad": "ALTO",
"resuelto": true,
"resuelto_por": "admin@neoapp.com",
"resuelto_at": "2026-07-29T11:00:00Z",
"notas_resolucion": "Se restableció la conexión manualmente",
"accion": "sync_error",
"datos_extra": {
"codigo_error": "ETIMEOUT",
"intentos": 3
}
},
{
"id": 2,
"tenant_id": "uuid-tenant",
"tipo_movimiento": "INCIDENTE",
"tabla_afectada": "dian",
"id_referencia": 42,
"descripcion": "Falló la facturación electrónica para la venta #42",
"usuario": "sistema",
"origen": "API",
"fecha": "2026-07-29",
"hora": "09:15:00",
"severidad": "CRITICO",
"resuelto": false,
"resuelto_por": null,
"resuelto_at": null,
"notas_resolucion": null,
"accion": "dian_error",
"datos_extra": {
"venta_id": 42,
"cufe": "",
"codigo_error": "HOST_RESPONSE_ERROR"
}
}
]

cURL:

Terminal window
curl "http://localhost/api/incidentes/?skip=0&limit=20&severidad=ALTO" \
-H "Authorization: Bearer <token>"

Python:

import httpx
resp = httpx.get("http://localhost/api/incidentes/",
params={"skip": 0, "limit": 20, "severidad": "ALTO"},
headers={"Authorization": f"Bearer :token"})
incidentes = resp.json()

JavaScript:

const resp = await fetch('http://localhost/api/incidentes/?skip=0&limit=20&severidad=ALTO', {
headers: {'Authorization': `Bearer $:token`}
});
const incidentes = await resp.json();

<MethodBadge method="GET" /> /api/incidentes/count [NUEVO]

Descripción: Obtiene el conteo de incidentes, con opción de filtrar por estado o severidad
Requiere Auth:
Permiso requerido: incidentes, leer

Parámetros query:

ParámetroTipoObligatorioDescripción
resueltoboolSi se envía, retorna solo el total filtrado (sin desglose)
severidadstringFiltrar por severidad antes de contar

Comportamiento:

  • Sin filtros: Retorna desglose completo (total, abiertos, resueltos)
  • Con resuelto: Retorna solo el total de ese estado (los otros campos en 0)
  • Con severidad: Cuenta solo los de esa severidad

Respuesta exitosa: 200 OK

Response (sin filtros):

{
"total": 15,
"abiertos": 8,
"resueltos": 7
}

Response (con resuelto=false):

{
"total": 8,
"abiertos": 0,
"resueltos": 0
}

cURL:

Terminal window
curl "http://localhost/api/incidentes/count" -H "Authorization: Bearer <token>"
curl "http://localhost/api/incidentes/count?resuelto=false" -H "Authorization: Bearer <token>"
curl "http://localhost/api/incidentes/count?severidad=CRITICO" -H "Authorization: Bearer <token>"

<MethodBadge method="GET" /> /api/incidentes/por-modulo [NUEVO]

Descripción: Retorna los incidentes agrupados por módulo (tabla_afectada). Útil para dashboards que muestran incidentes por área del sistema.
Requiere Auth:
Permiso requerido: incidentes, leer

Respuesta exitosa: 200 OK

Response:

{
"sync": [
{
"id": 1,
"descripcion": "Error de sincronización con el cloud: timeout",
"severidad": "ALTO",
"resuelto": true,
...
}
],
"dian": [
{
"id": 2,
"descripcion": "Falló la facturación electrónica para la venta #42",
"severidad": "CRITICO",
"resuelto": false,
...
}
],
"ventas": [
...
]
}

cURL:

Terminal window
curl "http://localhost/api/incidentes/por-modulo" -H "Authorization: Bearer <token>"

<MethodBadge method="GET" /> /api/incidentes/:incident_id [NUEVO]

Descripción: Obtiene un incidente por ID
Requiere Auth:
Permiso requerido: incidentes, leer

Respuesta exitosa: 200 OK
Errores: 404 (no encontrado)

cURL:

Terminal window
curl http://localhost/api/incidentes/1 -H "Authorization: Bearer <token>"

<MethodBadge method="POST" /> /api/incidentes/ [NUEVO]

Descripción: Crea un nuevo incidente. Puede ser usado tanto por el sistema (auto-reporte) como por usuarios del panel de administración.
Requiere Auth:
Permiso requerido: incidentes, crear

Request:

{
"modulo": "sync",
"accion": "sync_error",
"mensaje": "Error de sincronización con el cloud: timeout después de 30s",
"severidad": "ALTO",
"id_referencia": null,
"datos_extra": {
"codigo_error": "ETIMEOUT",
"intentos": 3,
"ultimo_exito": "2026-07-29T08:00:00Z"
}
}
CampoTipoObligatorioDescripción
modulostringMódulo del sistema donde ocurrió (ej: sync, dian, ventas)
accionstringAcción específica que falló (ej: sync_error, dian_error)
mensajestringDescripción legible del incidente
severidadstringSeveridad: CRITICO, ALTO, MEDIO (default), BAJO
id_referenciaintID opcional del registro relacionado (ej: venta_id)
datos_extraobjectMetadatos adicionales en JSON para debugging

Respuesta exitosa: 201 Created

Response: (objeto IncidentResponse completo con resuelto: false)

cURL:

Terminal window
curl -X POST http://localhost/api/incidentes/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"modulo":"sync","accion":"sync_error","mensaje":"Error de sincronización: timeout","severidad":"ALTO","datos_extra":{"codigo_error":"ETIMEOUT","intentos":3}}'

Python:

import httpx
resp = httpx.post("http://localhost/api/incidentes/",
json={"modulo": "sync", "accion": "sync_error", "mensaje": "Error de sincronización: timeout", "severidad": "ALTO"},
headers={"Authorization": f"Bearer :token"})
incidente = resp.json()

JavaScript:

const resp = await fetch('http://localhost/api/incidentes/', {
method: 'POST',
headers: {'Content-Type': 'application/json', 'Authorization': `Bearer $:token`},
body: JSON.stringify({modulo: 'sync', accion: 'sync_error', mensaje: 'Error de sincronización: timeout', severidad: 'ALTO'})
});
const incidente = await resp.json();

<MethodBadge method="PATCH" /> /api/incidentes/:incident_id/resolver [NUEVO]

Descripción: Marca un incidente como resuelto. Requiere indicar quién lo resolvió y opcionalmente notas de la resolución.
Requiere Auth:
Permiso requerido: incidentes, actualizar

Request:

{
"resuelto_por": "admin@neoapp.com",
"notas_resolucion": "Se restableció la conexión VPN y se re-intentó la sincronización exitosamente"
}
CampoTipoObligatorioDescripción
resuelto_porstringEmail o nombre de usuario que resolvió el incidente
notas_resolucionstringNotas opcionales sobre cómo se resolvió

Respuesta exitosa: 200 OK
Errores: 404 (incidente no encontrado)

Response:

{
"id": 1,
"descripcion": "Error de sincronización con el cloud: timeout",
"severidad": "ALTO",
"resuelto": true,
"resuelto_por": "admin@neoapp.com",
"resuelto_at": "2026-07-29T11:00:00Z",
"notas_resolucion": "Se restableció la conexión VPN y se re-intentó la sincronización exitosamente",
...
}

cURL:

Terminal window
curl -X PATCH http://localhost/api/incidentes/1/resolver \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"resuelto_por":"admin@neoapp.com","notas_resolucion":"Conexión restablecida"}'

Python:

import httpx
resp = httpx.patch("http://localhost/api/incidentes/1/resolver",
json={"resuelto_por": "admin@neoapp.com", "notas_resolucion": "Conexión restablecida"},
headers={"Authorization": f"Bearer :token"})
incidente = resp.json()

JavaScript:

const resp = await fetch('http://localhost/api/incidentes/1/resolver', {
method: 'PATCH',
headers: {'Content-Type': 'application/json', 'Authorization': `Bearer $:token`},
body: JSON.stringify({resuelto_por: 'admin@neoapp.com', notas_resolucion: 'Conexión restablecida'})
});