Buscar en la documentación

Modelo de datos

Diagrama entidad-relación, política de claves foráneas y criterios del esquema.

3 min de lecturaVer en GitHub
erDiagram
  users ||--o{ user_role : tiene
  roles ||--o{ user_role : asignado
  roles ||--o{ role_permission : agrupa
  permissions ||--o{ role_permission : concedido
  users ||--o{ incidents : "crea (created_by)"
  users |o--o{ incidents : "atiende (assigned_to)"
  priorities ||--o{ incidents : clasifica
  statuses ||--o{ incidents : "estado actual"
  statuses ||--o{ status_transitions : desde
  statuses ||--o{ status_transitions : hacia
  incidents ||--o{ incident_activities : historial
  users ||--o{ incident_activities : realiza
  activity_types ||--o{ incident_activities : tipo
  incidents ||--o{ incident_reopen_requests : "pedido de reapertura"
  users ||--o{ incident_reopen_requests : "pide o decide"
  incidents ||--o{ incident_comments : "conversación"
  users ||--o{ incident_comments : "escribe"
  users ||--o{ notifications : "recibe"
  notification_types ||--o{ notifications : tipo
  incidents ||--o{ notifications : "sobre"
  incident_comments |o--o{ notifications : "mensaje"
  incident_activities |o--o{ notifications : "cambio"
  permissions |o--o{ dashboard_widgets : "exige"
  users ||--o{ user_dashboard_widgets : "diseño"
  dashboard_widgets ||--o{ user_dashboard_widgets : "lugar"
  roles ||--o| mfa_policies : "exige MFA"
  users ||--o| user_mfa_factors : "segundo factor"
  users ||--o{ user_recovery_codes : "recuperación"
  users ||--o{ password_reset_codes : "recupera la contraseña"
  users ||--o{ user_permissions : "excepciones"
  permissions ||--o{ user_permissions : "concedido o quitado"
  users ||--o{ admin_actions : "administra"
  admin_action_types ||--o{ admin_actions : tipo
  system_event_types ||--o{ system_events : tipo
  users |o--o{ system_events : "cambia su estado"

Las tablas de las funcionalidades adicionales (MFA, recuperación de contraseña, logs del sistema, dashboard personalizable y tokens de sesión) se agregan con migraciones nuevas en la fase de cada funcionalidad, sin modificar las existentes.

Política de claves foráneas

Toda referencia es una clave foránea real; no hay relaciones polimórficas. La acción ante un borrado se elige según el valor histórico del dato:

RelaciónAcciónPor qué
incidents.created_by, incidents.assigned_to → usersRESTRICTNunca se pierde quién reportó o atendió algo. Los usuarios se desactivan, no se borran.
incident_activities → incidents, users, activity_typesRESTRICTEl historial es inmutable
incident_reopen_requests → incidents, users (pide y decide)RESTRICTLas solicitudes son parte del rastro del incidente
incident_comments → incidents, usersRESTRICTLos mensajes son parte del rastro del incidente
notifications → users, incident_activitiesCASCADEUn aviso no tiene sentido sin su destinatario ni sin el registro que lo originó
notifications → incidents, incident_comments, notification_typesRESTRICTIncidentes y mensajes no se borran de verdad, y MySQL no admite CASCADE en columnas de las que depende una columna calculada
incidents → priorities, statusesRESTRICTUn catálogo en uso no se borra; se desactiva
status_transitions → statusesRESTRICTIgual que el anterior
user_role.user_id → usersCASCADESolo aplica a un usuario sin historial (si tiene historial, el borrado ya está bloqueado)
role_permission.role_id → rolesCASCADESin el rol, sus asignaciones no significan nada
user_role.role_id, role_permission.permission_idRESTRICTNo se borra un rol o permiso en uso
user_permissions.user_id → usersCASCADELa excepción es parte de la cuenta
user_permissions.permission_id, user_permissions.granted_byRESTRICTNo se borra un permiso en uso ni a quien dio la excepción
admin_actions → users, admin_action_typesRESTRICTEl registro de la administración es inmutable
system_events → system_event_types, system_events.status_changed_by → usersRESTRICTUn tipo en uso no se borra; los usuarios se desactivan, no se borran
admin_actions.target_role_id → rolesSET NULLUn rol creado se puede eliminar; su historial queda sin enlace, con el código y el nombre en el detalle
mfa_policies.role_id → rolesCASCADELa política es parte del rol

Las claves foráneas usan siempre el mismo tipo que la clave a la que apuntan (BIGINT, SMALLINT o TINYINT sin signo).

Criterios generales

  • Identificadores: BIGINT interno para los JOIN y ulid público (único e inmutable) en users e incidents. Los catálogos se identifican por code.
  • Restricciones CHECK donde la regla es de los datos: nivel de prioridad positivo, transición entre estados distintos, versión de bloqueo mayor o igual a 1.
  • Nombres: tablas en plural y snake_case; claves foráneas <entidad>_id (o el rol que cumplen, como created_by).
  • Fechas: en UTC. utf8mb4_0900_ai_ci hace que las búsquedas no distingan tildes ni mayúsculas.
  • Limpieza en origen: correos en minúsculas y sin espacios; NOT NULL en todo lo obligatorio.

Diccionario

TablaPágina
usersusers
roles, permissions, role_permission, user_role, user_permissionsRoles y permisos
priorities, statuses, status_transitions, activity_typesCatálogos
incidentsincidents
incident_activitiesincident_activities
incident_reopen_requestsincident_reopen_requests
incident_commentsincident_comments
incident_code_sequencesincident_code_sequences
notification_types, notificationsnotifications
personal_access_tokenspersonal_access_tokens
dashboard_widgets, user_dashboard_widgetsDashboard
mfa_policies, user_mfa_factors, user_recovery_codesMFA
password_reset_codespassword_reset_codes
admin_action_types, admin_actionsadmin_actions
system_event_types, system_eventssystem_events
failed_jobsTabla estándar de Laravel para trabajos de cola fallidos

Datos iniciales: Seeders.

Dónde está en el código