fix: ajuste por colunas de filiais
This commit is contained in:
parent
c60bd7def8
commit
21e70256c7
|
|
@ -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}
|
||||
|
|
|
|||
Loading…
Reference in New Issue