Some checks failed
build-and-deploy / build-and-deploy (push) Failing after 1m47s
- Agregar PostgreSQL 16 con esquema completo - Crear API endpoints para lotes y operaciones - Implementar UI con Nuxt UI (tablas, formularios, trazabilidad) - Agregar datos de ejemplo del flujo completo - Documentar sistema en PLAN_TRAZABILIDAD.md
226 lines
8.2 KiB
PL/PgSQL
226 lines
8.2 KiB
PL/PgSQL
-- =====================================================
|
|
-- SISTEMA DE TRAZABILIDAD DE LOTES - ESQUEMA PRINCIPAL
|
|
-- =====================================================
|
|
-- Este esquema implementa un modelo de grafo para trazabilidad
|
|
-- de café desde ingreso de uva hasta secado final.
|
|
-- Permite rastrear divisiones, combinaciones y transformaciones.
|
|
|
|
-- Extensiones necesarias
|
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
|
|
-- =====================================================
|
|
-- TABLA: lotes
|
|
-- =====================================================
|
|
-- Representa cualquier estado físico del café en un momento dado.
|
|
-- Ejemplos: uva ingresada, café despulpado, café oreado, café secado, etc.
|
|
|
|
CREATE TABLE lotes (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
codigo TEXT UNIQUE, -- Código legible: UVA-001, SEC-042, etc.
|
|
tipo TEXT NOT NULL, -- uva, despulpado_primera, despulpado_segunda, despulpado_rechazos, oreado, presecado, reposo, secado
|
|
fecha_creado TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
lugar_id INTEGER, -- Referencia opcional a lugares (patio 1, pila 2, etc.)
|
|
cantidad_kg NUMERIC(10,2), -- Cantidad en kilogramos
|
|
meta JSONB, -- Información adicional (humedad, notas, etc.)
|
|
|
|
CONSTRAINT lotes_cantidad_positiva CHECK (cantidad_kg IS NULL OR cantidad_kg >= 0),
|
|
CONSTRAINT lotes_tipo_valido CHECK (tipo IN (
|
|
'uva',
|
|
'despulpado_primera',
|
|
'despulpado_segunda',
|
|
'despulpado_rechazos',
|
|
'oreado',
|
|
'presecado',
|
|
'reposo',
|
|
'secado'
|
|
))
|
|
);
|
|
|
|
-- Índices para búsquedas frecuentes
|
|
CREATE INDEX idx_lotes_tipo ON lotes(tipo);
|
|
CREATE INDEX idx_lotes_fecha_creado ON lotes(fecha_creado DESC);
|
|
CREATE INDEX idx_lotes_codigo ON lotes(codigo) WHERE codigo IS NOT NULL;
|
|
|
|
-- Comentarios
|
|
COMMENT ON TABLE lotes IS 'Representa cualquier estado físico del café en un momento dado';
|
|
COMMENT ON COLUMN lotes.codigo IS 'Código legible opcional para identificar el lote (ej: UVA-001, SEC-042)';
|
|
COMMENT ON COLUMN lotes.tipo IS 'Tipo de lote: uva, despulpado_*, oreado, presecado, reposo, secado';
|
|
COMMENT ON COLUMN lotes.meta IS 'Datos adicionales en formato JSON (ej: {humedad: 12.5, notas: "café especial"})';
|
|
|
|
|
|
-- =====================================================
|
|
-- TABLA: operaciones
|
|
-- =====================================================
|
|
-- Representa un evento donde lotes se transforman, combinan o dividen.
|
|
-- Ejemplos: ingreso de uva, despulpado, oreado, ajuste de merma, etc.
|
|
|
|
CREATE TABLE operaciones (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
tipo TEXT NOT NULL, -- Tipo de operación
|
|
fecha TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
lugar_id INTEGER, -- Referencia opcional a lugares
|
|
meta JSONB, -- Información adicional específica del tipo
|
|
|
|
CONSTRAINT operaciones_tipo_valido CHECK (tipo IN (
|
|
-- Operaciones de proceso normal
|
|
'ingreso',
|
|
'despulpado',
|
|
'oreado',
|
|
'presecado',
|
|
'reposo',
|
|
'secado',
|
|
'traslado',
|
|
'mezcla',
|
|
-- Operaciones de ajuste/corrección
|
|
'ajuste_merma',
|
|
'ajuste_cantidad',
|
|
'ajuste_tipo',
|
|
'correccion_asignacion',
|
|
'fusion_manual',
|
|
'division_manual'
|
|
))
|
|
);
|
|
|
|
-- Índices para búsquedas frecuentes
|
|
CREATE INDEX idx_operaciones_tipo ON operaciones(tipo);
|
|
CREATE INDEX idx_operaciones_fecha ON operaciones(fecha DESC);
|
|
|
|
-- Comentarios
|
|
COMMENT ON TABLE operaciones IS 'Eventos donde lotes se transforman, combinan o dividen';
|
|
COMMENT ON COLUMN operaciones.tipo IS 'Tipo de operación: ingreso, despulpado, oreado, ajuste_merma, etc.';
|
|
COMMENT ON COLUMN operaciones.meta IS 'Datos adicionales específicos del tipo de operación en formato JSON';
|
|
|
|
|
|
-- =====================================================
|
|
-- TABLA: operacion_lotes
|
|
-- =====================================================
|
|
-- Relación muchos a muchos entre operaciones y lotes.
|
|
-- Define qué lotes entran (input) y salen (output) de cada operación.
|
|
|
|
CREATE TABLE operacion_lotes (
|
|
operacion_id UUID NOT NULL REFERENCES operaciones(id) ON DELETE CASCADE,
|
|
lote_id UUID NOT NULL REFERENCES lotes(id) ON DELETE CASCADE,
|
|
rol TEXT NOT NULL, -- 'input' o 'output'
|
|
cantidad_kg NUMERIC(10,2), -- Cantidad específica usada/producida
|
|
|
|
PRIMARY KEY (operacion_id, lote_id, rol),
|
|
|
|
CONSTRAINT operacion_lotes_rol_valido CHECK (rol IN ('input', 'output')),
|
|
CONSTRAINT operacion_lotes_cantidad_positiva CHECK (cantidad_kg IS NULL OR cantidad_kg > 0)
|
|
);
|
|
|
|
-- Índices para navegación del grafo
|
|
CREATE INDEX idx_operacion_lotes_operacion ON operacion_lotes(operacion_id);
|
|
CREATE INDEX idx_operacion_lotes_lote ON operacion_lotes(lote_id);
|
|
CREATE INDEX idx_operacion_lotes_rol ON operacion_lotes(rol);
|
|
|
|
-- Comentarios
|
|
COMMENT ON TABLE operacion_lotes IS 'Define qué lotes entran y salen de cada operación (grafo de trazabilidad)';
|
|
COMMENT ON COLUMN operacion_lotes.rol IS 'input: lote usado en la operación | output: lote producido por la operación';
|
|
COMMENT ON COLUMN operacion_lotes.cantidad_kg IS 'Cantidad en kg que participó en esta relación específica';
|
|
|
|
|
|
-- =====================================================
|
|
-- FUNCIÓN: get_trazabilidad
|
|
-- =====================================================
|
|
-- Obtiene el historial completo de un lote caminando el grafo hacia atrás.
|
|
-- Retorna todos los lotes ancestros hasta llegar a los ingresos iniciales.
|
|
|
|
CREATE OR REPLACE FUNCTION get_trazabilidad(lote_id_inicial UUID)
|
|
RETURNS TABLE (
|
|
lote_id UUID,
|
|
codigo TEXT,
|
|
tipo TEXT,
|
|
cantidad_kg NUMERIC,
|
|
operacion_id UUID,
|
|
operacion_tipo TEXT,
|
|
profundidad INTEGER
|
|
) AS $$
|
|
BEGIN
|
|
RETURN QUERY
|
|
WITH RECURSIVE trazabilidad AS (
|
|
-- Punto de partida: el lote final
|
|
SELECT
|
|
l.id AS lote_id,
|
|
l.codigo,
|
|
l.tipo,
|
|
l.cantidad_kg,
|
|
ol.operacion_id,
|
|
o.tipo AS operacion_tipo,
|
|
0 AS profundidad
|
|
FROM lotes l
|
|
LEFT JOIN operacion_lotes ol ON ol.lote_id = l.id AND ol.rol = 'output'
|
|
LEFT JOIN operaciones o ON o.id = ol.operacion_id
|
|
WHERE l.id = lote_id_inicial
|
|
|
|
UNION ALL
|
|
|
|
-- Caminar hacia atrás: buscar lotes que fueron inputs
|
|
SELECT
|
|
l2.id AS lote_id,
|
|
l2.codigo,
|
|
l2.tipo,
|
|
l2.cantidad_kg,
|
|
ol2.operacion_id,
|
|
o2.tipo AS operacion_tipo,
|
|
t.profundidad + 1
|
|
FROM trazabilidad t
|
|
JOIN operacion_lotes ol_in
|
|
ON ol_in.operacion_id = t.operacion_id
|
|
AND ol_in.rol = 'input'
|
|
JOIN lotes l2
|
|
ON l2.id = ol_in.lote_id
|
|
LEFT JOIN operacion_lotes ol2
|
|
ON ol2.lote_id = l2.id
|
|
AND ol2.rol = 'output'
|
|
LEFT JOIN operaciones o2
|
|
ON o2.id = ol2.operacion_id
|
|
WHERE t.operacion_id IS NOT NULL -- Solo continuar si hay operación
|
|
)
|
|
SELECT * FROM trazabilidad
|
|
ORDER BY profundidad, tipo, codigo;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION get_trazabilidad IS 'Obtiene el historial completo de un lote caminando el grafo hacia atrás';
|
|
|
|
|
|
-- =====================================================
|
|
-- VISTA: vista_lotes_con_origen
|
|
-- =====================================================
|
|
-- Vista útil que muestra cada lote con información de la operación que lo creó.
|
|
|
|
CREATE OR REPLACE VIEW vista_lotes_con_origen AS
|
|
SELECT
|
|
l.id,
|
|
l.codigo,
|
|
l.tipo,
|
|
l.fecha_creado,
|
|
l.cantidad_kg,
|
|
l.meta,
|
|
o.id AS operacion_id,
|
|
o.tipo AS operacion_tipo,
|
|
o.fecha AS operacion_fecha
|
|
FROM lotes l
|
|
LEFT JOIN operacion_lotes ol
|
|
ON ol.lote_id = l.id
|
|
AND ol.rol = 'output'
|
|
LEFT JOIN operaciones o
|
|
ON o.id = ol.operacion_id;
|
|
|
|
COMMENT ON VIEW vista_lotes_con_origen IS 'Muestra lotes con información de la operación que los creó';
|
|
|
|
|
|
-- =====================================================
|
|
-- MENSAJES DE ÉXITO
|
|
-- =====================================================
|
|
DO $$
|
|
BEGIN
|
|
RAISE NOTICE '✓ Esquema de trazabilidad creado exitosamente';
|
|
RAISE NOTICE ' - Tabla lotes creada';
|
|
RAISE NOTICE ' - Tabla operaciones creada';
|
|
RAISE NOTICE ' - Tabla operacion_lotes creada';
|
|
RAISE NOTICE ' - Función get_trazabilidad() creada';
|
|
RAISE NOTICE ' - Vista vista_lotes_con_origen creada';
|
|
END $$;
|