refactor: enhance saldo calculation and display in registro-pontos page
- Updated the logic for calculating daily and period saldo differences to ensure accuracy by directly computing the difference between worked and expected hours. - Improved the display of saldo differences in the UI, including formatting adjustments for better readability. - Refactored the rendering logic to ensure consistent styling and user experience across the registro-pontos page.
This commit is contained in:
@@ -34,7 +34,7 @@
|
||||
? 'bg-red-50 border-red-200 text-red-700 dark:bg-red-900/20 dark:border-red-800 dark:text-red-400'
|
||||
: 'bg-green-50 border-green-200 text-green-700 dark:bg-green-900/20 dark:border-green-800 dark:text-green-400'
|
||||
}">
|
||||
<span class="font-bold">+{trabalhado.horas}h {trabalhado.minutos}min</span>
|
||||
<span class="font-bold text-green-600 dark:text-green-400">+{trabalhado.horas}h {trabalhado.minutos}min</span>
|
||||
<span class="text-base-content/50">/</span>
|
||||
<span class={isNegativo ? 'text-red-600 dark:text-red-400' : 'text-green-600 dark:text-green-400'}>
|
||||
{sinalDiferenca}{diferenca.horas}h {diferenca.minutos}min
|
||||
|
||||
@@ -421,11 +421,11 @@
|
||||
};
|
||||
} else {
|
||||
// Fallback: usar cálculo simples se não houver configuração
|
||||
const primeiroRegistro = grupoData.registros[0];
|
||||
if (primeiroRegistro && 'saldoDiario' in primeiroRegistro && primeiroRegistro.saldoDiario) {
|
||||
grupoData.saldoDiario = primeiroRegistro.saldoDiario;
|
||||
} else {
|
||||
grupoData.saldoDiario = calcularSaldoDiario(grupoData.registros);
|
||||
const primeiroRegistro = grupoData.registros[0];
|
||||
if (primeiroRegistro && 'saldoDiario' in primeiroRegistro && primeiroRegistro.saldoDiario) {
|
||||
grupoData.saldoDiario = primeiroRegistro.saldoDiario;
|
||||
} else {
|
||||
grupoData.saldoDiario = calcularSaldoDiario(grupoData.registros);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1496,9 +1496,12 @@
|
||||
saldoDiarioTotalDiferencaMinutos = -saldoDiarioTotalEsperadoMinutos; // Diferença negativa (0 - esperado)
|
||||
}
|
||||
|
||||
// Calcular diferença corretamente: trabalhado - esperado (não somar diferenças dos pares)
|
||||
const diferencaDiariaCorrigida = saldoDiarioTotalTrabalhadoMinutos - saldoDiarioTotalEsperadoMinutos;
|
||||
|
||||
// Armazenar saldo diário completo (usado no resumo do banco de horas)
|
||||
saldosDiariosPorData[data] = {
|
||||
diferencaMinutos: saldoDiarioTotalDiferencaMinutos,
|
||||
diferencaMinutos: diferencaDiariaCorrigida,
|
||||
trabalhadoMinutos: saldoDiarioTotalTrabalhadoMinutos,
|
||||
esperadoMinutos: saldoDiarioTotalEsperadoMinutos
|
||||
};
|
||||
@@ -1646,9 +1649,9 @@
|
||||
// Se não há tempo trabalhado, decrementar o tempo esperado completo
|
||||
if (saldoEsperado.trabalhadoMinutos === 0) {
|
||||
saldoDiarioAcumuladoMinutos -= saldoEsperado.esperadoMinutos;
|
||||
} else {
|
||||
} else {
|
||||
saldoDiarioAcumuladoMinutos -= saldoEsperado.trabalhadoMinutos;
|
||||
}
|
||||
}
|
||||
paresProcessadosParaSaldo.add(chavePar);
|
||||
}
|
||||
|
||||
@@ -1664,7 +1667,7 @@
|
||||
// Marcar linha para aplicar cor no saldo
|
||||
if (trabalhouMaisQueEsperado) {
|
||||
linha._saldoPositivo = true; // Verde: trabalhou mais que o esperado
|
||||
} else {
|
||||
} else {
|
||||
linha._saldoNegativo = true; // Vermelho: ainda falta trabalhar
|
||||
}
|
||||
|
||||
@@ -1756,9 +1759,9 @@
|
||||
content: `0h 0min parcial | Saldo: ${sinalSaldo}${saldoAcumuladoHoras}h ${saldoAcumuladoMinutosResto}min`,
|
||||
rowSpan: 2 // retorno_almoco + saida
|
||||
});
|
||||
} else {
|
||||
linha.push('-');
|
||||
}
|
||||
} else {
|
||||
linha.push('-');
|
||||
}
|
||||
} else {
|
||||
// Há registros reais mas este par não foi marcado completamente
|
||||
// Verificar se é um par completamente não marcado
|
||||
@@ -1921,7 +1924,6 @@
|
||||
const cargaHorariaDiariaEsperadaMinutos = minutosPar1EsperadoAjustadoConfig + minutosPar2EsperadoAjustadoConfig;
|
||||
|
||||
// Calcular saldos do período selecionado baseado nos saldos diários calculados
|
||||
let saldoPeriodoDiferencaMinutos = 0;
|
||||
let saldoPeriodoTrabalhadoMinutos = 0;
|
||||
let diasComSaldoPositivo = 0;
|
||||
let diasComSaldoNegativo = 0;
|
||||
@@ -1930,12 +1932,14 @@
|
||||
if (sections.registrosPonto && Object.keys(saldosDiariosPorData).length > 0) {
|
||||
// Somar todos os saldos diários do período
|
||||
for (const saldo of Object.values(saldosDiariosPorData)) {
|
||||
saldoPeriodoDiferencaMinutos += saldo.diferencaMinutos;
|
||||
saldoPeriodoTrabalhadoMinutos += saldo.trabalhadoMinutos;
|
||||
|
||||
if (saldo.diferencaMinutos > 0) {
|
||||
// Calcular diferença diária corretamente: trabalhado - esperado
|
||||
const diferencaDiaria = saldo.trabalhadoMinutos - saldo.esperadoMinutos;
|
||||
|
||||
if (diferencaDiaria > 0) {
|
||||
diasComSaldoPositivo++;
|
||||
} else if (saldo.diferencaMinutos < 0) {
|
||||
} else if (diferencaDiaria < 0) {
|
||||
diasComSaldoNegativo++;
|
||||
}
|
||||
|
||||
@@ -1962,15 +1966,22 @@
|
||||
for (const regs of Object.values(registrosPorDataPeriodo)) {
|
||||
const saldoDiario = calcularSaldoDiario(regs);
|
||||
if (saldoDiario) {
|
||||
saldoPeriodoDiferencaMinutos += saldoDiario.saldoMinutos;
|
||||
saldoPeriodoTrabalhadoMinutos += saldoDiario.saldoMinutos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calcular saldo esperado do período: carga horária diária × número de dias
|
||||
// SEMPRE calcular diretamente, não somar saldos diários esperados (pode duplicar)
|
||||
const saldoPeriodoEsperadoMinutos = cargaHorariaDiariaEsperadaMinutos * totalDiasPeriodo;
|
||||
|
||||
// Calcular diferença do período corretamente: trabalhado - esperado (para "Saldo do Período Exibido")
|
||||
const saldoPeriodoDiferencaMinutos = saldoPeriodoTrabalhadoMinutos - saldoPeriodoEsperadoMinutos;
|
||||
|
||||
// Calcular diferença do período (trabalhado - esperado) para exibição na linha "Diferença do Período"
|
||||
// Negativo quando trabalhado < esperado (vermelho), positivo quando trabalhado > esperado (verde)
|
||||
const diferencaPeriodoTrabalhadoMenosEsperado = saldoPeriodoTrabalhadoMinutos - saldoPeriodoEsperadoMinutos;
|
||||
|
||||
// Calcular médias diárias
|
||||
const mediaDiariaTrabalhadaHoras = totalDiasPeriodo > 0 ? Math.floor(saldoPeriodoTrabalhadoMinutos / 60 / totalDiasPeriodo) : 0;
|
||||
const mediaDiariaTrabalhadaMinutos = totalDiasPeriodo > 0 ? Math.floor((saldoPeriodoTrabalhadoMinutos / totalDiasPeriodo) % 60) : 0;
|
||||
@@ -1994,11 +2005,19 @@
|
||||
const mediaDiariaEsperadaMinutos = totalEsperadoDiarioMinutos % 60;
|
||||
|
||||
// Formatar valores
|
||||
// Saldo do Período Exibido: diferença (trabalhado - esperado)
|
||||
const horasPeriodoDiferenca = Math.floor(Math.abs(saldoPeriodoDiferencaMinutos) / 60);
|
||||
const minutosPeriodoDiferenca = Math.abs(saldoPeriodoDiferencaMinutos) % 60;
|
||||
const sinalPeriodoDiferenca = saldoPeriodoDiferencaMinutos >= 0 ? '+' : '-';
|
||||
const saldoPeriodoDiferencaFormatado = `${sinalPeriodoDiferenca}${horasPeriodoDiferenca}h ${minutosPeriodoDiferenca}min`;
|
||||
|
||||
// Diferença do Período: trabalhado - esperado
|
||||
// Negativo quando trabalhado < esperado (vermelho), positivo quando trabalhado > esperado (verde)
|
||||
const horasDiferencaPeriodo = Math.floor(Math.abs(diferencaPeriodoTrabalhadoMenosEsperado) / 60);
|
||||
const minutosDiferencaPeriodo = Math.abs(diferencaPeriodoTrabalhadoMenosEsperado) % 60;
|
||||
const sinalDiferencaPeriodo = diferencaPeriodoTrabalhadoMenosEsperado >= 0 ? '+' : '-';
|
||||
const diferencaPeriodoFormatado = `${sinalDiferencaPeriodo}${horasDiferencaPeriodo}h ${minutosDiferencaPeriodo}min`;
|
||||
|
||||
const horasPeriodoTrabalhado = Math.floor(saldoPeriodoTrabalhadoMinutos / 60);
|
||||
const minutosPeriodoTrabalhado = saldoPeriodoTrabalhadoMinutos % 60;
|
||||
const saldoPeriodoTrabalhadoFormatado = `+${horasPeriodoTrabalhado}h ${minutosPeriodoTrabalhado}min`;
|
||||
@@ -2049,7 +2068,7 @@
|
||||
bancoHorasData.push(['', '']); // Linha separadora
|
||||
bancoHorasData.push(['Saldo Trabalhado do Período', saldoPeriodoTrabalhadoFormatado]);
|
||||
bancoHorasData.push(['Saldo Esperado do Período', saldoPeriodoEsperadoFormatado]);
|
||||
bancoHorasData.push(['Diferença do Período', saldoPeriodoDiferencaFormatado]);
|
||||
bancoHorasData.push(['Diferença do Período', diferencaPeriodoFormatado]);
|
||||
|
||||
// Adicionar estatísticas
|
||||
bancoHorasData.push(['', '']); // Linha separadora
|
||||
@@ -2105,11 +2124,14 @@
|
||||
}
|
||||
} else if (valor.includes('+') || campo.includes('Trabalhado') || campo.includes('Esperado')) {
|
||||
// Verde para valores positivos ou campos de trabalhado/esperado
|
||||
if (campo.includes('Diferença') && saldoPeriodoDiferencaMinutos < 0) {
|
||||
data.cell.styles.textColor = [200, 0, 0]; // Vermelho se diferença negativa
|
||||
data.cell.styles.fontStyle = 'bold';
|
||||
} else if (campo.includes('Diferença') && saldoPeriodoDiferencaMinutos > 0) {
|
||||
data.cell.styles.textColor = [0, 128, 0]; // Verde se diferença positiva
|
||||
if (campo.includes('Diferença do Período')) {
|
||||
// Diferença do Período: trabalhado - esperado
|
||||
// Negativo quando trabalhado < esperado (vermelho), positivo quando trabalhado > esperado (verde)
|
||||
if (diferencaPeriodoTrabalhadoMenosEsperado < 0) {
|
||||
data.cell.styles.textColor = [200, 0, 0]; // Vermelho quando trabalhado < esperado
|
||||
} else if (diferencaPeriodoTrabalhadoMenosEsperado > 0) {
|
||||
data.cell.styles.textColor = [0, 128, 0]; // Verde quando trabalhado > esperado
|
||||
}
|
||||
data.cell.styles.fontStyle = 'bold';
|
||||
} else if (campo.includes('Trabalhado') || campo.includes('Esperado')) {
|
||||
data.cell.styles.textColor = [0, 128, 0]; // Verde para trabalhado/esperado
|
||||
@@ -2226,6 +2248,20 @@
|
||||
theme: 'grid',
|
||||
headStyles: { fillColor: [41, 128, 185], fontStyle: 'bold' },
|
||||
styles: { fontSize: 9 },
|
||||
columnStyles: {
|
||||
0: { cellWidth: 30 }, // Data
|
||||
1: { cellWidth: 40 }, // Tipo
|
||||
2: { cellWidth: 50, cellPadding: { top: 2, bottom: 2, left: 2, right: 2 } }, // Detalhes - maior largura
|
||||
3: { cellWidth: 40 }, // Motivo
|
||||
4: { cellWidth: 'auto' }, // Observações
|
||||
},
|
||||
didParseCell: function(data) {
|
||||
// Permitir quebra de linha na coluna Detalhes (índice 2)
|
||||
if (data.column.index === 2) {
|
||||
data.cell.styles.overflow = 'linebreak';
|
||||
data.cell.styles.cellWidth = 50;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const lastPage = doc.getNumberOfPages();
|
||||
@@ -2985,8 +3021,8 @@
|
||||
? `${distanciaExcedenteKm} km além do permitido`
|
||||
: `${distanciaExcedenteMetros} metros além do permitido`;
|
||||
geofencingData.push(['Distância Excedente', excedenteTexto]);
|
||||
}
|
||||
}
|
||||
}
|
||||
geofencingData.push(['Status', statusTexto]);
|
||||
|
||||
autoTable(doc, {
|
||||
@@ -3759,14 +3795,14 @@
|
||||
<td class="whitespace-nowrap font-semibold text-sm">{dataFormatada}</td>
|
||||
<td class="whitespace-nowrap">
|
||||
<span class="badge badge-outline badge-sm font-medium text-xs">
|
||||
{config
|
||||
? getTipoRegistroLabel(registro.tipo, {
|
||||
nomeEntrada: config.nomeEntrada,
|
||||
nomeSaidaAlmoco: config.nomeSaidaAlmoco,
|
||||
nomeRetornoAlmoco: config.nomeRetornoAlmoco,
|
||||
nomeSaida: config.nomeSaida,
|
||||
})
|
||||
: getTipoRegistroLabel(registro.tipo)}
|
||||
{config
|
||||
? getTipoRegistroLabel(registro.tipo, {
|
||||
nomeEntrada: config.nomeEntrada,
|
||||
nomeSaidaAlmoco: config.nomeSaidaAlmoco,
|
||||
nomeRetornoAlmoco: config.nomeRetornoAlmoco,
|
||||
nomeSaida: config.nomeSaida,
|
||||
})
|
||||
: getTipoRegistroLabel(registro.tipo)}
|
||||
</span>
|
||||
</td>
|
||||
<td class="whitespace-nowrap font-mono text-sm font-medium">{formatarHoraPonto(registro.hora, registro.minuto)}</td>
|
||||
@@ -3784,7 +3820,7 @@
|
||||
{#if grupoData.saldoDiarioComparativo}
|
||||
<SaldoDiarioComparativoBadge saldo={grupoData.saldoDiarioComparativo} size="md" />
|
||||
{:else if grupoData.saldoDiario}
|
||||
<SaldoDiarioBadge saldo={grupoData.saldoDiario} size="md" />
|
||||
<SaldoDiarioBadge saldo={grupoData.saldoDiario} size="md" />
|
||||
{:else}
|
||||
<span class="badge badge-ghost badge-lg">-</span>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user