Files
seguidorDeLotes/nuxt4/server/database
josedario87 6f49b315cb
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m3s
Corregir script de seed: separar RETURNING en múltiples INSERT
PostgreSQL no soporta RETURNING id INTO con múltiples variables cuando
se insertan múltiples filas. Separado en INSERT individuales.
2025-11-21 19:07:06 -06:00
..

Database - Scripts SQL

Este directorio contiene los scripts SQL para inicializar y gestionar la base de datos PostgreSQL del sistema de trazabilidad.


Archivos

01_schema.sql

Crea el esquema completo de la base de datos:

  • Tablas: lotes, operaciones, operacion_lotes
  • Índices para optimización
  • Función get_trazabilidad() para queries recursivas
  • Vista vista_lotes_con_origen
  • Constraints y validaciones

02_seed.sql

Datos de ejemplo que representan un flujo completo:

  • Ingreso de uva (2086 kg)
  • Despulpado → primera, segunda, rechazos
  • Oreado (con error de registro)
  • Ajuste de merma (1500 → 1480 kg)
  • Ajuste de tipo (oreado → presecado)
  • Reposo
  • Secado final (mezcla de 2 lotes = 2000 kg)

Ejecución Automática

Cuando usas Docker Compose, estos scripts se ejecutan automáticamente al iniciar PostgreSQL por primera vez gracias al montaje:

volumes:
  - ./nuxt4/server/database:/docker-entrypoint-initdb.d:ro

PostgreSQL ejecuta todos los archivos .sql en orden alfabético dentro de /docker-entrypoint-initdb.d/.

Orden de ejecución:

  1. 01_schema.sql - Crea estructura
  2. 02_seed.sql - Inserta datos de ejemplo

Ejecución Manual

Opción 1: Desde el contenedor Docker

# Conectarse al contenedor
docker exec -it seguidorDeLotes-postgres psql -U seguidor -d seguidor_lotes

# Dentro de psql, ejecutar:
\i /docker-entrypoint-initdb.d/01_schema.sql
\i /docker-entrypoint-initdb.d/02_seed.sql

Opción 2: Desde tu máquina local

# Asegúrate de tener psql instalado
psql -h localhost -U seguidor -d seguidor_lotes -f 01_schema.sql
psql -h localhost -U seguidor -d seguidor_lotes -f 02_seed.sql

Opción 3: Copiar y pegar en pgAdmin o DBeaver

Abre los archivos .sql en tu cliente SQL favorito y ejecútalos directamente.


Reiniciar la Base de Datos

Si necesitas empezar desde cero:

# Detener contenedores y eliminar volúmenes
docker-compose down -v

# Volver a iniciar (ejecutará scripts automáticamente)
docker-compose up -d

# Ver logs para confirmar
docker logs -f seguidorDeLotes-postgres

Verificar que todo está correcto

1. Conectarse a la base de datos

docker exec -it seguidorDeLotes-postgres psql -U seguidor -d seguidor_lotes

2. Listar tablas

\dt

Deberías ver:

              List of relations
 Schema |       Name       | Type  |  Owner
--------+------------------+-------+----------
 public | lotes            | table | seguidor
 public | operacion_lotes  | table | seguidor
 public | operaciones      | table | seguidor

3. Contar registros

SELECT
  (SELECT COUNT(*) FROM lotes) as total_lotes,
  (SELECT COUNT(*) FROM operaciones) as total_operaciones,
  (SELECT COUNT(*) FROM operacion_lotes) as total_relaciones;

Deberías ver algo como:

 total_lotes | total_operaciones | total_relaciones
-------------+-------------------+------------------
           9 |                 8 |               16

4. Ver lotes creados

SELECT codigo, tipo, cantidad_kg FROM lotes ORDER BY fecha_creado;

Deberías ver:

  codigo   |         tipo         | cantidad_kg
-----------+----------------------+-------------
 UVA-001   | uva                  |     2086.00
 PRIM-001  | despulpado_primera   |     1500.00
 SEG-001   | despulpado_segunda   |      400.00
 RECH-001  | despulpado_rechazos  |      150.00
 ORE-001   | oreado               |     1500.00
 ORE-001A  | oreado               |     1480.00
 PRE-001   | presecado            |     1480.00
 REP-001   | reposo               |     1480.00
 REP-002   | reposo               |      520.00
 SEC-001   | secado               |     2000.00

5. Probar la función de trazabilidad

SELECT * FROM get_trazabilidad(
  (SELECT id FROM lotes WHERE codigo = 'SEC-001')
);

Deberías ver: Todo el historial del lote SEC-001 desde el ingreso de uva.


Estructura de las Tablas

Tabla lotes

CREATE TABLE lotes (
  id              UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  codigo          TEXT UNIQUE,
  tipo            TEXT NOT NULL,
  fecha_creado    TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  lugar_id        INTEGER,
  cantidad_kg     NUMERIC(10,2),
  meta            JSONB
);

Tabla operaciones

CREATE TABLE operaciones (
  id           UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tipo         TEXT NOT NULL,
  fecha        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  lugar_id     INTEGER,
  meta         JSONB
);

Tabla operacion_lotes

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 CHECK (rol IN ('input', 'output')),
  cantidad_kg   NUMERIC(10,2),
  PRIMARY KEY (operacion_id, lote_id, rol)
);

Queries Útiles

Ver todas las operaciones de un lote

SELECT
  o.tipo AS operacion,
  o.fecha,
  ol.rol,
  ol.cantidad_kg
FROM operacion_lotes ol
JOIN operaciones o ON o.id = ol.operacion_id
WHERE ol.lote_id = (SELECT id FROM lotes WHERE codigo = 'SEC-001')
ORDER BY o.fecha;

Ver lotes que se usaron para crear un lote específico (inputs directos)

-- Inputs directos del lote SEC-001
SELECT
  l.codigo,
  l.tipo,
  l.cantidad_kg,
  o.tipo AS operacion_tipo
FROM lotes l
JOIN operacion_lotes ol_in ON ol_in.lote_id = l.id
JOIN operacion_lotes ol_out ON ol_out.operacion_id = ol_in.operacion_id
JOIN operaciones o ON o.id = ol_out.operacion_id
WHERE ol_out.lote_id = (SELECT id FROM lotes WHERE codigo = 'SEC-001')
  AND ol_out.rol = 'output'
  AND ol_in.rol = 'input';

Ver estadísticas de un período

SELECT
  tipo,
  COUNT(*) as total,
  SUM(cantidad_kg) as kg_totales
FROM operaciones
WHERE fecha >= NOW() - INTERVAL '30 days'
GROUP BY tipo
ORDER BY total DESC;

Migraciones Futuras

Cuando necesites hacer cambios al esquema en producción:

  1. Crear archivo de migración (ej: 03_add_lugares_table.sql)
  2. NO modificar 01_schema.sql ni 02_seed.sql directamente
  3. Aplicar migración manualmente en producción

Ejemplo de migración:

-- 03_add_lugares_table.sql
CREATE TABLE IF NOT EXISTS lugares (
  id SERIAL PRIMARY KEY,
  nombre TEXT NOT NULL,
  tipo TEXT, -- patio, pila, bodega, etc.
  capacidad_kg NUMERIC
);

-- Agregar foreign key a lotes
ALTER TABLE lotes
  ADD CONSTRAINT fk_lotes_lugar
  FOREIGN KEY (lugar_id) REFERENCES lugares(id);

Backup y Restore

Hacer backup

docker exec seguidorDeLotes-postgres pg_dump -U seguidor seguidor_lotes > backup_$(date +%Y%m%d).sql

Restaurar backup

cat backup_20251121.sql | docker exec -i seguidorDeLotes-postgres psql -U seguidor -d seguidor_lotes

Troubleshooting

"relation lotes does not exist"

Los scripts no se ejecutaron. Verificar:

docker logs seguidorDeLotes-postgres

Si ves errores, eliminar volumen y reiniciar:

docker-compose down -v
docker-compose up -d

"permission denied for schema public"

Problema de permisos. Conectarse como superuser:

docker exec -it seguidorDeLotes-postgres psql -U postgres -d seguidor_lotes

-- Dar permisos
GRANT ALL ON SCHEMA public TO seguidor;
GRANT ALL ON ALL TABLES IN SCHEMA public TO seguidor;

Los datos de ejemplo se duplican

02_seed.sql hace TRUNCATE al inicio. Si no quieres perder datos, comenta esa línea.


Referencias


Última actualización: 2025-11-21