fix: organização dos grupos por cod_grupo

This commit is contained in:
Alessandro Gonçaalves 2025-10-21 00:07:52 -03:00
parent a1d22d3ac6
commit 6f14b655f5
2 changed files with 317 additions and 40 deletions

View File

@ -14,6 +14,8 @@ interface DREItem {
codigo_conta: number; codigo_conta: number;
conta: string; conta: string;
valor: string; valor: string;
codgrupo?: string;
isCalculado?: boolean;
} }
interface HierarchicalRow { interface HierarchicalRow {
@ -257,38 +259,33 @@ export default function Teste() {
const buildHierarchicalData = (): HierarchicalRow[] => { const buildHierarchicalData = (): HierarchicalRow[] => {
const rows: HierarchicalRow[] = []; const rows: HierarchicalRow[] = [];
// Agrupar por grupo, mas tratar grupo 05 como subgrupo do grupo 04 // Agrupar por grupo
const grupos = data.reduce((acc, item) => { const grupos = data.reduce((acc, item) => {
// Se for grupo 05, adicionar ao grupo 04 como subgrupo
if (item.grupo.includes("05")) {
// Encontrar grupo 04 existente ou criar um
const grupo04Key = Object.keys(acc).find((key) => key.includes("04"));
if (grupo04Key) {
acc[grupo04Key].push(item);
} else {
// Se não existe grupo 04, criar um grupo especial
const grupo04Nome =
Object.keys(acc).find((key) => key.includes("04")) ||
"04 - GRUPO 04";
if (!acc[grupo04Nome]) {
acc[grupo04Nome] = [];
}
acc[grupo04Nome].push(item);
}
} else {
// Para outros grupos, agrupar normalmente
if (!acc[item.grupo]) { if (!acc[item.grupo]) {
acc[item.grupo] = []; acc[item.grupo] = [];
} }
acc[item.grupo].push(item); acc[item.grupo].push(item);
}
return acc; return acc;
}, {} as Record<string, DREItem[]>); }, {} as Record<string, DREItem[]>);
// Ordenar grupos // Ordenar grupos pelo CODGRUPO numérico
const sortedGrupos = Object.entries(grupos).sort(([a], [b]) => const sortedGrupos = Object.entries(grupos).sort(([grupoA, itemsA], [grupoB, itemsB]) => {
a.localeCompare(b) // Pegar o CODGRUPO do primeiro item de cada grupo
); const codgrupoA = itemsA[0]?.codgrupo || "";
const codgrupoB = itemsB[0]?.codgrupo || "";
// Se ambos têm CODGRUPO, ordenar numericamente
if (codgrupoA && codgrupoB) {
return parseInt(codgrupoA) - parseInt(codgrupoB);
}
// Se apenas um tem CODGRUPO, ele vem primeiro
if (codgrupoA && !codgrupoB) return -1;
if (!codgrupoA && codgrupoB) return 1;
// Se nenhum tem CODGRUPO, ordenar alfabeticamente
return grupoA.localeCompare(grupoB);
});
sortedGrupos.forEach(([grupo, items]) => { sortedGrupos.forEach(([grupo, items]) => {
const totalGrupo = items.reduce( const totalGrupo = items.reduce(
@ -461,8 +458,25 @@ export default function Teste() {
" bg-gradient-to-r from-blue-100 to-indigo-100 border-l-4 border-blue-500 shadow-lg"; " bg-gradient-to-r from-blue-100 to-indigo-100 border-l-4 border-blue-500 shadow-lg";
} }
// Verificar se é um grupo calculado
const isCalculado = row.grupo?.includes("CALCULADO") ||
row.grupo?.includes("FATURAMENTO LÍQUIDO") ||
row.grupo?.includes("LUCRO BRUTO") ||
row.grupo?.includes("MARGEM LOJA") ||
row.grupo?.includes("RESULTADO OPERACIONAL") ||
row.grupo?.includes("RESULTADO FINANCEIRO") ||
row.grupo?.includes("OUTRAS RECEITAS / DESPESAS") ||
row.grupo?.includes("LAIR") ||
row.grupo?.includes("IR") ||
row.grupo?.includes("CSLL") ||
row.grupo?.includes("LUCRO LÍQUIDO") ||
row.grupo?.includes("EBITDA");
switch (row.type) { switch (row.type) {
case "grupo": case "grupo":
if (isCalculado) {
return `${style} bg-gradient-to-r from-green-50/30 to-emerald-50/20 font-bold text-gray-900 border-b-2 border-green-200 border-l-4 border-green-400`;
}
return `${style} bg-gradient-to-r from-blue-50/20 to-indigo-50/20 font-bold text-gray-900 border-b-2 border-blue-200`; return `${style} bg-gradient-to-r from-blue-50/20 to-indigo-50/20 font-bold text-gray-900 border-b-2 border-blue-200`;
case "subgrupo": case "subgrupo":
return `${style} bg-gradient-to-r from-gray-50/30 to-blue-50/20 font-semibold text-gray-800`; return `${style} bg-gradient-to-r from-gray-50/30 to-blue-50/20 font-semibold text-gray-800`;
@ -480,6 +494,20 @@ export default function Teste() {
}; };
const renderCellContent = (row: HierarchicalRow) => { const renderCellContent = (row: HierarchicalRow) => {
// Verificar se é um grupo calculado
const isCalculado = row.grupo?.includes("CALCULADO") ||
row.grupo?.includes("FATURAMENTO LÍQUIDO") ||
row.grupo?.includes("LUCRO BRUTO") ||
row.grupo?.includes("MARGEM LOJA") ||
row.grupo?.includes("RESULTADO OPERACIONAL") ||
row.grupo?.includes("RESULTADO FINANCEIRO") ||
row.grupo?.includes("OUTRAS RECEITAS / DESPESAS") ||
row.grupo?.includes("LAIR") ||
row.grupo?.includes("IR") ||
row.grupo?.includes("CSLL") ||
row.grupo?.includes("LUCRO LÍQUIDO") ||
row.grupo?.includes("EBITDA");
switch (row.type) { switch (row.type) {
case "grupo": case "grupo":
return ( return (
@ -498,7 +526,17 @@ export default function Teste() {
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"
> >
<span className="font-bold text-gray-900">{row.grupo}</span> <div className="flex items-center gap-2">
{isCalculado && (
<span className="text-green-600 font-bold text-sm"></span>
)}
<span className={`font-bold ${isCalculado ? 'text-green-800' : 'text-gray-900'}`}>
{row.grupo}
</span>
{isCalculado && (
<span className="text-xs text-green-600 font-medium">(CALCULADO)</span>
)}
</div>
</button> </button>
</div> </div>
); );

View File

@ -13,19 +13,31 @@ export async function GET(request: NextRequest) {
console.log('✅ Query executada com sucesso:', data.length, 'registros encontrados'); console.log('✅ Query executada com sucesso:', data.length, 'registros encontrados');
// Transformar os dados do Oracle para o formato esperado pelo componente // Transformar os dados do Oracle para o formato esperado pelo componente
const transformedData = data.map((item: any) => ({ const transformedData = data.map((item: any) => {
const codgrupo = item.CODGRUPO || "";
const nomeGrupo = item.GRUPO || "";
return {
codfilial: "001", // Valor padrão codfilial: "001", // Valor padrão
data_competencia: item.DATA || "2023-03", // Usar DATA do Oracle data_competencia: item.DATA || "2023-03", // Usar DATA do Oracle
data_cai: item.DATA || "2023-03", // Usar DATA do Oracle data_cai: item.DATA || "2023-03", // Usar DATA do Oracle
grupo: item.GRUPO || "", // Usar GRUPO do Oracle grupo: codgrupo ? `${codgrupo} - ${nomeGrupo}` : nomeGrupo, // Concatenar código + nome
subgrupo: item.CENTROCUSTO || "", // Usar CENTROCUSTO como subgrupo subgrupo: item.CENTROCUSTO || "", // Usar CENTROCUSTO como subgrupo
centro_custo: item.CODIGOCENTROCUSTO || "", // Usar CODIGOCENTROCUSTO centro_custo: item.CODIGOCENTROCUSTO || "", // Usar CODIGOCENTROCUSTO
codigo_conta: parseInt(item.CODCONTA) || 0, // Converter CODCONTA para número codigo_conta: parseInt(item.CODCONTA) || 0, // Converter CODCONTA para número
conta: item.CONTA || "", // Usar CONTA do Oracle conta: item.CONTA || "", // Usar CONTA do Oracle
valor: item.VALOR?.toString() || "0", // Converter VALOR para string valor: item.VALOR?.toString() || "0", // Converter VALOR para string
})); codgrupo: codgrupo, // Adicionar código do grupo para cálculos
};
});
return NextResponse.json(transformedData); // Criar grupos calculados que não existem no Oracle
const gruposCalculados = criarGruposCalculados(transformedData);
// Combinar dados originais com grupos calculados
const dadosCompletos = [...transformedData, ...gruposCalculados];
return NextResponse.json(dadosCompletos);
} catch (error) { } catch (error) {
console.error('❌ Erro ao buscar dados DRE do Oracle:', error); console.error('❌ Erro ao buscar dados DRE do Oracle:', error);
@ -40,3 +52,230 @@ export async function GET(request: NextRequest) {
); );
} }
} }
function criarGruposCalculados(dados: any[]) {
const gruposCalculados: any[] = [];
// Agrupar dados por mês para cálculos
const dadosPorMes = dados.reduce((acc, item) => {
const mes = item.data_competencia;
if (!acc[mes]) acc[mes] = [];
acc[mes].push(item);
return acc;
}, {} as Record<string, any[]>);
// Para cada mês, criar os grupos calculados
Object.keys(dadosPorMes).forEach(mes => {
const dadosMes = dadosPorMes[mes];
// Calcular valores por grupo usando código numérico
const valoresPorGrupo = dadosMes.reduce((acc, item) => {
const codgrupo = item.codgrupo;
if (!acc[codgrupo]) acc[codgrupo] = 0;
acc[codgrupo] += parseFloat(item.valor);
return acc;
}, {} as Record<string, number>);
// 03 - Faturamento Líquido (01 + 02)
const faturamentoBruto = valoresPorGrupo['01'] || 0;
const devolucao = valoresPorGrupo['02'] || 0;
const faturamentoLiquido = faturamentoBruto + devolucao;
gruposCalculados.push({
codfilial: "001",
data_competencia: mes,
data_cai: mes,
grupo: "03 - FATURAMENTO LÍQUIDO",
subgrupo: "CALCULADO",
centro_custo: "CALCULADO",
codigo_conta: 0,
conta: "FATURAMENTO LÍQUIDO",
valor: faturamentoLiquido.toString(),
codgrupo: "03",
isCalculado: true
});
// 05 - Lucro Bruto (03 + 04)
const cmv = valoresPorGrupo['04'] || 0;
const lucroBruto = faturamentoLiquido + cmv;
gruposCalculados.push({
codfilial: "001",
data_competencia: mes,
data_cai: mes,
grupo: "05 - LUCRO BRUTO",
subgrupo: "CALCULADO",
centro_custo: "CALCULADO",
codigo_conta: 0,
conta: "LUCRO BRUTO",
valor: lucroBruto.toString(),
codgrupo: "05",
isCalculado: true
});
// 07 - Margem Loja (05 + 06)
const receitasGastosDiretos = valoresPorGrupo['06'] || 0;
const margemLoja = lucroBruto + receitasGastosDiretos;
gruposCalculados.push({
codfilial: "001",
data_competencia: mes,
data_cai: mes,
grupo: "07 - MARGEM LOJA",
subgrupo: "CALCULADO",
centro_custo: "CALCULADO",
codigo_conta: 0,
conta: "MARGEM LOJA",
valor: margemLoja.toString(),
codgrupo: "07",
isCalculado: true
});
// 10 - Resultado Operacional (07 + 08 + 09)
const verba = valoresPorGrupo['08'] || 0;
const receitasGastosIndiretos = valoresPorGrupo['09'] || 0;
const resultadoOperacional = margemLoja + verba + receitasGastosIndiretos;
gruposCalculados.push({
codfilial: "001",
data_competencia: mes,
data_cai: mes,
grupo: "10 - RESULTADO OPERACIONAL",
subgrupo: "CALCULADO",
centro_custo: "CALCULADO",
codigo_conta: 0,
conta: "RESULTADO OPERACIONAL",
valor: resultadoOperacional.toString(),
codgrupo: "10",
isCalculado: true
});
// 13 - Resultado Financeiro (11 + 12)
const receitaFinanceira = valoresPorGrupo['11'] || 0;
const despesaFinanceira = valoresPorGrupo['12'] || 0;
const resultadoFinanceiro = receitaFinanceira + despesaFinanceira;
gruposCalculados.push({
codfilial: "001",
data_competencia: mes,
data_cai: mes,
grupo: "13 - RESULTADO FINANCEIRO",
subgrupo: "CALCULADO",
centro_custo: "CALCULADO",
codigo_conta: 0,
conta: "RESULTADO FINANCEIRO",
valor: resultadoFinanceiro.toString(),
codgrupo: "13",
isCalculado: true
});
// 18 - Outras Receitas / Despesas (14 + 15 + 16 + 17)
const prejuizosPerdas = valoresPorGrupo['14'] || 0;
const inativas = valoresPorGrupo['15'] || 0;
const diretoria = valoresPorGrupo['16'] || 0;
const lancamentosSemCC = valoresPorGrupo['17'] || 0;
const outrasReceitasDespesas = prejuizosPerdas + inativas + diretoria + lancamentosSemCC;
gruposCalculados.push({
codfilial: "001",
data_competencia: mes,
data_cai: mes,
grupo: "18 - OUTRAS RECEITAS / DESPESAS",
subgrupo: "CALCULADO",
centro_custo: "CALCULADO",
codigo_conta: 0,
conta: "OUTRAS RECEITAS / DESPESAS",
valor: outrasReceitasDespesas.toString(),
codgrupo: "18",
isCalculado: true
});
// 19 - LAIR (10 + 13 + 18)
const lair = resultadoOperacional + resultadoFinanceiro + outrasReceitasDespesas;
gruposCalculados.push({
codfilial: "001",
data_competencia: mes,
data_cai: mes,
grupo: "19 - LAIR",
subgrupo: "CALCULADO",
centro_custo: "CALCULADO",
codigo_conta: 0,
conta: "LAIR",
valor: lair.toString(),
codgrupo: "19",
isCalculado: true
});
// 20 - IR (se LAIR > 0 calcular 20% e resultado negativo, se não 0)
const ir = lair > 0 ? -(lair * 0.20) : 0;
gruposCalculados.push({
codfilial: "001",
data_competencia: mes,
data_cai: mes,
grupo: "20 - IR",
subgrupo: "CALCULADO",
centro_custo: "CALCULADO",
codigo_conta: 0,
conta: "IMPOSTO DE RENDA",
valor: ir.toString(),
codgrupo: "20",
isCalculado: true
});
// 21 - CSLL (se LAIR > 0 calcular 9% e resultado negativo, se não 0)
const csll = lair > 0 ? -(lair * 0.09) : 0;
gruposCalculados.push({
codfilial: "001",
data_competencia: mes,
data_cai: mes,
grupo: "21 - CSLL",
subgrupo: "CALCULADO",
centro_custo: "CALCULADO",
codigo_conta: 0,
conta: "CONTRIBUIÇÃO SOCIAL SOBRE LUCRO LÍQUIDO",
valor: csll.toString(),
codgrupo: "21",
isCalculado: true
});
// 22 - Lucro Líquido (19 + 20 + 21)
const lucroLiquido = lair + ir + csll;
gruposCalculados.push({
codfilial: "001",
data_competencia: mes,
data_cai: mes,
grupo: "22 - LUCRO LÍQUIDO",
subgrupo: "CALCULADO",
centro_custo: "CALCULADO",
codigo_conta: 0,
conta: "LUCRO LÍQUIDO",
valor: lucroLiquido.toString(),
codgrupo: "22",
isCalculado: true
});
// 24 - EBITDA (19 - (13 + 18 + 23))
const despesaTributaria = valoresPorGrupo['23'] || 0;
const ebitda = lair - (resultadoFinanceiro + outrasReceitasDespesas + despesaTributaria);
gruposCalculados.push({
codfilial: "001",
data_competencia: mes,
data_cai: mes,
grupo: "24 - EBITDA",
subgrupo: "CALCULADO",
centro_custo: "CALCULADO",
codigo_conta: 0,
conta: "EBITDA",
valor: ebitda.toString(),
codgrupo: "24",
isCalculado: true
});
});
return gruposCalculados;
}