fix: correção da ordenação por CODGRUPO

This commit is contained in:
Alessandro Gonçaalves 2025-11-19 17:31:54 -03:00
parent 6ce426222e
commit 64d4397847
1 changed files with 146 additions and 108 deletions

View File

@ -563,9 +563,9 @@ export default function Teste() {
const newExpanded = new Set(prev); const newExpanded = new Set(prev);
if (newExpanded.has(entidade)) { if (newExpanded.has(entidade)) {
newExpanded.delete(entidade); newExpanded.delete(entidade);
} else { } else {
newExpanded.add(entidade); newExpanded.add(entidade);
} }
return newExpanded; return newExpanded;
}); });
}, []); }, []);
@ -587,9 +587,9 @@ export default function Teste() {
const newExpanded = new Set(prev); const newExpanded = new Set(prev);
if (newExpanded.has(chave)) { if (newExpanded.has(chave)) {
newExpanded.delete(chave); newExpanded.delete(chave);
} else { } else {
newExpanded.add(chave); newExpanded.add(chave);
} }
return newExpanded; return newExpanded;
}); });
}, []); }, []);
@ -775,23 +775,41 @@ export default function Teste() {
const rows: HierarchicalRow[] = []; const rows: HierarchicalRow[] = [];
// Nova hierarquia: [entidade, direto/indireto, cc, conta] // Nova hierarquia: [entidade, direto/indireto, cc, conta]
// Agrupar por entidade // Agrupar primeiro por CODGRUPO, depois por entidade
const entidades = data.reduce((acc, item) => { const gruposPorCodigo = data.reduce((acc, item) => {
const codgrupo = item.codgrupo || "";
if (!codgrupo) return acc;
if (!acc[codgrupo]) {
acc[codgrupo] = {};
}
const entidade = item.entidades || ""; const entidade = item.entidades || "";
if (!entidade) return acc; if (!entidade) return acc;
if (!acc[entidade]) { if (!acc[codgrupo][entidade]) {
acc[entidade] = []; acc[codgrupo][entidade] = [];
} }
acc[entidade].push(item); acc[codgrupo][entidade].push(item);
return acc; return acc;
}, {} as Record<string, DREItem[]>); }, {} as Record<string, Record<string, DREItem[]>>);
// Ordenar entidades alfabeticamente // Ordenar por CODGRUPO (numericamente), depois por entidade (alfabeticamente)
const sortedEntidades = Object.entries(entidades).sort(([entA], [entB]) => const sortedGrupos = Object.entries(gruposPorCodigo).sort(([codA], [codB]) => {
entA.localeCompare(entB) // Ordenar numericamente por CODGRUPO
); const numA = parseInt(codA) || 0;
const numB = parseInt(codB) || 0;
if (numA !== numB) {
return numA - numB;
}
// Se não for numérico, ordenar alfabeticamente
return codA.localeCompare(codB);
});
sortedEntidades.forEach(([entidade, items]) => { sortedGrupos.forEach(([codgrupo, entidades]) => {
// Ordenar entidades dentro do grupo alfabeticamente
const sortedEntidades = Object.entries(entidades).sort(([entA], [entB]) =>
entA.localeCompare(entB)
);
sortedEntidades.forEach(([entidade, items]) => {
const totalEntidade = items.reduce((sum, item) => sum + parseFloat(item.valor), 0); const totalEntidade = items.reduce((sum, item) => sum + parseFloat(item.valor), 0);
const valoresEntidadePorMes = calcularValoresPorMes(items); const valoresEntidadePorMes = calcularValoresPorMes(items);
@ -819,8 +837,8 @@ export default function Teste() {
acc[subgrupo] = []; acc[subgrupo] = [];
} }
acc[subgrupo].push(item); acc[subgrupo].push(item);
return acc; return acc;
}, {} as Record<string, DREItem[]>); }, {} as Record<string, DREItem[]>);
// Ordenar: DIRETO primeiro, depois INDIRETO // Ordenar: DIRETO primeiro, depois INDIRETO
const sortedDiretoIndireto = Object.entries(diretoIndireto).sort(([a], [b]) => { const sortedDiretoIndireto = Object.entries(diretoIndireto).sort(([a], [b]) => {
@ -833,9 +851,9 @@ export default function Teste() {
sortedDiretoIndireto.forEach(([diretoIndireto, diretoIndiretoItems]) => { sortedDiretoIndireto.forEach(([diretoIndireto, diretoIndiretoItems]) => {
const totalDiretoIndireto = diretoIndiretoItems.reduce( const totalDiretoIndireto = diretoIndiretoItems.reduce(
(sum, item) => sum + parseFloat(item.valor), (sum, item) => sum + parseFloat(item.valor),
0 0
); );
const valoresDiretoIndiretoPorMes = calcularValoresPorMes(diretoIndiretoItems); const valoresDiretoIndiretoPorMes = calcularValoresPorMes(diretoIndiretoItems);
// Verificar se direto/indireto contém faturamento líquido // Verificar se direto/indireto contém faturamento líquido
@ -843,9 +861,9 @@ export default function Teste() {
const codgrupoParaCalculoDI = temFaturamentoLiquidoDI ? "00" : ""; const codgrupoParaCalculoDI = temFaturamentoLiquidoDI ? "00" : "";
// Linha direto/indireto (Level 1) - sempre expandida // Linha direto/indireto (Level 1) - sempre expandida
rows.push({ rows.push({
type: "direto_indireto", type: "direto_indireto",
level: 1, level: 1,
entidade, entidade,
direto_indireto: diretoIndireto, direto_indireto: diretoIndireto,
total: totalDiretoIndireto, total: totalDiretoIndireto,
@ -863,27 +881,27 @@ export default function Teste() {
acc[centro] = []; acc[centro] = [];
} }
acc[centro].push(item); acc[centro].push(item);
return acc; return acc;
}, {} as Record<string, DREItem[]>); }, {} as Record<string, DREItem[]>);
// Ordenar centros de custo por CODIGOCENTROCUSTO // Ordenar centros de custo por CODIGOCENTROCUSTO
const sortedCentros = Object.entries(centros).sort(([centroA, itemsA], [centroB, itemsB]) => { const sortedCentros = Object.entries(centros).sort(([centroA, itemsA], [centroB, itemsB]) => {
const codigoA = itemsA[0]?.codigo_centro_custo || ""; const codigoA = itemsA[0]?.codigo_centro_custo || "";
const codigoB = itemsB[0]?.codigo_centro_custo || ""; const codigoB = itemsB[0]?.codigo_centro_custo || "";
if (codigoA && codigoB) { if (codigoA && codigoB) {
return codigoA.localeCompare(codigoB); return codigoA.localeCompare(codigoB);
} }
if (codigoA && !codigoB) return -1; if (codigoA && !codigoB) return -1;
if (!codigoA && codigoB) return 1; if (!codigoA && codigoB) return 1;
return centroA.localeCompare(centroB); return centroA.localeCompare(centroB);
}); });
sortedCentros.forEach(([centro, centroItems]) => { sortedCentros.forEach(([centro, centroItems]) => {
const totalCentro = centroItems.reduce( const totalCentro = centroItems.reduce(
(sum, item) => sum + parseFloat(item.valor), (sum, item) => sum + parseFloat(item.valor),
0 0
); );
const valoresCentroPorMes = calcularValoresPorMes(centroItems); const valoresCentroPorMes = calcularValoresPorMes(centroItems);
// Verificar se centro de custo contém faturamento líquido // Verificar se centro de custo contém faturamento líquido
const temFaturamentoLiquidoCC = centroItems.some(item => item.codgrupo === "00"); const temFaturamentoLiquidoCC = centroItems.some(item => item.codgrupo === "00");
@ -953,8 +971,9 @@ export default function Teste() {
percentuaisPorMes: calcularPercentuaisPorMes(valoresContaPorMes, codgrupoParaCalculoConta), percentuaisPorMes: calcularPercentuaisPorMes(valoresContaPorMes, codgrupoParaCalculoConta),
percentualTotal: calcularPercentualTotal(totalConta, codgrupoParaCalculoConta), percentualTotal: calcularPercentualTotal(totalConta, codgrupoParaCalculoConta),
}); });
}); });
}); });
});
}); });
}); });
@ -983,7 +1002,7 @@ export default function Teste() {
setExpandedEntidades(new Set(todasEntidades)); setExpandedEntidades(new Set(todasEntidades));
setExpandedDiretoIndireto(new Set(todosDiretoIndireto)); setExpandedDiretoIndireto(new Set(todosDiretoIndireto));
setExpandedCentros(new Set(todosCentros)); setExpandedCentros(new Set(todosCentros));
setIsAllExpanded(true); setIsAllExpanded(true);
}); });
@ -1577,23 +1596,41 @@ export default function Teste() {
const rows: HierarchicalRow[] = []; const rows: HierarchicalRow[] = [];
// Nova hierarquia: [entidade, direto/indireto, cc, conta] // Nova hierarquia: [entidade, direto/indireto, cc, conta]
// Agrupar por entidade // Agrupar primeiro por CODGRUPO, depois por entidade
const entidades = data.reduce((acc, item) => { const gruposPorCodigo = data.reduce((acc, item) => {
const codgrupo = item.codgrupo || "";
if (!codgrupo) return acc;
if (!acc[codgrupo]) {
acc[codgrupo] = {};
}
const entidade = item.entidades || ""; const entidade = item.entidades || "";
if (!entidade) return acc; if (!entidade) return acc;
if (!acc[entidade]) { if (!acc[codgrupo][entidade]) {
acc[entidade] = []; acc[codgrupo][entidade] = [];
} }
acc[entidade].push(item); acc[codgrupo][entidade].push(item);
return acc; return acc;
}, {} as Record<string, DREItem[]>); }, {} as Record<string, Record<string, DREItem[]>>);
// Ordenar entidades alfabeticamente // Ordenar por CODGRUPO (numericamente), depois por entidade (alfabeticamente)
const sortedEntidades = Object.entries(entidades).sort(([entA], [entB]) => const sortedGrupos = Object.entries(gruposPorCodigo).sort(([codA], [codB]) => {
entA.localeCompare(entB) // Ordenar numericamente por CODGRUPO
); const numA = parseInt(codA) || 0;
const numB = parseInt(codB) || 0;
if (numA !== numB) {
return numA - numB;
}
// Se não for numérico, ordenar alfabeticamente
return codA.localeCompare(codB);
});
sortedEntidades.forEach(([entidade, items]) => { sortedGrupos.forEach(([codgrupo, entidades]) => {
// Ordenar entidades dentro do grupo alfabeticamente
const sortedEntidades = Object.entries(entidades).sort(([entA], [entB]) =>
entA.localeCompare(entB)
);
sortedEntidades.forEach(([entidade, items]) => {
// Calcular total da entidade // Calcular total da entidade
const totalEntidade = items.reduce( const totalEntidade = items.reduce(
(sum, item) => sum + parseFloat(item.valor), (sum, item) => sum + parseFloat(item.valor),
@ -1675,44 +1712,44 @@ export default function Teste() {
return acc; return acc;
}, {} as Record<string, DREItem[]>); }, {} as Record<string, DREItem[]>);
// Ordenar centros de custo por CODIGOCENTROCUSTO // Ordenar centros de custo por CODIGOCENTROCUSTO
const sortedCentros = Object.entries(centros).sort(([centroA, itemsA], [centroB, itemsB]) => { const sortedCentros = Object.entries(centros).sort(([centroA, itemsA], [centroB, itemsB]) => {
const codigoA = itemsA[0]?.codigo_centro_custo || ""; const codigoA = itemsA[0]?.codigo_centro_custo || "";
const codigoB = itemsB[0]?.codigo_centro_custo || ""; const codigoB = itemsB[0]?.codigo_centro_custo || "";
if (codigoA && codigoB) { if (codigoA && codigoB) {
return codigoA.localeCompare(codigoB); return codigoA.localeCompare(codigoB);
} }
if (codigoA && !codigoB) return -1; if (codigoA && !codigoB) return -1;
if (!codigoA && codigoB) return 1; if (!codigoA && codigoB) return 1;
return centroA.localeCompare(centroB); return centroA.localeCompare(centroB);
}); });
sortedCentros.forEach(([centro, centroItems]) => { sortedCentros.forEach(([centro, centroItems]) => {
const totalCentro = centroItems.reduce( const totalCentro = centroItems.reduce(
(sum, item) => sum + parseFloat(item.valor), (sum, item) => sum + parseFloat(item.valor),
0 0
); );
const valoresCentroPorMes = calcularValoresPorMes(centroItems); const valoresCentroPorMes = calcularValoresPorMes(centroItems);
// Verificar se centro de custo contém faturamento líquido // Verificar se centro de custo contém faturamento líquido
const temFaturamentoLiquidoCC = centroItems.some(item => item.codgrupo === "00"); const temFaturamentoLiquidoCC = centroItems.some(item => item.codgrupo === "00");
const codgrupoParaCalculoCC = temFaturamentoLiquidoCC ? "00" : ""; const codgrupoParaCalculoCC = temFaturamentoLiquidoCC ? "00" : "";
// Linha do centro de custo (Level 2) // Linha do centro de custo (Level 2)
const chaveCentro = `${entidade}-${diretoIndireto}-${centro}`; const chaveCentro = `${entidade}-${diretoIndireto}-${centro}`;
rows.push({ rows.push({
type: "centro_custo", type: "centro_custo",
level: 2, level: 2,
entidade, entidade,
direto_indireto: diretoIndireto, direto_indireto: diretoIndireto,
centro_custo: centro, centro_custo: centro,
codigo_centro_custo: centroItems[0].codigo_centro_custo, codigo_centro_custo: centroItems[0].codigo_centro_custo,
total: totalCentro, total: totalCentro,
isExpanded: expandedCentros.has(chaveCentro), isExpanded: expandedCentros.has(chaveCentro),
valoresPorMes: valoresCentroPorMes, valoresPorMes: valoresCentroPorMes,
percentuaisPorMes: calcularPercentuaisPorMes(valoresCentroPorMes, codgrupoParaCalculoCC), percentuaisPorMes: calcularPercentuaisPorMes(valoresCentroPorMes, codgrupoParaCalculoCC),
percentualTotal: calcularPercentualTotal(totalCentro, codgrupoParaCalculoCC), percentualTotal: calcularPercentualTotal(totalCentro, codgrupoParaCalculoCC),
}); });
@ -1729,19 +1766,19 @@ export default function Teste() {
return acc; return acc;
}, {} as Record<string, DREItem[]>); }, {} as Record<string, DREItem[]>);
// Ordenar contas por CODCONTA // Ordenar contas por CODCONTA
const sortedContas = Object.entries(contas).sort(([contaA, itemsA], [contaB, itemsB]) => { const sortedContas = Object.entries(contas).sort(([contaA, itemsA], [contaB, itemsB]) => {
const codcontaA = itemsA[0]?.codigo_conta || 0; const codcontaA = itemsA[0]?.codigo_conta || 0;
const codcontaB = itemsB[0]?.codigo_conta || 0; const codcontaB = itemsB[0]?.codigo_conta || 0;
if (codcontaA && codcontaB) { if (codcontaA && codcontaB) {
return codcontaA - codcontaB; return codcontaA - codcontaB;
} }
if (codcontaA && !codcontaB) return -1; if (codcontaA && !codcontaB) return -1;
if (!codcontaA && codcontaB) return 1; if (!codcontaA && codcontaB) return 1;
return contaA.localeCompare(contaB); return contaA.localeCompare(contaB);
}); });
sortedContas.forEach(([conta, contaItems]) => { sortedContas.forEach(([conta, contaItems]) => {
@ -1757,7 +1794,7 @@ export default function Teste() {
// Linha da conta (Level 3) // Linha da conta (Level 3)
rows.push({ rows.push({
type: "conta", type: "conta",
level: 3, level: 3,
entidade, entidade,
direto_indireto: diretoIndireto, direto_indireto: diretoIndireto,
@ -1774,8 +1811,9 @@ export default function Teste() {
} }
}); });
} }
}); });
} }
});
}); });
return rows; return rows;
@ -1873,13 +1911,13 @@ export default function Teste() {
<div className="flex items-center gap-2 whitespace-nowrap"> <div className="flex items-center gap-2 whitespace-nowrap">
<button <button
onClick={() => toggleDiretoIndireto(`${row.entidade}-${row.direto_indireto}`)} onClick={() => toggleDiretoIndireto(`${row.entidade}-${row.direto_indireto}`)}
className="p-2 hover:bg-blue-100 rounded-lg transition-all duration-150 ease-in-out flex items-center justify-center w-8 h-8 flex-shrink-0 transform hover:scale-105" className="p-2 hover:bg-blue-100 rounded-lg transition-all duration-150 ease-in-out flex items-center justify-center w-8 h-8 flex-shrink-0 transform hover:scale-105"
> >
{row.isExpanded ? ( {row.isExpanded ? (
<ChevronDown className="w-4 h-4 text-blue-600 transition-transform duration-150" /> <ChevronDown className="w-4 h-4 text-blue-600 transition-transform duration-150" />
) : ( ) : (
<ChevronRight className="w-4 h-4 text-blue-600 transition-transform duration-150" /> <ChevronRight className="w-4 h-4 text-blue-600 transition-transform duration-150" />
)} )}
</button> </button>
<button <button
onClick={() => handleRowClick(row)} onClick={() => handleRowClick(row)}
@ -1898,19 +1936,19 @@ export default function Teste() {
<div className="flex items-center gap-2 whitespace-nowrap"> <div className="flex items-center gap-2 whitespace-nowrap">
<button <button
onClick={() => toggleCentro(`${row.entidade}-${row.direto_indireto}-${row.centro_custo}`)} onClick={() => toggleCentro(`${row.entidade}-${row.direto_indireto}-${row.centro_custo}`)}
className="p-2 hover:bg-blue-100 rounded-lg transition-all duration-150 ease-in-out flex items-center justify-center w-8 h-8 flex-shrink-0 transform hover:scale-105" className="p-2 hover:bg-blue-100 rounded-lg transition-all duration-150 ease-in-out flex items-center justify-center w-8 h-8 flex-shrink-0 transform hover:scale-105"
> >
{row.isExpanded ? ( {row.isExpanded ? (
<ChevronDown className="w-4 h-4 text-blue-600 transition-transform duration-150" /> <ChevronDown className="w-4 h-4 text-blue-600 transition-transform duration-150" />
) : ( ) : (
<ChevronRight className="w-4 h-4 text-blue-600 transition-transform duration-150" /> <ChevronRight className="w-4 h-4 text-blue-600 transition-transform duration-150" />
)} )}
</button> </button>
<button <button
onClick={() => handleRowClick(row)} onClick={() => handleRowClick(row)}
className="flex-1 text-left hover:bg-blue-50/50 p-2 rounded-lg cursor-pointer transition-all duration-200 truncate" className="flex-1 text-left hover:bg-blue-50/50 p-2 rounded-lg cursor-pointer transition-all duration-200 truncate"
> >
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="font-medium text-gray-700"> <span className="font-medium text-gray-700">
{row.codigo_centro_custo {row.codigo_centro_custo
? `${row.centro_custo} - ${row.codigo_centro_custo}` ? `${row.centro_custo} - ${row.codigo_centro_custo}`