Modelo de Datos

Modelo entidad-relación completo para Certexi — 15 tablas principales, 25 índices, registro inmutable de eventos y patrones de derivación de estado computado.

Última actualización: 2025-02-18

Modelo de Datos

Certexi usa PostgreSQL con Drizzle ORM para acceso tipo-seguro a la base de datos. El esquema sigue principios de event-sourcing — el estado mutable siempre se deriva de un registro inmutable de eventos.

Visión General Entidad-Relación

Loading diagram…

Tablas Principales

operators

Los usuarios autenticados que interactúan con el sistema.

ColumnaTipoDescripción
operator_idtext (PK)Identificador único
nametextNombre para mostrar
emailtextDirección de correo electrónico
roleenumoperator, supervisor, admin
nextcloud_idtextCuenta Nextcloud vinculada
created_attimestampHora de creación de la cuenta
last_activetimestampMarca de tiempo de última actividad

events (Registro Inmutable)

🚨

Solo-Adición

La tabla de eventos es el registro inmutable. Las filas NUNCA se actualizan ni eliminan. Todo el estado se deriva de reproducir eventos en orden cronológico.

ColumnaTipoDescripción
idserial (PK)ID auto-incremental
event_typeenumPLACED, REMOVED, VERIFIED, DISPUTED
slot_idint (FK)Slot destino
asset_barcodetextIdentificador del activo
operatortext (FK)Quién realizó la acción
timestamptimestamptzCuándo ocurrió
photo_urltextURL de la foto de evidencia
scale_weight_kgfloatPeso al momento del evento
evidence_hashtextHash SHA-256 del paquete de evidencia
merkle_roottextRaíz del árbol Merkle diario
cctv_clip_urltextClip CCTV vinculado (opcional)
work_order_reftextReferencia de orden de trabajo (opcional)

workflow_stage_history

Rastrea cada transición de etapa para unidades de transporte.

ColumnaTipoDescripción
idserial (PK)ID auto-incremental
transport_unit_idint (FK)Referencia a unidad de transporte
from_stagetextEtapa anterior
to_stagetextNueva etapa
operatortext (FK)Quién activó la transición
evidencejsonPaquete de evidencia
hashtextHash SHA-256 de la transición
created_attimestamptzHora de la transición

Índices

El esquema incluye 25 índices optimizados para patrones de consulta comunes:

TablaÍndiceColumnasPropósito
eventsidx_events_slot_timeslot_id, timestampConsultas de historial de slot
eventsidx_events_assetasset_barcodeBúsqueda de ubicación de activo
eventsidx_events_operatoroperator, timestampActividad del operador
eventsidx_events_type_timeevent_type, timestampConsultas filtradas por tipo
eventsidx_events_time_geotimestamp, locationConsultas de mapa por ventana de tiempo
slotsidx_slots_zonezoneListado de slots por zona
transport_unitsidx_tu_stagecurrent_stageConsultas Kanban
transport_unitsidx_tu_operatorassigned_operatorCarga de trabajo del operador
workflow_historyidx_wh_tutransport_unit_idHistorial de la unidad

Derivación de Estado

El estado actual nunca se almacena directamente — se computa desde el registro de eventos:

Loading diagram…

Ocupación de Slot

-- Obtener la ocupación actual de un slot
SELECT DISTINCT ON (slot_id)
  slot_id, event_type, asset_barcode, timestamp
FROM events
WHERE slot_id = $1
ORDER BY slot_id, timestamp DESC;
-- Si event_type = 'PLACED' → ocupado
-- Si event_type = 'REMOVED' → vacío

Ubicación de Activo

-- Encontrar dónde está ubicado actualmente un activo
SELECT DISTINCT ON (asset_barcode)
  slot_id, event_type, timestamp
FROM events
WHERE asset_barcode = $1
ORDER BY asset_barcode, timestamp DESC;

Utilización de Zona

-- Calcular utilización por zona
WITH latest_events AS (
  SELECT DISTINCT ON (slot_id)
    s.zone, e.event_type
  FROM events e
  JOIN slots s ON s.id = e.slot_id
  ORDER BY slot_id, e.timestamp DESC
)
SELECT zone,
  COUNT(*) FILTER (WHERE event_type = 'PLACED') AS occupied,
  COUNT(*) AS total
FROM latest_events
GROUP BY zone;

Migraciones

Drizzle ORM gestiona las migraciones del esquema con control de versiones:

# Generar migración a partir de cambios en el esquema
pnpm drizzle-kit generate:pg

# Aplicar migraciones pendientes
pnpm drizzle-kit push:pg

# Ver estado de migraciones
pnpm drizzle-kit status

Relacionado