fix: Adição da relação sintetico x analítico
This commit is contained in:
parent
e6c957e28a
commit
241141f794
|
|
@ -6,6 +6,7 @@ import {
|
||||||
getCoreRowModel,
|
getCoreRowModel,
|
||||||
getSortedRowModel,
|
getSortedRowModel,
|
||||||
getFilteredRowModel,
|
getFilteredRowModel,
|
||||||
|
ColumnFiltersState,
|
||||||
} from "@tanstack/react-table";
|
} from "@tanstack/react-table";
|
||||||
import { useVirtualizer } from "@tanstack/react-virtual";
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
|
|
@ -47,6 +48,15 @@ interface AnaliticoItem {
|
||||||
historico2: string;
|
historico2: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
|
// Campos adicionais do Oracle
|
||||||
|
entidade?: string;
|
||||||
|
tipo_parceiro?: string;
|
||||||
|
valor_previsto?: number;
|
||||||
|
valor_confirmado?: number;
|
||||||
|
valor_pago?: number;
|
||||||
|
numero_lancamento?: number;
|
||||||
|
ano_mes_comp?: string;
|
||||||
|
codgrupo?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AnaliticoProps {
|
interface AnaliticoProps {
|
||||||
|
|
@ -64,36 +74,67 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
const [data, setData] = React.useState<AnaliticoItem[]>([]);
|
const [data, setData] = React.useState<AnaliticoItem[]>([]);
|
||||||
const [loading, setLoading] = React.useState(false);
|
const [loading, setLoading] = React.useState(false);
|
||||||
const [globalFilter, setGlobalFilter] = React.useState("");
|
const [globalFilter, setGlobalFilter] = React.useState("");
|
||||||
const [columnFilters, setColumnFilters] = React.useState<any[]>([]);
|
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const [conditions, setConditions] = React.useState([
|
const [conditions, setConditions] = React.useState([
|
||||||
{ column: "", operator: "contains", value: "" },
|
{ column: "", operator: "contains", value: "" },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Estado para armazenar filtros externos (vindos do teste.tsx)
|
||||||
|
const [filtrosExternos, setFiltrosExternos] = React.useState(filtros);
|
||||||
|
|
||||||
|
// Atualizar filtros externos quando os props mudarem, mas preservar filtros internos
|
||||||
|
React.useEffect(() => {
|
||||||
|
setFiltrosExternos(filtros);
|
||||||
|
}, [filtros]);
|
||||||
|
|
||||||
const fetchData = React.useCallback(async () => {
|
const fetchData = React.useCallback(async () => {
|
||||||
// Só faz a requisição se tiver dataInicio e dataFim
|
// Só faz a requisição se tiver dataInicio e dataFim nos filtros externos
|
||||||
if (!filtros.dataInicio || !filtros.dataFim) {
|
if (!filtrosExternos.dataInicio || !filtrosExternos.dataFim) {
|
||||||
setData([]);
|
setData([]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const params = new URLSearchParams({
|
// Usar a nova API do Oracle
|
||||||
dataInicio: filtros.dataInicio,
|
const response = await fetch("/api/analitico-oracle");
|
||||||
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) {
|
if (response.ok) {
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
setData(result as AnaliticoItem[]);
|
|
||||||
|
// Aplicar filtros externos (vindos do teste.tsx) nos dados retornados
|
||||||
|
let filteredData = result as AnaliticoItem[];
|
||||||
|
|
||||||
|
// Filtro por período se especificado nos filtros externos
|
||||||
|
if (filtrosExternos.dataInicio && filtrosExternos.dataFim) {
|
||||||
|
filteredData = filteredData.filter((item: AnaliticoItem) => {
|
||||||
|
const dataItem = item.data_competencia || item.ano_mes_comp;
|
||||||
|
return dataItem && dataItem >= filtrosExternos.dataInicio && dataItem <= filtrosExternos.dataFim;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filtro por centro de custo se especificado nos filtros externos
|
||||||
|
if (filtrosExternos.centroCusto) {
|
||||||
|
filteredData = filteredData.filter((item: AnaliticoItem) =>
|
||||||
|
item.codigo_centrocusto === filtrosExternos.centroCusto
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filtro por código do grupo se especificado nos filtros externos
|
||||||
|
if (filtrosExternos.codigoGrupo) {
|
||||||
|
filteredData = filteredData.filter((item: AnaliticoItem) =>
|
||||||
|
item.codgrupo === filtrosExternos.codigoGrupo
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filtro por código da conta se especificado nos filtros externos
|
||||||
|
if (filtrosExternos.codigoConta) {
|
||||||
|
filteredData = filteredData.filter((item: AnaliticoItem) =>
|
||||||
|
item.codigo_conta === filtrosExternos.codigoConta
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setData(filteredData);
|
||||||
} else {
|
} else {
|
||||||
console.error("Erro ao buscar dados:", await response.text());
|
console.error("Erro ao buscar dados:", await response.text());
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +143,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}, [filtros]);
|
}, [filtrosExternos]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
|
|
@ -132,7 +173,10 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
accessorKey: "entidade",
|
accessorKey: "entidade",
|
||||||
header: "Entidade",
|
header: "Entidade",
|
||||||
filterFn: "advancedText",
|
filterFn: "advancedText",
|
||||||
cell: () => "-",
|
cell: ({ getValue }: { getValue: () => string }) => {
|
||||||
|
const value = getValue();
|
||||||
|
return value || "-";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "codigo_fornecedor",
|
accessorKey: "codigo_fornecedor",
|
||||||
|
|
@ -181,19 +225,58 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
accessorKey: "valor_previsto",
|
accessorKey: "valor_previsto",
|
||||||
header: "Valor Previsto",
|
header: "Valor Previsto",
|
||||||
filterFn: "advancedText",
|
filterFn: "advancedText",
|
||||||
cell: () => "-",
|
cell: ({ getValue }: { getValue: () => number }) => {
|
||||||
|
const value = getValue();
|
||||||
|
if (!value || value === 0) return "-";
|
||||||
|
const formatted = new Intl.NumberFormat("pt-BR", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "BRL",
|
||||||
|
}).format(value);
|
||||||
|
const isNegative = value < 0;
|
||||||
|
return (
|
||||||
|
<span className={isNegative ? "text-red-600" : "text-gray-900"}>
|
||||||
|
{formatted}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "valor_confirmado",
|
accessorKey: "valor_confirmado",
|
||||||
header: "Valor Confirmado",
|
header: "Valor Confirmado",
|
||||||
filterFn: "advancedText",
|
filterFn: "advancedText",
|
||||||
cell: () => "-",
|
cell: ({ getValue }: { getValue: () => number }) => {
|
||||||
|
const value = getValue();
|
||||||
|
if (!value || value === 0) return "-";
|
||||||
|
const formatted = new Intl.NumberFormat("pt-BR", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "BRL",
|
||||||
|
}).format(value);
|
||||||
|
const isNegative = value < 0;
|
||||||
|
return (
|
||||||
|
<span className={isNegative ? "text-red-600" : "text-gray-900"}>
|
||||||
|
{formatted}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "valor_pago",
|
accessorKey: "valor_pago",
|
||||||
header: "Valor Pago",
|
header: "Valor Pago",
|
||||||
filterFn: "advancedText",
|
filterFn: "advancedText",
|
||||||
cell: () => "-",
|
cell: ({ getValue }: { getValue: () => number }) => {
|
||||||
|
const value = getValue();
|
||||||
|
if (!value || value === 0) return "-";
|
||||||
|
const formatted = new Intl.NumberFormat("pt-BR", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "BRL",
|
||||||
|
}).format(value);
|
||||||
|
const isNegative = value < 0;
|
||||||
|
return (
|
||||||
|
<span className={isNegative ? "text-red-600" : "text-gray-900"}>
|
||||||
|
{formatted}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "historico",
|
accessorKey: "historico",
|
||||||
|
|
@ -209,7 +292,10 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
accessorKey: "numero_lancamento",
|
accessorKey: "numero_lancamento",
|
||||||
header: "Número do Lançamento",
|
header: "Número do Lançamento",
|
||||||
filterFn: "advancedText",
|
filterFn: "advancedText",
|
||||||
cell: () => "-",
|
cell: ({ getValue }: { getValue: () => number }) => {
|
||||||
|
const value = getValue();
|
||||||
|
return value || "-";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[]
|
[]
|
||||||
|
|
@ -217,7 +303,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
|
|
||||||
const filterFns = React.useMemo(
|
const filterFns = React.useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
advancedText: (row: any, columnId: string, filters: any[]) => {
|
advancedText: (row: any, columnId: string, filters: ColumnFiltersState) => {
|
||||||
if (!filters || filters.length === 0) return true;
|
if (!filters || filters.length === 0) return true;
|
||||||
|
|
||||||
// Se veio um único filtro (objeto), transforma em array
|
// Se veio um único filtro (objeto), transforma em array
|
||||||
|
|
@ -256,7 +342,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
|
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
data,
|
data,
|
||||||
columns,
|
columns: columns as any,
|
||||||
state: { globalFilter, columnFilters },
|
state: { globalFilter, columnFilters },
|
||||||
onGlobalFilterChange: setGlobalFilter,
|
onGlobalFilterChange: setGlobalFilter,
|
||||||
onColumnFiltersChange: setColumnFilters,
|
onColumnFiltersChange: setColumnFilters,
|
||||||
|
|
@ -306,6 +392,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
setConditions([{ column: "", operator: "contains", value: "" }]);
|
setConditions([{ column: "", operator: "contains", value: "" }]);
|
||||||
setColumnFilters([]);
|
setColumnFilters([]);
|
||||||
setGlobalFilter("");
|
setGlobalFilter("");
|
||||||
|
// Não limpar os filtros externos - eles vêm do teste.tsx
|
||||||
};
|
};
|
||||||
|
|
||||||
const [totalValor, setTotalValor] = React.useState(0);
|
const [totalValor, setTotalValor] = React.useState(0);
|
||||||
|
|
@ -314,7 +401,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
// Usar dados filtrados da tabela em vez dos dados originais
|
// Usar dados filtrados da tabela em vez dos dados originais
|
||||||
const filteredData = table.getRowModel().rows.map((row) => row.original);
|
const filteredData = table.getRowModel().rows.map((row) => row.original);
|
||||||
const newTotal = filteredData.reduce((sum, item) => {
|
const newTotal = filteredData.reduce((sum, item) => {
|
||||||
const valor =
|
const valor =
|
||||||
typeof item.valor === "string" ? parseFloat(item.valor) : item.valor;
|
typeof item.valor === "string" ? parseFloat(item.valor) : item.valor;
|
||||||
return sum + (isNaN(valor) ? 0 : valor);
|
return sum + (isNaN(valor) ? 0 : valor);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
@ -335,18 +422,32 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
// Usar EXATAMENTE a mesma lógica do totalValor
|
// Usar EXATAMENTE a mesma lógica do totalValor
|
||||||
const filteredData = table.getRowModel().rows.map((row) => row.original);
|
const filteredData = table.getRowModel().rows.map((row) => row.original);
|
||||||
const valorRealizado = filteredData.reduce((sum, item) => {
|
const valorRealizado = filteredData.reduce((sum, item) => {
|
||||||
const valor =
|
const valor = typeof item.valor === "string" ? parseFloat(item.valor) : item.valor;
|
||||||
typeof item.valor === "string" ? parseFloat(item.valor) : item.valor;
|
return sum + (isNaN(valor) ? 0 : valor);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
const valorPrevisto = filteredData.reduce((sum, item) => {
|
||||||
|
const valor = typeof item.valor_previsto === "string" ? parseFloat(item.valor_previsto) : (item.valor_previsto || 0);
|
||||||
|
return sum + (isNaN(valor) ? 0 : valor);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
const valorConfirmado = filteredData.reduce((sum, item) => {
|
||||||
|
const valor = typeof item.valor_confirmado === "string" ? parseFloat(item.valor_confirmado) : (item.valor_confirmado || 0);
|
||||||
|
return sum + (isNaN(valor) ? 0 : valor);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
const valorPago = filteredData.reduce((sum, item) => {
|
||||||
|
const valor = typeof item.valor_pago === "string" ? parseFloat(item.valor_pago) : (item.valor_pago || 0);
|
||||||
return sum + (isNaN(valor) ? 0 : valor);
|
return sum + (isNaN(valor) ? 0 : valor);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
valorRealizado,
|
valorRealizado,
|
||||||
valorPrevisto: 0, // Sempre 0 pois não há dados
|
valorPrevisto,
|
||||||
valorConfirmado: 0, // Sempre 0 pois não há dados
|
valorConfirmado,
|
||||||
valorPago: 0, // Sempre 0 pois não há dados
|
valorPago,
|
||||||
};
|
};
|
||||||
}, [table, data, columnFilters, globalFilter]);
|
}, [table]);
|
||||||
|
|
||||||
const exportToExcel = () => {
|
const exportToExcel = () => {
|
||||||
if (data.length === 0) return;
|
if (data.length === 0) return;
|
||||||
|
|
@ -442,6 +543,38 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Filtros Externos Ativos */}
|
||||||
|
{(filtrosExternos.dataInicio || filtrosExternos.centroCusto || filtrosExternos.codigoGrupo || filtrosExternos.codigoConta) && (
|
||||||
|
<div className="mb-4 p-3 bg-blue-50 border border-blue-200 rounded-lg">
|
||||||
|
<div className="flex items-center gap-2 mb-2">
|
||||||
|
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
|
||||||
|
<span className="text-sm font-medium text-blue-900">Filtros aplicados pela tabela DRE Gerencial:</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-wrap gap-2 text-xs text-blue-800">
|
||||||
|
{filtrosExternos.dataInicio && filtrosExternos.dataFim && (
|
||||||
|
<span className="px-2 py-1 bg-blue-100 rounded">
|
||||||
|
Período: {filtrosExternos.dataInicio} a {filtrosExternos.dataFim}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{filtrosExternos.centroCusto && (
|
||||||
|
<span className="px-2 py-1 bg-blue-100 rounded">
|
||||||
|
Centro: {filtrosExternos.centroCusto}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{filtrosExternos.codigoGrupo && (
|
||||||
|
<span className="px-2 py-1 bg-blue-100 rounded">
|
||||||
|
Grupo: {filtrosExternos.codigoGrupo}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{filtrosExternos.codigoConta && (
|
||||||
|
<span className="px-2 py-1 bg-blue-100 rounded">
|
||||||
|
Conta: {filtrosExternos.codigoConta}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Controls */}
|
{/* Controls */}
|
||||||
<div className="flex gap-3 flex-wrap">
|
<div className="flex gap-3 flex-wrap">
|
||||||
<Input
|
<Input
|
||||||
|
|
@ -472,7 +605,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
className="bg-white border-gray-300 hover:bg-red-50 hover:border-red-300 text-gray-700"
|
className="bg-white border-gray-300 hover:bg-red-50 hover:border-red-300 text-gray-700"
|
||||||
>
|
>
|
||||||
<X className="w-4 h-4 mr-2" />
|
<X className="w-4 h-4 mr-2" />
|
||||||
Limpar Filtros
|
Limpar Filtros Avançados
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{data.length > 0 && (
|
{data.length > 0 && (
|
||||||
|
|
@ -590,7 +723,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[100px] text-gray-500 whitespace-nowrap">
|
<div className="w-[100px] text-gray-500 whitespace-nowrap">
|
||||||
-
|
{row.original.entidade || "-"}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[160px] font-medium text-gray-900 whitespace-nowrap">
|
<div className="w-[160px] font-medium text-gray-900 whitespace-nowrap">
|
||||||
{row.original.codigo_fornecedor}
|
{row.original.codigo_fornecedor}
|
||||||
|
|
@ -625,21 +758,54 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
currency: "BRL",
|
currency: "BRL",
|
||||||
}).format(row.original.valor)}
|
}).format(row.original.valor)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[120px] text-gray-500 text-right whitespace-nowrap">
|
<div className="w-[120px] text-right whitespace-nowrap">
|
||||||
-
|
{row.original.valor_previsto && row.original.valor_previsto !== 0 ? (
|
||||||
|
<span className={`font-semibold ${
|
||||||
|
row.original.valor_previsto < 0 ? "text-red-600" : "text-gray-900"
|
||||||
|
}`}>
|
||||||
|
{new Intl.NumberFormat("pt-BR", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "BRL",
|
||||||
|
}).format(row.original.valor_previsto)}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-gray-500">-</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[130px] text-gray-500 text-right whitespace-nowrap">
|
<div className="w-[130px] text-right whitespace-nowrap">
|
||||||
-
|
{row.original.valor_confirmado && row.original.valor_confirmado !== 0 ? (
|
||||||
|
<span className={`font-semibold ${
|
||||||
|
row.original.valor_confirmado < 0 ? "text-red-600" : "text-gray-900"
|
||||||
|
}`}>
|
||||||
|
{new Intl.NumberFormat("pt-BR", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "BRL",
|
||||||
|
}).format(row.original.valor_confirmado)}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-gray-500">-</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[110px] text-gray-500 text-right whitespace-nowrap">
|
<div className="w-[110px] text-right whitespace-nowrap">
|
||||||
-
|
{row.original.valor_pago && row.original.valor_pago !== 0 ? (
|
||||||
</div>
|
<span className={`font-semibold ${
|
||||||
|
row.original.valor_pago < 0 ? "text-red-600" : "text-gray-900"
|
||||||
|
}`}>
|
||||||
|
{new Intl.NumberFormat("pt-BR", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "BRL",
|
||||||
|
}).format(row.original.valor_pago)}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-gray-500">-</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
className="w-[200px] text-gray-700 truncate"
|
className="w-[200px] text-gray-700 truncate"
|
||||||
title={row.original.historico}
|
title={row.original.historico}
|
||||||
>
|
>
|
||||||
{row.original.historico}
|
{row.original.historico}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="w-[200px] text-gray-700 truncate"
|
className="w-[200px] text-gray-700 truncate"
|
||||||
title={row.original.historico2}
|
title={row.original.historico2}
|
||||||
|
|
@ -647,7 +813,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
{row.original.historico2}
|
{row.original.historico2}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[50px] text-gray-500 whitespace-nowrap">
|
<div className="w-[50px] text-gray-500 whitespace-nowrap">
|
||||||
-
|
{row.original.numero_lancamento || "-"}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -682,14 +848,47 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
currency: "BRL",
|
currency: "BRL",
|
||||||
}).format(columnTotals.valorRealizado)}
|
}).format(columnTotals.valorRealizado)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[120px] text-right whitespace-nowrap text-gray-500">
|
<div className="w-[120px] text-right whitespace-nowrap">
|
||||||
-
|
{columnTotals.valorPrevisto !== 0 ? (
|
||||||
|
<span className={`font-bold ${
|
||||||
|
columnTotals.valorPrevisto < 0 ? "text-red-600" : "text-green-600"
|
||||||
|
}`}>
|
||||||
|
{new Intl.NumberFormat("pt-BR", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "BRL",
|
||||||
|
}).format(columnTotals.valorPrevisto)}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-gray-500">-</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[130px] text-right whitespace-nowrap text-gray-500">
|
<div className="w-[130px] text-right whitespace-nowrap">
|
||||||
-
|
{columnTotals.valorConfirmado !== 0 ? (
|
||||||
|
<span className={`font-bold ${
|
||||||
|
columnTotals.valorConfirmado < 0 ? "text-red-600" : "text-green-600"
|
||||||
|
}`}>
|
||||||
|
{new Intl.NumberFormat("pt-BR", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "BRL",
|
||||||
|
}).format(columnTotals.valorConfirmado)}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-gray-500">-</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[110px] text-right whitespace-nowrap text-gray-500">
|
<div className="w-[110px] text-right whitespace-nowrap">
|
||||||
-
|
{columnTotals.valorPago !== 0 ? (
|
||||||
|
<span className={`font-bold ${
|
||||||
|
columnTotals.valorPago < 0 ? "text-red-600" : "text-green-600"
|
||||||
|
}`}>
|
||||||
|
{new Intl.NumberFormat("pt-BR", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "BRL",
|
||||||
|
}).format(columnTotals.valorPago)}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-gray-500">-</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[200px] whitespace-nowrap"></div>
|
<div className="w-[200px] whitespace-nowrap"></div>
|
||||||
<div className="w-[200px] whitespace-nowrap"></div>
|
<div className="w-[200px] whitespace-nowrap"></div>
|
||||||
|
|
@ -748,6 +947,9 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
<DialogTitle className="text-xl font-semibold text-gray-900">
|
<DialogTitle className="text-xl font-semibold text-gray-900">
|
||||||
Filtros Avançados
|
Filtros Avançados
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
|
<p className="text-sm text-gray-600">
|
||||||
|
Estes filtros são aplicados sobre os dados já filtrados pela tabela DRE Gerencial.
|
||||||
|
</p>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="space-y-4 max-h-96 overflow-y-auto bg-white">
|
<div className="space-y-4 max-h-96 overflow-y-auto bg-white">
|
||||||
|
|
@ -873,7 +1075,7 @@ export default function AnaliticoComponent({ filtros }: AnaliticoProps) {
|
||||||
onClick={clearFilters}
|
onClick={clearFilters}
|
||||||
className="flex-1 border-gray-300 text-gray-700 hover:bg-gray-50"
|
className="flex-1 border-gray-300 text-gray-700 hover:bg-gray-50"
|
||||||
>
|
>
|
||||||
Limpar todos
|
Limpar filtros avançados
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={applyFilters}
|
onClick={applyFilters}
|
||||||
|
|
|
||||||
|
|
@ -988,9 +988,9 @@ export default function Teste() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SheetFooter className="flex gap-3">
|
<SheetFooter className="flex gap-3">
|
||||||
<Button variant="outline" onClick={limparFiltros} className="flex-1">
|
{/* <Button variant="outline" onClick={limparFiltros} className="flex-1">
|
||||||
Limpar filtros
|
Limpar filtros
|
||||||
</Button>
|
</Button> */}
|
||||||
<Button variant="outline" onClick={() => setIsFilterOpen(false)} className="flex-1">
|
<Button variant="outline" onClick={() => setIsFilterOpen(false)} className="flex-1">
|
||||||
Cancelar
|
Cancelar
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
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...');
|
||||||
|
|
||||||
|
// Query para buscar dados da tabela DRE_RESULTADO_ANALITICO
|
||||||
|
const sql = `SELECT * FROM DRE_RESULTADO_ANALITICO ORDER BY DTVENC, CODFORNEC, CODCONTA`;
|
||||||
|
|
||||||
|
const data = await executeOracleQuery(sql);
|
||||||
|
|
||||||
|
console.log('✅ Query executada com sucesso:', data.length, 'registros encontrados');
|
||||||
|
|
||||||
|
// Transformar os dados do Oracle para o formato esperado pelo componente
|
||||||
|
const transformedData = data.map((item: any) => ({
|
||||||
|
codigo_grupo: item.CODGRUPO || "",
|
||||||
|
codigo_subgrupo: "", // Não existe na tabela Oracle
|
||||||
|
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: "", // Não existe na tabela Oracle
|
||||||
|
data_caixa: item.DTCAIXA ? new Date(item.DTCAIXA).toISOString().split('T')[0] : "",
|
||||||
|
codigo_conta: item.CODCONTA || "",
|
||||||
|
conta: item.CONTA || "",
|
||||||
|
codigo_centrocusto: item.CODIGOCENTROCUSTO || "",
|
||||||
|
valor: 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 || 0,
|
||||||
|
valor_confirmado: item.VLCONFIRMADO || 0,
|
||||||
|
valor_pago: item.VLPAGO || 0,
|
||||||
|
numero_lancamento: item.NUMLANC || 0,
|
||||||
|
ano_mes_comp: item.ANOMESCOMP || "",
|
||||||
|
codgrupo: item.CODGRUPO || ""
|
||||||
|
}));
|
||||||
|
|
||||||
|
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 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue