fix: divisão de colunas por filial
This commit is contained in:
parent
21e70256c7
commit
078c4842ed
|
|
@ -66,6 +66,8 @@ const TableRow = memo(({
|
|||
renderCellContent,
|
||||
mesesDisponiveis,
|
||||
opcoesFiliais,
|
||||
filiaisSelecionadas,
|
||||
filtrosAplicados,
|
||||
formatCurrency,
|
||||
formatCurrencyWithColor,
|
||||
getFixedCellBackground
|
||||
|
|
@ -78,6 +80,8 @@ const TableRow = memo(({
|
|||
renderCellContent: (row: HierarchicalRow) => React.ReactNode;
|
||||
mesesDisponiveis: string[];
|
||||
opcoesFiliais: string[];
|
||||
filiaisSelecionadas: string[];
|
||||
filtrosAplicados: boolean;
|
||||
formatCurrency: (value: number) => string;
|
||||
formatCurrencyWithColor: (value: number) => { formatted: string; isNegative: boolean };
|
||||
getFixedCellBackground: (row: HierarchicalRow) => string;
|
||||
|
|
@ -99,7 +103,12 @@ const TableRow = memo(({
|
|||
|
||||
{/* Colunas de valores por mês e por filial - cada filial tem suas próprias colunas */}
|
||||
{mesesDisponiveis.map((mes) =>
|
||||
(opcoesFiliais.length > 0 ? opcoesFiliais : ['']).map((filial: string) => (
|
||||
((filtrosAplicados && filiaisSelecionadas.length > 0) ? filiaisSelecionadas : (opcoesFiliais.length > 0 ? opcoesFiliais : [''])).map((filial: string) => {
|
||||
// Só exibir se a filial estiver selecionada ou se não houver filtros aplicados
|
||||
if (filtrosAplicados && filiaisSelecionadas.length > 0 && !filiaisSelecionadas.includes(filial)) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<React.Fragment key={`${mes}-${filial || 'default'}`}>
|
||||
<td
|
||||
className="px-2 py-1 text-right font-semibold cursor-pointer hover:bg-blue-50/50 transition-colors duration-200 whitespace-nowrap overflow-hidden w-[120px] min-w-[120px]"
|
||||
|
|
@ -167,7 +176,8 @@ const TableRow = memo(({
|
|||
)}
|
||||
</td>
|
||||
</React.Fragment>
|
||||
))
|
||||
);
|
||||
})
|
||||
)}
|
||||
|
||||
{/* Coluna Total */}
|
||||
|
|
@ -339,23 +349,23 @@ export default function Teste() {
|
|||
}
|
||||
};
|
||||
|
||||
const formatCurrency = (value: string | number) => {
|
||||
const formatCurrency = React.useCallback((value: string | number) => {
|
||||
const numValue = typeof value === "string" ? parseFloat(value) : value;
|
||||
return numValue.toLocaleString("pt-BR", {
|
||||
style: "currency",
|
||||
currency: "BRL",
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
|
||||
const formatCurrencyWithColor = (value: string | number) => {
|
||||
const formatCurrencyWithColor = React.useCallback((value: string | number) => {
|
||||
const numValue = typeof value === "string" ? parseFloat(value) : value;
|
||||
const formatted = formatCurrency(value);
|
||||
const isNegative = numValue < 0;
|
||||
return { formatted, isNegative };
|
||||
};
|
||||
}, [formatCurrency]);
|
||||
|
||||
// Função para lidar com clique nas linhas
|
||||
const handleRowClick = (row: HierarchicalRow, mesSelecionado?: string) => {
|
||||
const handleRowClick = React.useCallback((row: HierarchicalRow, mesSelecionado?: string) => {
|
||||
console.log('🖱️ Clique na linha:', row);
|
||||
console.log('📅 Mês selecionado:', mesSelecionado);
|
||||
|
||||
|
|
@ -431,7 +441,7 @@ export default function Teste() {
|
|||
|
||||
console.log('🎯 Novos filtros para analítico:', novosFiltros);
|
||||
setAnaliticoFiltros(novosFiltros);
|
||||
};
|
||||
}, [data]);
|
||||
|
||||
const toggleGrupo = useCallback((codigoGrupo: string) => {
|
||||
setExpandedGrupos(prev => {
|
||||
|
|
@ -464,7 +474,7 @@ export default function Teste() {
|
|||
};
|
||||
|
||||
// Função auxiliar para calcular valores por mês
|
||||
const calcularValoresPorMes = (items: DREItem[]): Record<string, number> => {
|
||||
const calcularValoresPorMes = React.useCallback((items: DREItem[]): Record<string, number> => {
|
||||
const valoresPorMes: Record<string, number> = {};
|
||||
|
||||
mesesDisponiveis.forEach(mes => {
|
||||
|
|
@ -479,16 +489,18 @@ export default function Teste() {
|
|||
});
|
||||
|
||||
return valoresPorMes;
|
||||
};
|
||||
}, [mesesDisponiveis]);
|
||||
|
||||
// Função auxiliar para calcular valores por mês e por filial
|
||||
const calcularValoresPorMesPorFilial = (items: DREItem[]): Record<string, Record<string, number>> => {
|
||||
const calcularValoresPorMesPorFilial = React.useCallback((items: DREItem[]): Record<string, Record<string, number>> => {
|
||||
const valoresPorMesPorFilial: Record<string, Record<string, number>> = {};
|
||||
|
||||
// Extrair filiais únicas dos items se opcoesFiliais ainda não estiver disponível
|
||||
const filiaisDisponiveis = opcoesFiliais.length > 0
|
||||
? opcoesFiliais
|
||||
: [...new Set(items.map(item => item.filial || item.codfilial).filter(Boolean))] as string[];
|
||||
// Usar filiais selecionadas se houver filtros aplicados, senão usar todas as opções disponíveis
|
||||
const filiaisDisponiveis = (filtrosAplicados && filiaisSelecionadas.length > 0)
|
||||
? filiaisSelecionadas
|
||||
: (opcoesFiliais.length > 0
|
||||
? opcoesFiliais
|
||||
: [...new Set(items.map(item => item.filial || item.codfilial).filter(Boolean))] as string[]);
|
||||
|
||||
mesesDisponiveis.forEach(mes => {
|
||||
valoresPorMesPorFilial[mes] = {};
|
||||
|
|
@ -500,7 +512,7 @@ export default function Teste() {
|
|||
items.forEach((item) => {
|
||||
const anoMes = item.data_competencia;
|
||||
const filial = item.filial || item.codfilial || "";
|
||||
if (anoMes && valoresPorMesPorFilial[anoMes] && filial) {
|
||||
if (anoMes && valoresPorMesPorFilial[anoMes] && filial && filiaisDisponiveis.includes(filial)) {
|
||||
if (!valoresPorMesPorFilial[anoMes][filial]) {
|
||||
valoresPorMesPorFilial[anoMes][filial] = 0;
|
||||
}
|
||||
|
|
@ -509,10 +521,49 @@ export default function Teste() {
|
|||
});
|
||||
|
||||
return valoresPorMesPorFilial;
|
||||
};
|
||||
}, [mesesDisponiveis, opcoesFiliais, filtrosAplicados, filiaisSelecionadas]);
|
||||
|
||||
// Memoizar valores do grupo 01 por mês para evitar recálculos repetidos
|
||||
const valoresGrupo01PorMesMemo = React.useMemo(() => {
|
||||
const valores: Record<string, number> = {};
|
||||
mesesDisponiveis.forEach(mes => {
|
||||
valores[mes] = data
|
||||
.filter(item => {
|
||||
const codgrupo = item.codgrupo || item.codigo_grupo || "";
|
||||
return codgrupo === "01" && item.data_competencia === mes;
|
||||
})
|
||||
.reduce((sum, item) => sum + parseFloat(item.valor), 0);
|
||||
});
|
||||
return valores;
|
||||
}, [data, mesesDisponiveis]);
|
||||
|
||||
// Memoizar valores do grupo 01 por mês e por filial
|
||||
const valoresGrupo01PorMesPorFilialMemo = React.useMemo(() => {
|
||||
const valores: Record<string, Record<string, number>> = {};
|
||||
// Usar filiais selecionadas se houver filtros aplicados, senão usar todas as opções disponíveis
|
||||
const filiaisDisponiveis = (filtrosAplicados && filiaisSelecionadas.length > 0)
|
||||
? filiaisSelecionadas
|
||||
: (opcoesFiliais.length > 0
|
||||
? opcoesFiliais
|
||||
: [...new Set(data.map(item => item.filial || item.codfilial).filter(Boolean))] as string[]);
|
||||
|
||||
mesesDisponiveis.forEach(mes => {
|
||||
valores[mes] = {};
|
||||
filiaisDisponiveis.forEach(filial => {
|
||||
valores[mes][filial] = data
|
||||
.filter(item => {
|
||||
const codgrupo = item.codgrupo || item.codigo_grupo || "";
|
||||
const itemFilial = item.filial || item.codfilial || "";
|
||||
return codgrupo === "01" && item.data_competencia === mes && itemFilial === filial;
|
||||
})
|
||||
.reduce((sum, item) => sum + parseFloat(item.valor), 0);
|
||||
});
|
||||
});
|
||||
return valores;
|
||||
}, [data, mesesDisponiveis, opcoesFiliais, filtrosAplicados, filiaisSelecionadas]);
|
||||
|
||||
// Função para calcular percentuais baseado no CODGRUPO 01 (FATURAMENTO LÍQUIDO)
|
||||
const calcularPercentuaisPorMes = (
|
||||
const calcularPercentuaisPorMes = React.useCallback((
|
||||
valoresPorMes: Record<string, number>,
|
||||
codigoGrupo?: string
|
||||
): Record<string, number> => {
|
||||
|
|
@ -526,21 +577,10 @@ export default function Teste() {
|
|||
return percentuais;
|
||||
}
|
||||
|
||||
// Calcular valores do grupo 01 por mês (base para cálculo)
|
||||
const valoresGrupo01PorMes: Record<string, number> = {};
|
||||
mesesDisponiveis.forEach(mes => {
|
||||
valoresGrupo01PorMes[mes] = data
|
||||
.filter(item => {
|
||||
const codgrupo = item.codgrupo || item.codigo_grupo || "";
|
||||
return codgrupo === "01" && item.data_competencia === mes;
|
||||
})
|
||||
.reduce((sum, item) => sum + parseFloat(item.valor), 0);
|
||||
});
|
||||
|
||||
// Calcular percentuais baseado no grupo 01
|
||||
// Usar valores memoizados do grupo 01
|
||||
Object.keys(valoresPorMes).forEach((mes) => {
|
||||
const valorAtual = valoresPorMes[mes];
|
||||
const valorGrupo01 = valoresGrupo01PorMes[mes] || 0;
|
||||
const valorGrupo01 = valoresGrupo01PorMesMemo[mes] || 0;
|
||||
|
||||
if (valorGrupo01 !== 0) {
|
||||
percentuais[mes] = (valorAtual / valorGrupo01) * 100;
|
||||
|
|
@ -550,19 +590,21 @@ export default function Teste() {
|
|||
});
|
||||
|
||||
return percentuais;
|
||||
};
|
||||
}, [mesesDisponiveis, valoresGrupo01PorMesMemo]);
|
||||
|
||||
// Função para calcular percentuais por mês e por filial baseado no CODGRUPO 01
|
||||
const calcularPercentuaisPorMesPorFilial = (
|
||||
const calcularPercentuaisPorMesPorFilial = React.useCallback((
|
||||
valoresPorMesPorFilial: Record<string, Record<string, number>>,
|
||||
codigoGrupo?: string
|
||||
): Record<string, Record<string, number>> => {
|
||||
const percentuaisPorMesPorFilial: Record<string, Record<string, number>> = {};
|
||||
|
||||
// Extrair filiais únicas dos valores se opcoesFiliais ainda não estiver disponível
|
||||
const filiaisDisponiveis = opcoesFiliais.length > 0
|
||||
? opcoesFiliais
|
||||
: Object.keys(valoresPorMesPorFilial[mesesDisponiveis[0] || ""] || {});
|
||||
// Usar filiais selecionadas se houver filtros aplicados, senão usar todas as opções disponíveis
|
||||
const filiaisDisponiveis = (filtrosAplicados && filiaisSelecionadas.length > 0)
|
||||
? filiaisSelecionadas
|
||||
: (opcoesFiliais.length > 0
|
||||
? opcoesFiliais
|
||||
: Object.keys(valoresPorMesPorFilial[mesesDisponiveis[0] || ""] || {}));
|
||||
|
||||
// Se for CODGRUPO 01, sempre retornar 100% para todas as filiais
|
||||
if (codigoGrupo === "01") {
|
||||
|
|
@ -575,27 +617,12 @@ export default function Teste() {
|
|||
return percentuaisPorMesPorFilial;
|
||||
}
|
||||
|
||||
// Calcular valores do grupo 01 por mês e por filial (base para cálculo)
|
||||
const valoresGrupo01PorMesPorFilial: Record<string, Record<string, number>> = {};
|
||||
mesesDisponiveis.forEach(mes => {
|
||||
valoresGrupo01PorMesPorFilial[mes] = {};
|
||||
filiaisDisponiveis.forEach(filial => {
|
||||
valoresGrupo01PorMesPorFilial[mes][filial] = data
|
||||
.filter(item => {
|
||||
const codgrupo = item.codgrupo || item.codigo_grupo || "";
|
||||
const itemFilial = item.filial || item.codfilial || "";
|
||||
return codgrupo === "01" && item.data_competencia === mes && itemFilial === filial;
|
||||
})
|
||||
.reduce((sum, item) => sum + parseFloat(item.valor), 0);
|
||||
});
|
||||
});
|
||||
|
||||
// Calcular percentuais baseado no grupo 01 por filial
|
||||
// Usar valores memoizados do grupo 01
|
||||
mesesDisponiveis.forEach(mes => {
|
||||
percentuaisPorMesPorFilial[mes] = {};
|
||||
filiaisDisponiveis.forEach(filial => {
|
||||
const valorAtual = valoresPorMesPorFilial[mes]?.[filial] || 0;
|
||||
const valorGrupo01 = valoresGrupo01PorMesPorFilial[mes]?.[filial] || 0;
|
||||
const valorGrupo01 = valoresGrupo01PorMesPorFilialMemo[mes]?.[filial] || 0;
|
||||
|
||||
if (valorGrupo01 !== 0) {
|
||||
percentuaisPorMesPorFilial[mes][filial] = (valorAtual / valorGrupo01) * 100;
|
||||
|
|
@ -606,31 +633,34 @@ export default function Teste() {
|
|||
});
|
||||
|
||||
return percentuaisPorMesPorFilial;
|
||||
};
|
||||
}, [mesesDisponiveis, opcoesFiliais, valoresGrupo01PorMesPorFilialMemo, filtrosAplicados, filiaisSelecionadas]);
|
||||
|
||||
// Função para calcular percentual do total baseado no CODGRUPO 01
|
||||
const calcularPercentualTotal = (total: number, codigoGrupo?: string): number => {
|
||||
// Se for CODGRUPO 01, sempre retornar 100%
|
||||
if (codigoGrupo === "01") {
|
||||
return 100;
|
||||
}
|
||||
|
||||
// Calcular total do grupo 01 (base para cálculo)
|
||||
const totalGrupo01 = data
|
||||
// Memoizar total do grupo 01
|
||||
const totalGrupo01Memo = React.useMemo(() => {
|
||||
return data
|
||||
.filter(item => {
|
||||
const codgrupo = item.codgrupo || item.codigo_grupo || "";
|
||||
return codgrupo === "01";
|
||||
})
|
||||
.reduce((sum, item) => sum + parseFloat(item.valor), 0);
|
||||
}, [data]);
|
||||
|
||||
if (totalGrupo01 !== 0) {
|
||||
return (total / totalGrupo01) * 100;
|
||||
// Função para calcular percentual do total baseado no CODGRUPO 01
|
||||
const calcularPercentualTotal = React.useCallback((total: number, codigoGrupo?: string): number => {
|
||||
// Se for CODGRUPO 01, sempre retornar 100%
|
||||
if (codigoGrupo === "01") {
|
||||
return 100;
|
||||
}
|
||||
|
||||
// Usar total memoizado do grupo 01
|
||||
if (totalGrupo01Memo !== 0) {
|
||||
return (total / totalGrupo01Memo) * 100;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}, [totalGrupo01Memo]);
|
||||
|
||||
const buildHierarchicalData = (): HierarchicalRow[] => {
|
||||
const buildHierarchicalData = React.useCallback((): HierarchicalRow[] => {
|
||||
const rows: HierarchicalRow[] = [];
|
||||
|
||||
// Hierarquia simplificada: [grupo, conta]
|
||||
|
|
@ -790,9 +820,9 @@ export default function Teste() {
|
|||
});
|
||||
|
||||
return rows;
|
||||
};
|
||||
}, [data, mesesDisponiveis, expandedGrupos, opcoesFiliais, filtrosAplicados, filiaisSelecionadas, calcularValoresPorMes, calcularValoresPorMesPorFilial, calcularPercentuaisPorMes, calcularPercentuaisPorMesPorFilial, calcularPercentualTotal]);
|
||||
|
||||
const getRowStyle = (row: HierarchicalRow) => {
|
||||
const getRowStyle = React.useCallback((row: HierarchicalRow) => {
|
||||
const baseStyle =
|
||||
"transition-all duration-200 hover:bg-gradient-to-r hover:from-blue-50/30 hover:to-indigo-50/30";
|
||||
|
||||
|
|
@ -816,9 +846,9 @@ export default function Teste() {
|
|||
default:
|
||||
return style;
|
||||
}
|
||||
};
|
||||
}, [linhaSelecionada]);
|
||||
|
||||
const getFixedCellBackground = (row: HierarchicalRow): string => {
|
||||
const getFixedCellBackground = React.useCallback((row: HierarchicalRow): string => {
|
||||
const linhaId = `${row.type}-${row.codigo_grupo || ""}-${row.codigo_conta || ""}`;
|
||||
const isSelected = linhaSelecionada === linhaId;
|
||||
|
||||
|
|
@ -836,13 +866,13 @@ export default function Teste() {
|
|||
default:
|
||||
return "bg-white";
|
||||
}
|
||||
};
|
||||
}, [linhaSelecionada]);
|
||||
|
||||
const getIndentStyle = (level: number) => {
|
||||
const getIndentStyle = React.useCallback((level: number) => {
|
||||
return { paddingLeft: `${level * 20}px` };
|
||||
};
|
||||
}, []);
|
||||
|
||||
const renderCellContent = (row: HierarchicalRow) => {
|
||||
const renderCellContent = React.useCallback((row: HierarchicalRow) => {
|
||||
switch (row.type) {
|
||||
case "grupo":
|
||||
return (
|
||||
|
|
@ -917,7 +947,7 @@ export default function Teste() {
|
|||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}, [toggleGrupo, handleRowClick]);
|
||||
|
||||
const toggleExpandAll = () => {
|
||||
if (isAllExpanded) {
|
||||
|
|
@ -1109,7 +1139,13 @@ export default function Teste() {
|
|||
console.log('✅ Arquivo XLSX completo exportado:', nomeArquivo);
|
||||
};
|
||||
|
||||
const hierarchicalData = buildHierarchicalData();
|
||||
// Memoizar dados hierárquicos para evitar recálculos desnecessários
|
||||
const hierarchicalData = React.useMemo(() => {
|
||||
if (!data.length || !mesesDisponiveis.length) {
|
||||
return [];
|
||||
}
|
||||
return buildHierarchicalData();
|
||||
}, [buildHierarchicalData]);
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-none mx-auto p-2">
|
||||
|
|
@ -1370,7 +1406,7 @@ export default function Teste() {
|
|||
Descrição
|
||||
</th>
|
||||
{mesesDisponiveis.map((mes) =>
|
||||
(opcoesFiliais.length > 0 ? opcoesFiliais : ['']).map((filial: string) => (
|
||||
((filtrosAplicados && filiaisSelecionadas.length > 0) ? filiaisSelecionadas : (opcoesFiliais.length > 0 ? opcoesFiliais : [''])).map((filial: string) => (
|
||||
<React.Fragment key={`${mes}-${filial || 'default'}`}>
|
||||
<th className="px-2 py-2 text-right text-xs font-semibold text-gray-700 uppercase tracking-wide w-[120px] min-w-[120px] bg-gradient-to-r from-blue-50 to-indigo-50">
|
||||
{mes}{filial && <><br/>
|
||||
|
|
@ -1408,6 +1444,8 @@ export default function Teste() {
|
|||
renderCellContent={renderCellContent}
|
||||
mesesDisponiveis={mesesDisponiveis}
|
||||
opcoesFiliais={opcoesFiliais}
|
||||
filiaisSelecionadas={filiaisSelecionadas}
|
||||
filtrosAplicados={filtrosAplicados}
|
||||
formatCurrency={formatCurrency}
|
||||
formatCurrencyWithColor={formatCurrencyWithColor}
|
||||
getFixedCellBackground={getFixedCellBackground}
|
||||
|
|
|
|||
Loading…
Reference in New Issue