refactor: update fichaPontoPDF and processamento to enhance legend styling and accumulate saldo for all days, improving report accuracy
This commit is contained in:
@@ -372,29 +372,59 @@ export function adicionarLegenda(doc: jsPDF, yPosition: number): number {
|
||||
doc.text('LEGENDA', 15, yPosition);
|
||||
yPosition += 10;
|
||||
|
||||
const legendaData: Array<[string, string]> = [
|
||||
['Cor de Fundo - Branco', 'Dia normal'],
|
||||
['Cor de Fundo - Azul Claro', 'Dia com atestado médico'],
|
||||
['Cor de Fundo - Amarelo Claro', 'Dia com ausência aprovada'],
|
||||
['Cor de Fundo - Verde Claro', 'Dia abonado'],
|
||||
['Cor de Fundo - Cinza Claro', 'Dia não computado (dispensa/férias)'],
|
||||
['Cor de Fundo - Laranja Claro', 'Dia com inconsistência'],
|
||||
['Texto Verde', 'Saldo positivo / Registro marcado'],
|
||||
['Texto Vermelho', 'Saldo negativo / Registro não marcado'],
|
||||
['✓', 'Registro marcado'],
|
||||
['✗', 'Registro não marcado'],
|
||||
['⚠', 'Inconsistência detectada'],
|
||||
['🏥', 'Atestado médico'],
|
||||
['🚫', 'Ausência'],
|
||||
['📋', 'Licença'],
|
||||
['✅', 'Abonado'],
|
||||
['⏸', 'Não computado']
|
||||
// Corpo da legenda com cores aplicadas e siglas intuitivas
|
||||
const legendaData: Array<
|
||||
[
|
||||
string | { content: string; styles?: { fillColor?: number[]; textColor?: number[]; fontStyle?: string } },
|
||||
string
|
||||
]
|
||||
> = [
|
||||
[
|
||||
{ content: 'Fundo Branco (DN)', styles: { fillColor: [255, 255, 255] } },
|
||||
'Dia normal'
|
||||
],
|
||||
[
|
||||
{ content: 'Fundo Azul Claro (AT)', styles: { fillColor: [230, 240, 255] } },
|
||||
'Dia com atestado médico'
|
||||
],
|
||||
[
|
||||
{ content: 'Fundo Amarelo Claro (AUS)', styles: { fillColor: [255, 255, 230] } },
|
||||
'Dia com ausência aprovada'
|
||||
],
|
||||
[
|
||||
{ content: 'Fundo Verde Claro (ABO)', styles: { fillColor: [230, 255, 230] } },
|
||||
'Dia abonado'
|
||||
],
|
||||
[
|
||||
{ content: 'Fundo Cinza Claro (NC)', styles: { fillColor: [240, 240, 240] } },
|
||||
'Dia não computado (dispensa/férias)'
|
||||
],
|
||||
[
|
||||
{ content: 'Fundo Laranja Claro (INC)', styles: { fillColor: [255, 240, 230] } },
|
||||
'Dia com inconsistência'
|
||||
],
|
||||
[
|
||||
{ content: 'Texto Verde', styles: { textColor: [0, 128, 0], fontStyle: 'bold' } },
|
||||
'Saldo positivo / Registro marcado'
|
||||
],
|
||||
[
|
||||
{ content: 'Texto Vermelho', styles: { textColor: [200, 0, 0], fontStyle: 'bold' } },
|
||||
'Saldo negativo / Registro não marcado'
|
||||
],
|
||||
['RM', 'Registro marcado'],
|
||||
['RNM', 'Registro não marcado'],
|
||||
['INC', 'Inconsistência detectada'],
|
||||
['AT', 'Atestado médico'],
|
||||
['AUS', 'Ausência'],
|
||||
['LIC', 'Licença'],
|
||||
['ABO', 'Abonado'],
|
||||
['NC', 'Não computado']
|
||||
];
|
||||
|
||||
autoTable(doc, {
|
||||
startY: yPosition,
|
||||
head: [['Símbolo/Cor', 'Significado']],
|
||||
body: legendaData,
|
||||
body: legendaData as unknown as Array<Array<string | { content: string; styles?: { fillColor?: number[]; textColor?: number[]; fontStyle?: string } }>>,
|
||||
theme: 'striped',
|
||||
headStyles: {
|
||||
fillColor: [60, 60, 60],
|
||||
@@ -410,7 +440,25 @@ export function adicionarLegenda(doc: jsPDF, yPosition: number): number {
|
||||
1: { cellWidth: 110 }
|
||||
},
|
||||
margin: { left: 15, right: 15 },
|
||||
styles: { cellPadding: 3 }
|
||||
styles: { cellPadding: 3 },
|
||||
didParseCell: (data) => {
|
||||
// aplicar estilos de cor/texto definidos nas células da primeira coluna
|
||||
if (data.section === 'body' && data.column.index === 0) {
|
||||
const raw = data.row.raw?.[0];
|
||||
if (raw && typeof raw === 'object' && 'styles' in raw && raw.styles) {
|
||||
const styles = raw.styles as { fillColor?: number[]; textColor?: number[]; fontStyle?: string };
|
||||
if (styles.fillColor) {
|
||||
data.cell.styles.fillColor = styles.fillColor;
|
||||
}
|
||||
if (styles.textColor) {
|
||||
data.cell.styles.textColor = styles.textColor;
|
||||
}
|
||||
if (styles.fontStyle) {
|
||||
data.cell.styles.fontStyle = styles.fontStyle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const finalYLegenda = (doc as JsPDFWithAutoTable).lastAutoTable?.finalY ?? yPosition + 10;
|
||||
@@ -446,3 +494,4 @@ export function adicionarRodape(doc: jsPDF): void {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -628,25 +628,34 @@ export async function processarDadosFichaPonto(
|
||||
}
|
||||
|
||||
// Calcular saldo acumulado para cada dia
|
||||
// Agora consideramos todos os dias que possuem saldo diário, inclusive
|
||||
// atestados, ausências e dias não computados, para que o resumo do período
|
||||
// reflita qualquer trabalho realizado e a carga horária esperada.
|
||||
let saldoAcumulado = 0;
|
||||
|
||||
for (const dia of diasProcessados) {
|
||||
if (dia.computado && dia.saldoDiario) {
|
||||
if (dia.saldoDiario) {
|
||||
saldoAcumulado += dia.saldoDiario.diferencaMinutos;
|
||||
}
|
||||
dia.saldoAcumulado = saldoAcumulado;
|
||||
}
|
||||
|
||||
// Calcular resumo com formatações
|
||||
const totalHorasTrabalhadas = diasProcessados
|
||||
.filter((d) => d.computado)
|
||||
.reduce((acc, d) => acc + (d.saldoDiario?.trabalhadoMinutos || 0), 0);
|
||||
const totalHorasEsperadas = diasProcessados
|
||||
.filter((d) => d.computado)
|
||||
.reduce((acc, d) => acc + (d.saldoDiario?.esperadoMinutos || 0), 0);
|
||||
const diferencaTotal = diasProcessados
|
||||
.filter((d) => d.computado)
|
||||
.reduce((acc, d) => acc + (d.saldoDiario?.diferencaMinutos || 0), 0);
|
||||
// Total de horas trabalhadas e esperadas passa a considerar todos os dias,
|
||||
// não apenas os marcados como "computados", para que trechos trabalhados
|
||||
// em dias de ausência/dispensa também apareçam no resumo.
|
||||
const totalHorasTrabalhadas = diasProcessados.reduce(
|
||||
(acc, d) => acc + (d.saldoDiario?.trabalhadoMinutos || 0),
|
||||
0
|
||||
);
|
||||
const totalHorasEsperadas = diasProcessados.reduce(
|
||||
(acc, d) => acc + (d.saldoDiario?.esperadoMinutos || 0),
|
||||
0
|
||||
);
|
||||
const diferencaTotal = diasProcessados.reduce(
|
||||
(acc, d) => acc + (d.saldoDiario?.diferencaMinutos || 0),
|
||||
0
|
||||
);
|
||||
const saldoPeriodo = diferencaTotal;
|
||||
const saldoFinal =
|
||||
diasProcessados.length > 0 ? diasProcessados[diasProcessados.length - 1]!.saldoAcumulado : 0;
|
||||
|
||||
@@ -85,3 +85,4 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -85,3 +85,4 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user