Problemas resueltos: - Eliminada dependencia de UUIDs hardcodeados en tests - Agregadas validaciones específicas de valores esperados - Implementado cleanup automático de datos de test Cambios principales: Tests organizados por categoría (7 archivos nuevos): - test_structure.sql: 8 tests de estructura de BD - test_constraints.sql: 6 tests de validaciones - test_triggers.sql: 3 tests de triggers automáticos - test_queries.sql: 5 tests de queries típicas - test_functions.sql: 3 tests de funciones auxiliares - test_edge_cases.sql: 7 tests de casos límite - test_indexes.sql: 6 tests de uso de índices Mejoras implementadas: - Cada test genera sus propios datos dinámicamente - Tests usan bloques DO $$ con UUIDs generados - Validaciones específicas con valores esperados - Cleanup automático al finalizar cada test - Tests de casos edge (arrays vacíos, NULL, límites) - Verificación de uso de índices con EXPLAIN test_all.sql actualizado: - Ahora ejecuta todos los archivos organizados - Total: ~38 tests independientes y robustos - Progreso visual por categoría - ASCII art y mejor presentación Todos los tests verificados y funcionando correctamente
rioCata - Sistema de Catación de Café
Sistema digital para realizar sesiones de catación de café de manera ordenada y profesional.
Arquitectura
- Base de datos: PostgreSQL 16 con extensiones para JSONB y arrays
- Containerización: Docker Compose
- Estructura de datos: Modelo relacional optimizado para catación profesional
Estructura del Proyecto
rioCata/
├── docker-compose.yml # Configuración de servicios
├── scripts/ # Scripts de gestión y administración
│ ├── riocata.sh # Script helper principal
│ └── README.md # Documentación de scripts
├── postgres/
│ ├── init/ # Scripts de inicialización (ejecutados automáticamente)
│ │ ├── 01_schema.sql # Tipos y tablas
│ │ ├── 02_functions.sql # Funciones y triggers
│ │ ├── 03_indexes.sql # Índices de optimización
│ │ └── 04_sample_data.sql # Datos de prueba
│ └── tests/ # Scripts de testing
│ ├── test_all.sql # Suite completa de tests
│ └── example_queries.sql # Queries de ejemplo
└── README.md
Inicio Rápido
1. Levantar el entorno
docker-compose up -d
Esto iniciará PostgreSQL con todos los scripts de inicialización ejecutados automáticamente.
2. Verificar que el servicio está corriendo
docker-compose ps
Deberías ver riocata_postgres en estado Up.
3. Conectarse a la base de datos
docker-compose exec postgres psql -U riocata_user -d riocata
4. Ejecutar los tests
Una vez dentro de psql:
\i postgres/tests/test_all.sql
Esto ejecutará 18 tests que validan:
- Existencia de tablas y tipos
- Funcionamiento de triggers
- Constraints de validación
- Queries típicas
- Funciones auxiliares
5. Explorar los datos de ejemplo
\i postgres/tests/example_queries.sql
Esto ejecutará 17 queries de ejemplo que muestran:
- Listado de sesiones, muestras y evaluaciones
- Top evaluaciones por puntaje
- Evaluaciones con defectos
- Promedios de parámetros por muestra
- Análisis de notas de fragancia y sabor
- Estadísticas por catador
Scripts Helper
Para facilitar la gestión del proyecto, hay scripts helper disponibles en la carpeta scripts/.
Script Principal: riocata.sh
El script scripts/riocata.sh proporciona comandos útiles para gestión:
# Ver ayuda
./scripts/riocata.sh help
# Iniciar servicios
./scripts/riocata.sh start
# Conectarse a PostgreSQL
./scripts/riocata.sh psql
# Ejecutar tests
./scripts/riocata.sh test
# Ejecutar queries de ejemplo
./scripts/riocata.sh queries
# Ver estado
./scripts/riocata.sh status
# Crear backup
./scripts/riocata.sh backup
# Restaurar backup
./scripts/riocata.sh restore backup_20251017_143022.sql
# Detener servicios
./scripts/riocata.sh stop
# Reiniciar todo (borra datos - ¡CUIDADO!)
./scripts/riocata.sh reset
Documentación completa: Ver scripts/README.md para información detallada sobre todos los comandos disponibles.
Modelo de Datos
Tablas Principales
sesion
Representa una sesión de catación.
id: UUID (PK)codigo: Código único (ej. "S-2025-10-17-01")fecha: Fecha de la cataciónnombre: Nombre descriptivo (ej. "Mesa Laboratorio #1")
auth.users
Usuarios/catadores del sistema (simula Supabase auth.users).
id: UUID (PK)email: Email úniconombre: Nombre del catador
sesion_participante
Relación de catadores participantes en una sesión.
id: UUID (PK)sesion_id: FK a sesioncatador_id: FK a auth.usersrol: Rol del participante (catador, juez, etc.)
muestra
Muestras de café evaluadas en una sesión.
id: UUID (PK)sesion_id: FK a sesioncodigo: Código de la muestra (ej. "Muestra A-101")posicion: Orden físico en la mesa
evaluacion
Evaluación completa de una muestra por un catador.
Campos de intensidades (JSONB):
intensidades: JSON con 8 parámetros (descriptiva 1-15, afectiva 1-10):- fragancia, aroma, sabor, saborResidual
- acidez, dulzor, sensacionBoca, impresionGlobal
Campos de notas (JSONB arrays):
fragancia_aroma_notas: Array de objetos {categoria, subcategoria, notaEspecifica}sabor_notas: Array de objetos {categoria, subcategoria, notaEspecifica}
Campos de arrays:
tazas_no_uniformes: smallint[] (valores 1-5)tazas_defectuosas: smallint[] (valores 1-5)sensacion_en_boca: text[] (Áspero, Suave, Aceitoso, Metálico, Astringente)gustos_predominantes: text[] (1-2 elementos: Salado, Amargo, Ácido, Dulce, Umami)
Otros campos:
defecto: ENUM (Mohoso, Fenólico, Papa)otras_notas: Texto librepuntaje_final: int (calculado automáticamente por trigger)
Triggers Automáticos
trg_eval_updated_at: Actualizaupdated_aten cada UPDATEtrg_eval_score_bi: Calculapuntaje_finalcomo suma de valores afectivos
Constraints de Validación
- Tazas no uniformes/defectuosas: solo valores 1-5
- Sensaciones en boca: solo valores permitidos
- Gustos predominantes: máximo 2 elementos
- Intensidades descriptivas: rango 1-15
- Intensidades afectivas: rango 1-10
- Una evaluación única por participante/muestra
Funciones Auxiliares
get_promedio_parametro_afectivo(sesion_id, parametro)
Obtiene el promedio de un parámetro afectivo para toda una sesión.
SELECT get_promedio_parametro_afectivo(
'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
'acidez'
);
get_top_muestras(sesion_id, limit)
Obtiene las mejores muestras de una sesión ordenadas por puntaje.
SELECT * FROM get_top_muestras(
'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
3
);
Queries Típicas
Promedio de dulzor por sesión
SELECT s.id, AVG(((e.intensidades->'dulzor'->>'afectiva')::int))
FROM sesion s
JOIN muestra m ON m.sesion_id = s.id
JOIN evaluacion e ON e.muestra_id = m.id
WHERE s.id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
GROUP BY s.id;
Buscar evaluaciones con defecto específico
SELECT e.*
FROM evaluacion e
WHERE e.defecto = 'Fenólico';
Buscar taza defectuosa específica (usando índice GIN)
SELECT e.*
FROM evaluacion e
WHERE e.tazas_defectuosas @> ARRAY[5]::smallint[];
Top 3 muestras por puntaje
SELECT m.codigo, e.puntaje_final, sp.catador_id
FROM muestra m
JOIN evaluacion e ON e.muestra_id = m.id
JOIN sesion_participante sp ON sp.id = e.sesion_participante_id
WHERE m.sesion_id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
ORDER BY e.puntaje_final DESC
LIMIT 3;
Filtrar por acidez alta (usa índice funcional)
SELECT *
FROM evaluacion
WHERE ((intensidades->'acidez'->>'afectiva')::int) >= 8;
Datos de Prueba
El sistema viene con datos de prueba precargados:
- 3 usuarios: Dario, Juan Pérez, María González
- 1 sesión: "Mesa Laboratorio #1 - Lotes Lavados"
- 3 muestras: A-101, B-202, C-303
- 5 evaluaciones: Con variedad de puntajes, defectos, y características
Configuración
Credenciales por defecto (docker-compose.yml)
- Base de datos:
riocata - Usuario:
riocata_user - Contraseña:
riocata_password - Puerto:
5432
Modificar credenciales
Edita docker-compose.yml y cambia las variables de entorno:
environment:
POSTGRES_DB: tu_base_de_datos
POSTGRES_USER: tu_usuario
POSTGRES_PASSWORD: tu_contraseña
Comandos Útiles
Ver logs de PostgreSQL
docker-compose logs -f postgres
Reiniciar la base de datos (¡CUIDADO! Borra todos los datos)
docker-compose down -v
docker-compose up -d
Backup de la base de datos
docker-compose exec postgres pg_dump -U riocata_user riocata > backup.sql
Restaurar backup
docker-compose exec -T postgres psql -U riocata_user -d riocata < backup.sql
Ejecutar script SQL desde el host
docker-compose exec -T postgres psql -U riocata_user -d riocata < mi_script.sql
Optimizaciones
El esquema incluye múltiples índices para optimizar queries comunes:
- Índices B-tree en claves foráneas y puntaje_final
- Índices GIN en JSONB y arrays (para operadores @>, &&, etc.)
- Índices funcionales para valores específicos en JSONB
- Índices de texto para búsqueda full-text en español
Próximos Pasos
- Frontend: Desarrollar UI en Nuxt 4
- API: Crear endpoints REST/GraphQL
- Autenticación: Integrar con Supabase Auth
- Análisis: Dashboards y reportes estadísticos
- Export: Generar PDFs de sesiones de catación
Desarrollo
Para desarrollar sobre este esquema:
- Los scripts en
postgres/init/solo se ejecutan la primera vez - Para aplicar cambios, usa migrations o reinicia el contenedor con
-v - Los tests en
postgres/tests/son re-ejecutables sin problemas
Soporte
Para reportar problemas o sugerencias, contacta al equipo de Nucleo Rio Frio.
Desarrollado por Nucleo Rio Frio con Claude Code