Un mismo formulario sirve para crear y para editar. Al crear, ayuda a la persona: elige la prioridad en tarjetas con su plazo, sugiere el vencimiento, muestra incidentes parecidos ya reportados y una vista previa. La API valida todo de nuevo y es quien decide el código, el estado inicial y el vencimiento si no se indicó uno.
Paso a paso
- PersonaLlena título, descripción y prioridad
En
/incidentes/nuevo. Si escribe un título, "¿Ya lo reportaron?" busca parecidos tras 400 ms. Puede elegir el vencimiento (Sugerido, Hoy, Mañana u Otra fecha) y, si tiene permiso, a quién asignarlo o "Asignármelo". - Navegador¿Los campos se ven bien?
Validación solo de experiencia (título de 5 a 80 caracteres con contador, campos obligatorios). La regla de verdad está en la API.
- NavegadorEnvía POST /incidents con Idempotency-Key
La clave se genera por contenido: reintentar el mismo envío (doble clic, red lenta) reutiliza la clave; cambiar algo genera otra.
- API¿Ya llegó esa clave con éxito?
La clave es por persona y por ruta y se recuerda 24 h. Si llega con otro contenido, responde 409
IDEMPOTENCY_KEY_REUSED; si el primer envío sigue en curso, 409IDEMPOTENCY_IN_PROGRESS. - APIDevuelve la misma respuesta, sin crear otro
Con la cabecera
Idempotent-Replayed. - API¿Datos válidos y permiso para crear?
Título de 5 a 80, descripción hasta 5.000, prioridad activa del catálogo, vencimiento en el futuro (si viene) y permiso
incidents.create. - APISi trae asignado, ¿lo puede asignar?
A cualquiera con
incidents.assign; solo a sí mismo conincidents.take. Quien no puede asignar a otros recibe siempre 403, para no revelar a quién se podría asignar. - APIFija el vencimiento
Si la persona lo indicó, se respeta. Si no, ahora + el tiempo de la prioridad (Baja 5 días, Media 3 días, Alta 1 día, Crítica 4 h; datos editables del catálogo).
- Base de datosToma el siguiente código del año
Ejemplo
TZ-26-0142: prefijo, año del negocio (America/Bogota) y consecutivo deincident_code_sequences, tomado en la misma transacción con una sola sentencia atómica. - Base de datosGuarda el incidente y su historial
En la misma transacción: el incidente en el estado inicial (Abierto),
created_byobligatorio, y la entradacreateddel historial (con el asignado si lo hubo), con IP y navegador. - Cola y avisosAvisa del cambio tras confirmar
Solo después del commit: sube la generación de la caché del dashboard, emite
incident.changeda los canales que pueden verlo y crea las notificaciones (al asignado; a coordinación si es crítico o queda sin asignar). - NavegadorAbre el detalle con "Incidente TZ-26-0142 creado"
Qué ve la persona en cada error
| Código | HTTP | Cuándo | Mensaje en pantalla |
|---|---|---|---|
VALIDATION_FAILED | 422 | Algún campo no cumple; cada campo trae su código (TOO_SHORT, TOO_LONG…) | Hay datos por corregir. Revisa los campos marcados. (y el mensaje de cada campo debajo de él) |
FORBIDDEN_ACTION | 403 | Sin permiso para crear, o para asignar a esa persona | No tienes permiso para hacer esta acción. Si crees que deberías tenerlo, habla con un administrador. |
INVALID_ASSIGNEE | 422 | Quien asigna eligió a alguien que no puede recibir incidentes | Esta persona no puede recibir incidentes. Elige a alguien de la lista. |
IDEMPOTENCY_IN_PROGRESS | 409 | El mismo envío todavía se está procesando | Tu incidente se está creando. Espera unos segundos antes de intentarlo de nuevo. |
IDEMPOTENCY_KEY_REUSED | 409 | La misma clave llegó con otro contenido | No pudimos confirmar el envío. Recarga la página e inténtalo de nuevo. |
Dónde está en el código
CreateIncident: permiso, asignado, vencimiento y transacción.CreateIncidentRequestyIncidentRequest: validación.EnsureIdempotency: doble envío.IncidentCodeseIncidentRules: código del año y vencimiento.EloquentIncidentRepository: guarda y emiteIncidentChanged.useIncidentFormeIncidentFormPage.- Explicación del módulo: Módulo Incidents e Idempotencia.