fix: dupla visão

This commit is contained in:
Alessandro Gonçaalves 2025-10-22 12:49:04 -03:00
parent acb094271b
commit 75e452312c
2 changed files with 191 additions and 228 deletions

View File

@ -31,6 +31,7 @@ interface DREItem {
grupo: string; grupo: string;
subgrupo: string; subgrupo: string;
centro_custo: string; centro_custo: string;
codigo_centro_custo: string;
codigo_conta: number; codigo_conta: number;
conta: string; conta: string;
valor: string; valor: string;
@ -44,6 +45,7 @@ interface HierarchicalRow {
grupo?: string; grupo?: string;
subgrupo?: string; subgrupo?: string;
centro_custo?: string; centro_custo?: string;
codigo_centro_custo?: string;
conta?: string; conta?: string;
codigo_conta?: number; codigo_conta?: number;
total?: number; total?: number;
@ -58,7 +60,6 @@ const TableRow = memo(({
row, row,
index, index,
toggleGroup, toggleGroup,
toggleSubgrupo,
toggleCentro, toggleCentro,
handleRowClick, handleRowClick,
getRowStyle, getRowStyle,
@ -71,7 +72,6 @@ const TableRow = memo(({
row: HierarchicalRow; row: HierarchicalRow;
index: number; index: number;
toggleGroup: (grupo: string) => void; toggleGroup: (grupo: string) => void;
toggleSubgrupo: (subgrupo: string) => void;
toggleCentro: (centro: string) => void; toggleCentro: (centro: string) => void;
handleRowClick: (row: HierarchicalRow, mes?: string) => void; handleRowClick: (row: HierarchicalRow, mes?: string) => void;
getRowStyle: (row: HierarchicalRow) => string; getRowStyle: (row: HierarchicalRow) => string;
@ -175,9 +175,6 @@ export default function Teste() {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set()); const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set());
const [expandedSubgrupos, setExpandedSubgrupos] = useState<Set<string>>(
new Set()
);
const [expandedCentros, setExpandedCentros] = useState<Set<string>>( const [expandedCentros, setExpandedCentros] = useState<Set<string>>(
new Set() new Set()
); );
@ -384,7 +381,7 @@ export default function Teste() {
const novosFiltros = { const novosFiltros = {
dataInicio: dataInicioFiltro, dataInicio: dataInicioFiltro,
dataFim: dataFimFiltro, dataFim: dataFimFiltro,
centroCusto: row.centro_custo || "", centroCusto: row.codigo_centro_custo || "", // ✅ Usar código do centro de custo
codigoGrupo, codigoGrupo,
codigoSubgrupo, codigoSubgrupo,
codigoConta: row.codigo_conta?.toString() || "", codigoConta: row.codigo_conta?.toString() || "",
@ -407,17 +404,6 @@ export default function Teste() {
}); });
}, []); }, []);
const toggleSubgrupo = useCallback((subgrupo: string) => {
setExpandedSubgrupos(prev => {
const newExpanded = new Set(prev);
if (newExpanded.has(subgrupo)) {
newExpanded.delete(subgrupo);
} else {
newExpanded.add(subgrupo);
}
return newExpanded;
});
}, []);
const toggleCentro = useCallback((centro: string) => { const toggleCentro = useCallback((centro: string) => {
setExpandedCentros(prev => { setExpandedCentros(prev => {
@ -443,7 +429,7 @@ export default function Teste() {
setCentrosCustoSelecionados(prev => { setCentrosCustoSelecionados(prev => {
if (prev.includes(centro)) { if (prev.includes(centro)) {
return prev.filter(c => c !== centro); return prev.filter(c => c !== centro);
} else { } else {
return [...prev, centro]; return [...prev, centro];
} }
}); });
@ -453,7 +439,7 @@ export default function Teste() {
setContasSelecionadas(prev => { setContasSelecionadas(prev => {
if (prev.includes(conta)) { if (prev.includes(conta)) {
return prev.filter(c => c !== conta); return prev.filter(c => c !== conta);
} else { } else {
return [...prev, conta]; return [...prev, conta];
} }
}); });
@ -480,24 +466,30 @@ export default function Teste() {
// Recolher tudo - usar startTransition para atualizações não urgentes // Recolher tudo - usar startTransition para atualizações não urgentes
startTransition(() => { startTransition(() => {
setExpandedGroups(new Set()); setExpandedGroups(new Set());
setExpandedSubgrupos(new Set());
setExpandedCentros(new Set()); setExpandedCentros(new Set());
setIsAllExpanded(false); setIsAllExpanded(false);
}); });
} else { } else {
// Expandir todos os grupos usando dados originais - usar startTransition para atualizações não urgentes // Expandir todos os grupos e contas usando dados originais - usar startTransition para atualizações não urgentes
startTransition(() => { startTransition(() => {
const todosGrupos = [...new Set(data.map(item => item.grupo))]; const todosGrupos = [...new Set(data.map(item => item.grupo))];
const todosSubgrupos = [...new Set(data.map(item => `${item.grupo}-${item.subgrupo}`))];
const todosCentros = [...new Set(data.map(item => `${item.grupo}-${item.subgrupo}-${item.centro_custo}`))];
setExpandedGroups(new Set(todosGrupos)); if (ordemHierarquiaContasPrimeiro) {
setExpandedSubgrupos(new Set(todosSubgrupos)); // Nova ordem: expandir grupos e contas
setExpandedCentros(new Set(todosCentros)); const todasContas = [...new Set(data.map(item => `${item.grupo}-${item.conta}`))];
setExpandedGroups(new Set(todosGrupos));
setExpandedCentros(new Set(todasContas));
} else {
// Ordem original: expandir grupos e centros de custo
const todosCentros = [...new Set(data.map(item => `${item.grupo}-${item.centro_custo}`))];
setExpandedGroups(new Set(todosGrupos));
setExpandedCentros(new Set(todosCentros));
}
setIsAllExpanded(true); setIsAllExpanded(true);
}); });
} }
}, [isAllExpanded, data]); }, [isAllExpanded, data, ordemHierarquiaContasPrimeiro]);
const limparFiltros = () => { const limparFiltros = () => {
const agora = new Date(); const agora = new Date();
@ -741,99 +733,59 @@ export default function Teste() {
}); });
if (expandedGroups.has(grupo)) { if (expandedGroups.has(grupo)) {
// Agrupar por subgrupo dentro do grupo if (ordemHierarquiaContasPrimeiro) {
const subgrupos = items.reduce((acc, item) => { // ORDEM: Grupos → Contas → Centros de Custo
// Se o item originalmente era do grupo 05, agrupar tudo sob o nome do grupo 05
if (item.grupo.includes("05")) { // Agrupar por conta dentro do grupo
const subgrupoKey = item.grupo; // Usar o nome completo do grupo 05 const contas = items.reduce((acc, item) => {
if (!acc[subgrupoKey]) { if (!acc[item.conta]) {
acc[subgrupoKey] = []; acc[item.conta] = [];
} }
acc[subgrupoKey].push(item); acc[item.conta].push(item);
} else {
// Para outros itens, agrupar normalmente por subgrupo
if (!acc[item.subgrupo]) {
acc[item.subgrupo] = [];
}
acc[item.subgrupo].push(item);
}
return acc; return acc;
}, {} as Record<string, DREItem[]>); }, {} as Record<string, DREItem[]>);
// Ordenar subgrupos // Ordenar contas por CODCONTA
const sortedSubgrupos = Object.entries(subgrupos).sort(([a], [b]) => const sortedContas = Object.entries(contas).sort(([contaA, itemsA], [contaB, itemsB]) => {
a.localeCompare(b) const codcontaA = itemsA[0]?.codigo_conta || 0;
); const codcontaB = itemsB[0]?.codigo_conta || 0;
sortedSubgrupos.forEach(([subgrupo, subgrupoItems]) => { if (codcontaA && codcontaB) {
const totalSubgrupo = subgrupoItems.reduce( return codcontaA - codcontaB;
}
if (codcontaA && !codcontaB) return -1;
if (!codcontaA && codcontaB) return 1;
return contaA.localeCompare(contaB);
});
sortedContas.forEach(([conta, contaItems]) => {
const totalConta = contaItems.reduce(
(sum, item) => sum + parseFloat(item.valor), (sum, item) => sum + parseFloat(item.valor),
0 0
); );
// Linha do subgrupo // Linha da conta (Level 1)
const valoresSubgrupoPorMes = calcularValoresPorMes(subgrupoItems); const valoresContaPorMes = calcularValoresPorMes(contaItems);
rows.push({ rows.push({
type: "subgrupo", type: "conta",
level: 1, level: 1,
grupo, grupo,
subgrupo, conta,
total: totalSubgrupo, codigo_conta: contaItems[0].codigo_conta,
isExpanded: expandedSubgrupos.has(`${grupo}-${subgrupo}`), total: totalConta,
valoresPorMes: valoresSubgrupoPorMes, isExpanded: expandedCentros.has(`${grupo}-${conta}`),
valoresPorMes: valoresContaPorMes,
percentuaisPorMes: calcularPercentuaisPorMes( percentuaisPorMes: calcularPercentuaisPorMes(
valoresSubgrupoPorMes, valoresContaPorMes,
grupo grupo
), ),
}); });
if (expandedSubgrupos.has(`${grupo}-${subgrupo}`)) { if (expandedCentros.has(`${grupo}-${conta}`)) {
if (ordemHierarquiaContasPrimeiro) { // Agrupar por centro de custo dentro da conta
// NOVA ORDEM: Contas primeiro, depois Centros de Custo const centros = contaItems.reduce((acc, item) => {
// Agrupar por conta dentro do subgrupo
const contas = subgrupoItems.reduce((acc, item) => {
if (!acc[item.conta]) {
acc[item.conta] = [];
}
acc[item.conta].push(item);
return acc;
}, {} as Record<string, DREItem[]>);
// Ordenar contas
const sortedContas = Object.entries(contas).sort(([a], [b]) =>
a.localeCompare(b)
);
sortedContas.forEach(([conta, contaItems]) => {
const totalConta = contaItems.reduce(
(sum, item) => sum + parseFloat(item.valor),
0
);
// Linha da conta (Level 2 - antes era Level 3)
const valoresContaPorMes = calcularValoresPorMes(contaItems);
rows.push({
type: "conta",
level: 2,
grupo,
subgrupo,
conta,
codigo_conta: contaItems[0].codigo_conta,
total: totalConta,
isExpanded: expandedCentros.has(
`${grupo}-${subgrupo}-${conta}`
),
valoresPorMes: valoresContaPorMes,
percentuaisPorMes: calcularPercentuaisPorMes(
valoresContaPorMes,
grupo
),
});
if (expandedCentros.has(`${grupo}-${subgrupo}-${conta}`)) {
// Agrupar por centro de custo dentro da conta
const centros = contaItems.reduce((acc, item) => {
if (!acc[item.centro_custo]) { if (!acc[item.centro_custo]) {
acc[item.centro_custo] = []; acc[item.centro_custo] = [];
} }
@ -841,52 +793,72 @@ export default function Teste() {
return acc; return acc;
}, {} as Record<string, DREItem[]>); }, {} as Record<string, DREItem[]>);
// Ordenar centros de custo // Ordenar centros de custo por CODIGOCENTROCUSTO
const sortedCentros = Object.entries(centros).sort(([a], [b]) => const sortedCentros = Object.entries(centros).sort(([centroA, itemsA], [centroB, itemsB]) => {
a.localeCompare(b) const codigoA = itemsA[0]?.codigo_centro_custo || "";
); const codigoB = itemsB[0]?.codigo_centro_custo || "";
sortedCentros.forEach(([centro, centroItems]) => { if (codigoA && codigoB) {
const totalCentro = centroItems.reduce( return codigoA.localeCompare(codigoB);
}
if (codigoA && !codigoB) return -1;
if (!codigoA && codigoB) return 1;
return centroA.localeCompare(centroB);
});
sortedCentros.forEach(([centro, centroItems]) => {
const totalCentro = centroItems.reduce(
(sum, item) => sum + parseFloat(item.valor), (sum, item) => sum + parseFloat(item.valor),
0 0
); );
// Linha do centro de custo (Level 3 - antes era Level 2) // Linha do centro de custo (Level 2)
const valoresCentroPorMes = calcularValoresPorMes(centroItems); const valoresCentroPorMes = calcularValoresPorMes(centroItems);
rows.push({ rows.push({
type: "centro_custo", type: "centro_custo",
level: 3, level: 2,
grupo, grupo,
subgrupo, centro_custo: centro,
centro_custo: centro, conta,
conta, codigo_centro_custo: centroItems[0].codigo_centro_custo,
total: totalCentro, total: totalCentro,
valoresPorMes: valoresCentroPorMes, valoresPorMes: valoresCentroPorMes,
percentuaisPorMes: calcularPercentuaisPorMes( percentuaisPorMes: calcularPercentuaisPorMes(
valoresCentroPorMes, valoresCentroPorMes,
grupo grupo
), ),
}); });
});
}
}); });
} else { }
// ORDEM ORIGINAL: Centros de Custo primeiro, depois Contas });
} else {
// ORDEM ORIGINAL: Grupos → Centros de Custo → Contas
// Agrupar por centro de custo dentro do subgrupo // Agrupar por centro de custo dentro do grupo
const centros = subgrupoItems.reduce((acc, item) => { const centros = items.reduce((acc, item) => {
if (!acc[item.centro_custo]) { if (!acc[item.centro_custo]) {
acc[item.centro_custo] = []; acc[item.centro_custo] = [];
} }
acc[item.centro_custo].push(item); acc[item.centro_custo].push(item);
return acc; return acc;
}, {} as Record<string, DREItem[]>); }, {} as Record<string, DREItem[]>);
// Ordenar centros de custo // Ordenar centros de custo por CODIGOCENTROCUSTO
const sortedCentros = Object.entries(centros).sort(([a], [b]) => const sortedCentros = Object.entries(centros).sort(([centroA, itemsA], [centroB, itemsB]) => {
a.localeCompare(b) const codigoA = itemsA[0]?.codigo_centro_custo || "";
); const codigoB = itemsB[0]?.codigo_centro_custo || "";
if (codigoA && codigoB) {
return codigoA.localeCompare(codigoB);
}
if (codigoA && !codigoB) return -1;
if (!codigoA && codigoB) return 1;
return centroA.localeCompare(centroB);
});
sortedCentros.forEach(([centro, centroItems]) => { sortedCentros.forEach(([centro, centroItems]) => {
const totalCentro = centroItems.reduce( const totalCentro = centroItems.reduce(
@ -894,18 +866,16 @@ export default function Teste() {
0 0
); );
// Linha do centro de custo // Linha do centro de custo (Level 1)
const valoresCentroPorMes = calcularValoresPorMes(centroItems); const valoresCentroPorMes = calcularValoresPorMes(centroItems);
rows.push({ rows.push({
type: "centro_custo", type: "centro_custo",
level: 2, level: 1,
grupo, grupo,
subgrupo,
centro_custo: centro, centro_custo: centro,
codigo_centro_custo: centroItems[0].codigo_centro_custo,
total: totalCentro, total: totalCentro,
isExpanded: expandedCentros.has( isExpanded: expandedCentros.has(`${grupo}-${centro}`),
`${grupo}-${subgrupo}-${centro}`
),
valoresPorMes: valoresCentroPorMes, valoresPorMes: valoresCentroPorMes,
percentuaisPorMes: calcularPercentuaisPorMes( percentuaisPorMes: calcularPercentuaisPorMes(
valoresCentroPorMes, valoresCentroPorMes,
@ -913,7 +883,7 @@ export default function Teste() {
), ),
}); });
if (expandedCentros.has(`${grupo}-${subgrupo}-${centro}`)) { if (expandedCentros.has(`${grupo}-${centro}`)) {
// Agrupar por conta dentro do centro de custo // Agrupar por conta dentro do centro de custo
const contas = centroItems.reduce((acc, item) => { const contas = centroItems.reduce((acc, item) => {
if (!acc[item.conta]) { if (!acc[item.conta]) {
@ -923,10 +893,20 @@ export default function Teste() {
return acc; return acc;
}, {} as Record<string, DREItem[]>); }, {} as Record<string, DREItem[]>);
// Ordenar contas // Ordenar contas por CODCONTA
const sortedContas = Object.entries(contas).sort(([a], [b]) => const sortedContas = Object.entries(contas).sort(([contaA, itemsA], [contaB, itemsB]) => {
a.localeCompare(b) const codcontaA = itemsA[0]?.codigo_conta || 0;
); const codcontaB = itemsB[0]?.codigo_conta || 0;
if (codcontaA && codcontaB) {
return codcontaA - codcontaB;
}
if (codcontaA && !codcontaB) return -1;
if (!codcontaA && codcontaB) return 1;
return contaA.localeCompare(contaB);
});
sortedContas.forEach(([conta, contaItems]) => { sortedContas.forEach(([conta, contaItems]) => {
const totalConta = contaItems.reduce( const totalConta = contaItems.reduce(
@ -934,13 +914,12 @@ export default function Teste() {
0 0
); );
// Linha da conta // Linha da conta (Level 2)
const valoresContaPorMes = calcularValoresPorMes(contaItems); const valoresContaPorMes = calcularValoresPorMes(contaItems);
rows.push({ rows.push({
type: "conta", type: "conta",
level: 3, level: 2,
grupo, grupo,
subgrupo,
centro_custo: centro, centro_custo: centro,
conta, conta,
codigo_conta: contaItems[0].codigo_conta, codigo_conta: contaItems[0].codigo_conta,
@ -954,9 +933,7 @@ export default function Teste() {
}); });
} }
}); });
}
} }
});
} }
}); });
@ -1032,78 +1009,19 @@ export default function Teste() {
{row.grupo} {row.grupo}
</span> </span>
{isCalculado && ( {isCalculado && (
// <span className="text-blue-600 font-bold text-sm">⚡</span> <span className="text-blue-600 font-bold text-sm"></span>
<></>
)} )}
</div> </div>
</button> </button>
</div> </div>
); );
case "subgrupo":
return (
<div className="flex items-center gap-2 whitespace-nowrap">
<button
onClick={() => toggleSubgrupo(`${row.grupo}-${row.subgrupo}`)}
className="p-2 hover:bg-blue-100 rounded-lg transition-all duration-150 ease-in-out flex items-center justify-center w-8 h-8 flex-shrink-0 transform hover:scale-105"
>
{row.isExpanded ? (
<ChevronDown className="w-4 h-4 text-blue-600 transition-transform duration-150" />
) : (
<ChevronRight className="w-4 h-4 text-blue-600 transition-transform duration-150" />
)}
</button>
<button
onClick={() => handleRowClick(row)}
className="flex-1 text-left hover:bg-blue-50/50 p-2 rounded-lg cursor-pointer transition-all duration-200 truncate"
>
<span className="font-semibold text-gray-800">
{row.subgrupo}
</span>
</button>
</div>
);
case "centro_custo":
return (
<div className="flex items-center gap-2 whitespace-nowrap">
{ordemHierarquiaContasPrimeiro ? (
// Nova ordem: Centro de custo é level 3 (sem botão de toggle)
<div className="w-8 h-8 flex items-center justify-center flex-shrink-0">
<span className="text-gray-400 font-bold text-lg"></span>
</div>
) : (
// Ordem original: Centro de custo é level 2 (com botão de toggle)
<button
onClick={() =>
toggleCentro(`${row.grupo}-${row.subgrupo}-${row.centro_custo}`)
}
className="p-2 hover:bg-blue-100 rounded-lg transition-all duration-150 ease-in-out flex items-center justify-center w-8 h-8 flex-shrink-0 transform hover:scale-105"
>
{row.isExpanded ? (
<ChevronDown className="w-4 h-4 text-blue-600 transition-transform duration-150" />
) : (
<ChevronRight className="w-4 h-4 text-blue-600 transition-transform duration-150" />
)}
</button>
)}
<button
onClick={() => handleRowClick(row)}
className="flex-1 text-left hover:bg-blue-50/50 p-2 rounded-lg cursor-pointer transition-all duration-200 truncate"
>
<span className="font-medium text-gray-700">
{row.centro_custo}
</span>
</button>
</div>
);
case "conta": case "conta":
return ( return (
<div className="flex items-center gap-2 whitespace-nowrap"> <div className="flex items-center gap-2 whitespace-nowrap">
{ordemHierarquiaContasPrimeiro ? ( {ordemHierarquiaContasPrimeiro ? (
// Nova ordem: Conta é level 2 (com botão de toggle) // Nova ordem: Conta é level 1 (com botão de toggle)
<button <button
onClick={() => onClick={() => toggleCentro(`${row.grupo}-${row.conta}`)}
toggleCentro(`${row.grupo}-${row.subgrupo}-${row.conta}`)
}
className="p-2 hover:bg-blue-100 rounded-lg transition-all duration-150 ease-in-out flex items-center justify-center w-8 h-8 flex-shrink-0 transform hover:scale-105" className="p-2 hover:bg-blue-100 rounded-lg transition-all duration-150 ease-in-out flex items-center justify-center w-8 h-8 flex-shrink-0 transform hover:scale-105"
> >
{row.isExpanded ? ( {row.isExpanded ? (
@ -1111,9 +1029,9 @@ export default function Teste() {
) : ( ) : (
<ChevronRight className="w-4 h-4 text-blue-600 transition-transform duration-150" /> <ChevronRight className="w-4 h-4 text-blue-600 transition-transform duration-150" />
)} )}
</button> </button>
) : ( ) : (
// Ordem original: Conta é level 3 (sem botão de toggle) // Ordem original: Conta é level 2 (sem botão de toggle)
<div className="w-8 h-8 flex items-center justify-center flex-shrink-0"> <div className="w-8 h-8 flex items-center justify-center flex-shrink-0">
<span className="text-gray-400 font-bold text-lg"></span> <span className="text-gray-400 font-bold text-lg"></span>
</div> </div>
@ -1122,7 +1040,52 @@ export default function Teste() {
onClick={() => handleRowClick(row)} onClick={() => handleRowClick(row)}
className="flex-1 text-left hover:bg-blue-50/50 p-2 rounded-lg cursor-pointer transition-all duration-200 truncate" className="flex-1 text-left hover:bg-blue-50/50 p-2 rounded-lg cursor-pointer transition-all duration-200 truncate"
> >
<span className="font-normal text-gray-600">{row.conta}</span> <div className="flex items-center gap-2">
<span className="font-semibold text-gray-800">
{row.conta}
</span>
{row.codigo_conta && (
<span className="text-xs text-gray-500 bg-gray-100 px-2 py-1 rounded">
{row.codigo_conta}
</span>
)}
</div>
</button>
</div>
);
case "centro_custo":
return (
<div className="flex items-center gap-2 whitespace-nowrap">
{ordemHierarquiaContasPrimeiro ? (
// Nova ordem: Centro de custo é level 2 (sem botão de toggle)
<div className="w-8 h-8 flex items-center justify-center flex-shrink-0">
<span className="text-gray-400 font-bold text-lg"></span>
</div>
) : (
// Ordem original: Centro de custo é level 1 (com botão de toggle)
<button
onClick={() => toggleCentro(`${row.grupo}-${row.centro_custo}`)}
className="p-2 hover:bg-blue-100 rounded-lg transition-all duration-150 ease-in-out flex items-center justify-center w-8 h-8 flex-shrink-0 transform hover:scale-105"
>
{row.isExpanded ? (
<ChevronDown className="w-4 h-4 text-blue-600 transition-transform duration-150" />
) : (
<ChevronRight className="w-4 h-4 text-blue-600 transition-transform duration-150" />
)}
</button>
)}
<button
onClick={() => handleRowClick(row)}
className="flex-1 text-left hover:bg-blue-50/50 p-2 rounded-lg cursor-pointer transition-all duration-200 truncate"
>
<div className="flex items-center gap-2">
<span className="font-medium text-gray-700">
{row.codigo_centro_custo
? `${row.centro_custo} - ${row.codigo_centro_custo}`
: row.centro_custo
}
</span>
</div>
</button> </button>
</div> </div>
); );
@ -1527,7 +1490,6 @@ export default function Teste() {
row={row} row={row}
index={index} index={index}
toggleGroup={toggleGroup} toggleGroup={toggleGroup}
toggleSubgrupo={toggleSubgrupo}
toggleCentro={toggleCentro} toggleCentro={toggleCentro}
handleRowClick={handleRowClick} handleRowClick={handleRowClick}
getRowStyle={getRowStyle} getRowStyle={getRowStyle}

View File

@ -23,7 +23,8 @@ export async function GET(request: NextRequest) {
data_cai: item.DATA || "2023-03", // Usar DATA do Oracle data_cai: item.DATA || "2023-03", // Usar DATA do Oracle
grupo: codgrupo ? `${codgrupo} - ${nomeGrupo}` : nomeGrupo, // Concatenar código + nome grupo: codgrupo ? `${codgrupo} - ${nomeGrupo}` : nomeGrupo, // Concatenar código + nome
subgrupo: item.CENTROCUSTO || "", // Usar CENTROCUSTO como subgrupo subgrupo: item.CENTROCUSTO || "", // Usar CENTROCUSTO como subgrupo
centro_custo: item.CODIGOCENTROCUSTO || "", // Usar CODIGOCENTROCUSTO centro_custo: item.CENTROCUSTO || "", // Usar CENTROCUSTO (nome do centro)
codigo_centro_custo: item.CODIGOCENTROCUSTO || "", // Usar CODIGOCENTROCUSTO (código do centro)
codigo_conta: parseInt(item.CODCONTA) || 0, // Converter CODCONTA para número codigo_conta: parseInt(item.CODCONTA) || 0, // Converter CODCONTA para número
conta: item.CONTA || "", // Usar CONTA do Oracle conta: item.CONTA || "", // Usar CONTA do Oracle
valor: item.VALOR?.toString() || "0", // Converter VALOR para string valor: item.VALOR?.toString() || "0", // Converter VALOR para string