Merge pull request #67 from JurunenseDevInterno/fix/grid-analitico-DRE-dre-entidade

ajuste nas grid da DRE e dre-entidade, verificado que era exibido mais de uma vez na dre-entidade o mesmo lancamento e não era na query e sim a falta de um id para manter a unicidade dos dados, revalidado tambem nos outros routes para manter a unicidade
This commit is contained in:
Felipe Batista 2025-12-23 13:18:39 -03:00 committed by GitHub
commit eb6480b57e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 1751 additions and 1377 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
import { NextRequest, NextResponse } from 'next/server';
import { executeOracleQuery } from '@/db/oracle';
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
try {
@ -22,8 +22,12 @@ export async function GET(request: NextRequest) {
const excluirCodigoConta = searchParams.get('excluirCodigoConta');
// Novos parâmetros para códigos selecionados no filtro
const codigosCentrosCustoSelecionados = searchParams.get('codigosCentrosCustoSelecionados');
const codigosContasSelecionadas = searchParams.get('codigosContasSelecionadas');
const codigosCentrosCustoSelecionados = searchParams.get(
'codigosCentrosCustoSelecionados'
);
const codigosContasSelecionadas = searchParams.get(
'codigosContasSelecionadas'
);
console.log('🎯 Filtros recebidos na API:', {
dataInicio,
@ -35,14 +39,17 @@ export async function GET(request: NextRequest) {
excluirCentroCusto,
excluirCodigoConta,
codigosCentrosCustoSelecionados,
codigosContasSelecionadas
codigosContasSelecionadas,
});
console.log('🔍 Verificação específica de centroCusto:', {
centroCusto,
tipo: typeof centroCusto,
vazio: centroCusto === null || centroCusto === undefined || centroCusto === '',
vazio:
centroCusto === null || centroCusto === undefined || centroCusto === '',
codigosCentrosCustoSelecionados,
codigosCentrosCustoSelecionadosVazio: !codigosCentrosCustoSelecionados || codigosCentrosCustoSelecionados === ''
codigosCentrosCustoSelecionadosVazio:
!codigosCentrosCustoSelecionados ||
codigosCentrosCustoSelecionados === '',
});
// Construir query SQL com filtros usando a view DESPESA_ENTIDADE_ANALITICO
@ -52,10 +59,17 @@ export async function GET(request: NextRequest) {
// Filtro por período (usando ANOMESCOMP)
if (dataInicio && dataFim) {
sql += ` AND ANOMESCOMP >= :${paramIndex} AND ANOMESCOMP <= :${paramIndex + 1}`;
sql += ` AND ANOMESCOMP >= :${paramIndex} AND ANOMESCOMP <= :${
paramIndex + 1
}`;
params.push(dataInicio, dataFim);
paramIndex += 2;
console.log('📅 Adicionando filtro de período:', dataInicio, 'a', dataFim);
console.log(
'📅 Adicionando filtro de período:',
dataInicio,
'a',
dataFim
);
}
// Filtro por código do grupo
@ -87,10 +101,13 @@ export async function GET(request: NextRequest) {
console.log('🔍 Antes de aplicar filtro de centro de custo:', {
codigosCentrosCustoSelecionados,
centroCusto,
codigosCentrosCustoSelecionadosVazio: !codigosCentrosCustoSelecionados || codigosCentrosCustoSelecionados.trim() === '',
codigosCentrosCustoSelecionadosVazio:
!codigosCentrosCustoSelecionados ||
codigosCentrosCustoSelecionados.trim() === '',
centroCustoVazio: !centroCusto || centroCusto.trim() === '',
centroCustoLength: centroCusto?.length,
codigosCentrosCustoSelecionadosLength: codigosCentrosCustoSelecionados?.length
codigosCentrosCustoSelecionadosLength:
codigosCentrosCustoSelecionados?.length,
});
// IMPORTANTE: Quando centroCusto individual é fornecido (clique na célula), ele tem PRIORIDADE ABSOLUTA
@ -101,21 +118,44 @@ export async function GET(request: NextRequest) {
sql += ` AND CODIGOCENTROCUSTO = :${paramIndex}`;
params.push(centroCusto);
paramIndex++;
console.log('🏢 PRIORIDADE: Filtrando APENAS por centroCusto individual (clique na célula):', centroCusto);
console.log('⚠️ Ignorando codigosCentrosCustoSelecionados do filtro geral quando há centroCusto individual');
console.log('📝 SQL após adicionar filtro =:', sql.substring(0, 200) + '...');
} else if (codigosCentrosCustoSelecionados && codigosCentrosCustoSelecionados.trim() !== '') {
console.log(
'🏢 PRIORIDADE: Filtrando APENAS por centroCusto individual (clique na célula):',
centroCusto
);
console.log(
'⚠️ Ignorando codigosCentrosCustoSelecionados do filtro geral quando há centroCusto individual'
);
console.log(
'📝 SQL após adicionar filtro =:',
sql.substring(0, 200) + '...'
);
} else if (
codigosCentrosCustoSelecionados &&
codigosCentrosCustoSelecionados.trim() !== ''
) {
// Se só codigosCentrosCustoSelecionados existe (sem clique na célula), usar ele
const codigosArray = codigosCentrosCustoSelecionados.split(',').filter(c => c.trim() !== '');
const codigosArray = codigosCentrosCustoSelecionados
.split(',')
.filter((c) => c.trim() !== '');
if (codigosArray.length > 0) {
const placeholders = codigosArray.map(() => `:${paramIndex++}`).join(',');
const placeholders = codigosArray
.map(() => `:${paramIndex++}`)
.join(',');
sql += ` AND 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) + '...');
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) + '...'
);
}
} else {
console.log('⚠️ Nenhum filtro de centro de custo aplicado - ambos estão vazios');
console.log(
'⚠️ Nenhum filtro de centro de custo aplicado - ambos estão vazios'
);
}
// Exclusão de centro de custo específico (quando desmarcado)
@ -147,19 +187,33 @@ export async function GET(request: NextRequest) {
sql += ` ORDER BY DTVENC, CODFORNEC, CODCONTA`;
// Log detalhado da query SQL final
console.log('═══════════════════════════════════════════════════════════════');
console.log(
'═══════════════════════════════════════════════════════════════'
);
console.log('🗄️ QUERY SQL FINAL:');
console.log('═══════════════════════════════════════════════════════════════');
console.log(
'═══════════════════════════════════════════════════════════════'
);
console.log(sql);
console.log('═══════════════════════════════════════════════════════════════');
console.log('📋 PARÂMETROS FINAIS (na ordem dos placeholders :1, :2, :3, ...):');
console.log('═══════════════════════════════════════════════════════════════');
console.log(
'═══════════════════════════════════════════════════════════════'
);
console.log(
'📋 PARÂMETROS FINAIS (na ordem dos placeholders :1, :2, :3, ...):'
);
console.log(
'═══════════════════════════════════════════════════════════════'
);
params.forEach((param, index) => {
console.log(` :${index + 1} = ${param} (${typeof param})`);
});
console.log('═══════════════════════════════════════════════════════════════');
console.log(
'═══════════════════════════════════════════════════════════════'
);
console.log('📊 RESUMO DOS FILTROS APLICADOS:');
console.log('═══════════════════════════════════════════════════════════════');
console.log(
'═══════════════════════════════════════════════════════════════'
);
console.log({
temPeriodo: dataInicio && dataFim,
periodo: dataInicio && dataFim ? `${dataInicio} a ${dataFim}` : 'N/A',
@ -178,60 +232,111 @@ export async function GET(request: NextRequest) {
temExcluirCentroCusto: !!excluirCentroCusto,
excluirCentroCusto: excluirCentroCusto || 'N/A',
temExcluirCodigoConta: !!excluirCodigoConta,
excluirCodigoConta: excluirCodigoConta || 'N/A'
excluirCodigoConta: excluirCodigoConta || 'N/A',
});
console.log('═══════════════════════════════════════════════════════════════');
console.log(
'═══════════════════════════════════════════════════════════════'
);
// Se há centroCusto individual, destacar especialmente
if (centroCusto && centroCusto.trim() !== '') {
console.log('🎯 FILTRO INDIVIDUAL DE CENTRO DE CUSTO ATIVO (clique na célula)');
console.log(
'🎯 FILTRO INDIVIDUAL DE CENTRO DE CUSTO ATIVO (clique na célula)'
);
console.log(` Centro de Custo: ${centroCusto}`);
console.log(' ⚠️ Este filtro tem PRIORIDADE sobre codigosCentrosCustoSelecionados');
console.log(
' ⚠️ Este filtro tem PRIORIDADE sobre codigosCentrosCustoSelecionados'
);
}
console.log('═══════════════════════════════════════════════════════════════');
console.log(
'═══════════════════════════════════════════════════════════════'
);
const data = await executeOracleQuery(sql, params);
console.log('✅ Query executada com sucesso:', data.length, 'registros encontrados');
console.log(
'✅ Query executada com sucesso:',
data.length,
'registros encontrados'
);
console.log('📝 Primeiros 3 registros:', data.slice(0, 3));
// Transformar os dados do Oracle para o formato esperado pelo componente
// Usando a view DESPESA_ENTIDADE_ANALITICO
const transformedData = data.map((item: any) => {
const transformedData = data.map((item: any, index: number) => {
// Gerar ID único: combinar NUMLANC com índice para garantir unicidade
// Se NUMLANC for null/undefined, usar índice + outros campos para criar ID único
const numLanc =
item.NUMLANC !== null && item.NUMLANC !== undefined
? item.NUMLANC
: null;
const uniqueId =
numLanc !== null
? `${numLanc}-${item.CODFORNEC || ''}-${item.CODCONTA || ''}-${
item.CODIGOCENTROCUSTO || ''
}-${index}`
: `row-${item.CODFORNEC || ''}-${item.CODCONTA || ''}-${
item.CODIGOCENTROCUSTO || ''
}-${item.DTVENC || ''}-${index}`;
return {
codigo_grupo: item.CODGRUPO || "",
codigo_subgrupo: item.SUBGRUPO || "", // SUBGRUPO existe na nova view
codigo_fornecedor: item.CODFORNEC || "",
nome_fornecedor: item.FORNECEDOR || "",
id: item.NUMLANC || 0,
codfilial: "001", // Valor padrão
recnum: item.NUMLANC || 0,
data_competencia: item.ANOMESCOMP || "",
data_vencimento: item.DTVENC ? new Date(item.DTVENC).toISOString().split('T')[0] : "",
data_pagamento: item.DTPAGTO ? new Date(item.DTPAGTO).toISOString().split('T')[0] : "",
data_caixa: item.DTCAIXA ? new Date(item.DTCAIXA).toISOString().split('T')[0] : "",
codigo_conta: item.CODCONTA || "",
conta: item.CONTA || "",
codigo_centrocusto: item.CODIGOCENTROCUSTO || "",
centro_custo: item.CENTROCUSTO || "",
valor: item.VLREALIZADO !== null && item.VLREALIZADO !== undefined ? Number(item.VLREALIZADO) : 0,
historico: item.HISTORICO || "",
historico2: item.HISTORICO2 || "",
codigo_grupo: item.CODGRUPO || '',
codigo_subgrupo: item.SUBGRUPO || '', // SUBGRUPO existe na nova view
codigo_fornecedor: item.CODFORNEC || '',
nome_fornecedor: item.FORNECEDOR || '',
id: uniqueId,
codfilial: '001', // Valor padrão
recnum: numLanc !== null ? numLanc : index,
data_competencia: item.ANOMESCOMP || '',
data_vencimento: item.DTVENC
? new Date(item.DTVENC).toISOString().split('T')[0]
: '',
data_pagamento: item.DTPAGTO
? new Date(item.DTPAGTO).toISOString().split('T')[0]
: '',
data_caixa: item.DTCAIXA
? new Date(item.DTCAIXA).toISOString().split('T')[0]
: '',
codigo_conta: item.CODCONTA || '',
conta: item.CONTA || '',
codigo_centrocusto: item.CODIGOCENTROCUSTO || '',
centro_custo: item.CENTROCUSTO || '',
valor:
item.VLREALIZADO !== null && item.VLREALIZADO !== undefined
? Number(item.VLREALIZADO)
: 0,
historico: item.HISTORICO || '',
historico2: item.HISTORICO2 || '',
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
// Campos adicionais do Oracle
entidade: item.ENTIDADE || "",
tipo_parceiro: item.TIPOPARCEIRO || "",
valor_previsto: item.VLPREVISTO !== null && item.VLPREVISTO !== undefined ? Number(item.VLPREVISTO) : 0,
valor_confirmado: item.VLCONFIRMADO !== null && item.VLCONFIRMADO !== undefined ? Number(item.VLCONFIRMADO) : 0,
valor_pago: item.VLPAGO !== null && item.VLPAGO !== undefined ? Number(item.VLPAGO) : 0,
entidade: item.ENTIDADE || '',
tipo_parceiro: item.TIPOPARCEIRO || '',
valor_previsto:
item.VLPREVISTO !== null && item.VLPREVISTO !== undefined
? Number(item.VLPREVISTO)
: 0,
valor_confirmado:
item.VLCONFIRMADO !== null && item.VLCONFIRMADO !== undefined
? Number(item.VLCONFIRMADO)
: 0,
valor_pago:
item.VLPAGO !== null && item.VLPAGO !== undefined
? Number(item.VLPAGO)
: 0,
numero_lancamento: item.NUMLANC || 0,
ano_mes_comp: item.ANOMESCOMP || "",
codgrupo: item.CODGRUPO || "",
ano_mes_comp: item.ANOMESCOMP || '',
codgrupo: item.CODGRUPO || '',
// Novos campos
data_lancamento: item.DTLANC ? new Date(item.DTLANC).toISOString().split('T')[0] : "",
data_compensacao: item.DTCOMPENSACAO ? new Date(item.DTCOMPENSACAO).toISOString().split('T')[0] : "",
data_pagto: item.DTPAGTO ? new Date(item.DTPAGTO).toISOString().split('T')[0] : ""
data_lancamento: item.DTLANC
? new Date(item.DTLANC).toISOString().split('T')[0]
: '',
data_compensacao: item.DTCOMPENSACAO
? new Date(item.DTCOMPENSACAO).toISOString().split('T')[0]
: '',
data_pagto: item.DTPAGTO
? new Date(item.DTPAGTO).toISOString().split('T')[0]
: '',
};
});
@ -239,7 +344,6 @@ export async function GET(request: NextRequest) {
console.log('📝 Primeiros 3 transformados:', transformedData.slice(0, 3));
return NextResponse.json(transformedData);
} catch (error) {
console.error('❌ Erro ao buscar dados analíticos do Oracle:', error);
@ -247,10 +351,9 @@ export async function GET(request: NextRequest) {
{
success: false,
error: error instanceof Error ? error.message : 'Erro desconhecido',
details: error instanceof Error ? error.stack : undefined
details: error instanceof Error ? error.stack : undefined,
},
{ status: 500 }
);
}
}

View File

@ -235,15 +235,30 @@ WHERE 1=1`;
// Transformar os dados do Oracle para o formato esperado pelo componente
// Usando a view VB_DRE_FILIAL_DESPESA_ANALITICO
const transformedData = data.map((item: any) => {
const transformedData = data.map((item: any, index: number) => {
// Gerar ID único: combinar NUMLANC com índice para garantir unicidade
// Se NUMLANC for null/undefined, usar índice + outros campos para criar ID único
const numLanc =
item.NUMLANC !== null && item.NUMLANC !== undefined
? item.NUMLANC
: null;
const uniqueId =
numLanc !== null
? `${numLanc}-${item.CODFORNEC || ''}-${item.CODCONTA || ''}-${
item.CODIGOCENTROCUSTO || ''
}-${index}`
: `row-${item.CODFORNEC || ''}-${item.CODCONTA || ''}-${
item.CODIGOCENTROCUSTO || ''
}-${item.DTVENC || ''}-${index}`;
return {
codigo_grupo: item.CODGRUPO || "",
codigo_subgrupo: item.SUBGRUPO || "", // SUBGRUPO existe na nova view
codigo_fornecedor: item.CODFORNEC || "",
nome_fornecedor: item.FORNECEDOR || "",
id: item.NUMLANC || 0,
id: uniqueId,
codfilial: item.CODFILIAL || item.FILIAL || "001", // Usar CODFILIAL do JOIN ou FILIAL da view
recnum: item.NUMLANC || 0,
recnum: numLanc !== null ? numLanc : index,
data_competencia: item.ANOMESCOMP || "",
data_vencimento: item.DTVENC ? new Date(item.DTVENC).toISOString().split('T')[0] : "",
data_pagamento: item.DTPAGTO ? new Date(item.DTPAGTO).toISOString().split('T')[0] : "",

View File

@ -119,7 +119,7 @@ export async function GET(request: NextRequest) {
console.log('📝 Primeiros 3 registros:', data.slice(0, 3));
// Transformar os dados do Oracle para o formato esperado pelo componente
const transformedData = data.map((item: any) => {
const transformedData = data.map((item: any, index: number) => {
// Debug dos valores monetários
// console.log('🔍 Item original:', {
// VLREALIZADO: item.VLREALIZADO,
@ -129,14 +129,29 @@ export async function GET(request: NextRequest) {
// tipo_VLREALIZADO: typeof item.VLREALIZADO
// });
// Gerar ID único: combinar NUMLANC com índice para garantir unicidade
// Se NUMLANC for null/undefined, usar índice + outros campos para criar ID único
const numLanc =
item.NUMLANC !== null && item.NUMLANC !== undefined
? item.NUMLANC
: null;
const uniqueId =
numLanc !== null
? `${numLanc}-${item.CODFORNEC || ''}-${item.CODCONTA || ''}-${
item.CODIGOCENTROCUSTO || ''
}-${index}`
: `row-${item.CODFORNEC || ''}-${item.CODCONTA || ''}-${
item.CODIGOCENTROCUSTO || ''
}-${item.DTVENC || ''}-${index}`;
return {
codigo_grupo: item.CODGRUPO || "",
codigo_subgrupo: "", // Não existe na tabela Oracle
codigo_fornecedor: item.CODFORNEC || "",
nome_fornecedor: item.FORNECEDOR || "",
id: item.NUMLANC || 0,
id: uniqueId,
codfilial: "001", // Valor padrão
recnum: item.NUMLANC || 0,
recnum: numLanc !== null ? numLanc : index,
data_competencia: item.ANOMESCOMP || "",
data_vencimento: item.DTVENC ? new Date(item.DTVENC).toISOString().split('T')[0] : "",
data_pagamento: item.DTPAGTO ? new Date(item.DTPAGTO).toISOString().split('T')[0] : "",

File diff suppressed because it is too large Load Diff

View File

@ -57,7 +57,7 @@ interface AnaliticoItem {
codigo_subgrupo: string;
codigo_fornecedor: string;
nome_fornecedor: string;
id: number;
id: string | number; // Pode ser string (gerado pela API) ou number (legado)
codfilial: string;
recnum: number;
data_competencia: string;
@ -501,10 +501,25 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
return filterValues.includes(stringValue);
});
})
.map((row, index) => ({
.map((row, index) => {
// Garantir ID único: usar o id original se existir, senão criar baseado em recnum e índice
const originalId =
row.id !== null && row.id !== undefined
? typeof row.id === 'string' && row.id !== ''
? row.id
: String(row.id)
: null;
const recnumValue =
row.recnum !== null && row.recnum !== undefined ? row.recnum : null;
const uniqueId = originalId
? `filtered-${originalId}`
: `filtered-${recnumValue !== null ? recnumValue : 'idx'}-${index}`;
return {
...row,
id: `filtered-${row.id || row.recnum || index}`, // Garantir ID único e estável
}));
id: uniqueId, // Garantir ID único e estável (agora é string)
};
});
}, [data, columnFilters]);
// Função para renderizar header com filtro Excel
@ -1110,9 +1125,24 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
disableColumnSorting={true}
pagination={false}
disableVirtualization={false}
getRowId={(row: any) =>
row.id || `row-${row.recnum || Math.random()}`
getRowId={(row: any) => {
// Usar verificação explícita para garantir que id seja usado mesmo se for string vazia
if (
row.id !== null &&
row.id !== undefined &&
row.id !== ''
) {
return String(row.id);
}
// Fallback: usar recnum se disponível, senão criar ID único
const recnumValue =
row.recnum !== null && row.recnum !== undefined
? row.recnum
: null;
return recnumValue !== null
? `row-${recnumValue}`
: `row-${Math.random()}-${Date.now()}`;
}}
sx={{
height: '100%',
width: '100%',