All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 53s
- 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.
128 lines
4.6 KiB
TypeScript
128 lines
4.6 KiB
TypeScript
import { METABASE_QUERIES } from '../../config/metabase-queries'
|
|
|
|
/**
|
|
* Execute all comparativa cosechas queries in parallel
|
|
* Returns data for the Comparativa de Cosechas page
|
|
*/
|
|
export default defineEventHandler(async (event) => {
|
|
const body = await readBody(event)
|
|
|
|
const { cosechas_ids = [], incluir_anulados = false } = body
|
|
|
|
try {
|
|
// First, get all cards to find our comparativa queries
|
|
const allCards = await getMetabaseCards('all')
|
|
|
|
// Find our comparativa queries by name using centralized config
|
|
const queryNames = METABASE_QUERIES.comparativa
|
|
|
|
const cards: Record<string, any> = {}
|
|
|
|
console.log('[Comparativa] Available cards:', allCards.map((c: any) => ({ id: c.id, name: c.name })))
|
|
console.log('[Comparativa] 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(`[Comparativa] Query not found: ${name}`)
|
|
} else {
|
|
console.log(`[Comparativa] Found card ${key}: ${name} (ID: ${card.id})`)
|
|
cards[key] = card
|
|
}
|
|
}
|
|
|
|
console.log('[Comparativa] Cards to execute:', Object.keys(cards))
|
|
|
|
// Build parameters array for Metabase queries
|
|
// Las queries SQL nativas usan template-tags de tipo 'text' para arrays
|
|
const parameters = [
|
|
{
|
|
type: 'text',
|
|
target: ['variable', ['template-tag', 'cosechas_ids']],
|
|
value: cosechas_ids
|
|
},
|
|
{
|
|
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(`[Comparativa] No card ID for ${name}`)
|
|
return defaultValue
|
|
}
|
|
|
|
try {
|
|
console.log(`[Comparativa] Executing query: ${name} (ID: ${cardId}) with params:`, JSON.stringify(parameters))
|
|
const result = await executeCardQuery(cardId, parameters)
|
|
console.log(`[Comparativa] 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(`[Comparativa] Error executing ${name}:`, error.message, error.stack)
|
|
return defaultValue
|
|
}
|
|
}
|
|
|
|
const [
|
|
datosDiariosCompletos,
|
|
totalesPorCosecha,
|
|
datosAcumuladosPorDia,
|
|
metadataCosechas
|
|
] = await Promise.all([
|
|
executeWithErrorHandling('datosDiariosCompletos', cards.datos_diarios_completos?.id, { data: { rows: [], cols: [] } }),
|
|
executeWithErrorHandling('totalesPorCosecha', cards.totales_por_cosecha?.id, { data: { rows: [], cols: [] } }),
|
|
executeWithErrorHandling('datosAcumuladosPorDia', cards.datos_acumulados_por_dia?.id, { data: { rows: [], cols: [] } }),
|
|
executeWithErrorHandling('metadataCosechas', cards.metadata_cosechas?.id, { data: { rows: [], cols: [] } })
|
|
])
|
|
|
|
// Transform Metabase responses to objects for easier frontend consumption
|
|
const transformMultipleRows = (result: any) => {
|
|
console.log('[Comparativa] 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('[Comparativa] 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('[Comparativa] transformMultipleRows output:', transformed.length, 'rows')
|
|
return transformed
|
|
}
|
|
|
|
// Return all data in a structured format
|
|
return {
|
|
datosDiariosCompletos: transformMultipleRows(datosDiariosCompletos),
|
|
totalesPorCosecha: transformMultipleRows(totalesPorCosecha),
|
|
datosAcumuladosPorDia: transformMultipleRows(datosAcumuladosPorDia),
|
|
metadataCosechas: transformMultipleRows(metadataCosechas)
|
|
}
|
|
} catch (error: any) {
|
|
console.error('[API] Failed to execute comparativa queries:', error)
|
|
throw createError({
|
|
statusCode: error.statusCode || 500,
|
|
statusMessage: error.statusMessage || 'Failed to execute comparativa queries'
|
|
})
|
|
}
|
|
})
|