From 494ffb6d3b4479e56ddf688b65d18f710ed2a027 Mon Sep 17 00:00:00 2001 From: josedario87 Date: Thu, 30 Oct 2025 16:47:59 -0600 Subject: [PATCH] Feat: Agregar footer con resumen a todos los botones de copiar texto MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implementa un footer consistente en todas las funciones de copiar texto que incluye informaciΓ³n de contexto del informe: Footer incluye: - πŸ“… Rango de fechas aplicado - πŸ“¦ Cantidad de ingresos filtrados vs total - πŸ‘₯ Cantidad de clientes con ingresos vs total - πŸ• Fecha y hora de generaciΓ³n Cambios en archivos: - informe-ingresos.vue: Footer en Lista, Top 10 y Serie Temporal - TotalesIngresoCompra.vue: Recibe contadores y metadata - TotalesMonetarios.vue: Recibe contadores y metadata - TotalesVerde.vue: Recibe contadores y metadata El footer usa datos de la query "Informe Ingresos - Contadores de Filtros" que proporciona totales con y sin filtros aplicados. --- .../app/components/TotalesIngresoCompra.vue | 19 +++++- .../app/components/TotalesMonetarios.vue | 19 +++++- nuxt4-app/app/components/TotalesVerde.vue | 19 +++++- nuxt4-app/app/pages/informe-ingresos.vue | 60 +++++++++++++++++-- 4 files changed, 108 insertions(+), 9 deletions(-) diff --git a/nuxt4-app/app/components/TotalesIngresoCompra.vue b/nuxt4-app/app/components/TotalesIngresoCompra.vue index 635da46..a86acc1 100644 --- a/nuxt4-app/app/components/TotalesIngresoCompra.vue +++ b/nuxt4-app/app/components/TotalesIngresoCompra.vue @@ -146,6 +146,14 @@ const props = defineProps<{ total_qq_oreado_deposito: number total_qq_seco_deposito: number } + contadores?: { + total_ingresos?: number + ingresos_filtrados?: number + total_clientes?: number + clientes_con_ingresos_filtrados?: number + } + rangoLegible: string + lastUpdated: string }>() // Toggle de unidades: 'lb' | 'qq' | 'both' @@ -189,6 +197,15 @@ const formatNumber = (value: number) => { } async function copiarTexto() { + const footer = ` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ“Š RESUMEN +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ“… Rango: ${props.rangoLegible} +πŸ“¦ Ingresos: ${props.contadores?.ingresos_filtrados || 0} de ${props.contadores?.total_ingresos || 0} registros +πŸ‘₯ Clientes: ${props.contadores?.clientes_con_ingresos_filtrados || 0} de ${props.contadores?.total_clientes || 0} clientes +πŸ• Generado: ${props.lastUpdated}` + const texto = `β˜• TOTALES DE INGRESO Y COMPRA πŸ‡ UVA: @@ -209,7 +226,7 @@ async function copiarTexto() { πŸ“Š TOTALES GENERALES: QQ Seco Ingresado: ${formatNumber(props.data.total_qq_seco_ingresado)} QQ QQ Seco Comprado: ${formatNumber(props.data.total_qq_seco_comprado)} QQ - QQ Seco en DepΓ³sito: ${formatNumber(props.data.total_qq_seco_deposito)} QQ` + QQ Seco en DepΓ³sito: ${formatNumber(props.data.total_qq_seco_deposito)} QQ${footer}` await navigator.clipboard.writeText(texto) alert('βœ… Totales de Ingreso y Compra copiados al portapapeles') diff --git a/nuxt4-app/app/components/TotalesMonetarios.vue b/nuxt4-app/app/components/TotalesMonetarios.vue index 97bc6fa..36bf30c 100644 --- a/nuxt4-app/app/components/TotalesMonetarios.vue +++ b/nuxt4-app/app/components/TotalesMonetarios.vue @@ -113,6 +113,14 @@ const props = defineProps<{ inversion_restante_oreado: number inversion_restante_esperada: number } + contadores?: { + total_ingresos?: number + ingresos_filtrados?: number + total_clientes?: number + clientes_con_ingresos_filtrados?: number + } + rangoLegible: string + lastUpdated: string }>() // Toggle de unidades para precios de Uva: 'lb' | 'qq' | 'both' @@ -154,6 +162,15 @@ const formatCurrency = (value: number) => { } async function copiarTexto() { + const footer = ` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ“Š RESUMEN +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ“… Rango: ${props.rangoLegible} +πŸ“¦ Ingresos: ${props.contadores?.ingresos_filtrados || 0} de ${props.contadores?.total_ingresos || 0} registros +πŸ‘₯ Clientes: ${props.contadores?.clientes_con_ingresos_filtrados || 0} de ${props.contadores?.total_clientes || 0} clientes +πŸ• Generado: ${props.lastUpdated}` + const texto = `πŸ’° TOTALES MONETARIOS πŸ’΅ INVERSIΓ“N HASTA LA FECHA: @@ -172,7 +189,7 @@ async function copiarTexto() { Restante Uva: ${formatCurrency(props.data.inversion_restante_uva)} Restante Mojado: ${formatCurrency(props.data.inversion_restante_mojado)} Restante Oreado: ${formatCurrency(props.data.inversion_restante_oreado)} - Total Restante: ${formatCurrency(props.data.inversion_restante_esperada)}` + Total Restante: ${formatCurrency(props.data.inversion_restante_esperada)}${footer}` await navigator.clipboard.writeText(texto) alert('βœ… Totales Monetarios copiados al portapapeles') diff --git a/nuxt4-app/app/components/TotalesVerde.vue b/nuxt4-app/app/components/TotalesVerde.vue index 4afc5f9..d402ecb 100644 --- a/nuxt4-app/app/components/TotalesVerde.vue +++ b/nuxt4-app/app/components/TotalesVerde.vue @@ -82,6 +82,14 @@ const props = defineProps<{ inversion_restante_verde: number total_lb_neto_comprado_verde: number } + contadores?: { + total_ingresos?: number + ingresos_filtrados?: number + total_clientes?: number + clientes_con_ingresos_filtrados?: number + } + rangoLegible: string + lastUpdated: string }>() const formatNumber = (value: number) => { @@ -102,6 +110,15 @@ const formatCurrency = (value: number) => { } async function copiarTexto() { + const footer = ` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ“Š RESUMEN +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ“… Rango: ${props.rangoLegible} +πŸ“¦ Ingresos: ${props.contadores?.ingresos_filtrados || 0} de ${props.contadores?.total_ingresos || 0} registros +πŸ‘₯ Clientes: ${props.contadores?.clientes_con_ingresos_filtrados || 0} de ${props.contadores?.total_clientes || 0} clientes +πŸ• Generado: ${props.lastUpdated}` + const texto = `🌱 CAFΓ‰ VERDE πŸ“Š TOTALES: @@ -112,7 +129,7 @@ async function copiarTexto() { πŸ’΅ FINANCIERO: Precio Promedio Pagado: ${formatCurrency(props.data.precio_promedio_verde_pagado)}/lb InversiΓ³n Hasta la Fecha: ${formatCurrency(props.data.inversion_verde_hasta_fecha)} - InversiΓ³n Restante: ${formatCurrency(props.data.inversion_restante_verde)}` + InversiΓ³n Restante: ${formatCurrency(props.data.inversion_restante_verde)}${footer}` await navigator.clipboard.writeText(texto) alert('βœ… Totales de CafΓ© Verde copiados al portapapeles') diff --git a/nuxt4-app/app/pages/informe-ingresos.vue b/nuxt4-app/app/pages/informe-ingresos.vue index 0e6d690..7136172 100644 --- a/nuxt4-app/app/pages/informe-ingresos.vue +++ b/nuxt4-app/app/pages/informe-ingresos.vue @@ -363,9 +363,27 @@ - - - + + + @@ -849,6 +867,16 @@ async function loadOpcionesFiltros() { async function copiarListaIngresosTexto() { if (!data.value?.listaIngresos || data.value.listaIngresos.length === 0) return + const contadores = data.value.contadores || {} + const footer = ` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ“Š RESUMEN +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ“… Rango: ${rangoLegible.value} +πŸ“¦ Ingresos: ${contadores.ingresos_filtrados || 0} de ${contadores.total_ingresos || 0} registros +πŸ‘₯ Clientes: ${contadores.clientes_con_ingresos_filtrados || 0} de ${contadores.total_clientes || 0} clientes +πŸ• Generado: ${lastUpdated.value}` + const texto = `πŸ“Š LISTA DE INGRESOS - ${data.value.listaIngresos.length} registros Rango: ${rangoLegible.value} Generado: ${lastUpdated.value} @@ -862,7 +890,7 @@ ${idx + 1}. ID: ${ing.id} πŸ’° Precio: L ${ing.precio ? ing.precio.toFixed(2) : '-'} πŸ’΅ Total: L ${ing.total_a_pagar ? ing.total_a_pagar.toFixed(2) : '-'} πŸ“ Estado: ${ing.estado || '-'} -`).join('\n')}` +`).join('\n')}${footer}` await navigator.clipboard.writeText(texto) alert('βœ… Lista de ingresos copiada al portapapeles') @@ -879,6 +907,16 @@ async function copiarListaIngresosJSON() { async function copiarTop10ClientesTexto() { if (!data.value?.listaClientes || data.value.listaClientes.length === 0) return + const contadores = data.value.contadores || {} + const footer = ` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ“Š RESUMEN +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ“… Rango: ${rangoLegible.value} +πŸ“¦ Ingresos: ${contadores.ingresos_filtrados || 0} de ${contadores.total_ingresos || 0} registros +πŸ‘₯ Clientes: ${contadores.clientes_con_ingresos_filtrados || 0} de ${contadores.total_clientes || 0} clientes +πŸ• Generado: ${lastUpdated.value}` + const top10 = data.value.listaClientes.slice(0, 10) const texto = `πŸ† TOP 10 CLIENTES Rango: ${rangoLegible.value} @@ -891,7 +929,7 @@ ${idx + 1}. ${cliente.cliente_nombre || 'Sin nombre'} πŸ’° Total Pagado: L ${cliente.total_pagado ? cliente.total_pagado.toFixed(2) : '0.00'} πŸ“¦ Ingresos: ${cliente.num_ingresos || 0} βš–οΈ Quintales: ${cliente.total_qq_seco ? cliente.total_qq_seco.toFixed(2) : '0.00'} qq -`).join('\n')}` +`).join('\n')}${footer}` await navigator.clipboard.writeText(texto) alert('βœ… Top 10 clientes copiado al portapapeles') @@ -909,6 +947,16 @@ async function copiarTop10ClientesJSON() { async function copiarSerieTemporalTexto() { if (!data.value?.serieTemporal || data.value.serieTemporal.length === 0) return + const contadores = data.value.contadores || {} + const footer = ` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ“Š RESUMEN +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ“… Rango: ${rangoLegible.value} +πŸ“¦ Ingresos: ${contadores.ingresos_filtrados || 0} de ${contadores.total_ingresos || 0} registros +πŸ‘₯ Clientes: ${contadores.clientes_con_ingresos_filtrados || 0} de ${contadores.total_clientes || 0} clientes +πŸ• Generado: ${lastUpdated.value}` + const texto = `πŸ“ˆ SERIE TEMPORAL ACUMULADA - ${data.value.serieTemporal.length} puntos Rango: ${rangoLegible.value} Generado: ${lastUpdated.value} @@ -922,7 +970,7 @@ ${idx + 1}. πŸ“… ${punto.fecha_grupo ? new Date(punto.fecha_grupo).toLocaleDateS πŸ’° InversiΓ³n: L ${punto.inversion_periodo ? punto.inversion_periodo.toFixed(2) : '0.00'} πŸ“Š Acumulado: ${punto.peso_seco_acumulado ? punto.peso_seco_acumulado.toFixed(2) : '0.00'} qq πŸ’΅ Total Acum: L ${punto.inversion_acumulada ? punto.inversion_acumulada.toFixed(2) : '0.00'} -`).join('\n')}` +`).join('\n')}${footer}` await navigator.clipboard.writeText(texto) alert('βœ… Serie temporal copiada al portapapeles')