/** * 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 const queryNames = [ 'panorama_totales_financieros_principales', 'panorama_totales_ingreso_compra', 'panorama_totales_monetarios', 'panorama_totales_verde', 'panorama_secos_vendidos', 'panorama_rechazos_subproductos', 'panorama_serie_temporal_diaria', 'panorama_top_clientes', 'panorama_conteo_registros' ] const cards: Record = {} for (const name of queryNames) { const card = allCards.find((c: any) => c.name === name) if (!card) { console.warn(`[Panorama] Query not found: ${name}`) } else { cards[name] = card } } // Build parameters array for Metabase queries // Los valores null se pasan directamente a Metabase para que use sus propios defaults const parameters = [ { type: 'date/single', target: ['variable', ['template-tag', 'fecha_desde']], value: fecha_desde }, { type: 'date/single', target: ['variable', ['template-tag', 'fecha_hasta']], value: fecha_hasta }, { type: 'category', 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})`) const result = await executeCardQuery(cardId, parameters) console.log(`[Panorama] Query ${name} returned ${result.data?.rows?.length || 0} rows`) return result } catch (error: any) { console.error(`[Panorama] Error executing ${name}:`, error.message) return defaultValue } } const [ financieros, ingresoCompra, monetarios, verde, secosVendidos, rechazos, serieTemporal, topClientes, conteos ] = await Promise.all([ executeWithErrorHandling('financieros', cards['panorama_totales_financieros_principales']?.id, { data: { rows: [[0, 0, 0]], cols: [] } }), executeWithErrorHandling('ingresoCompra', cards['panorama_totales_ingreso_compra']?.id, { data: { rows: [[]], cols: [] } }), executeWithErrorHandling('monetarios', cards['panorama_totales_monetarios']?.id, { data: { rows: [[]], cols: [] } }), executeWithErrorHandling('verde', cards['panorama_totales_verde']?.id, { data: { rows: [[]], cols: [] } }), executeWithErrorHandling('secosVendidos', cards['panorama_secos_vendidos']?.id, { data: { rows: [[]], cols: [] } }), executeWithErrorHandling('rechazos', cards['panorama_rechazos_subproductos']?.id, { data: { rows: [], cols: [] } }), executeWithErrorHandling('serieTemporal', cards['panorama_serie_temporal_diaria']?.id, { data: { rows: [], cols: [] } }), executeWithErrorHandling('topClientes', cards['panorama_top_clientes']?.id, { data: { rows: [], cols: [] } }), executeWithErrorHandling('conteos', cards['panorama_conteo_registros']?.id, { data: { rows: [[0, 0, 0, 0]], cols: [] } }) ]) // Transform Metabase responses to objects for easier frontend consumption const transformSingleRow = (result: any) => { if (!result.data?.rows?.[0] || !result.data?.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] }) return obj } const transformMultipleRows = (result: any) => { if (!result.data?.rows || !result.data?.cols) return [] const cols = result.data.cols return result.data.rows.map((row: any[]) => { const obj: any = {} cols.forEach((col: any, index: number) => { obj[col.name] = row[index] }) return obj }) } // 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' }) } })