Files
analiticaNucleo/nuxt4-app/server/api/metabase/panorama.post.ts
josedario87 ce7bec7d4c
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 47s
Fix: corregir tipos de parámetros para queries nativas SQL de Metabase
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.
2025-10-29 10:32:10 -06:00

174 lines
6.3 KiB
TypeScript

import { METABASE_QUERIES } from '../../config/metabase-queries'
/**
* Execute all panorama queries in parallel
* Returns data for the Panorama Facturador page
*/
export default defineEventHandler(async (event) => {
const body = await readBody(event)
const { fecha_desde = null, fecha_hasta = null, incluir_anulados = false } = body
try {
// First, get all cards to find our panorama queries
const allCards = await getMetabaseCards('all')
// Find our panorama queries by name using centralized config
const queryNames = METABASE_QUERIES.panorama
const cards: Record<string, any> = {}
console.log('[Panorama] Available cards:', allCards.map((c: any) => ({ id: c.id, name: c.name })))
console.log('[Panorama] Looking for queries:', queryNames)
for (const [key, name] of Object.entries(queryNames)) {
const card = allCards.find((c: any) => c.name === name)
if (!card) {
console.warn(`[Panorama] Query not found: ${name}`)
} else {
console.log(`[Panorama] Found card ${key}: ${name} (ID: ${card.id})`)
cards[key] = card
}
}
console.log('[Panorama] Cards to execute:', Object.keys(cards))
// Build parameters array for Metabase queries
// Las queries SQL nativas usan template-tags de tipo 'text' para fechas, no 'date/single'
const parameters = [
{
type: 'text',
target: ['variable', ['template-tag', 'fecha_desde']],
value: fecha_desde || ''
},
{
type: 'text',
target: ['variable', ['template-tag', 'fecha_hasta']],
value: fecha_hasta || ''
},
{
type: 'boolean',
target: ['variable', ['template-tag', 'incluir_anulados']],
value: incluir_anulados
}
]
// Execute all queries in parallel with error handling
const executeWithErrorHandling = async (name: string, cardId: number | undefined, defaultValue: any) => {
if (!cardId) {
console.warn(`[Panorama] No card ID for ${name}`)
return defaultValue
}
try {
console.log(`[Panorama] Executing query: ${name} (ID: ${cardId}) with params:`, JSON.stringify(parameters))
const result = await executeCardQuery(cardId, parameters)
console.log(`[Panorama] Query ${name} result:`, {
hasData: !!result.data,
rowsLength: result.data?.rows?.length || 0,
colsLength: result.data?.cols?.length || 0,
firstRow: result.data?.rows?.[0] || null
})
return result
} catch (error: any) {
console.error(`[Panorama] Error executing ${name}:`, error.message, error.stack)
return defaultValue
}
}
const [
financieros,
ingresoCompra,
monetarios,
verde,
secosVendidos,
rechazos,
serieTemporal,
topClientes,
conteos
] = await Promise.all([
executeWithErrorHandling('financieros', cards.totales_financieros_principales?.id, { data: { rows: [[0, 0, 0]], cols: [] } }),
executeWithErrorHandling('ingresoCompra', cards.totales_ingreso_compra?.id, { data: { rows: [[]], cols: [] } }),
executeWithErrorHandling('monetarios', cards.totales_monetarios?.id, { data: { rows: [[]], cols: [] } }),
executeWithErrorHandling('verde', cards.totales_verde?.id, { data: { rows: [[]], cols: [] } }),
executeWithErrorHandling('secosVendidos', cards.secos_vendidos?.id, { data: { rows: [[]], cols: [] } }),
executeWithErrorHandling('rechazos', cards.rechazos_subproductos?.id, { data: { rows: [], cols: [] } }),
executeWithErrorHandling('serieTemporal', cards.serie_temporal_diaria?.id, { data: { rows: [], cols: [] } }),
executeWithErrorHandling('topClientes', cards.top_clientes?.id, { data: { rows: [], cols: [] } }),
executeWithErrorHandling('conteos', cards.conteo_registros?.id, { data: { rows: [[0, 0, 0, 0]], cols: [] } })
])
// Transform Metabase responses to objects for easier frontend consumption
const transformSingleRow = (result: any) => {
console.log('[Panorama] transformSingleRow input:', {
hasData: !!result.data,
hasRows: !!result.data?.rows,
hasCols: !!result.data?.cols,
rowsLength: result.data?.rows?.length,
colsLength: result.data?.cols?.length
})
if (!result.data?.rows?.[0] || !result.data?.cols) {
console.warn('[Panorama] transformSingleRow: Missing data, rows, or cols')
return {}
}
const row = result.data.rows[0]
const cols = result.data.cols
const obj: any = {}
cols.forEach((col: any, index: number) => {
obj[col.name] = row[index]
})
console.log('[Panorama] transformSingleRow output:', obj)
return obj
}
const transformMultipleRows = (result: any) => {
console.log('[Panorama] transformMultipleRows input:', {
hasData: !!result.data,
hasRows: !!result.data?.rows,
hasCols: !!result.data?.cols,
rowsLength: result.data?.rows?.length
})
if (!result.data?.rows || !result.data?.cols) {
console.warn('[Panorama] transformMultipleRows: Missing data, rows, or cols')
return []
}
const cols = result.data.cols
const transformed = result.data.rows.map((row: any[]) => {
const obj: any = {}
cols.forEach((col: any, index: number) => {
obj[col.name] = row[index]
})
return obj
})
console.log('[Panorama] transformMultipleRows output:', transformed.length, 'rows')
return transformed
}
// Return all data in a structured format
return {
financieros: transformSingleRow(financieros),
ingresoCompra: transformSingleRow(ingresoCompra),
monetarios: transformSingleRow(monetarios),
verde: transformSingleRow(verde),
secosVendidos: transformSingleRow(secosVendidos),
rechazos: transformMultipleRows(rechazos),
serieTemporal: transformMultipleRows(serieTemporal),
topClientes: transformMultipleRows(topClientes),
conteos: transformSingleRow(conteos)
}
} catch (error: any) {
console.error('[API] Failed to execute panorama queries:', error)
throw createError({
statusCode: error.statusCode || 500,
statusMessage: error.statusMessage || 'Failed to execute panorama queries'
})
}
})