- 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
348 lines
9.0 KiB
Markdown
348 lines
9.0 KiB
Markdown
# 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
|