Feat: Agregar footer con resumen a todos los botones de copiar texto
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 49s
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 49s
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.
This commit is contained in:
@@ -146,6 +146,14 @@ const props = defineProps<{
|
|||||||
total_qq_oreado_deposito: number
|
total_qq_oreado_deposito: number
|
||||||
total_qq_seco_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'
|
// Toggle de unidades: 'lb' | 'qq' | 'both'
|
||||||
@@ -189,6 +197,15 @@ const formatNumber = (value: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function copiarTexto() {
|
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
|
const texto = `☕ TOTALES DE INGRESO Y COMPRA
|
||||||
|
|
||||||
🍇 UVA:
|
🍇 UVA:
|
||||||
@@ -209,7 +226,7 @@ async function copiarTexto() {
|
|||||||
📊 TOTALES GENERALES:
|
📊 TOTALES GENERALES:
|
||||||
QQ Seco Ingresado: ${formatNumber(props.data.total_qq_seco_ingresado)} QQ
|
QQ Seco Ingresado: ${formatNumber(props.data.total_qq_seco_ingresado)} QQ
|
||||||
QQ Seco Comprado: ${formatNumber(props.data.total_qq_seco_comprado)} 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)
|
await navigator.clipboard.writeText(texto)
|
||||||
alert('✅ Totales de Ingreso y Compra copiados al portapapeles')
|
alert('✅ Totales de Ingreso y Compra copiados al portapapeles')
|
||||||
|
|||||||
@@ -113,6 +113,14 @@ const props = defineProps<{
|
|||||||
inversion_restante_oreado: number
|
inversion_restante_oreado: number
|
||||||
inversion_restante_esperada: 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'
|
// Toggle de unidades para precios de Uva: 'lb' | 'qq' | 'both'
|
||||||
@@ -154,6 +162,15 @@ const formatCurrency = (value: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function copiarTexto() {
|
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
|
const texto = `💰 TOTALES MONETARIOS
|
||||||
|
|
||||||
💵 INVERSIÓN HASTA LA FECHA:
|
💵 INVERSIÓN HASTA LA FECHA:
|
||||||
@@ -172,7 +189,7 @@ async function copiarTexto() {
|
|||||||
Restante Uva: ${formatCurrency(props.data.inversion_restante_uva)}
|
Restante Uva: ${formatCurrency(props.data.inversion_restante_uva)}
|
||||||
Restante Mojado: ${formatCurrency(props.data.inversion_restante_mojado)}
|
Restante Mojado: ${formatCurrency(props.data.inversion_restante_mojado)}
|
||||||
Restante Oreado: ${formatCurrency(props.data.inversion_restante_oreado)}
|
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)
|
await navigator.clipboard.writeText(texto)
|
||||||
alert('✅ Totales Monetarios copiados al portapapeles')
|
alert('✅ Totales Monetarios copiados al portapapeles')
|
||||||
|
|||||||
@@ -82,6 +82,14 @@ const props = defineProps<{
|
|||||||
inversion_restante_verde: number
|
inversion_restante_verde: number
|
||||||
total_lb_neto_comprado_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) => {
|
const formatNumber = (value: number) => {
|
||||||
@@ -102,6 +110,15 @@ const formatCurrency = (value: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function copiarTexto() {
|
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
|
const texto = `🌱 CAFÉ VERDE
|
||||||
|
|
||||||
📊 TOTALES:
|
📊 TOTALES:
|
||||||
@@ -112,7 +129,7 @@ async function copiarTexto() {
|
|||||||
💵 FINANCIERO:
|
💵 FINANCIERO:
|
||||||
Precio Promedio Pagado: ${formatCurrency(props.data.precio_promedio_verde_pagado)}/lb
|
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 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)
|
await navigator.clipboard.writeText(texto)
|
||||||
alert('✅ Totales de Café Verde copiados al portapapeles')
|
alert('✅ Totales de Café Verde copiados al portapapeles')
|
||||||
|
|||||||
@@ -363,9 +363,27 @@
|
|||||||
</UCard>
|
</UCard>
|
||||||
|
|
||||||
<!-- Secciones de Totales -->
|
<!-- Secciones de Totales -->
|
||||||
<TotalesIngresoCompra v-if="pageSections.totalesCafe" :data="data.totalesIngresoCompra" />
|
<TotalesIngresoCompra
|
||||||
<TotalesMonetarios v-if="pageSections.totalesCafe" :data="data.totalesMonetarios" />
|
v-if="pageSections.totalesCafe"
|
||||||
<TotalesVerde v-if="pageSections.totalesVerde" :data="data.totalesVerde" />
|
:data="data.totalesIngresoCompra"
|
||||||
|
:contadores="data.contadores"
|
||||||
|
:rango-legible="rangoLegible"
|
||||||
|
:last-updated="lastUpdated"
|
||||||
|
/>
|
||||||
|
<TotalesMonetarios
|
||||||
|
v-if="pageSections.totalesCafe"
|
||||||
|
:data="data.totalesMonetarios"
|
||||||
|
:contadores="data.contadores"
|
||||||
|
:rango-legible="rangoLegible"
|
||||||
|
:last-updated="lastUpdated"
|
||||||
|
/>
|
||||||
|
<TotalesVerde
|
||||||
|
v-if="pageSections.totalesVerde"
|
||||||
|
:data="data.totalesVerde"
|
||||||
|
:contadores="data.contadores"
|
||||||
|
:rango-legible="rangoLegible"
|
||||||
|
:last-updated="lastUpdated"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- Lista de Ingresos -->
|
<!-- Lista de Ingresos -->
|
||||||
<UCard v-if="pageSections.tablaIngresos" class="brand-card border border-transparent">
|
<UCard v-if="pageSections.tablaIngresos" class="brand-card border border-transparent">
|
||||||
@@ -849,6 +867,16 @@ async function loadOpcionesFiltros() {
|
|||||||
async function copiarListaIngresosTexto() {
|
async function copiarListaIngresosTexto() {
|
||||||
if (!data.value?.listaIngresos || data.value.listaIngresos.length === 0) return
|
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
|
const texto = `📊 LISTA DE INGRESOS - ${data.value.listaIngresos.length} registros
|
||||||
Rango: ${rangoLegible.value}
|
Rango: ${rangoLegible.value}
|
||||||
Generado: ${lastUpdated.value}
|
Generado: ${lastUpdated.value}
|
||||||
@@ -862,7 +890,7 @@ ${idx + 1}. ID: ${ing.id}
|
|||||||
💰 Precio: L ${ing.precio ? ing.precio.toFixed(2) : '-'}
|
💰 Precio: L ${ing.precio ? ing.precio.toFixed(2) : '-'}
|
||||||
💵 Total: L ${ing.total_a_pagar ? ing.total_a_pagar.toFixed(2) : '-'}
|
💵 Total: L ${ing.total_a_pagar ? ing.total_a_pagar.toFixed(2) : '-'}
|
||||||
📍 Estado: ${ing.estado || '-'}
|
📍 Estado: ${ing.estado || '-'}
|
||||||
`).join('\n')}`
|
`).join('\n')}${footer}`
|
||||||
|
|
||||||
await navigator.clipboard.writeText(texto)
|
await navigator.clipboard.writeText(texto)
|
||||||
alert('✅ Lista de ingresos copiada al portapapeles')
|
alert('✅ Lista de ingresos copiada al portapapeles')
|
||||||
@@ -879,6 +907,16 @@ async function copiarListaIngresosJSON() {
|
|||||||
async function copiarTop10ClientesTexto() {
|
async function copiarTop10ClientesTexto() {
|
||||||
if (!data.value?.listaClientes || data.value.listaClientes.length === 0) return
|
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 top10 = data.value.listaClientes.slice(0, 10)
|
||||||
const texto = `🏆 TOP 10 CLIENTES
|
const texto = `🏆 TOP 10 CLIENTES
|
||||||
Rango: ${rangoLegible.value}
|
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'}
|
💰 Total Pagado: L ${cliente.total_pagado ? cliente.total_pagado.toFixed(2) : '0.00'}
|
||||||
📦 Ingresos: ${cliente.num_ingresos || 0}
|
📦 Ingresos: ${cliente.num_ingresos || 0}
|
||||||
⚖️ Quintales: ${cliente.total_qq_seco ? cliente.total_qq_seco.toFixed(2) : '0.00'} qq
|
⚖️ Quintales: ${cliente.total_qq_seco ? cliente.total_qq_seco.toFixed(2) : '0.00'} qq
|
||||||
`).join('\n')}`
|
`).join('\n')}${footer}`
|
||||||
|
|
||||||
await navigator.clipboard.writeText(texto)
|
await navigator.clipboard.writeText(texto)
|
||||||
alert('✅ Top 10 clientes copiado al portapapeles')
|
alert('✅ Top 10 clientes copiado al portapapeles')
|
||||||
@@ -909,6 +947,16 @@ async function copiarTop10ClientesJSON() {
|
|||||||
async function copiarSerieTemporalTexto() {
|
async function copiarSerieTemporalTexto() {
|
||||||
if (!data.value?.serieTemporal || data.value.serieTemporal.length === 0) return
|
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
|
const texto = `📈 SERIE TEMPORAL ACUMULADA - ${data.value.serieTemporal.length} puntos
|
||||||
Rango: ${rangoLegible.value}
|
Rango: ${rangoLegible.value}
|
||||||
Generado: ${lastUpdated.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'}
|
💰 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
|
📊 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'}
|
💵 Total Acum: L ${punto.inversion_acumulada ? punto.inversion_acumulada.toFixed(2) : '0.00'}
|
||||||
`).join('\n')}`
|
`).join('\n')}${footer}`
|
||||||
|
|
||||||
await navigator.clipboard.writeText(texto)
|
await navigator.clipboard.writeText(texto)
|
||||||
alert('✅ Serie temporal copiada al portapapeles')
|
alert('✅ Serie temporal copiada al portapapeles')
|
||||||
|
|||||||
Reference in New Issue
Block a user