- Crear 5 queries SQL en Metabase para datos de empleados:
* Contadores generales (horas, días, tareas)
* Lista de empleados con totales agregados
* Detalle de tareas realizadas
* Detalle de asistencias con cálculo de horas
* Opciones de filtros disponibles
- Implementar backend API endpoint /api/metabase/informe-empleados
* Soporte para filtros por fecha, empleados, títulos de tareas y planillas
* Ejecución paralela de queries con manejo de errores
* Transformación de datos de Metabase a formato consumible
- Crear componente TotalesEmpleados.vue
* Visualización de métricas principales (horas, días, tareas)
* Cálculo de promedios por empleado
* Funcionalidad de copiar texto/JSON
- Implementar página informe-empleados.vue
* Layout tipo informe con selector de fechas
* Filtros avanzados por empleado, títulos de tareas y planillas
* Tabla integrada de empleados con métricas clave
* Estados de carga, error y bienvenida
* Detección de cambios pendientes
- Actualizar configuración de queries en metabase-queries.ts
Estructura trabajada:
- clientes (empleado = true)
- asistencias (con cálculo de horas trabajadas)
- tareas_realizadas (con títulos y planillas)
- planillas (con totales y rangos de fechas)
- Crear 8 queries en Metabase para análisis de comercios:
* Lista de comercios con datos de cliente (ID: 62)
* Totales monetarios y distribución de pagos (ID: 63)
* Totales de peso por tipo de café (ID: 64)
* Top 10 comercios por inversión (ID: 65)
* Serie temporal con acumulados (ID: 66)
* Opciones de filtros disponibles (ID: 67)
* Contadores para estadísticas (ID: 68)
* Detalle de ingresos por comercio (ID: 69)
- Crear endpoint POST /api/metabase/informe-comercios
* Ejecuta 8 queries en paralelo
* Soporta filtros: fechas, clientes, tipos, comercio_ids, granularidad
* Manejo robusto de errores por query individual
* Transformación de resultados a objetos JavaScript
- Actualizar configuración de queries en metabase-queries.ts
* Agregar sección informe_comercios con 8 queries
* Agregar type helper InformeComerciosQueryKey
- Documentar progreso completo en INFORME_COMERCIOS_PROGRESO.md
* Backend 100% completado
* Frontend pendiente (componentes Vue y página principal)
* Guía detallada de queries y estructura de datos
* Próximos pasos y opciones de implementación
Progreso: 70% (Backend completo, Frontend pendiente)
Query 59 (metadata_cosechas) no necesita parámetros porque devuelve
todas las cosechas disponibles, no solo las seleccionadas. Pasarle
parámetros causa que devuelva datos vacíos.
- Actualizar Queries 56-59 en Metabase via API:
* Eliminar filtro de 'incluir_anulados' (columnas no existen en vista_resumen_ingresos)
* Usar 'total_lempiras_mojado_oreado' en lugar de columnas separadas
* Mantener cast ::text[] para parámetro cosechas_ids
- Actualizar backend (comparativa-cosechas.post.ts):
* Eliminar parámetro incluir_anulados del body
* Mantener conversión de array JS a formato PostgreSQL {elem1,elem2}
- Actualizar frontend (comparativa-cosechas.vue):
* Eliminar envío de parámetro incluir_anulados en fetch
Queries funcionando correctamente con vista_resumen_ingresos.
- Agregar contador de Queries Comparativa (4/4) en estadísticas
- Agregar nueva tab "Queries Comparativa" en metabase-debug
- Actualizar endpoint query-config para incluir queries comparativa
- Agregar computeds comparativaQueries y missingComparativaQueries
- Mostrar las 4 queries de comparativa con sus detalles
- Reorganizar grid de estadísticas para 6 columnas
La nueva tab permite visualizar y debuggear las queries:
- comparativa_datos_diarios_completos
- comparativa_totales_por_cosecha
- comparativa_datos_acumulados_por_dia
- comparativa_metadata_cosechas
- Agregar configuración de queries comparativa en metabase-queries.ts
- Crear endpoint /api/metabase/comparativa-cosechas.post.ts
- Crear 4 queries en Metabase:
* comparativa_datos_diarios_completos (ID: 56)
* comparativa_totales_por_cosecha (ID: 57)
* comparativa_datos_acumulados_por_dia (ID: 58)
* comparativa_metadata_cosechas (ID: 59)
- Restaurar página comparativa-cosechas.vue con nueva arquitectura
- Remover badge de mantenimiento del sidebar
- Integrar con componentes CosechasHeatmap, CosechasEvolucion y CosechasTotales
- Usar vista_resumen_ingresos como fuente de datos
La página permite comparar métricas entre diferentes cosechas de café
con visualizaciones interactivas y filtros configurables.
Problema: Las queries de Metabase en el endpoint /api/metabase/informe
retornaban 0 filas porque se enviaban par\u00e1metros con arrays vac\u00edos,
lo cual activaba filtros condicionales sin valores.
Soluci\u00f3n: Modificar buildParameters() para solo incluir par\u00e1metros
opcionales (cliente_ids, tipos, estados, ubicaciones, calidades) cuando
tengan valores (arrays no vac\u00edos). Los filtros condicionales [[...]]
de Metabase ahora se omiten correctamente cuando no hay valores.
BREAKING: Violación de arquitectura corregida
- Eliminar endpoint /api/postgres/query (acceso directo a DB prohibido)
- Cambiar /api/clientes para usar query de Metabase en lugar de SQL directo
- Crear endpoint /api/metabase/opciones-filtros para obtener opciones
- Cambiar loadOpcionesFiltros para usar API en lugar de MCP directo
- Usar "Informe Ingresos - Lista de Clientes con Totales" para clientes
- Usar "Informe Ingresos - Opciones de Filtros" para opciones
- Respetar filosofía: Metabase calcula TODO, Vue solo renderiza
- La app NUNCA habla directamente con bases de datos
Cambios principales:
- Cambiar tipo de parámetros de fecha de 'date/single' a 'text'
- Cambiar tipo de parámetro booleano de 'category' a 'boolean'
- Cambiar tipo de parámetros de categoría de 'category' a 'text'
Las queries SQL nativas en Metabase usan template-tags con tipos específicos
que deben coincidir exactamente con el tipo definido en el template-tag,
no con los tipos de UI de Metabase.
Archivos modificados:
- server/api/metabase/panorama.post.ts
- server/api/metabase/informe.post.ts
Resuelve el problema donde todas las queries retornaban error 500 y
respuestas vacías debido a tipos de parámetros incompatibles.
- Agregar logs para verificar que las cards se encuentren correctamente
- Agregar logs detallados de los parámetros enviados a cada query
- Agregar logs de la estructura de respuesta de Metabase
- Agregar logs de la transformación de datos (single row y multiple rows)
- Esto ayudará a diagnosticar por qué las respuestas están vacías
- Modificar panorama.post.ts e informe.post.ts para convertir fecha_desde y fecha_hasta null a strings vacíos
- Las queries de Metabase usan NULLIF(?, '') para detectar parámetros vacíos
- Esto permite que las queries usen sus defaults (fecha actual) correctamente
Cambios principales:
- Refactorizar todos los componentes de panorama para recibir datos directos de Metabase
* TotalesMonetarios.vue: cambiar de props.metrics a props.data
* TotalesIngresoCompra.vue: cambiar de props.metrics a props.data
* TotalesVerde.vue: cambiar de props.metrics a props.data
* SecosVendidos.vue: cambiar de props.metrics a props.data
- Eliminar fechas hardcodeadas en panorama.post.ts
* Pasar valores null directamente a Metabase para usar sus defaults
- Marcar composables obsoletos para Panorama Facturador
* useIngresosMetrics.ts: agregar advertencia de no uso en Panorama
* useRechazosMetrics.ts: agregar advertencia de no uso en Panorama
Resultado: Todos los cálculos (agregaciones, promedios ponderados) se hacen en Metabase mediante SQL. Los componentes Vue solo renderizan valores ya calculados.
- Remover badge de mantenimiento del sidebar
- Eliminar endpoints de debug temporales
- Panorama funcionando con todas las secciones:
* Totales Financieros
* Café Seco - Inventario y Proyecciones
* Totales de Ingreso y Compra
* Totales Monetarios
* Café Verde
* Rechazos y Subproductos
- Todas las 9 queries de Metabase ejecutándose correctamente
- Datos reales mostrados en tiempo real
Las queries de Metabase tienen fecha_desde y fecha_hasta como parametros
requeridos con valores por defecto. Cuando se envia null, Metabase rechaza
la query. Ahora usamos los defaults cuando no se especifican fechas.
- Crear endpoint /api/metabase/panorama.post.ts que ejecuta las 9 queries en paralelo
- Restaurar y adaptar panorama.vue para usar el nuevo endpoint
- Crear componentes auxiliares: SecosVendidos, TotalesIngresoCompra, TotalesMonetarios, TotalesVerde, MetricBox, RechazosRechazoCard
- Adaptar RechazosSubproductos para recibir data directamente de Metabase
- Toda la transformación de datos ocurre en las queries SQL de Metabase
- Sin uso de stores ni composables de métricas
- Agregar documentación de queries en archivos MD
- Crear componente MetabaseCardDisplay para mostrar detalles de queries
- Crear componente MetabaseCardsTable para listar todas las queries
- Crear página /metabase-debug con vistas de tabla, cards y queries Panorama
- Agregar API routes para cards de Metabase (GET, POST, export)
- Actualizar metabase.ts para soportar API Key authentication
- Agregar configuración de Metabase API Key en nuxt.config.ts
- Documentar todos los endpoints disponibles en METABASE_API_ENDPOINTS.md
Metabase API returns {data: [...], total: number} instead of
a direct array. Update databases endpoint to extract and return
only the data array for easier frontend consumption.
Verified working with:
- facturador supabase (PostgreSQL, ID: 2)
- Sample Database (H2, ID: 1)
Add complete integration with Metabase API to fetch data from
'facturador supabase' database.
Features:
- Server-side Metabase authentication using session tokens
- Utility functions for Metabase API requests with auto-retry
- API endpoints to proxy Metabase requests
- GET /api/metabase/databases - List all databases
- GET /api/metabase/tables/:databaseId - Get tables and metadata
- POST /api/metabase/query - Execute queries against tables
- useMetabase() composable for frontend consumption
- getDatabases() - Fetch available databases
- getDatabaseMetadata() - Get tables and fields info
- queryTable() - Execute queries with filters and limits
- resultToObjects() - Helper to convert results to objects
Session tokens are cached and auto-refreshed when expired.
This enables the application to display real data from the
facturador database without using embeds or iframes.