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 = {} 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' }) } })