# 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 ```bash docker-compose up -d ``` Esto iniciará PostgreSQL con todos los scripts de inicialización ejecutados automáticamente. ### 2. Verificar que el servicio está corriendo ```bash docker-compose ps ``` Deberías ver `riocata_postgres` en estado `Up`. ### 3. Conectarse a la base de datos ```bash docker-compose exec postgres psql -U riocata_user -d riocata ``` ### 4. Ejecutar los tests Una vez dentro de psql: ```sql \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 ```sql \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: ```bash # 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ón - `nombre`: Nombre descriptivo (ej. "Mesa Laboratorio #1") #### `auth.users` Usuarios/catadores del sistema (simula Supabase auth.users). - `id`: UUID (PK) - `email`: Email único - `nombre`: Nombre del catador #### `sesion_participante` Relación de catadores participantes en una sesión. - `id`: UUID (PK) - `sesion_id`: FK a sesion - `catador_id`: FK a auth.users - `rol`: Rol del participante (catador, juez, etc.) #### `muestra` Muestras de café evaluadas en una sesión. - `id`: UUID (PK) - `sesion_id`: FK a sesion - `codigo`: 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 libre - `puntaje_final`: int (calculado automáticamente por trigger) ### Triggers Automáticos 1. **`trg_eval_updated_at`**: Actualiza `updated_at` en cada UPDATE 2. **`trg_eval_score_bi`**: Calcula `puntaje_final` como 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. ```sql 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. ```sql SELECT * FROM get_top_muestras( 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 3 ); ``` ## Queries Típicas ### Promedio de dulzor por sesión ```sql 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 ```sql SELECT e.* FROM evaluacion e WHERE e.defecto = 'Fenólico'; ``` ### Buscar taza defectuosa específica (usando índice GIN) ```sql SELECT e.* FROM evaluacion e WHERE e.tazas_defectuosas @> ARRAY[5]::smallint[]; ``` ### Top 3 muestras por puntaje ```sql 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) ```sql 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: ```yaml environment: POSTGRES_DB: tu_base_de_datos POSTGRES_USER: tu_usuario POSTGRES_PASSWORD: tu_contraseña ``` ## Comandos Útiles ### Ver logs de PostgreSQL ```bash docker-compose logs -f postgres ``` ### Reiniciar la base de datos (¡CUIDADO! Borra todos los datos) ```bash docker-compose down -v docker-compose up -d ``` ### Backup de la base de datos ```bash docker-compose exec postgres pg_dump -U riocata_user riocata > backup.sql ``` ### Restaurar backup ```bash docker-compose exec -T postgres psql -U riocata_user -d riocata < backup.sql ``` ### Ejecutar script SQL desde el host ```bash 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 1. **Frontend**: Desarrollar UI en Nuxt 4 2. **API**: Crear endpoints REST/GraphQL 3. **Autenticación**: Integrar con Supabase Auth 4. **Análisis**: Dashboards y reportes estadísticos 5. **Export**: Generar PDFs de sesiones de catación ## Desarrollo Para desarrollar sobre este esquema: 1. Los scripts en `postgres/init/` solo se ejecutan la primera vez 2. Para aplicar cambios, usa migrations o reinicia el contenedor con `-v` 3. 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