feat: implement error handling and logging in server hooks to capture and notify on 404 and 500 errors, enhancing server reliability and monitoring
This commit is contained in:
@@ -2,6 +2,8 @@ import { v } from 'convex/values';
|
||||
import { mutation, query, internalMutation } from './_generated/server';
|
||||
import { internal } from './_generated/api';
|
||||
import { Id, Doc } from './_generated/dataModel';
|
||||
import { verificarLicencaAtiva } from './atestadosLicencas';
|
||||
import { getCurrentUserFunction } from './auth';
|
||||
|
||||
// Validador para períodos
|
||||
const periodoValidator = v.object({
|
||||
@@ -46,7 +48,7 @@ function agruparPorSolicitacao(registros: Array<Doc<'ferias'>>): Array<{
|
||||
grupos.get(chave)!.push(registro);
|
||||
}
|
||||
|
||||
return Array.from(grupos.entries()).map(([_, periodos]) => {
|
||||
return Array.from(grupos.entries()).map(([, periodos]) => {
|
||||
// Ordenar por data de criação para manter ordem
|
||||
periodos.sort((a, b) => a._creationTime - b._creationTime);
|
||||
|
||||
@@ -819,7 +821,15 @@ export const atualizarStatusTodosFuncionarios = internalMutation({
|
||||
}
|
||||
}
|
||||
|
||||
const novoStatus = emFerias ? 'em_ferias' : 'ativo';
|
||||
// Determinar o status: férias tem prioridade sobre licença
|
||||
let novoStatus: 'ativo' | 'em_ferias' | 'em_licenca';
|
||||
if (emFerias) {
|
||||
novoStatus = 'em_ferias';
|
||||
} else {
|
||||
// Se não está em férias, verificar se está em licença
|
||||
const emLicenca = await verificarLicencaAtiva(ctx, func._id, hoje);
|
||||
novoStatus = emLicenca ? 'em_licenca' : 'ativo';
|
||||
}
|
||||
|
||||
if (func.statusFerias !== novoStatus) {
|
||||
await ctx.db.patch(func._id, { statusFerias: novoStatus });
|
||||
@@ -829,3 +839,142 @@ export const atualizarStatusTodosFuncionarios = internalMutation({
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Internal Mutation: Atualizar status de um funcionário específico
|
||||
export const atualizarStatusFuncionario = internalMutation({
|
||||
args: {
|
||||
funcionarioId: v.id('funcionarios')
|
||||
},
|
||||
returns: v.null(),
|
||||
handler: async (ctx, args) => {
|
||||
const func = await ctx.db.get(args.funcionarioId);
|
||||
if (!func) return null;
|
||||
|
||||
const hoje = new Date();
|
||||
hoje.setHours(0, 0, 0, 0);
|
||||
|
||||
// Buscar todos os registros de férias que podem estar em férias
|
||||
const feriasAprovadas = await ctx.db
|
||||
.query('ferias')
|
||||
.withIndex('by_funcionario_and_status', (q) =>
|
||||
q.eq('funcionarioId', func._id).eq('status', 'aprovado')
|
||||
)
|
||||
.collect();
|
||||
|
||||
const feriasAjustadas = await ctx.db
|
||||
.query('ferias')
|
||||
.withIndex('by_funcionario_and_status', (q) =>
|
||||
q.eq('funcionarioId', func._id).eq('status', 'data_ajustada_aprovada')
|
||||
)
|
||||
.collect();
|
||||
|
||||
const feriasEmFerias = await ctx.db
|
||||
.query('ferias')
|
||||
.withIndex('by_funcionario_and_status', (q) =>
|
||||
q.eq('funcionarioId', func._id).eq('status', 'EmFérias')
|
||||
)
|
||||
.collect();
|
||||
|
||||
const idsAprovados = new Set(feriasAprovadas.map((f) => f._id));
|
||||
const idsAjustados = new Set(feriasAjustadas.map((f) => f._id));
|
||||
const statusAnteriorPorId = new Map<Id<'ferias'>, 'aprovado' | 'data_ajustada_aprovada'>();
|
||||
|
||||
for (const ferias of feriasEmFerias) {
|
||||
if (ferias.historicoAlteracoes && ferias.historicoAlteracoes.length > 0) {
|
||||
const historico = ferias.historicoAlteracoes;
|
||||
for (let i = historico.length - 1; i >= 0; i--) {
|
||||
const entrada = historico[i];
|
||||
if (entrada.acao.includes('Aprovado') || entrada.acao.includes('aprovado')) {
|
||||
statusAnteriorPorId.set(ferias._id, 'aprovado');
|
||||
break;
|
||||
} else if (entrada.acao.includes('Data ajustada') || entrada.acao.includes('ajustada')) {
|
||||
statusAnteriorPorId.set(ferias._id, 'data_ajustada_aprovada');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!statusAnteriorPorId.has(ferias._id)) {
|
||||
statusAnteriorPorId.set(ferias._id, 'aprovado');
|
||||
}
|
||||
}
|
||||
|
||||
const todasFerias = [...feriasAprovadas, ...feriasAjustadas, ...feriasEmFerias];
|
||||
|
||||
let emFerias = false;
|
||||
for (const ferias of todasFerias) {
|
||||
const inicio = new Date(ferias.dataInicio);
|
||||
const fim = new Date(ferias.dataFim);
|
||||
inicio.setHours(0, 0, 0, 0);
|
||||
fim.setHours(23, 59, 59, 999);
|
||||
|
||||
if (hoje >= inicio && hoje <= fim) {
|
||||
emFerias = true;
|
||||
|
||||
if (ferias.status !== 'EmFérias') {
|
||||
await ctx.db.patch(ferias._id, {
|
||||
status: 'EmFérias'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (ferias.status === 'EmFérias') {
|
||||
let statusAnterior: 'aprovado' | 'data_ajustada_aprovada';
|
||||
|
||||
if (idsAprovados.has(ferias._id)) {
|
||||
statusAnterior = 'aprovado';
|
||||
} else if (idsAjustados.has(ferias._id)) {
|
||||
statusAnterior = 'data_ajustada_aprovada';
|
||||
} else {
|
||||
statusAnterior = statusAnteriorPorId.get(ferias._id) || 'aprovado';
|
||||
}
|
||||
|
||||
await ctx.db.patch(ferias._id, {
|
||||
status: statusAnterior
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determinar o status: férias tem prioridade sobre licença
|
||||
let novoStatus: 'ativo' | 'em_ferias' | 'em_licenca';
|
||||
if (emFerias) {
|
||||
novoStatus = 'em_ferias';
|
||||
console.log(`[atualizarStatusFuncionario] Funcionário ${func._id} está em férias`);
|
||||
} else {
|
||||
// Se não está em férias, verificar se está em licença
|
||||
const emLicenca = await verificarLicencaAtiva(ctx, func._id, hoje);
|
||||
novoStatus = emLicenca ? 'em_licenca' : 'ativo';
|
||||
console.log(
|
||||
`[atualizarStatusFuncionario] Funcionário ${func._id}: emLicenca=${emLicenca}, novoStatus=${novoStatus}`
|
||||
);
|
||||
}
|
||||
|
||||
if (func.statusFerias !== novoStatus) {
|
||||
console.log(
|
||||
`[atualizarStatusFuncionario] Atualizando status de ${func.statusFerias} para ${novoStatus}`
|
||||
);
|
||||
await ctx.db.patch(func._id, { statusFerias: novoStatus });
|
||||
} else {
|
||||
console.log(`[atualizarStatusFuncionario] Status já está correto: ${novoStatus}`);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Mutation pública para atualizar status do funcionário atual (útil para debug/teste)
|
||||
export const atualizarMeuStatus = mutation({
|
||||
args: {},
|
||||
returns: v.null(),
|
||||
handler: async (ctx) => {
|
||||
const usuario = await getCurrentUserFunction(ctx);
|
||||
if (!usuario || !usuario.funcionarioId) {
|
||||
throw new Error('Usuário não encontrado ou não possui funcionário associado');
|
||||
}
|
||||
|
||||
await ctx.runMutation(internal.ferias.atualizarStatusFuncionario, {
|
||||
funcionarioId: usuario.funcionarioId
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user