Merge pull request #47 from JurunenseDevInterno/feat-visao-entidade-analitica

Feat visao entidade analitica
This commit is contained in:
Alessandro Gonçalves 2025-11-21 00:16:05 -03:00 committed by GitHub
commit f7b1669ccc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 4733 additions and 0 deletions

View File

@ -0,0 +1,256 @@
import { NextRequest, NextResponse } from 'next/server';
import { executeOracleQuery } from '@/db/oracle';
export async function GET(request: NextRequest) {
try {
console.log('🔄 Buscando dados analíticos do Oracle (Entidade)...');
console.log('📋 URL completa:', request.url);
console.log('🔍 Query params:', request.nextUrl.searchParams.toString());
console.log('📊 Headers:', Object.fromEntries(request.headers.entries()));
// Extrair parâmetros de query
const searchParams = request.nextUrl.searchParams;
const dataInicio = searchParams.get('dataInicio');
const dataFim = searchParams.get('dataFim');
const centroCusto = searchParams.get('centroCusto');
const codigoGrupo = searchParams.get('codigoGrupo');
const codigoSubgrupo = searchParams.get('codigoSubgrupo');
const codigoConta = searchParams.get('codigoConta');
// Parâmetros para exclusão de valores específicos
const excluirCentroCusto = searchParams.get('excluirCentroCusto');
const excluirCodigoConta = searchParams.get('excluirCodigoConta');
// Novos parâmetros para códigos selecionados no filtro
const codigosCentrosCustoSelecionados = searchParams.get('codigosCentrosCustoSelecionados');
const codigosContasSelecionadas = searchParams.get('codigosContasSelecionadas');
console.log('🎯 Filtros recebidos na API:', {
dataInicio,
dataFim,
centroCusto,
codigoGrupo,
codigoSubgrupo,
codigoConta,
excluirCentroCusto,
excluirCodigoConta,
codigosCentrosCustoSelecionados,
codigosContasSelecionadas
});
console.log('🔍 Verificação específica de centroCusto:', {
centroCusto,
tipo: typeof centroCusto,
vazio: centroCusto === null || centroCusto === undefined || centroCusto === '',
codigosCentrosCustoSelecionados,
codigosCentrosCustoSelecionadosVazio: !codigosCentrosCustoSelecionados || codigosCentrosCustoSelecionados === ''
});
// Construir query SQL com filtros usando a view DESPESA_ENTIDADE_ANALITICO
let sql = `SELECT * FROM DESPESA_ENTIDADE_ANALITICO WHERE 1=1`;
const params: any[] = [];
let paramIndex = 1;
// Filtro por período (usando ANOMESCOMP)
if (dataInicio && dataFim) {
sql += ` AND ANOMESCOMP >= :${paramIndex} AND ANOMESCOMP <= :${paramIndex + 1}`;
params.push(dataInicio, dataFim);
paramIndex += 2;
console.log('📅 Adicionando filtro de período:', dataInicio, 'a', dataFim);
}
// Filtro por código do grupo
if (codigoGrupo) {
sql += ` AND CODGRUPO = :${paramIndex}`;
params.push(codigoGrupo);
paramIndex++;
console.log('📊 Adicionando filtro de grupo:', codigoGrupo);
}
// Filtro por subgrupo (DIRETO, INDIRETO, SEM CC, etc.)
if (codigoSubgrupo) {
sql += ` AND SUBGRUPO = :${paramIndex}`;
params.push(codigoSubgrupo);
paramIndex++;
console.log('📊 Adicionando filtro de subgrupo:', codigoSubgrupo);
}
// Filtro por código da conta
if (codigoConta) {
sql += ` AND 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
console.log('🔍 Antes de aplicar filtro de centro de custo:', {
codigosCentrosCustoSelecionados,
centroCusto,
codigosCentrosCustoSelecionadosVazio: !codigosCentrosCustoSelecionados || codigosCentrosCustoSelecionados.trim() === '',
centroCustoVazio: !centroCusto || centroCusto.trim() === '',
centroCustoLength: centroCusto?.length,
codigosCentrosCustoSelecionadosLength: codigosCentrosCustoSelecionados?.length
});
// IMPORTANTE: Quando centroCusto individual é fornecido (clique na célula), ele tem PRIORIDADE ABSOLUTA
// e deve filtrar APENAS por ele, ignorando codigosCentrosCustoSelecionados do filtro geral
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 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() !== '') {
// Se só codigosCentrosCustoSelecionados existe (sem clique na célula), usar ele
const codigosArray = codigosCentrosCustoSelecionados.split(',').filter(c => c.trim() !== '');
if (codigosArray.length > 0) {
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) + '...');
}
} else {
console.log('⚠️ Nenhum filtro de centro de custo aplicado - ambos estão vazios');
}
// 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 CODIGOCENTROCUSTO != :${paramIndex}`;
params.push(excluirCentroCusto);
paramIndex++;
console.log('🚫 Excluindo centro de custo:', excluirCentroCusto);
}
// Exclusão de código de conta específico (quando desmarcado)
if (excluirCodigoConta) {
sql += ` AND CODCONTA != :${paramIndex}`;
params.push(excluirCodigoConta);
paramIndex++;
console.log('🚫 Excluindo código de conta:', excluirCodigoConta);
}
// Filtro por códigos de contas selecionadas no filtro
if (codigosContasSelecionadas) {
const codigosArray = codigosContasSelecionadas.split(',');
const placeholders = codigosArray.map(() => `:${paramIndex++}`).join(',');
sql += ` AND CODCONTA IN (${placeholders})`;
params.push(...codigosArray);
console.log('💰 Filtrando por códigos de contas:', codigosArray);
}
sql += ` ORDER BY DTVENC, CODFORNEC, CODCONTA`;
// Log detalhado da query SQL final
console.log('═══════════════════════════════════════════════════════════════');
console.log('🗄️ QUERY SQL FINAL:');
console.log('═══════════════════════════════════════════════════════════════');
console.log(sql);
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('📊 RESUMO DOS FILTROS APLICADOS:');
console.log('═══════════════════════════════════════════════════════════════');
console.log({
temPeriodo: dataInicio && dataFim,
periodo: dataInicio && dataFim ? `${dataInicio} a ${dataFim}` : 'N/A',
temCodigoGrupo: !!codigoGrupo,
codigoGrupo: codigoGrupo || 'N/A',
temCodigoSubgrupo: !!codigoSubgrupo,
codigoSubgrupo: codigoSubgrupo || 'N/A',
temCentroCusto: !!centroCusto,
centroCusto: centroCusto || 'N/A',
temCodigosCentrosCustoSelecionados: !!codigosCentrosCustoSelecionados,
codigosCentrosCustoSelecionados: codigosCentrosCustoSelecionados || 'N/A',
temCodigoConta: !!codigoConta,
codigoConta: codigoConta || 'N/A',
temCodigosContasSelecionadas: !!codigosContasSelecionadas,
codigosContasSelecionadas: codigosContasSelecionadas || 'N/A',
temExcluirCentroCusto: !!excluirCentroCusto,
excluirCentroCusto: excluirCentroCusto || 'N/A',
temExcluirCodigoConta: !!excluirCodigoConta,
excluirCodigoConta: excluirCodigoConta || 'N/A'
});
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(` Centro de Custo: ${centroCusto}`);
console.log(' ⚠️ Este filtro tem PRIORIDADE sobre codigosCentrosCustoSelecionados');
}
console.log('═══════════════════════════════════════════════════════════════');
const data = await executeOracleQuery(sql, params);
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) => {
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 || "",
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,
numero_lancamento: item.NUMLANC || 0,
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] : ""
};
});
console.log('🔄 Dados transformados:', transformedData.length, 'registros');
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);
return NextResponse.json(
{
success: false,
error: error instanceof Error ? error.message : 'Erro desconhecido',
details: error instanceof Error ? error.stack : undefined
},
{ status: 500 }
);
}
}

