Inicializar rioCata - Sistema de Catación de Café

- Base de datos PostgreSQL 16 con extensiones JSONB y arrays
- Docker Compose para containerización
- Scripts SQL de inicialización (schema, funciones, índices, datos de prueba)
- Suite de tests de validación (18 tests)
- Queries de ejemplo (17 queries)
- Script helper para gestión (scripts/riocata.sh)
- Documentación completa en README.md

Estructura:
- 4 tablas principales: sesion, auth.users, sesion_participante, muestra, evaluacion
- Tipo ENUM para defectos
- 2 triggers automáticos (updated_at, puntaje_final)
- 19 índices de optimización (GIN, B-tree, funcionales)
- Constraints de validación para arrays y JSONB
- 2 funciones auxiliares para análisis
This commit is contained in:
2025-10-17 17:00:48 -06:00
commit f682c3db51
11 changed files with 2166 additions and 0 deletions

View File

@@ -0,0 +1,296 @@
-- ============================================
-- rioCata - Queries de Ejemplo
-- ============================================
-- Este archivo contiene queries de ejemplo
-- para explorar los datos de catación
-- ============================================
\echo '=========================================='
\echo 'Queries de Ejemplo - rioCata'
\echo '=========================================='
\echo ''
-- ============================================
-- QUERY 1: Listar todas las sesiones
-- ============================================
\echo '[QUERY 1] Sesiones de catación:'
SELECT
codigo,
fecha,
nombre,
created_at
FROM sesion
ORDER BY fecha DESC;
\echo ''
-- ============================================
-- QUERY 2: Participantes de una sesión
-- ============================================
\echo '[QUERY 2] Participantes de la sesión S-2025-10-17-01:'
SELECT
u.nombre AS catador,
u.email,
sp.rol
FROM sesion s
JOIN sesion_participante sp ON sp.sesion_id = s.id
JOIN auth.users u ON u.id = sp.catador_id
WHERE s.codigo = 'S-2025-10-17-01';
\echo ''
-- ============================================
-- QUERY 3: Muestras de una sesión
-- ============================================
\echo '[QUERY 3] Muestras de la sesión S-2025-10-17-01:'
SELECT
m.codigo AS muestra,
m.posicion,
COUNT(e.id) AS num_evaluaciones
FROM sesion s
JOIN muestra m ON m.sesion_id = s.id
LEFT JOIN evaluacion e ON e.muestra_id = m.id
WHERE s.codigo = 'S-2025-10-17-01'
GROUP BY m.id, m.codigo, m.posicion
ORDER BY m.posicion;
\echo ''
-- ============================================
-- QUERY 4: Top 5 evaluaciones por puntaje
-- ============================================
\echo '[QUERY 4] Top 5 evaluaciones por puntaje final:'
SELECT
m.codigo AS muestra,
u.nombre AS catador,
e.puntaje_final,
e.otras_notas
FROM evaluacion e
JOIN muestra m ON m.id = e.muestra_id
JOIN sesion_participante sp ON sp.id = e.sesion_participante_id
JOIN auth.users u ON u.id = sp.catador_id
ORDER BY e.puntaje_final DESC
LIMIT 5;
\echo ''
-- ============================================
-- QUERY 5: Evaluaciones con defectos
-- ============================================
\echo '[QUERY 5] Evaluaciones con defectos:'
SELECT
m.codigo AS muestra,
u.nombre AS catador,
e.defecto,
e.tazas_defectuosas,
e.puntaje_final
FROM evaluacion e
JOIN muestra m ON m.id = e.muestra_id
JOIN sesion_participante sp ON sp.id = e.sesion_participante_id
JOIN auth.users u ON u.id = sp.catador_id
WHERE e.defecto IS NOT NULL
ORDER BY e.created_at;
\echo ''
-- ============================================
-- QUERY 6: Promedio de puntajes por muestra
-- ============================================
\echo '[QUERY 6] Promedio de puntajes por muestra:'
SELECT
m.codigo AS muestra,
COUNT(e.id) AS num_evaluaciones,
ROUND(AVG(e.puntaje_final), 2) AS puntaje_promedio,
MIN(e.puntaje_final) AS puntaje_minimo,
MAX(e.puntaje_final) AS puntaje_maximo
FROM muestra m
LEFT JOIN evaluacion e ON e.muestra_id = m.id
GROUP BY m.id, m.codigo
ORDER BY puntaje_promedio DESC NULLS LAST;
\echo ''
-- ============================================
-- QUERY 7: Promedios de parámetros afectivos por muestra
-- ============================================
\echo '[QUERY 7] Promedios de parámetros afectivos por muestra:'
SELECT
m.codigo AS muestra,
ROUND(AVG((e.intensidades->'fragancia'->>'afectiva')::int), 2) AS fragancia,
ROUND(AVG((e.intensidades->'aroma'->>'afectiva')::int), 2) AS aroma,
ROUND(AVG((e.intensidades->'sabor'->>'afectiva')::int), 2) AS sabor,
ROUND(AVG((e.intensidades->'acidez'->>'afectiva')::int), 2) AS acidez,
ROUND(AVG((e.intensidades->'dulzor'->>'afectiva')::int), 2) AS dulzor
FROM muestra m
JOIN evaluacion e ON e.muestra_id = m.id
GROUP BY m.id, m.codigo
ORDER BY m.codigo;
\echo ''
-- ============================================
-- QUERY 8: Evaluaciones con tazas no uniformes
-- ============================================
\echo '[QUERY 8] Evaluaciones con tazas no uniformes:'
SELECT
m.codigo AS muestra,
u.nombre AS catador,
e.tazas_no_uniformes,
e.puntaje_final
FROM evaluacion e
JOIN muestra m ON m.id = e.muestra_id
JOIN sesion_participante sp ON sp.id = e.sesion_participante_id
JOIN auth.users u ON u.id = sp.catador_id
WHERE array_length(e.tazas_no_uniformes, 1) > 0
ORDER BY array_length(e.tazas_no_uniformes, 1) DESC;
\echo ''
-- ============================================
-- QUERY 9: Notas de fragancia/aroma más comunes
-- ============================================
\echo '[QUERY 9] Categorías de fragancia/aroma más frecuentes:'
SELECT
nota->>'categoria' AS categoria,
COUNT(*) AS frecuencia
FROM evaluacion e,
jsonb_array_elements(e.fragancia_aroma_notas) AS nota
GROUP BY nota->>'categoria'
ORDER BY frecuencia DESC;
\echo ''
-- ============================================
-- QUERY 10: Notas de sabor más comunes
-- ============================================
\echo '[QUERY 10] Categorías de sabor más frecuentes:'
SELECT
nota->>'categoria' AS categoria,
COUNT(*) AS frecuencia
FROM evaluacion e,
jsonb_array_elements(e.sabor_notas) AS nota
GROUP BY nota->>'categoria'
ORDER BY frecuencia DESC;
\echo ''
-- ============================================
-- QUERY 11: Gustos predominantes más comunes
-- ============================================
\echo '[QUERY 11] Gustos predominantes más frecuentes:'
SELECT
UNNEST(gustos_predominantes) AS gusto,
COUNT(*) AS frecuencia
FROM evaluacion
GROUP BY gusto
ORDER BY frecuencia DESC;
\echo ''
-- ============================================
-- QUERY 12: Sensaciones en boca más comunes
-- ============================================
\echo '[QUERY 12] Sensaciones en boca más frecuentes:'
SELECT
UNNEST(sensacion_en_boca) AS sensacion,
COUNT(*) AS frecuencia
FROM evaluacion
GROUP BY sensacion
ORDER BY frecuencia DESC;
\echo ''
-- ============================================
-- QUERY 13: Comparación de catadores
-- ============================================
\echo '[QUERY 13] Estadísticas por catador:'
SELECT
u.nombre AS catador,
COUNT(e.id) AS num_evaluaciones,
ROUND(AVG(e.puntaje_final), 2) AS puntaje_promedio,
MIN(e.puntaje_final) AS puntaje_minimo,
MAX(e.puntaje_final) AS puntaje_maximo
FROM auth.users u
JOIN sesion_participante sp ON sp.catador_id = u.id
LEFT JOIN evaluacion e ON e.sesion_participante_id = sp.id
GROUP BY u.id, u.nombre
ORDER BY puntaje_promedio DESC;
\echo ''
-- ============================================
-- QUERY 14: Usando función auxiliar get_top_muestras
-- ============================================
\echo '[QUERY 14] Top 3 muestras usando función auxiliar:'
SELECT * FROM get_top_muestras('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 3);
\echo ''
-- ============================================
-- QUERY 15: Evaluaciones con alta acidez (>= 8)
-- ============================================
\echo '[QUERY 15] Evaluaciones con acidez afectiva >= 8:'
SELECT
m.codigo AS muestra,
u.nombre AS catador,
(e.intensidades->'acidez'->>'afectiva')::int AS acidez_afectiva,
e.puntaje_final
FROM evaluacion e
JOIN muestra m ON m.id = e.muestra_id
JOIN sesion_participante sp ON sp.id = e.sesion_participante_id
JOIN auth.users u ON u.id = sp.catador_id
WHERE ((e.intensidades->'acidez'->>'afectiva')::int) >= 8
ORDER BY acidez_afectiva DESC;
\echo ''
-- ============================================
-- QUERY 16: Búsqueda de texto en otras_notas
-- ============================================
\echo '[QUERY 16] Evaluaciones que mencionan "balanceado" en otras_notas:'
SELECT
m.codigo AS muestra,
u.nombre AS catador,
e.puntaje_final,
SUBSTRING(e.otras_notas, 1, 80) AS nota_preview
FROM evaluacion e
JOIN muestra m ON m.id = e.muestra_id
JOIN sesion_participante sp ON sp.id = e.sesion_participante_id
JOIN auth.users u ON u.id = sp.catador_id
WHERE to_tsvector('spanish', COALESCE(e.otras_notas, '')) @@ to_tsquery('spanish', 'balanceado')
ORDER BY e.puntaje_final DESC;
\echo ''
-- ============================================
-- QUERY 17: Detalle completo de una evaluación
-- ============================================
\echo '[QUERY 17] Detalle completo de la mejor evaluación:'
SELECT
s.nombre AS sesion,
s.fecha,
m.codigo AS muestra,
u.nombre AS catador,
u.email,
e.puntaje_final,
jsonb_pretty(e.intensidades) AS intensidades,
jsonb_pretty(e.fragancia_aroma_notas) AS fragancia_aroma,
jsonb_pretty(e.sabor_notas) AS sabor,
e.tazas_no_uniformes,
e.tazas_defectuosas,
e.sensacion_en_boca,
e.gustos_predominantes,
e.defecto,
e.otras_notas
FROM evaluacion e
JOIN muestra m ON m.id = e.muestra_id
JOIN sesion s ON s.id = m.sesion_id
JOIN sesion_participante sp ON sp.id = e.sesion_participante_id
JOIN auth.users u ON u.id = sp.catador_id
ORDER BY e.puntaje_final DESC
LIMIT 1;
\echo ''
\echo '=========================================='
\echo 'Fin de queries de ejemplo'
\echo '=========================================='