feat: enhance Banco de Horas management with new reporting features, including adjustments and inconsistencies tracking, advanced filters, and Excel export functionality

This commit is contained in:
2025-12-06 09:32:55 -03:00
parent 72450d1f28
commit aec3201410
14 changed files with 4730 additions and 22 deletions

View File

@@ -2,6 +2,7 @@ import { v } from 'convex/values';
import { mutation, query } from './_generated/server';
import type { QueryCtx, MutationCtx } from './_generated/server';
import { api } from './_generated/api';
import { internal } from './_generated/api';
import { Id, Doc } from './_generated/dataModel';
import { parseLocalDate, formatarDataBR } from './utils/datas';
import { getCurrentUserFunction } from './auth';
@@ -267,6 +268,36 @@ export const contarPendentesGestor = query({
}
});
// Helper: Recalcular banco de horas em um período
async function recalcularBancoHorasPeriodo(
ctx: MutationCtx,
funcionarioId: Id<'funcionarios'>,
dataInicio: string,
dataFim: string
): Promise<void> {
// Gerar todas as datas do período
const dataInicioObj = new Date(dataInicio);
const dataFimObj = new Date(dataFim);
const datas: string[] = [];
const dataAtual = new Date(dataInicioObj);
while (dataAtual <= dataFimObj) {
const ano = dataAtual.getFullYear();
const mes = String(dataAtual.getMonth() + 1).padStart(2, '0');
const dia = String(dataAtual.getDate()).padStart(2, '0');
datas.push(`${ano}-${mes}-${dia}`);
dataAtual.setDate(dataAtual.getDate() + 1);
}
// Recalcular para cada data usando a mutation interna (agendar para execução assíncrona)
for (let i = 0; i < datas.length; i++) {
await ctx.scheduler.runAfter(i * 100, internal.pontos.recalcularBancoHorasData, {
funcionarioId,
data: datas[i]!
});
}
}
// Helper: Verificar se há sobreposição de datas
function verificarSobreposicao(
inicio1: string,
@@ -641,6 +672,9 @@ export const aprovar = mutation({
}
}
// Recalcular banco de horas para todas as datas do período da ausência aprovada
await recalcularBancoHorasPeriodo(ctx, solicitacao.funcionarioId, solicitacao.dataInicio, solicitacao.dataFim);
return null;
}
});