From 414ae8526421940ee6a5952744d01bf3a16f505c Mon Sep 17 00:00:00 2001 From: deyvisonwanderley Date: Mon, 22 Dec 2025 17:17:23 -0300 Subject: [PATCH] feat: improve vacation status update logic to include user information when status is set to 'Cancelado_RH' and refactor work hour calculation to handle multiple entries and exits more effectively --- packages/backend/convex/ferias.ts | 9 ++- packages/backend/convex/pontos.ts | 97 ++++++++++--------------------- 2 files changed, 39 insertions(+), 67 deletions(-) diff --git a/packages/backend/convex/ferias.ts b/packages/backend/convex/ferias.ts index 862fa1a..78d5887 100644 --- a/packages/backend/convex/ferias.ts +++ b/packages/backend/convex/ferias.ts @@ -821,8 +821,13 @@ export const atualizarStatus = mutation({ throw new Error('Período de férias não encontrado'); } - // Atualizar status e histórico - const acao = `Status alterado para ${args.novoStatus}`; + // Buscar usuário que está alterando o status para incluir na mensagem quando for Cancelado_RH + let acao = `Status alterado para ${args.novoStatus}`; + if (args.novoStatus === 'Cancelado_RH') { + const usuarioRH = await ctx.db.get(args.usuarioId); + const nomeUsuario = usuarioRH?.nome || 'Usuário Desconhecido'; + acao = `Status alterado para Cancelado_RH por ${nomeUsuario}`; + } const updateData: { status: typeof args.novoStatus; diff --git a/packages/backend/convex/pontos.ts b/packages/backend/convex/pontos.ts index 332a0b0..63638b2 100644 --- a/packages/backend/convex/pontos.ts +++ b/packages/backend/convex/pontos.ts @@ -1400,78 +1400,45 @@ function calcularHorasTrabalhadas( return minutosA - minutosB; }); - // Procurar registros principais - const entrada = registrosOrdenados.find((r) => r.tipo === 'entrada'); - const saidaAlmoco = registrosOrdenados.find((r) => r.tipo === 'saida_almoco'); - const retornoAlmoco = registrosOrdenados.find((r) => r.tipo === 'retorno_almoco'); - const saida = registrosOrdenados.find((r) => r.tipo === 'saida'); + let totalMinutos = 0; + let entradaPendente: { hora: number; minuto: number } | null = null; - // Caso 1: Tem entrada e saída completas - if (entrada && saida) { - const minutosEntrada = entrada.hora * 60 + entrada.minuto; - const minutosSaida = saida.hora * 60 + saida.minuto; + // Processar registros sequencialmente para capturar todos os períodos de trabalho + // Isso permite calcular múltiplas entradas/saídas no mesmo dia + for (const registro of registrosOrdenados) { + const minutosRegistro = registro.hora * 60 + registro.minuto; - // Caso 1.1: Tem intervalo de almoço completo (saída almoço + retorno almoço) - if (saidaAlmoco && retornoAlmoco) { - const minutosSaidaAlmoco = saidaAlmoco.hora * 60 + saidaAlmoco.minuto; - const minutosRetornoAlmoco = retornoAlmoco.hora * 60 + retornoAlmoco.minuto; - - // Validar ordem lógica - if ( - minutosSaidaAlmoco > minutosEntrada && - minutosRetornoAlmoco > minutosSaidaAlmoco && - minutosSaida > minutosRetornoAlmoco - ) { - const horasManha = minutosSaidaAlmoco - minutosEntrada; - const horasTarde = minutosSaida - minutosRetornoAlmoco; - return horasManha + horasTarde; + if (registro.tipo === 'entrada') { + // Se já havia uma entrada pendente sem saída, ignorar a anterior (inconsistência) + // e usar a nova entrada + entradaPendente = { hora: registro.hora, minuto: registro.minuto }; + } else if (registro.tipo === 'saida_almoco') { + // Se há entrada pendente, calcular período da manhã + if (entradaPendente) { + const minutosEntrada = entradaPendente.hora * 60 + entradaPendente.minuto; + if (minutosRegistro > minutosEntrada) { + totalMinutos += minutosRegistro - minutosEntrada; + } + // Limpar entrada pendente após saída almoço (aguardar retorno) + entradaPendente = null; } - } - - // Caso 1.2: Tem apenas saída almoço (sem retorno) - considerar apenas manhã - if (saidaAlmoco && !retornoAlmoco) { - const minutosSaidaAlmoco = saidaAlmoco.hora * 60 + saidaAlmoco.minuto; - if (minutosSaidaAlmoco > minutosEntrada) { - return minutosSaidaAlmoco - minutosEntrada; - } - } - - // Caso 1.3: Tem apenas retorno almoço (sem saída) - considerar apenas tarde - if (!saidaAlmoco && retornoAlmoco) { - const minutosRetornoAlmoco = retornoAlmoco.hora * 60 + retornoAlmoco.minuto; - if (minutosSaida > minutosRetornoAlmoco) { - return minutosSaida - minutosRetornoAlmoco; - } - } - - // Caso 1.4: Sem intervalo de almoço registrado - calcular direto - if (!saidaAlmoco && !retornoAlmoco) { - if (minutosSaida > minutosEntrada) { - return minutosSaida - minutosEntrada; + } else if (registro.tipo === 'retorno_almoco') { + // Marcar como nova entrada para período da tarde + entradaPendente = { hora: registro.hora, minuto: registro.minuto }; + } else if (registro.tipo === 'saida') { + // Se há entrada pendente (pode ser entrada inicial ou retorno almoço), calcular período + if (entradaPendente) { + const minutosEntrada = entradaPendente.hora * 60 + entradaPendente.minuto; + if (minutosRegistro > minutosEntrada) { + totalMinutos += minutosRegistro - minutosEntrada; + } + // Limpar entrada pendente após saída + entradaPendente = null; } } } - // Caso 2: Tem apenas entrada (sem saída) - retornar 0 (dia incompleto) - if (entrada && !saida) { - // Se tiver saída almoço, considerar até a saída almoço - if (saidaAlmoco) { - const minutosEntrada = entrada.hora * 60 + entrada.minuto; - const minutosSaidaAlmoco = saidaAlmoco.hora * 60 + saidaAlmoco.minuto; - if (minutosSaidaAlmoco > minutosEntrada) { - return minutosSaidaAlmoco - minutosEntrada; - } - } - return 0; - } - - // Caso 3: Tem apenas saída (sem entrada) - inconsistência, retornar 0 - if (saida && !entrada) { - return 0; - } - - // Caso 4: Não tem entrada nem saída - retornar 0 - return 0; + return totalMinutos; } /**