From 5ab2e45966a586b7b7f1f6d0c5548bde0328311e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alessandro=20Gon=C3=A7aalves?= Date: Wed, 10 Dec 2025 09:00:06 -0300 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20adicionada=20a=20coluna=20de=20tota?= =?UTF-8?q?lizador=20por=20per=C3=ADodo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/dre-filial/teste.tsx | 187 ++++++++++++++++++++++++----------- 1 file changed, 127 insertions(+), 60 deletions(-) diff --git a/src/app/dre-filial/teste.tsx b/src/app/dre-filial/teste.tsx index 44e706c..30b6780 100644 --- a/src/app/dre-filial/teste.tsx +++ b/src/app/dre-filial/teste.tsx @@ -102,42 +102,97 @@ const TableRow = memo(({ {/* Colunas de valores por mês e por filial - cada filial tem suas próprias colunas */} - {mesesDisponiveis.map((mes) => - ((filtrosAplicados && filiaisSelecionadas.length > 0) ? filiaisSelecionadas : (opcoesFiliais.length > 0 ? opcoesFiliais : [''])).map((filial: string) => { - // Só exibir se a filial estiver selecionada ou se não houver filtros aplicados - if (filtrosAplicados && filiaisSelecionadas.length > 0 && !filiaisSelecionadas.includes(filial)) { - return null; - } - return ( - - handleRowClick(row, mes, filial)} - title={ - filial && row.valoresPorMesPorFilial?.[mes]?.[filial] !== undefined - ? formatCurrency(row.valoresPorMesPorFilial[mes][filial]) - : row.valoresPorMes?.[mes] !== undefined - ? formatCurrency(row.valoresPorMes[mes]) - : "-" + {mesesDisponiveis.map((mes) => { + const filiaisParaMes = (filtrosAplicados && filiaisSelecionadas.length > 0) + ? filiaisSelecionadas + : (opcoesFiliais.length > 0 ? opcoesFiliais : ['']); + + return ( + + {/* Colunas de filiais para este mês */} + {filiaisParaMes.map((filial: string) => { + // Só exibir se a filial estiver selecionada ou se não houver filtros aplicados + if (filtrosAplicados && filiaisSelecionadas.length > 0 && !filiaisSelecionadas.includes(filial)) { + return null; } + return ( + + handleRowClick(row, mes, filial)} + title={ + filial && row.valoresPorMesPorFilial?.[mes]?.[filial] !== undefined + ? formatCurrency(row.valoresPorMesPorFilial[mes][filial]) + : row.valoresPorMes?.[mes] !== undefined + ? formatCurrency(row.valoresPorMes[mes]) + : "-" + } + > + {filial && row.valoresPorMesPorFilial?.[mes]?.[filial] !== undefined && row.valoresPorMesPorFilial[mes][filial] !== 0 ? ( + (() => { + const valor = row.valoresPorMesPorFilial[mes][filial]; + const { formatted, isNegative } = formatCurrencyWithColor(valor); + return ( + + {formatted} + + ); + })() + ) : !filial && row.valoresPorMes?.[mes] !== undefined ? ( + (() => { + const { formatted, isNegative } = formatCurrencyWithColor(row.valoresPorMes[mes]); + return ( + + {formatted} + + ); + })() + ) : ( + - + )} + + handleRowClick(row, mes, filial)} + title={ + filial && row.percentuaisPorMesPorFilial?.[mes]?.[filial] !== undefined + ? `${row.percentuaisPorMesPorFilial[mes][filial].toFixed(1)}%` + : row.percentuaisPorMes?.[mes] !== undefined + ? `${row.percentuaisPorMes[mes].toFixed(1)}%` + : "-" + } + > + {filial && row.percentuaisPorMesPorFilial?.[mes]?.[filial] !== undefined && row.percentuaisPorMesPorFilial[mes][filial] !== 0 ? ( + `${row.percentuaisPorMesPorFilial[mes][filial].toFixed(1)}%` + ) : !filial && row.percentuaisPorMes?.[mes] !== undefined ? ( + `${row.percentuaisPorMes[mes].toFixed(1)}%` + ) : ( + - + )} + + + ); + })} + + {/* Colunas de totalizador para este mês */} + handleRowClick(row, mes)} + title={row.valoresPorMes?.[mes] !== undefined ? formatCurrency(row.valoresPorMes[mes]) : "-"} > - {filial && row.valoresPorMesPorFilial?.[mes]?.[filial] !== undefined && row.valoresPorMesPorFilial[mes][filial] !== 0 ? ( - (() => { - const valor = row.valoresPorMesPorFilial[mes][filial]; - const { formatted, isNegative } = formatCurrencyWithColor(valor); - return ( - - {formatted} - - ); - })() - ) : !filial && row.valoresPorMes?.[mes] !== undefined ? ( + {row.valoresPorMes?.[mes] !== undefined ? ( (() => { const { formatted, isNegative } = formatCurrencyWithColor(row.valoresPorMes[mes]); return ( @@ -145,7 +200,7 @@ const TableRow = memo(({ className={ isNegative ? "text-red-600 font-bold" - : "text-gray-900" + : "text-green-700 font-bold" } > {formatted} @@ -157,28 +212,21 @@ const TableRow = memo(({ )} handleRowClick(row, mes, filial)} + className="px-2 py-1 text-center font-bold cursor-pointer hover:bg-green-50/50 transition-colors duration-200 whitespace-nowrap overflow-hidden w-[100px] min-w-[100px] bg-green-50/30" + onClick={() => handleRowClick(row, mes)} title={ - filial && row.percentuaisPorMesPorFilial?.[mes]?.[filial] !== undefined - ? `${row.percentuaisPorMesPorFilial[mes][filial].toFixed(1)}%` - : row.percentuaisPorMes?.[mes] !== undefined + row.percentuaisPorMes?.[mes] !== undefined ? `${row.percentuaisPorMes[mes].toFixed(1)}%` : "-" } > - {filial && row.percentuaisPorMesPorFilial?.[mes]?.[filial] !== undefined && row.percentuaisPorMesPorFilial[mes][filial] !== 0 ? ( - `${row.percentuaisPorMesPorFilial[mes][filial].toFixed(1)}%` - ) : !filial && row.percentuaisPorMes?.[mes] !== undefined ? ( - `${row.percentuaisPorMes[mes].toFixed(1)}%` - ) : ( - - - )} + {row.percentuaisPorMes?.[mes] !== undefined + ? `${row.percentuaisPorMes[mes].toFixed(1)}%` + : -} ); - }) - )} + })} {/* Coluna Total */} Descrição - {mesesDisponiveis.map((mes) => - ((filtrosAplicados && filiaisSelecionadas.length > 0) ? filiaisSelecionadas : (opcoesFiliais.length > 0 ? opcoesFiliais : [''])).map((filial: string) => ( - - - {mes}{filial && <>
- Filial - {filial}} + {mesesDisponiveis.map((mes) => { + const filiaisParaMes = (filtrosAplicados && filiaisSelecionadas.length > 0) + ? filiaisSelecionadas + : (opcoesFiliais.length > 0 ? opcoesFiliais : ['']); + + return ( + + {/* Cabeçalhos de filiais para este mês */} + {filiaisParaMes.map((filial: string) => ( + + + {mes}{filial && <>
+ Filial - {filial}} + + + %{filial && <>
+ Filial - {filial}} + +
+ ))} + + {/* Cabeçalhos de totalizador para este mês */} + + {mes}
+ Total - - %{filial && <>
- Filial - {filial}} + + %
+ Total
- )) - )} + ); + })} Total From 900fad9707747194dee77ee31bb17f2440fa839a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alessandro=20Gon=C3=A7aalves?= Date: Wed, 10 Dec 2025 09:30:21 -0300 Subject: [PATCH 2/3] fix: totalizador --- src/app/api/analitico-filial-oracle/route.ts | 24 +++++++++++--------- src/app/dre-filial/teste.tsx | 16 ++++++++++++- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/app/api/analitico-filial-oracle/route.ts b/src/app/api/analitico-filial-oracle/route.ts index 7d415af..8b1fecc 100644 --- a/src/app/api/analitico-filial-oracle/route.ts +++ b/src/app/api/analitico-filial-oracle/route.ts @@ -52,6 +52,8 @@ export async function GET(request: NextRequest) { let sql = ''; const params: any[] = []; let paramIndex = 1; + const temJoin = !!codFilial; + const prefixo = temJoin ? 'VB.' : ''; // Usar prefixo apenas quando há JOIN // Se houver filtro por filial, fazer JOIN com FILIAL_CC if (codFilial) { @@ -73,7 +75,7 @@ WHERE 1=1`; // Filtro por período (usando ANOMESCOMP) if (dataInicio && dataFim) { - sql += ` AND VB.ANOMESCOMP >= :${paramIndex} AND VB.ANOMESCOMP <= :${paramIndex + 1}`; + sql += ` AND ${prefixo}ANOMESCOMP >= :${paramIndex} AND ${prefixo}ANOMESCOMP <= :${paramIndex + 1}`; params.push(dataInicio, dataFim); paramIndex += 2; console.log('📅 Adicionando filtro de período:', dataInicio, 'a', dataFim); @@ -81,7 +83,7 @@ WHERE 1=1`; // Filtro por código do grupo if (codigoGrupo) { - sql += ` AND VB.CODGRUPO = :${paramIndex}`; + sql += ` AND ${prefixo}CODGRUPO = :${paramIndex}`; params.push(codigoGrupo); paramIndex++; console.log('📊 Adicionando filtro de grupo:', codigoGrupo); @@ -89,7 +91,7 @@ WHERE 1=1`; // Filtro por subgrupo (DIRETO, INDIRETO, SEM CC, etc.) if (codigoSubgrupo) { - sql += ` AND VB.SUBGRUPO = :${paramIndex}`; + sql += ` AND ${prefixo}SUBGRUPO = :${paramIndex}`; params.push(codigoSubgrupo); paramIndex++; console.log('📊 Adicionando filtro de subgrupo:', codigoSubgrupo); @@ -97,11 +99,11 @@ WHERE 1=1`; // Filtro por código da conta if (codigoConta) { - sql += ` AND VB.CODCONTA = :${paramIndex}`; + sql += ` AND ${prefixo}CODCONTA = :${paramIndex}`; params.push(codigoConta); paramIndex++; console.log('💰 Adicionando filtro de conta:', codigoConta); - } + } // Filtro por códigos de centros de custo selecionados no filtro // Se houver codigosCentrosCustoSelecionados E centroCusto individual, incluir ambos @@ -119,7 +121,7 @@ WHERE 1=1`; if (centroCusto && centroCusto.trim() !== '') { // Quando há centroCusto individual (clique na célula), usar APENAS ele // Ignorar codigosCentrosCustoSelecionados do filtro geral para garantir filtro preciso - sql += ` AND VB.CODIGOCENTROCUSTO = :${paramIndex}`; + sql += ` AND ${prefixo}CODIGOCENTROCUSTO = :${paramIndex}`; params.push(centroCusto); paramIndex++; console.log('🏢 PRIORIDADE: Filtrando APENAS por centroCusto individual (clique na célula):', centroCusto); @@ -130,7 +132,7 @@ WHERE 1=1`; const codigosArray = codigosCentrosCustoSelecionados.split(',').filter(c => c.trim() !== ''); if (codigosArray.length > 0) { const placeholders = codigosArray.map(() => `:${paramIndex++}`).join(','); - sql += ` AND VB.CODIGOCENTROCUSTO IN (${placeholders})`; + sql += ` AND ${prefixo}CODIGOCENTROCUSTO IN (${placeholders})`; params.push(...codigosArray); console.log('🏢 Filtrando por códigos de centros de custo selecionados (filtro geral):', codigosArray); console.log('📝 SQL após adicionar filtro IN:', sql.substring(0, 200) + '...'); @@ -142,7 +144,7 @@ WHERE 1=1`; // Exclusão de centro de custo específico (quando desmarcado) // Só aplicar se não houver codigosCentrosCustoSelecionados, para evitar conflito if (excluirCentroCusto && !codigosCentrosCustoSelecionados) { - sql += ` AND VB.CODIGOCENTROCUSTO != :${paramIndex}`; + sql += ` AND ${prefixo}CODIGOCENTROCUSTO != :${paramIndex}`; params.push(excluirCentroCusto); paramIndex++; console.log('🚫 Excluindo centro de custo:', excluirCentroCusto); @@ -150,7 +152,7 @@ WHERE 1=1`; // Exclusão de código de conta específico (quando desmarcado) if (excluirCodigoConta) { - sql += ` AND VB.CODCONTA != :${paramIndex}`; + sql += ` AND ${prefixo}CODCONTA != :${paramIndex}`; params.push(excluirCodigoConta); paramIndex++; console.log('🚫 Excluindo código de conta:', excluirCodigoConta); @@ -160,12 +162,12 @@ WHERE 1=1`; if (codigosContasSelecionadas) { const codigosArray = codigosContasSelecionadas.split(','); const placeholders = codigosArray.map(() => `:${paramIndex++}`).join(','); - sql += ` AND VB.CODCONTA IN (${placeholders})`; + sql += ` AND ${prefixo}CODCONTA IN (${placeholders})`; params.push(...codigosArray); console.log('💰 Filtrando por códigos de contas:', codigosArray); } - sql += ` ORDER BY VB.DTVENC, VB.CODFORNEC, VB.CODCONTA`; + sql += ` ORDER BY ${prefixo}DTVENC, ${prefixo}CODFORNEC, ${prefixo}CODCONTA`; // Log detalhado da query SQL final console.log('═══════════════════════════════════════════════════════════════'); diff --git a/src/app/dre-filial/teste.tsx b/src/app/dre-filial/teste.tsx index 30b6780..e0ab44d 100644 --- a/src/app/dre-filial/teste.tsx +++ b/src/app/dre-filial/teste.tsx @@ -417,6 +417,7 @@ export default function Teste() { const handleRowClick = React.useCallback((row: HierarchicalRow, mesSelecionado?: string, filialSelecionada?: string) => { console.log('🖱️ Clique na linha:', row); console.log('📅 Mês selecionado:', mesSelecionado); + console.log('🏢 Filial selecionada:', filialSelecionada); // Linhas calculadas não devem abrir o componente analítico if (row.type === "calculado") { @@ -453,6 +454,15 @@ export default function Teste() { return false; } + // Se é um totalizador (mesSelecionado presente mas filialSelecionada não), não filtrar por filial + // Caso contrário, filtrar por filial se especificada + if (filialSelecionada) { + const itemFilial = item.filial || item.codfilial || ""; + if (itemFilial !== filialSelecionada) { + return false; + } + } + if (row.type === "grupo") { return item.codigo_grupo === row.codigo_grupo || item.codgrupo === row.codigo_grupo; } else if (row.type === "conta") { @@ -475,6 +485,7 @@ export default function Teste() { } // Determinar CODFILIAL baseado na filial selecionada + // Se é um totalizador (mesSelecionado presente mas filialSelecionada não), deixar vazio para incluir todas as filiais let codFilialFiltro = ""; if (filialSelecionada) { // Se a filial selecionada já é um código numérico, usar diretamente @@ -495,6 +506,8 @@ export default function Teste() { } } } + // Se mesSelecionado está presente mas filialSelecionada não, é um totalizador + // Deixar codFilialFiltro vazio para incluir todas as filiais daquele mês const novosFiltros = { dataInicio: dataInicioFiltro, @@ -503,7 +516,7 @@ export default function Teste() { codigoGrupo: codigoGrupoFiltro, codigoSubgrupo: "", // Não aplicável na hierarquia filial codigoConta: codigoContaFiltro, - codFilial: codFilialFiltro, + codFilial: codFilialFiltro, // Vazio para totalizador = todas as filiais do mês linhaSelecionada: row.grupo || row.conta || "", excluirCentroCusto: "", excluirCodigoConta: "", @@ -512,6 +525,7 @@ export default function Teste() { }; console.log('🎯 Novos filtros para analítico:', novosFiltros); + console.log('📊 É totalizador?', mesSelecionado && !filialSelecionada ? 'SIM' : 'NÃO'); setAnaliticoFiltros(novosFiltros); }, [data]); From 0ea85582fa14bc5c9f5f910c64dad5b4a99f8406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alessandro=20Gon=C3=A7aalves?= Date: Wed, 10 Dec 2025 09:34:49 -0300 Subject: [PATCH 3/3] fix: ajuste no calculo totalizador --- src/app/api/analitico-filial-oracle/route.ts | 27 +++++++++++++----- src/app/dre-filial/teste.tsx | 29 +++++++++++++++++--- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/app/api/analitico-filial-oracle/route.ts b/src/app/api/analitico-filial-oracle/route.ts index 8b1fecc..6dae070 100644 --- a/src/app/api/analitico-filial-oracle/route.ts +++ b/src/app/api/analitico-filial-oracle/route.ts @@ -52,11 +52,14 @@ export async function GET(request: NextRequest) { let sql = ''; const params: any[] = []; let paramIndex = 1; - const temJoin = !!codFilial; + + // Verificar se há múltiplas filiais (separadas por vírgula) + const filiaisArray = codFilial ? codFilial.split(',').map(f => f.trim()).filter(f => f !== '') : []; + const temJoin = filiaisArray.length > 0; const prefixo = temJoin ? 'VB.' : ''; // Usar prefixo apenas quando há JOIN // Se houver filtro por filial, fazer JOIN com FILIAL_CC - if (codFilial) { + if (temJoin) { sql = `SELECT FC.CODFILIAL, VB.* FROM VB_DRE_FILIAL_DESPESA_ANALITICO VB INNER JOIN FILIAL_CC FC ON FC.CC = VB.CODIGOCENTROCUSTO @@ -66,11 +69,21 @@ WHERE 1=1`; } // Filtro por filial (usando JOIN com FILIAL_CC) - if (codFilial) { - sql += ` AND FC.CODFILIAL = :${paramIndex}`; - params.push(codFilial); - paramIndex++; - console.log('🏢 Adicionando filtro de filial (CODFILIAL):', codFilial); + // Se houver múltiplas filiais, usar IN; caso contrário, usar = + if (temJoin) { + if (filiaisArray.length === 1) { + // Uma única filial - usar = + sql += ` AND FC.CODFILIAL = :${paramIndex}`; + params.push(filiaisArray[0]); + paramIndex++; + console.log('🏢 Adicionando filtro de filial única (CODFILIAL):', filiaisArray[0]); + } else { + // Múltiplas filiais - usar IN + const placeholders = filiaisArray.map(() => `:${paramIndex++}`).join(','); + sql += ` AND FC.CODFILIAL IN (${placeholders})`; + params.push(...filiaisArray); + console.log('🏢 Adicionando filtro de múltiplas filiais (CODFILIAL IN):', filiaisArray); + } } // Filtro por período (usando ANOMESCOMP) diff --git a/src/app/dre-filial/teste.tsx b/src/app/dre-filial/teste.tsx index e0ab44d..c95f67e 100644 --- a/src/app/dre-filial/teste.tsx +++ b/src/app/dre-filial/teste.tsx @@ -485,7 +485,7 @@ export default function Teste() { } // Determinar CODFILIAL baseado na filial selecionada - // Se é um totalizador (mesSelecionado presente mas filialSelecionada não), deixar vazio para incluir todas as filiais + // Se é um totalizador (mesSelecionado presente mas filialSelecionada não), incluir todas as filiais selecionadas let codFilialFiltro = ""; if (filialSelecionada) { // Se a filial selecionada já é um código numérico, usar diretamente @@ -505,9 +505,30 @@ export default function Teste() { codFilialFiltro = filialSelecionada; } } + } else if (mesSelecionado) { + // Se mesSelecionado está presente mas filialSelecionada não, é um totalizador + // Incluir todas as filiais selecionadas (ou todas disponíveis se nenhuma estiver selecionada) + const filiaisParaTotalizador = filiaisSelecionadas.length > 0 + ? filiaisSelecionadas + : opcoesFiliais; + + // Converter nomes de filiais para códigos CODFILIAL + const codigosFiliais = filiaisParaTotalizador.map(filial => { + if (/^\d+$/.test(filial)) { + return filial; + } else { + const itemComFilial = data.find((item: DREItem) => { + const itemFilial = item.filial || item.codfilial || ""; + return itemFilial === filial; + }); + return itemComFilial?.codfilial || filial; + } + }).filter(Boolean); + + // Passar como string separada por vírgula para a API processar com IN + codFilialFiltro = codigosFiliais.join(','); + console.log('📊 Totalizador: incluindo todas as filiais selecionadas:', codigosFiliais); } - // Se mesSelecionado está presente mas filialSelecionada não, é um totalizador - // Deixar codFilialFiltro vazio para incluir todas as filiais daquele mês const novosFiltros = { dataInicio: dataInicioFiltro, @@ -527,7 +548,7 @@ export default function Teste() { console.log('🎯 Novos filtros para analítico:', novosFiltros); console.log('📊 É totalizador?', mesSelecionado && !filialSelecionada ? 'SIM' : 'NÃO'); setAnaliticoFiltros(novosFiltros); - }, [data]); + }, [data, filiaisSelecionadas, opcoesFiliais]); const toggleGrupo = useCallback((codigoGrupo: string) => { setExpandedGrupos(prev => {