View File

@ -0,0 +1,87 @@
import { NextRequest, NextResponse } from 'next/server';
import { executeOracleQuery } from '@/db/oracle';
export async function GET(request: NextRequest) {
try {
console.log('🔄 Buscando dados DRE do Oracle (Entidade) - View DESPESA_ENTIDADE_SINTETICO...');
// Query para buscar dados da view DESPESA_ENTIDADE_SINTETICO
const sql = `SELECT * FROM DESPESA_ENTIDADE_SINTETICO ORDER BY ENTIDADE, SUBGRUPO, CODIGOCENTROCUSTO, CODCONTA`;
const data = await executeOracleQuery(sql);
console.log('✅ Query executada com sucesso:', data.length, 'registros encontrados');
// Debug: Verificar estrutura dos dados
if (data.length > 0) {
console.log('🔍 Primeiro registro do Oracle:', Object.keys(data[0]));
console.log('🔍 Primeiro registro completo:', data[0]);
console.log('🔍 Valores únicos de ENTIDADE:', [...new Set(data.map((item: any) => item.ENTIDADE).filter(Boolean))]);
console.log('🔍 Valores únicos de SUBGRUPO:', [...new Set(data.map((item: any) => item.SUBGRUPO).filter(Boolean))]);
}
// Transformar os dados do Oracle para o formato esperado pelo componente
const transformedData = data.map((item: any) => {
// Converter DATA para formato YYYY-MM se necessário
let dataCompetencia = item.DATA;
if (dataCompetencia) {
// Se DATA for uma string no formato YYYY-MM, usar diretamente
if (typeof dataCompetencia === 'string' && dataCompetencia.match(/^\d{4}-\d{2}$/)) {
// Já está no formato correto
} else if (dataCompetencia instanceof Date) {
// Se for Date, converter para YYYY-MM
const year = dataCompetencia.getFullYear();
const month = String(dataCompetencia.getMonth() + 1).padStart(2, '0');
dataCompetencia = `${year}-${month}`;
} else {
// Tentar converter string de data para YYYY-MM
try {
const date = new Date(dataCompetencia);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
dataCompetencia = `${year}-${month}`;
} catch (e) {
console.warn('⚠️ Erro ao converter DATA:', dataCompetencia);
dataCompetencia = "2023-03"; // Valor padrão
}
}
} else {
dataCompetencia = "2023-03"; // Valor padrão
}
return {
codfilial: "001", // Valor padrão
data_competencia: dataCompetencia,
data_cai: dataCompetencia,
grupo: item.CODGRUPO || "", // CODGRUPO
subgrupo: item.SUBGRUPO || "", // SUBGRUPO (DIRETO/INDIRETO)
centro_custo: item.CENTROCUSTO || "", // CENTROCUSTO (nome do centro)
codigo_centro_custo: item.CODIGOCENTROCUSTO || "", // CODIGOCENTROCUSTO (código do centro)
codigo_conta: parseInt(item.CODCONTA) || 0, // Converter CODCONTA para número
conta: item.CONTA || "", // CONTA
valor: item.VALOR?.toString() || "0", // Converter VALOR para string
codgrupo: item.CODGRUPO || "", // CODGRUPO
entidades: item.ENTIDADE || "", // ENTIDADE
};
});
console.log('✅ Dados transformados:', transformedData.length, 'registros');
console.log('🔍 Exemplo de registro transformado:', transformedData[0]);
return NextResponse.json(transformedData);
} catch (error) {
console.error('❌ Erro ao buscar dados DRE do Oracle:', error);
return NextResponse.json(
{
success: false,
error: error instanceof Error ? error.message : 'Erro desconhecido',
details: error instanceof Error ? error.stack : undefined
},
{ status: 500 }
);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
import Teste from './teste';
export default function DreEntidadePage() {
return (
<div className="w-full min-h-screen p-1">
<Teste />
</div>
);
}

File diff suppressed because it is too large Load Diff