fix: ajuste por colunas de filiais

This commit is contained in:
Alessandro Gonçaalves 2025-12-09 17:41:58 -03:00
parent c60bd7def8
commit 21e70256c7
1 changed files with 187 additions and 45 deletions

View File

@ -49,7 +49,9 @@ interface HierarchicalRow {
total?: number;
isExpanded?: boolean;
valoresPorMes?: Record<string, number>;
valoresPorMesPorFilial?: Record<string, Record<string, number>>; // mes -> filial -> valor
percentuaisPorMes?: Record<string, number>;
percentuaisPorMesPorFilial?: Record<string, Record<string, number>>; // mes -> filial -> percentual
percentualTotal?: number;
isCalculado?: boolean;
}
@ -63,6 +65,7 @@ const TableRow = memo(({
getIndentStyle,
renderCellContent,
mesesDisponiveis,
opcoesFiliais,
formatCurrency,
formatCurrencyWithColor,
getFixedCellBackground
@ -74,6 +77,7 @@ const TableRow = memo(({
getIndentStyle: (level: number) => React.CSSProperties;
renderCellContent: (row: HierarchicalRow) => React.ReactNode;
mesesDisponiveis: string[];
opcoesFiliais: string[];
formatCurrency: (value: number) => string;
formatCurrencyWithColor: (value: number) => { formatted: string; isNegative: boolean };
getFixedCellBackground: (row: HierarchicalRow) => string;
@ -93,22 +97,25 @@ const TableRow = memo(({
</div>
</td>
{/* Colunas de valores por mês */}
{mesesDisponiveis.map((mes) => (
<React.Fragment key={mes}>
{/* 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) => (
<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]"
onClick={() => handleRowClick(row, mes)}
title={
row.valoresPorMes && row.valoresPorMes[mes]
filial && row.valoresPorMesPorFilial?.[mes]?.[filial] !== undefined
? formatCurrency(row.valoresPorMesPorFilial[mes][filial])
: row.valoresPorMes?.[mes] !== undefined
? formatCurrency(row.valoresPorMes[mes])
: "-"
}
>
{row.valoresPorMes && row.valoresPorMes[mes]
? (() => {
const { formatted, isNegative } =
formatCurrencyWithColor(row.valoresPorMes[mes]);
{filial && row.valoresPorMesPorFilial?.[mes]?.[filial] !== undefined && row.valoresPorMesPorFilial[mes][filial] !== 0 ? (
(() => {
const valor = row.valoresPorMesPorFilial[mes][filial];
const { formatted, isNegative } = formatCurrencyWithColor(valor);
return (
<span
className={
@ -121,25 +128,47 @@ const TableRow = memo(({
</span>
);
})()
: "-"}
) : !filial && row.valoresPorMes?.[mes] !== undefined ? (
(() => {
const { formatted, isNegative } = formatCurrencyWithColor(row.valoresPorMes[mes]);
return (
<span
className={
isNegative
? "text-red-600 font-bold"
: "text-gray-900"
}
>
{formatted}
</span>
);
})()
) : (
<span className="text-gray-400">-</span>
)}
</td>
<td
className="px-2 py-1 text-center font-medium cursor-pointer hover:bg-blue-50/50 transition-colors duration-200 whitespace-nowrap overflow-hidden w-[100px] min-w-[100px]"
onClick={() => handleRowClick(row, mes)}
title={
row.percentuaisPorMes &&
row.percentuaisPorMes[mes] !== undefined
filial && row.percentuaisPorMesPorFilial?.[mes]?.[filial] !== undefined
? `${row.percentuaisPorMesPorFilial[mes][filial].toFixed(1)}%`
: row.percentuaisPorMes?.[mes] !== undefined
? `${row.percentuaisPorMes[mes].toFixed(1)}%`
: "-"
}
>
{row.percentuaisPorMes &&
row.percentuaisPorMes[mes] !== undefined
? `${row.percentuaisPorMes[mes].toFixed(1)}%`
: "-"}
{filial && row.percentuaisPorMesPorFilial?.[mes]?.[filial] !== undefined && row.percentuaisPorMesPorFilial[mes][filial] !== 0 ? (
`${row.percentuaisPorMesPorFilial[mes][filial].toFixed(1)}%`
) : !filial && row.percentuaisPorMes?.[mes] !== undefined ? (
`${row.percentuaisPorMes[mes].toFixed(1)}%`
) : (
<span className="text-gray-400">-</span>
)}
</td>
</React.Fragment>
))}
))
)}
{/* Coluna Total */}
<td
@ -452,6 +481,36 @@ export default function Teste() {
return valoresPorMes;
};
// Função auxiliar para calcular valores por mês e por filial
const calcularValoresPorMesPorFilial = (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[];
mesesDisponiveis.forEach(mes => {
valoresPorMesPorFilial[mes] = {};
filiaisDisponiveis.forEach(filial => {
valoresPorMesPorFilial[mes][filial] = 0;
});
});
items.forEach((item) => {
const anoMes = item.data_competencia;
const filial = item.filial || item.codfilial || "";
if (anoMes && valoresPorMesPorFilial[anoMes] && filial) {
if (!valoresPorMesPorFilial[anoMes][filial]) {
valoresPorMesPorFilial[anoMes][filial] = 0;
}
valoresPorMesPorFilial[anoMes][filial] += parseFloat(item.valor);
}
});
return valoresPorMesPorFilial;
};
// Função para calcular percentuais baseado no CODGRUPO 01 (FATURAMENTO LÍQUIDO)
const calcularPercentuaisPorMes = (
valoresPorMes: Record<string, number>,
@ -493,6 +552,62 @@ export default function Teste() {
return percentuais;
};
// Função para calcular percentuais por mês e por filial baseado no CODGRUPO 01
const calcularPercentuaisPorMesPorFilial = (
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] || ""] || {});
// Se for CODGRUPO 01, sempre retornar 100% para todas as filiais
if (codigoGrupo === "01") {
mesesDisponiveis.forEach(mes => {
percentuaisPorMesPorFilial[mes] = {};
filiaisDisponiveis.forEach(filial => {
percentuaisPorMesPorFilial[mes][filial] = 100;
});
});
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
mesesDisponiveis.forEach(mes => {
percentuaisPorMesPorFilial[mes] = {};
filiaisDisponiveis.forEach(filial => {
const valorAtual = valoresPorMesPorFilial[mes]?.[filial] || 0;
const valorGrupo01 = valoresGrupo01PorMesPorFilial[mes]?.[filial] || 0;
if (valorGrupo01 !== 0) {
percentuaisPorMesPorFilial[mes][filial] = (valorAtual / valorGrupo01) * 100;
} else {
percentuaisPorMesPorFilial[mes][filial] = 0;
}
});
});
return percentuaisPorMesPorFilial;
};
// 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%
@ -553,6 +668,7 @@ export default function Teste() {
0
);
const valoresGrupoPorMes = calcularValoresPorMes(items);
const valoresGrupoPorMesPorFilial = calcularValoresPorMesPorFilial(items);
// Linha do grupo (Level 0)
rows.push({
@ -563,7 +679,9 @@ export default function Teste() {
total: totalGrupo,
isExpanded: expandedGrupos.has(codgrupo),
valoresPorMes: valoresGrupoPorMes,
valoresPorMesPorFilial: valoresGrupoPorMesPorFilial,
percentuaisPorMes: calcularPercentuaisPorMes(valoresGrupoPorMes, codgrupo),
percentuaisPorMesPorFilial: calcularPercentuaisPorMesPorFilial(valoresGrupoPorMesPorFilial, codgrupo),
percentualTotal: calcularPercentualTotal(totalGrupo, codgrupo),
});
@ -597,6 +715,7 @@ export default function Teste() {
0
);
const valoresContaPorMes = calcularValoresPorMes(contaItems);
const valoresContaPorMesPorFilial = calcularValoresPorMesPorFilial(contaItems);
// Linha da conta (Level 1)
rows.push({
@ -609,7 +728,9 @@ export default function Teste() {
total: totalConta,
isExpanded: false,
valoresPorMes: valoresContaPorMes,
valoresPorMesPorFilial: valoresContaPorMesPorFilial,
percentuaisPorMes: calcularPercentuaisPorMes(valoresContaPorMes, codgrupo),
percentuaisPorMesPorFilial: calcularPercentuaisPorMesPorFilial(valoresContaPorMesPorFilial, codgrupo),
percentualTotal: calcularPercentualTotal(totalConta, codgrupo),
});
});
@ -633,6 +754,20 @@ export default function Teste() {
valoresMargemPorMes[mes] = valor01 - valor02;
});
// Calcular valores por mês e por filial para MARGEM DE LOJA
const valoresMargemPorMesPorFilial: Record<string, Record<string, number>> = {};
const valoresGrupo01PorFilial = gruposPorCodigo["01"] ? calcularValoresPorMesPorFilial(gruposPorCodigo["01"]) : {};
const valoresGrupo02PorFilial = gruposPorCodigo["02"] ? calcularValoresPorMesPorFilial(gruposPorCodigo["02"]) : {};
mesesDisponiveis.forEach(mes => {
valoresMargemPorMesPorFilial[mes] = {};
opcoesFiliais.forEach(filial => {
const valor01 = valoresGrupo01PorFilial[mes]?.[filial] || 0;
const valor02 = valoresGrupo02PorFilial[mes]?.[filial] || 0;
valoresMargemPorMesPorFilial[mes][filial] = valor01 - valor02;
});
});
// Calcular total
const totalMargem = Object.values(valoresMargemPorMes).reduce((sum, val) => sum + val, 0);
@ -645,7 +780,9 @@ export default function Teste() {
total: totalMargem,
isExpanded: false,
valoresPorMes: valoresMargemPorMes,
valoresPorMesPorFilial: valoresMargemPorMesPorFilial,
percentuaisPorMes: calcularPercentuaisPorMes(valoresMargemPorMes, "MARGEM"),
percentuaisPorMesPorFilial: calcularPercentuaisPorMesPorFilial(valoresMargemPorMesPorFilial, "MARGEM"),
percentualTotal: calcularPercentualTotal(totalMargem, "MARGEM"),
isCalculado: true,
});
@ -1232,16 +1369,20 @@ export default function Teste() {
<th className="px-4 py-2 text-left text-xs font-semibold text-gray-700 uppercase tracking-wide w-[300px] min-w-[300px] bg-gradient-to-r from-blue-50 to-indigo-50 sticky left-0 z-20 shadow-[2px_0_4px_rgba(0,0,0,0.1)]">
Descrição
</th>
{mesesDisponiveis.map((mes) => (
<React.Fragment key={mes}>
{mesesDisponiveis.map((mes) =>
(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}
{mes}{filial && <><br/>
<span className="text-[10px] font-normal text-gray-600">Filial - {filial}</span></>}
</th>
<th className="px-2 py-2 text-center text-xs font-semibold text-gray-500 uppercase tracking-wide w-[100px] min-w-[100px] bg-gradient-to-r from-blue-50 to-indigo-50">
%
%{filial && <><br/>
<span className="text-[10px] font-normal text-gray-600">Filial - {filial}</span></>}
</th>
</React.Fragment>
))}
))
)}
<th className="px-4 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">
Total
</th>
@ -1266,6 +1407,7 @@ export default function Teste() {
getIndentStyle={getIndentStyle}
renderCellContent={renderCellContent}
mesesDisponiveis={mesesDisponiveis}
opcoesFiliais={opcoesFiliais}
formatCurrency={formatCurrency}
formatCurrencyWithColor={formatCurrencyWithColor}
getFixedCellBackground={getFixedCellBackground}