fix: ajuste por colunas de filiais
This commit is contained in:
parent
c60bd7def8
commit
21e70256c7
|
|
@ -49,7 +49,9 @@ interface HierarchicalRow {
|
||||||
total?: number;
|
total?: number;
|
||||||
isExpanded?: boolean;
|
isExpanded?: boolean;
|
||||||
valoresPorMes?: Record<string, number>;
|
valoresPorMes?: Record<string, number>;
|
||||||
|
valoresPorMesPorFilial?: Record<string, Record<string, number>>; // mes -> filial -> valor
|
||||||
percentuaisPorMes?: Record<string, number>;
|
percentuaisPorMes?: Record<string, number>;
|
||||||
|
percentuaisPorMesPorFilial?: Record<string, Record<string, number>>; // mes -> filial -> percentual
|
||||||
percentualTotal?: number;
|
percentualTotal?: number;
|
||||||
isCalculado?: boolean;
|
isCalculado?: boolean;
|
||||||
}
|
}
|
||||||
|
|
@ -63,6 +65,7 @@ const TableRow = memo(({
|
||||||
getIndentStyle,
|
getIndentStyle,
|
||||||
renderCellContent,
|
renderCellContent,
|
||||||
mesesDisponiveis,
|
mesesDisponiveis,
|
||||||
|
opcoesFiliais,
|
||||||
formatCurrency,
|
formatCurrency,
|
||||||
formatCurrencyWithColor,
|
formatCurrencyWithColor,
|
||||||
getFixedCellBackground
|
getFixedCellBackground
|
||||||
|
|
@ -74,6 +77,7 @@ const TableRow = memo(({
|
||||||
getIndentStyle: (level: number) => React.CSSProperties;
|
getIndentStyle: (level: number) => React.CSSProperties;
|
||||||
renderCellContent: (row: HierarchicalRow) => React.ReactNode;
|
renderCellContent: (row: HierarchicalRow) => React.ReactNode;
|
||||||
mesesDisponiveis: string[];
|
mesesDisponiveis: string[];
|
||||||
|
opcoesFiliais: string[];
|
||||||
formatCurrency: (value: number) => string;
|
formatCurrency: (value: number) => string;
|
||||||
formatCurrencyWithColor: (value: number) => { formatted: string; isNegative: boolean };
|
formatCurrencyWithColor: (value: number) => { formatted: string; isNegative: boolean };
|
||||||
getFixedCellBackground: (row: HierarchicalRow) => string;
|
getFixedCellBackground: (row: HierarchicalRow) => string;
|
||||||
|
|
@ -93,22 +97,25 @@ const TableRow = memo(({
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
{/* Colunas de valores por mês */}
|
{/* Colunas de valores por mês e por filial - cada filial tem suas próprias colunas */}
|
||||||
{mesesDisponiveis.map((mes) => (
|
{mesesDisponiveis.map((mes) =>
|
||||||
<React.Fragment key={mes}>
|
(opcoesFiliais.length > 0 ? opcoesFiliais : ['']).map((filial: string) => (
|
||||||
<td
|
<React.Fragment key={`${mes}-${filial || 'default'}`}>
|
||||||
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]"
|
<td
|
||||||
onClick={() => handleRowClick(row, mes)}
|
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]"
|
||||||
title={
|
onClick={() => handleRowClick(row, mes)}
|
||||||
row.valoresPorMes && row.valoresPorMes[mes]
|
title={
|
||||||
? formatCurrency(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 (
|
return (
|
||||||
<span
|
<span
|
||||||
className={
|
className={
|
||||||
|
|
@ -121,25 +128,47 @@ const TableRow = memo(({
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
})()
|
})()
|
||||||
: "-"}
|
) : !filial && row.valoresPorMes?.[mes] !== undefined ? (
|
||||||
</td>
|
(() => {
|
||||||
<td
|
const { formatted, isNegative } = formatCurrencyWithColor(row.valoresPorMes[mes]);
|
||||||
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]"
|
return (
|
||||||
onClick={() => handleRowClick(row, mes)}
|
<span
|
||||||
title={
|
className={
|
||||||
row.percentuaisPorMes &&
|
isNegative
|
||||||
row.percentuaisPorMes[mes] !== undefined
|
? "text-red-600 font-bold"
|
||||||
? `${row.percentuaisPorMes[mes].toFixed(1)}%`
|
: "text-gray-900"
|
||||||
: "-"
|
}
|
||||||
}
|
>
|
||||||
>
|
{formatted}
|
||||||
{row.percentuaisPorMes &&
|
</span>
|
||||||
row.percentuaisPorMes[mes] !== undefined
|
);
|
||||||
? `${row.percentuaisPorMes[mes].toFixed(1)}%`
|
})()
|
||||||
: "-"}
|
) : (
|
||||||
</td>
|
<span className="text-gray-400">-</span>
|
||||||
</React.Fragment>
|
)}
|
||||||
))}
|
</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={
|
||||||
|
filial && row.percentuaisPorMesPorFilial?.[mes]?.[filial] !== undefined
|
||||||
|
? `${row.percentuaisPorMesPorFilial[mes][filial].toFixed(1)}%`
|
||||||
|
: 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 */}
|
{/* Coluna Total */}
|
||||||
<td
|
<td
|
||||||
|
|
@ -452,6 +481,36 @@ export default function Teste() {
|
||||||
return valoresPorMes;
|
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)
|
// Função para calcular percentuais baseado no CODGRUPO 01 (FATURAMENTO LÍQUIDO)
|
||||||
const calcularPercentuaisPorMes = (
|
const calcularPercentuaisPorMes = (
|
||||||
valoresPorMes: Record<string, number>,
|
valoresPorMes: Record<string, number>,
|
||||||
|
|
@ -493,6 +552,62 @@ export default function Teste() {
|
||||||
return percentuais;
|
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
|
// Função para calcular percentual do total baseado no CODGRUPO 01
|
||||||
const calcularPercentualTotal = (total: number, codigoGrupo?: string): number => {
|
const calcularPercentualTotal = (total: number, codigoGrupo?: string): number => {
|
||||||
// Se for CODGRUPO 01, sempre retornar 100%
|
// Se for CODGRUPO 01, sempre retornar 100%
|
||||||
|
|
@ -553,6 +668,7 @@ export default function Teste() {
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const valoresGrupoPorMes = calcularValoresPorMes(items);
|
const valoresGrupoPorMes = calcularValoresPorMes(items);
|
||||||
|
const valoresGrupoPorMesPorFilial = calcularValoresPorMesPorFilial(items);
|
||||||
|
|
||||||
// Linha do grupo (Level 0)
|
// Linha do grupo (Level 0)
|
||||||
rows.push({
|
rows.push({
|
||||||
|
|
@ -563,7 +679,9 @@ export default function Teste() {
|
||||||
total: totalGrupo,
|
total: totalGrupo,
|
||||||
isExpanded: expandedGrupos.has(codgrupo),
|
isExpanded: expandedGrupos.has(codgrupo),
|
||||||
valoresPorMes: valoresGrupoPorMes,
|
valoresPorMes: valoresGrupoPorMes,
|
||||||
|
valoresPorMesPorFilial: valoresGrupoPorMesPorFilial,
|
||||||
percentuaisPorMes: calcularPercentuaisPorMes(valoresGrupoPorMes, codgrupo),
|
percentuaisPorMes: calcularPercentuaisPorMes(valoresGrupoPorMes, codgrupo),
|
||||||
|
percentuaisPorMesPorFilial: calcularPercentuaisPorMesPorFilial(valoresGrupoPorMesPorFilial, codgrupo),
|
||||||
percentualTotal: calcularPercentualTotal(totalGrupo, codgrupo),
|
percentualTotal: calcularPercentualTotal(totalGrupo, codgrupo),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -597,6 +715,7 @@ export default function Teste() {
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const valoresContaPorMes = calcularValoresPorMes(contaItems);
|
const valoresContaPorMes = calcularValoresPorMes(contaItems);
|
||||||
|
const valoresContaPorMesPorFilial = calcularValoresPorMesPorFilial(contaItems);
|
||||||
|
|
||||||
// Linha da conta (Level 1)
|
// Linha da conta (Level 1)
|
||||||
rows.push({
|
rows.push({
|
||||||
|
|
@ -609,7 +728,9 @@ export default function Teste() {
|
||||||
total: totalConta,
|
total: totalConta,
|
||||||
isExpanded: false,
|
isExpanded: false,
|
||||||
valoresPorMes: valoresContaPorMes,
|
valoresPorMes: valoresContaPorMes,
|
||||||
|
valoresPorMesPorFilial: valoresContaPorMesPorFilial,
|
||||||
percentuaisPorMes: calcularPercentuaisPorMes(valoresContaPorMes, codgrupo),
|
percentuaisPorMes: calcularPercentuaisPorMes(valoresContaPorMes, codgrupo),
|
||||||
|
percentuaisPorMesPorFilial: calcularPercentuaisPorMesPorFilial(valoresContaPorMesPorFilial, codgrupo),
|
||||||
percentualTotal: calcularPercentualTotal(totalConta, codgrupo),
|
percentualTotal: calcularPercentualTotal(totalConta, codgrupo),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -633,6 +754,20 @@ export default function Teste() {
|
||||||
valoresMargemPorMes[mes] = valor01 - valor02;
|
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
|
// Calcular total
|
||||||
const totalMargem = Object.values(valoresMargemPorMes).reduce((sum, val) => sum + val, 0);
|
const totalMargem = Object.values(valoresMargemPorMes).reduce((sum, val) => sum + val, 0);
|
||||||
|
|
||||||
|
|
@ -645,7 +780,9 @@ export default function Teste() {
|
||||||
total: totalMargem,
|
total: totalMargem,
|
||||||
isExpanded: false,
|
isExpanded: false,
|
||||||
valoresPorMes: valoresMargemPorMes,
|
valoresPorMes: valoresMargemPorMes,
|
||||||
|
valoresPorMesPorFilial: valoresMargemPorMesPorFilial,
|
||||||
percentuaisPorMes: calcularPercentuaisPorMes(valoresMargemPorMes, "MARGEM"),
|
percentuaisPorMes: calcularPercentuaisPorMes(valoresMargemPorMes, "MARGEM"),
|
||||||
|
percentuaisPorMesPorFilial: calcularPercentuaisPorMesPorFilial(valoresMargemPorMesPorFilial, "MARGEM"),
|
||||||
percentualTotal: calcularPercentualTotal(totalMargem, "MARGEM"),
|
percentualTotal: calcularPercentualTotal(totalMargem, "MARGEM"),
|
||||||
isCalculado: true,
|
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)]">
|
<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
|
Descrição
|
||||||
</th>
|
</th>
|
||||||
{mesesDisponiveis.map((mes) => (
|
{mesesDisponiveis.map((mes) =>
|
||||||
<React.Fragment key={mes}>
|
(opcoesFiliais.length > 0 ? opcoesFiliais : ['']).map((filial: string) => (
|
||||||
<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">
|
<React.Fragment key={`${mes}-${filial || 'default'}`}>
|
||||||
{mes}
|
<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">
|
||||||
</th>
|
{mes}{filial && <><br/>
|
||||||
<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">
|
<span className="text-[10px] font-normal text-gray-600">Filial - {filial}</span></>}
|
||||||
%
|
</th>
|
||||||
</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">
|
||||||
</React.Fragment>
|
%{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">
|
<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
|
Total
|
||||||
</th>
|
</th>
|
||||||
|
|
@ -1266,6 +1407,7 @@ export default function Teste() {
|
||||||
getIndentStyle={getIndentStyle}
|
getIndentStyle={getIndentStyle}
|
||||||
renderCellContent={renderCellContent}
|
renderCellContent={renderCellContent}
|
||||||
mesesDisponiveis={mesesDisponiveis}
|
mesesDisponiveis={mesesDisponiveis}
|
||||||
|
opcoesFiliais={opcoesFiliais}
|
||||||
formatCurrency={formatCurrency}
|
formatCurrency={formatCurrency}
|
||||||
formatCurrencyWithColor={formatCurrencyWithColor}
|
formatCurrencyWithColor={formatCurrencyWithColor}
|
||||||
getFixedCellBackground={getFixedCellBackground}
|
getFixedCellBackground={getFixedCellBackground}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue