fix: correção da exportação dos dados sintéticos
This commit is contained in:
parent
beeedbff69
commit
a5ce93042c
|
|
@ -1,12 +1,13 @@
|
|||
"use client";
|
||||
|
||||
import { LoaderPinwheel, ChevronDown, ChevronRight, Filter, Maximize2, Minimize2 } from "lucide-react";
|
||||
import { LoaderPinwheel, ChevronDown, ChevronRight, Filter, Maximize2, Minimize2, Download } from "lucide-react";
|
||||
import { useEffect, useState, useCallback, startTransition, memo } from "react";
|
||||
import AnaliticoComponent from "./analitico";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import * as XLSX from "xlsx";
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
|
|
@ -498,6 +499,299 @@ export default function Teste() {
|
|||
setContasSelecionadas([]);
|
||||
};
|
||||
|
||||
const exportarXLSX = () => {
|
||||
if (!data.length) {
|
||||
console.log('⚠️ Nenhum dado para exportar');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('📊 Exportando TODOS os dados expandidos para XLSX...');
|
||||
|
||||
// Criar uma versão completamente expandida dos dados hierárquicos
|
||||
const dadosCompletosExpandidos = buildHierarchicalDataCompleta();
|
||||
|
||||
// Preparar dados para exportação
|
||||
const dadosExportacao = dadosCompletosExpandidos.map((row, index) => {
|
||||
const linha: any = {
|
||||
'Linha': index + 1,
|
||||
'Tipo': row.type,
|
||||
'Nível': row.level,
|
||||
'Grupo': row.grupo || '',
|
||||
'Centro de Custo': row.centro_custo || '',
|
||||
'Conta': row.conta || '',
|
||||
'Código Centro': row.codigo_centro_custo || '',
|
||||
'Código Conta': row.codigo_conta || '',
|
||||
'Total': row.total || 0,
|
||||
};
|
||||
|
||||
// Adicionar colunas dos meses
|
||||
mesesDisponiveis.forEach(mes => {
|
||||
const valor = row.valoresPorMes?.[mes] || 0;
|
||||
const percentual = row.percentuaisPorMes?.[mes] || 0;
|
||||
linha[`Valor ${mes}`] = valor;
|
||||
linha[`% ${mes}`] = percentual;
|
||||
});
|
||||
|
||||
return linha;
|
||||
});
|
||||
|
||||
// Criar workbook
|
||||
const wb = XLSX.utils.book_new();
|
||||
|
||||
// Criar worksheet principal
|
||||
const ws = XLSX.utils.json_to_sheet(dadosExportacao);
|
||||
|
||||
// Ajustar largura das colunas
|
||||
const colWidths = [
|
||||
{ wch: 8 }, // Linha
|
||||
{ wch: 15 }, // Tipo
|
||||
{ wch: 8 }, // Nível
|
||||
{ wch: 30 }, // Grupo
|
||||
{ wch: 25 }, // Centro de Custo
|
||||
{ wch: 35 }, // Conta
|
||||
{ wch: 15 }, // Código Centro
|
||||
{ wch: 12 }, // Código Conta
|
||||
{ wch: 15 }, // Total
|
||||
];
|
||||
|
||||
// Adicionar larguras para colunas dos meses
|
||||
mesesDisponiveis.forEach(() => {
|
||||
colWidths.push({ wch: 15 }); // Valor
|
||||
colWidths.push({ wch: 10 }); // %
|
||||
});
|
||||
|
||||
ws['!cols'] = colWidths;
|
||||
|
||||
// Adicionar worksheet ao workbook
|
||||
XLSX.utils.book_append_sheet(wb, ws, 'DRE Gerencial Completo');
|
||||
|
||||
// Criar worksheet de resumo
|
||||
const resumoData = [
|
||||
{ 'Informação': 'Período', 'Valor': `${filtros.periodoDe} a ${filtros.periodoAte}` },
|
||||
{ 'Informação': 'Grupo', 'Valor': filtros.grupo },
|
||||
{ 'Informação': 'Subgrupo', 'Valor': filtros.subgrupo },
|
||||
{ 'Informação': 'Centro de Custo', 'Valor': filtros.centroCusto },
|
||||
{ 'Informação': 'Conta', 'Valor': filtros.conta },
|
||||
{ 'Informação': 'Valor Mínimo', 'Valor': filtros.valorMin || 'N/A' },
|
||||
{ 'Informação': 'Valor Máximo', 'Valor': filtros.valorMax || 'N/A' },
|
||||
{ 'Informação': 'Busca Textual', 'Valor': filtros.buscaTextual || 'N/A' },
|
||||
{ 'Informação': 'Ordem Hierárquica', 'Valor': ordemHierarquiaContasPrimeiro ? 'Contas → Centros' : 'Centros → Contas' },
|
||||
{ 'Informação': 'Total de Registros', 'Valor': dadosCompletosExpandidos.length },
|
||||
{ 'Informação': 'Data de Exportação', 'Valor': new Date().toLocaleString('pt-BR') },
|
||||
];
|
||||
|
||||
const wsResumo = XLSX.utils.json_to_sheet(resumoData);
|
||||
wsResumo['!cols'] = [{ wch: 20 }, { wch: 30 }];
|
||||
XLSX.utils.book_append_sheet(wb, wsResumo, 'Resumo');
|
||||
|
||||
// Gerar nome do arquivo
|
||||
const dataAtual = new Date().toISOString().split('T')[0];
|
||||
const nomeArquivo = `DRE_Gerencial_Completo_${dataAtual}.xlsx`;
|
||||
|
||||
// Exportar arquivo
|
||||
XLSX.writeFile(wb, nomeArquivo);
|
||||
|
||||
console.log('✅ Arquivo XLSX completo exportado:', nomeArquivo);
|
||||
};
|
||||
|
||||
// Função para construir dados hierárquicos completamente expandidos
|
||||
const buildHierarchicalDataCompleta = (): HierarchicalRow[] => {
|
||||
const rows: HierarchicalRow[] = [];
|
||||
|
||||
// Agrupar dados por grupo
|
||||
const grupos = data.reduce((acc, item) => {
|
||||
if (!acc[item.grupo]) {
|
||||
acc[item.grupo] = [];
|
||||
}
|
||||
acc[item.grupo].push(item);
|
||||
return acc;
|
||||
}, {} as Record<string, DREItem[]>);
|
||||
|
||||
// Ordenar grupos por código
|
||||
const sortedGrupos = Object.entries(grupos).sort(([grupoA, itemsA], [grupoB, itemsB]) => {
|
||||
const codigoA = itemsA[0]?.codgrupo || "";
|
||||
const codigoB = itemsB[0]?.codgrupo || "";
|
||||
return codigoA.localeCompare(codigoB);
|
||||
});
|
||||
|
||||
sortedGrupos.forEach(([grupo, items]) => {
|
||||
const totalGrupo = items.reduce(
|
||||
(sum, item) => sum + parseFloat(item.valor),
|
||||
0
|
||||
);
|
||||
|
||||
// Linha do grupo (Level 0)
|
||||
const valoresGrupoPorMes = calcularValoresPorMes(items);
|
||||
rows.push({
|
||||
type: "grupo",
|
||||
level: 0,
|
||||
grupo,
|
||||
total: totalGrupo,
|
||||
valoresPorMes: valoresGrupoPorMes,
|
||||
percentuaisPorMes: calcularPercentuaisPorMes(valoresGrupoPorMes, grupo),
|
||||
isCalculado: items[0]?.isCalculado || false,
|
||||
});
|
||||
|
||||
if (ordemHierarquiaContasPrimeiro) {
|
||||
// ORDEM: Grupos → Contas → Centros de Custo
|
||||
|
||||
// Agrupar por conta dentro do grupo
|
||||
const contas = items.reduce((acc, item) => {
|
||||
if (!acc[item.conta]) {
|
||||
acc[item.conta] = [];
|
||||
}
|
||||
acc[item.conta].push(item);
|
||||
return acc;
|
||||
}, {} as Record<string, DREItem[]>);
|
||||
|
||||
// Ordenar contas por CODCONTA
|
||||
const sortedContas = Object.entries(contas).sort(([contaA, itemsA], [contaB, itemsB]) => {
|
||||
const codigoA = itemsA[0]?.codigo_conta || 0;
|
||||
const codigoB = itemsB[0]?.codigo_conta || 0;
|
||||
return codigoA - codigoB;
|
||||
});
|
||||
|
||||
sortedContas.forEach(([conta, contaItems]) => {
|
||||
const totalConta = contaItems.reduce(
|
||||
(sum, item) => sum + parseFloat(item.valor),
|
||||
0
|
||||
);
|
||||
|
||||
// Linha da conta (Level 1)
|
||||
const valoresContaPorMes = calcularValoresPorMes(contaItems);
|
||||
rows.push({
|
||||
type: "conta",
|
||||
level: 1,
|
||||
grupo,
|
||||
conta,
|
||||
codigo_conta: contaItems[0].codigo_conta,
|
||||
codigo_centro_custo: contaItems[0].codigo_centro_custo,
|
||||
total: totalConta,
|
||||
valoresPorMes: valoresContaPorMes,
|
||||
percentuaisPorMes: calcularPercentuaisPorMes(valoresContaPorMes, grupo),
|
||||
});
|
||||
|
||||
// Agrupar por centro de custo dentro da conta
|
||||
const centros = contaItems.reduce((acc, item) => {
|
||||
if (!acc[item.centro_custo]) {
|
||||
acc[item.centro_custo] = [];
|
||||
}
|
||||
acc[item.centro_custo].push(item);
|
||||
return acc;
|
||||
}, {} as Record<string, DREItem[]>);
|
||||
|
||||
// Ordenar centros de custo por CODIGOCENTROCUSTO
|
||||
const sortedCentros = Object.entries(centros).sort(([centroA, itemsA], [centroB, itemsB]) => {
|
||||
const codigoA = itemsA[0]?.codigo_centro_custo || "";
|
||||
const codigoB = itemsB[0]?.codigo_centro_custo || "";
|
||||
return codigoA.localeCompare(codigoB);
|
||||
});
|
||||
|
||||
sortedCentros.forEach(([centro, centroItems]) => {
|
||||
const totalCentro = centroItems.reduce(
|
||||
(sum, item) => sum + parseFloat(item.valor),
|
||||
0
|
||||
);
|
||||
|
||||
// Linha do centro de custo (Level 2)
|
||||
const valoresCentroPorMes = calcularValoresPorMes(centroItems);
|
||||
rows.push({
|
||||
type: "centro_custo",
|
||||
level: 2,
|
||||
grupo,
|
||||
centro_custo: centro,
|
||||
conta,
|
||||
codigo_conta: contaItems[0].codigo_conta,
|
||||
codigo_centro_custo: centroItems[0].codigo_centro_custo,
|
||||
total: totalCentro,
|
||||
valoresPorMes: valoresCentroPorMes,
|
||||
percentuaisPorMes: calcularPercentuaisPorMes(valoresCentroPorMes, grupo),
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// ORDEM ORIGINAL: Grupos → Centros de Custo → Contas
|
||||
|
||||
// Agrupar por centro de custo dentro do grupo
|
||||
const centros = items.reduce((acc, item) => {
|
||||
if (!acc[item.centro_custo]) {
|
||||
acc[item.centro_custo] = [];
|
||||
}
|
||||
acc[item.centro_custo].push(item);
|
||||
return acc;
|
||||
}, {} as Record<string, DREItem[]>);
|
||||
|
||||
// Ordenar centros de custo por CODIGOCENTROCUSTO
|
||||
const sortedCentros = Object.entries(centros).sort(([centroA, itemsA], [centroB, itemsB]) => {
|
||||
const codigoA = itemsA[0]?.codigo_centro_custo || "";
|
||||
const codigoB = itemsB[0]?.codigo_centro_custo || "";
|
||||
return codigoA.localeCompare(codigoB);
|
||||
});
|
||||
|
||||
sortedCentros.forEach(([centro, centroItems]) => {
|
||||
const totalCentro = centroItems.reduce(
|
||||
(sum, item) => sum + parseFloat(item.valor),
|
||||
0
|
||||
);
|
||||
|
||||
// Linha do centro de custo (Level 1)
|
||||
const valoresCentroPorMes = calcularValoresPorMes(centroItems);
|
||||
rows.push({
|
||||
type: "centro_custo",
|
||||
level: 1,
|
||||
grupo,
|
||||
centro_custo: centro,
|
||||
codigo_conta: centroItems[0].codigo_conta,
|
||||
codigo_centro_custo: centroItems[0].codigo_centro_custo,
|
||||
total: totalCentro,
|
||||
valoresPorMes: valoresCentroPorMes,
|
||||
percentuaisPorMes: calcularPercentuaisPorMes(valoresCentroPorMes, grupo),
|
||||
});
|
||||
|
||||
// Agrupar por conta dentro do centro de custo
|
||||
const contas = centroItems.reduce((acc, item) => {
|
||||
if (!acc[item.conta]) {
|
||||
acc[item.conta] = [];
|
||||
}
|
||||
acc[item.conta].push(item);
|
||||
return acc;
|
||||
}, {} as Record<string, DREItem[]>);
|
||||
|
||||
// Ordenar contas por CODCONTA
|
||||
const sortedContas = Object.entries(contas).sort(([contaA, itemsA], [contaB, itemsB]) => {
|
||||
const codigoA = itemsA[0]?.codigo_conta || 0;
|
||||
const codigoB = itemsB[0]?.codigo_conta || 0;
|
||||
return codigoA - codigoB;
|
||||
});
|
||||
|
||||
sortedContas.forEach(([conta, contaItems]) => {
|
||||
const totalConta = contaItems.reduce(
|
||||
(sum, item) => sum + parseFloat(item.valor),
|
||||
0
|
||||
);
|
||||
|
||||
// Linha da conta (Level 2)
|
||||
const valoresContaPorMes = calcularValoresPorMes(contaItems);
|
||||
rows.push({
|
||||
type: "conta",
|
||||
level: 2,
|
||||
grupo,
|
||||
centro_custo: centro,
|
||||
conta,
|
||||
codigo_conta: contaItems[0].codigo_conta,
|
||||
codigo_centro_custo: centroItems[0].codigo_centro_custo,
|
||||
total: totalConta,
|
||||
valoresPorMes: valoresContaPorMes,
|
||||
percentuaisPorMes: calcularPercentuaisPorMes(valoresContaPorMes, grupo),
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return rows;
|
||||
};
|
||||
|
||||
const toggleExpandAll = useCallback(() => {
|
||||
if (isAllExpanded) {
|
||||
// Recolher tudo - usar startTransition para atualizações não urgentes
|
||||
|
|
@ -1157,6 +1451,18 @@ export default function Teste() {
|
|||
|
||||
{/* Controles */}
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Botão de Exportar XLSX */}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={exportarXLSX}
|
||||
disabled={!filtrosAplicados || hierarchicalData.length === 0}
|
||||
className="flex items-center gap-2 text-xs h-8 px-3 transition-all duration-150 ease-in-out hover:scale-105 disabled:hover:scale-100"
|
||||
>
|
||||
<Download className="w-4 h-4" />
|
||||
Exportar XLSX
|
||||
</Button>
|
||||
|
||||
{/* Botão de Expandir/Recolher */}
|
||||
<Button
|
||||
variant="outline"
|
||||
|
|
|
|||
Loading…
Reference in New Issue