ajusteste feitos para analise analitica
This commit is contained in:
parent
eb2398702a
commit
eb7c6547fd
|
|
@ -0,0 +1,293 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { ArrowDown, ArrowUp, ArrowUpDown } from 'lucide-react';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
interface AnaliticoItem {
|
||||||
|
codigo_grupo: string;
|
||||||
|
codigo_subgrupo: string;
|
||||||
|
codigo_fornecedor: string;
|
||||||
|
nome_fornecedor: string;
|
||||||
|
id: number;
|
||||||
|
codfilial: string;
|
||||||
|
recnum: number;
|
||||||
|
data_competencia: string;
|
||||||
|
data_vencimento: string;
|
||||||
|
data_pagamento: string;
|
||||||
|
data_caixa: string;
|
||||||
|
codigo_conta: string;
|
||||||
|
conta: string;
|
||||||
|
codigo_centrocusto: string;
|
||||||
|
valor: number;
|
||||||
|
historico: string;
|
||||||
|
historico2: string;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type SortField = 'nome_fornecedor' | 'data_competencia' | 'valor' | 'conta';
|
||||||
|
type SortDirection = 'asc' | 'desc';
|
||||||
|
|
||||||
|
interface SortConfig {
|
||||||
|
field: SortField;
|
||||||
|
direction: SortDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AnaliticoProps {
|
||||||
|
filtros: {
|
||||||
|
dataInicio: string;
|
||||||
|
dataFim: string;
|
||||||
|
centroCusto?: string;
|
||||||
|
codigoGrupo?: string;
|
||||||
|
codigoSubgrupo?: string;
|
||||||
|
codigoConta?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
|
const [data, setData] = useState<AnaliticoItem[]>([]);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [sortConfig, setSortConfig] = useState<SortConfig>({
|
||||||
|
field: 'data_competencia',
|
||||||
|
direction: 'desc',
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchData = useCallback(async () => {
|
||||||
|
// Só faz a requisição se tiver dataInicio e dataFim
|
||||||
|
if (!filtros.dataInicio || !filtros.dataFim) {
|
||||||
|
setData([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
dataInicio: filtros.dataInicio,
|
||||||
|
dataFim: filtros.dataFim,
|
||||||
|
...(filtros.centroCusto && { centroCusto: filtros.centroCusto }),
|
||||||
|
...(filtros.codigoGrupo && { codigoGrupo: filtros.codigoGrupo }),
|
||||||
|
...(filtros.codigoSubgrupo && {
|
||||||
|
codigoSubgrupo: filtros.codigoSubgrupo,
|
||||||
|
}),
|
||||||
|
...(filtros.codigoConta && { codigoConta: filtros.codigoConta }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await fetch(`/api/analitico?${params}`);
|
||||||
|
if (response.ok) {
|
||||||
|
const result = await response.json();
|
||||||
|
setData(result as AnaliticoItem[]);
|
||||||
|
} else {
|
||||||
|
console.error('Erro ao buscar dados:', await response.text());
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro ao buscar dados:', error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}, [filtros]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchData();
|
||||||
|
}, [fetchData]);
|
||||||
|
|
||||||
|
const handleSort = (field: SortField) => {
|
||||||
|
setSortConfig((prev) => ({
|
||||||
|
field,
|
||||||
|
direction:
|
||||||
|
prev.field === field && prev.direction === 'asc' ? 'desc' : 'asc',
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSortIcon = (field: SortField) => {
|
||||||
|
if (sortConfig.field !== field) {
|
||||||
|
return <ArrowUpDown className="ml-1 h-3 w-3" />;
|
||||||
|
}
|
||||||
|
return sortConfig.direction === 'asc' ? (
|
||||||
|
<ArrowUp className="ml-1 h-3 w-3" />
|
||||||
|
) : (
|
||||||
|
<ArrowDown className="ml-1 h-3 w-3" />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const sortedData = [...data].sort((a, b) => {
|
||||||
|
const aValue = a[sortConfig.field];
|
||||||
|
const bValue = b[sortConfig.field];
|
||||||
|
|
||||||
|
if (typeof aValue === 'string' && typeof bValue === 'string') {
|
||||||
|
return sortConfig.direction === 'asc'
|
||||||
|
? aValue.localeCompare(bValue)
|
||||||
|
: bValue.localeCompare(aValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof aValue === 'number' && typeof bValue === 'number') {
|
||||||
|
return sortConfig.direction === 'asc' ? aValue - bValue : bValue - aValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
const formatCurrency = (value: number) => {
|
||||||
|
return new Intl.NumberFormat('pt-BR', {
|
||||||
|
style: 'currency',
|
||||||
|
currency: 'BRL',
|
||||||
|
}).format(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDate = (dateString: string) => {
|
||||||
|
return new Date(dateString).toLocaleDateString('pt-BR');
|
||||||
|
};
|
||||||
|
|
||||||
|
const totalValor = data.reduce((sum, item) => {
|
||||||
|
const valor =
|
||||||
|
typeof item.valor === 'string' ? parseFloat(item.valor) : item.valor;
|
||||||
|
return sum + (isNaN(valor) ? 0 : valor);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full mt-6 border-t pt-4">
|
||||||
|
<div className="flex justify-between items-center mb-4">
|
||||||
|
<h2 className="text-lg font-bold">Análise Analítica</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Filtros aplicados */}
|
||||||
|
{/* <div className="mb-4 p-3 bg-gray-50 rounded-md">
|
||||||
|
<div className="text-sm">
|
||||||
|
<strong>Filtros aplicados:</strong>
|
||||||
|
<div className="flex flex-wrap gap-2 mt-1">
|
||||||
|
{filtros.centroCusto && (
|
||||||
|
<span className="px-2 py-1 bg-blue-100 text-blue-800 rounded text-xs">
|
||||||
|
Centro: {filtros.centroCusto}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{filtros.codigoGrupo && (
|
||||||
|
<span className="px-2 py-1 bg-green-100 text-green-800 rounded text-xs">
|
||||||
|
Grupo: {filtros.codigoGrupo}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{filtros.codigoSubgrupo && (
|
||||||
|
<span className="px-2 py-1 bg-yellow-100 text-yellow-800 rounded text-xs">
|
||||||
|
Subgrupo: {filtros.codigoSubgrupo}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{filtros.codigoConta && (
|
||||||
|
<span className="px-2 py-1 bg-purple-100 text-purple-800 rounded text-xs">
|
||||||
|
Conta: {filtros.codigoConta}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
|
||||||
|
{/* Resumo */}
|
||||||
|
|
||||||
|
{/* Tabela */}
|
||||||
|
<div className="w-full max-h-[400px] overflow-y-auto border rounded-md relative">
|
||||||
|
{/* Header fixo */}
|
||||||
|
<div
|
||||||
|
className="sticky top-0 z-30 border-b shadow-sm"
|
||||||
|
style={{ backgroundColor: 'white', opacity: 1 }}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="flex p-3 font-semibold text-xs"
|
||||||
|
style={{ backgroundColor: 'white', opacity: 1 }}
|
||||||
|
>
|
||||||
|
<div className="flex-1 min-w-[150px] max-w-[200px]">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => handleSort('nome_fornecedor')}
|
||||||
|
className="h-auto p-0 font-semibold"
|
||||||
|
>
|
||||||
|
Fornecedor
|
||||||
|
{getSortIcon('nome_fornecedor')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-[100px] max-w-[120px] text-right">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => handleSort('data_competencia')}
|
||||||
|
className="h-auto p-0 font-semibold"
|
||||||
|
>
|
||||||
|
Data
|
||||||
|
{getSortIcon('data_competencia')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-[120px] max-w-[150px] text-right">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => handleSort('conta')}
|
||||||
|
className="h-auto p-0 font-semibold"
|
||||||
|
>
|
||||||
|
Conta
|
||||||
|
{getSortIcon('conta')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-[100px] max-w-[120px] text-right">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => handleSort('valor')}
|
||||||
|
className="h-auto p-0 font-semibold"
|
||||||
|
>
|
||||||
|
Valor
|
||||||
|
{getSortIcon('valor')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-[200px] max-w-[300px]">Histórico</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{loading ? (
|
||||||
|
<div className="p-8 text-center text-sm text-gray-500">
|
||||||
|
Carregando dados analíticos...
|
||||||
|
</div>
|
||||||
|
) : sortedData.length === 0 ? (
|
||||||
|
<div className="p-8 text-center text-sm text-gray-500">
|
||||||
|
Nenhum dado analítico encontrado para os filtros aplicados.
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
sortedData.map((row, index) => (
|
||||||
|
<div key={index} className="flex border-b hover:bg-gray-50">
|
||||||
|
<div className="flex-1 min-w-[150px] max-w-[200px] p-1 text-xs">
|
||||||
|
{row.nome_fornecedor || '-'}
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-[100px] max-w-[120px] text-right p-1 text-xs">
|
||||||
|
{formatDate(row.data_competencia)}
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-[120px] max-w-[150px] text-right p-1 text-xs">
|
||||||
|
{row.conta}
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-[100px] max-w-[120px] text-right p-1 text-xs font-medium">
|
||||||
|
{formatCurrency(
|
||||||
|
typeof row.valor === 'string'
|
||||||
|
? parseFloat(row.valor)
|
||||||
|
: row.valor
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-[200px] max-w-[300px] p-1 text-xs">
|
||||||
|
{row.historico || '-'}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{data.length > 0 && (
|
||||||
|
<div className="mb-4 p-4 bg-blue-50 border rounded-md">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-semibold">
|
||||||
|
Total de Registros: {data.length}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-semibold">
|
||||||
|
Valor Total: {formatCurrency(totalValor)}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import { Button } from '@/components/ui/button';
|
||||||
// Removed unused table imports
|
// Removed unused table imports
|
||||||
import { ArrowDown, ArrowUp, ArrowUpDown, BarChart3 } from 'lucide-react';
|
import { ArrowDown, ArrowUp, ArrowUpDown, BarChart3 } from 'lucide-react';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
import AnaliticoComponent from './analitico';
|
||||||
|
|
||||||
interface DREItem {
|
interface DREItem {
|
||||||
codfilial: string;
|
codfilial: string;
|
||||||
|
|
@ -55,6 +56,16 @@ export default function Teste() {
|
||||||
});
|
});
|
||||||
const [mesesDisponiveis, setMesesDisponiveis] = useState<string[]>([]);
|
const [mesesDisponiveis, setMesesDisponiveis] = useState<string[]>([]);
|
||||||
|
|
||||||
|
// Estados para analítico
|
||||||
|
const [analiticoFiltros, setAnaliticoFiltros] = useState({
|
||||||
|
dataInicio: '',
|
||||||
|
dataFim: '',
|
||||||
|
centroCusto: '',
|
||||||
|
codigoGrupo: '',
|
||||||
|
codigoSubgrupo: '',
|
||||||
|
codigoConta: '',
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
@ -62,10 +73,13 @@ export default function Teste() {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
setError(null);
|
||||||
const response = await fetch('/api/dre');
|
const response = await fetch('/api/dre');
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Erro ao carregar dados');
|
throw new Error(`Erro ao carregar dados: ${response.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
setData(result);
|
setData(result);
|
||||||
|
|
||||||
|
|
@ -97,6 +111,47 @@ export default function Teste() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Função para extrair códigos dos grupos e subgrupos
|
||||||
|
const extractCodes = (grupo: string, subgrupo?: string) => {
|
||||||
|
const grupoMatch = grupo.match(/^(\d+)/);
|
||||||
|
const codigoGrupo = grupoMatch ? grupoMatch[1] : '';
|
||||||
|
|
||||||
|
let codigoSubgrupo = '';
|
||||||
|
if (subgrupo) {
|
||||||
|
const subgrupoMatch = subgrupo.match(/^(\d+(?:\.\d+)+)/);
|
||||||
|
codigoSubgrupo = subgrupoMatch ? subgrupoMatch[1] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return { codigoGrupo, codigoSubgrupo };
|
||||||
|
};
|
||||||
|
|
||||||
|
// Função para lidar com clique nas linhas
|
||||||
|
const handleRowClick = (row: HierarchicalRow) => {
|
||||||
|
if (!data.length) return;
|
||||||
|
|
||||||
|
// Pegar todas as datas disponíveis para definir o período
|
||||||
|
const datas = data.map((item) => item.data_competencia);
|
||||||
|
const dataInicio = Math.min(...datas.map((d) => new Date(d).getTime()));
|
||||||
|
const dataFim = Math.max(...datas.map((d) => new Date(d).getTime()));
|
||||||
|
|
||||||
|
const dataInicioStr = new Date(dataInicio).toISOString().substring(0, 7); // YYYY-MM
|
||||||
|
const dataFimStr = new Date(dataFim).toISOString().substring(0, 7); // YYYY-MM
|
||||||
|
|
||||||
|
const { codigoGrupo, codigoSubgrupo } = extractCodes(
|
||||||
|
row.grupo || '',
|
||||||
|
row.subgrupo
|
||||||
|
);
|
||||||
|
|
||||||
|
setAnaliticoFiltros({
|
||||||
|
dataInicio: dataInicioStr,
|
||||||
|
dataFim: dataFimStr,
|
||||||
|
centroCusto: row.centro_custo || '',
|
||||||
|
codigoGrupo,
|
||||||
|
codigoSubgrupo,
|
||||||
|
codigoConta: row.codigo_conta?.toString() || '',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const toggleGroup = (grupo: string) => {
|
const toggleGroup = (grupo: string) => {
|
||||||
const newExpanded = new Set(expandedGroups);
|
const newExpanded = new Set(expandedGroups);
|
||||||
if (newExpanded.has(grupo)) {
|
if (newExpanded.has(grupo)) {
|
||||||
|
|
@ -404,7 +459,12 @@ export default function Teste() {
|
||||||
>
|
>
|
||||||
{row.isExpanded ? '▼' : '▶'}
|
{row.isExpanded ? '▼' : '▶'}
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => handleRowClick(row)}
|
||||||
|
className="flex-1 text-left hover:bg-blue-50 p-1 rounded cursor-pointer"
|
||||||
|
>
|
||||||
<span className="font-semibold">{row.grupo}</span>
|
<span className="font-semibold">{row.grupo}</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case 'subgrupo':
|
case 'subgrupo':
|
||||||
|
|
@ -416,7 +476,12 @@ export default function Teste() {
|
||||||
>
|
>
|
||||||
{row.isExpanded ? '▼' : '▶'}
|
{row.isExpanded ? '▼' : '▶'}
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => handleRowClick(row)}
|
||||||
|
className="flex-1 text-left hover:bg-blue-50 p-1 rounded cursor-pointer"
|
||||||
|
>
|
||||||
<span className="font-medium">{row.subgrupo}</span>
|
<span className="font-medium">{row.subgrupo}</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case 'centro_custo':
|
case 'centro_custo':
|
||||||
|
|
@ -430,14 +495,24 @@ export default function Teste() {
|
||||||
>
|
>
|
||||||
{row.isExpanded ? '▼' : '▶'}
|
{row.isExpanded ? '▼' : '▶'}
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => handleRowClick(row)}
|
||||||
|
className="flex-1 text-left hover:bg-blue-50 p-1 rounded cursor-pointer"
|
||||||
|
>
|
||||||
<span className="font-medium">{row.centro_custo}</span>
|
<span className="font-medium">{row.centro_custo}</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case 'conta':
|
case 'conta':
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-muted-foreground">•</span>
|
<span className="text-muted-foreground">•</span>
|
||||||
|
<button
|
||||||
|
onClick={() => handleRowClick(row)}
|
||||||
|
className="flex-1 text-left hover:bg-blue-50 p-1 rounded cursor-pointer"
|
||||||
|
>
|
||||||
<span>{row.conta}</span>
|
<span>{row.conta}</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
|
|
@ -546,6 +621,11 @@ export default function Teste() {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Componente Analítico */}
|
||||||
|
{!loading && data.length > 0 && (
|
||||||
|
<AnaliticoComponent filtros={analiticoFiltros} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
import db from '@/db';
|
||||||
|
import { sql } from 'drizzle-orm';
|
||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
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');
|
||||||
|
|
||||||
|
if (!dataInicio || !dataFim) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ message: 'Parâmetros obrigatórios: dataInicio, dataFim' },
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let whereConditions = [];
|
||||||
|
let params = [dataInicio, dataFim];
|
||||||
|
|
||||||
|
if (centroCusto) {
|
||||||
|
whereConditions.push(`ffa.codigo_centrocusto = $${params.length + 1}`);
|
||||||
|
params.push(centroCusto);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codigoGrupo) {
|
||||||
|
whereConditions.push(`drec.codigo_grupo = $${params.length + 1}`);
|
||||||
|
params.push(codigoGrupo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codigoSubgrupo) {
|
||||||
|
whereConditions.push(`dg.codigo_subgrupo = $${params.length + 1}`);
|
||||||
|
params.push(codigoSubgrupo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codigoConta) {
|
||||||
|
whereConditions.push(`ffa.codigo_conta = $${params.length + 1}`);
|
||||||
|
params.push(codigoConta);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query com filtros aplicados
|
||||||
|
let query;
|
||||||
|
|
||||||
|
if (centroCusto || codigoGrupo || codigoSubgrupo || codigoConta) {
|
||||||
|
// Query com filtros específicos
|
||||||
|
const conditions = [];
|
||||||
|
if (centroCusto)
|
||||||
|
conditions.push(`ffa.codigo_centrocusto = '${centroCusto}'`);
|
||||||
|
if (codigoConta) conditions.push(`ffa.codigo_conta = '${codigoConta}'`);
|
||||||
|
|
||||||
|
const whereClause =
|
||||||
|
conditions.length > 0 ? `AND ${conditions.join(' AND ')}` : '';
|
||||||
|
|
||||||
|
query = sql`
|
||||||
|
SELECT
|
||||||
|
ffa.codigo_fornecedor,
|
||||||
|
ffa.nome_fornecedor,
|
||||||
|
ffa.id,
|
||||||
|
ffa.codfilial,
|
||||||
|
ffa.recnum,
|
||||||
|
ffa.data_competencia,
|
||||||
|
ffa.data_vencimento,
|
||||||
|
ffa.data_pagamento,
|
||||||
|
ffa.data_caixa,
|
||||||
|
ffa.codigo_conta,
|
||||||
|
ffa.conta,
|
||||||
|
ffa.codigo_centrocusto,
|
||||||
|
ffa.valor,
|
||||||
|
ffa.historico,
|
||||||
|
ffa.historico2,
|
||||||
|
ffa.created_at,
|
||||||
|
ffa.updated_at
|
||||||
|
FROM fato_financeiro_analitico AS ffa
|
||||||
|
WHERE to_char(ffa.data_competencia, 'YYYY-MM') BETWEEN ${dataInicio} AND ${dataFim}
|
||||||
|
${sql.raw(whereClause)}
|
||||||
|
LIMIT 50
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
// Query sem filtros específicos
|
||||||
|
query = sql`
|
||||||
|
SELECT
|
||||||
|
ffa.codigo_fornecedor,
|
||||||
|
ffa.nome_fornecedor,
|
||||||
|
ffa.id,
|
||||||
|
ffa.codfilial,
|
||||||
|
ffa.recnum,
|
||||||
|
ffa.data_competencia,
|
||||||
|
ffa.data_vencimento,
|
||||||
|
ffa.data_pagamento,
|
||||||
|
ffa.data_caixa,
|
||||||
|
ffa.codigo_conta,
|
||||||
|
ffa.conta,
|
||||||
|
ffa.codigo_centrocusto,
|
||||||
|
ffa.valor,
|
||||||
|
ffa.historico,
|
||||||
|
ffa.historico2,
|
||||||
|
ffa.created_at,
|
||||||
|
ffa.updated_at
|
||||||
|
FROM fato_financeiro_analitico AS ffa
|
||||||
|
WHERE to_char(ffa.data_competencia, 'YYYY-MM') BETWEEN ${dataInicio} AND ${dataFim}
|
||||||
|
LIMIT 50
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await db.execute(query);
|
||||||
|
|
||||||
|
return NextResponse.json(data.rows);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro ao buscar dados analíticos:', error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
message: 'Erro ao buscar dados analíticos',
|
||||||
|
error: error instanceof Error ? error.message : String(error),
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue