import { v } from 'convex/values'; import type { Id } from './_generated/dataModel'; import { type MutationCtx, query } from './_generated/server'; /** * Helper function para registrar atividades no sistema * Use em todas as mutations que modificam dados */ export async function registrarAtividade( ctx: MutationCtx, usuarioId: Id<'usuarios'>, acao: string, recurso: string, detalhes?: string, recursoId?: string ) { await ctx.db.insert('logsAtividades', { usuarioId, acao, recurso, recursoId, detalhes, timestamp: Date.now() }); } /** * Lista atividades com filtros */ export const listarAtividades = query({ args: { usuarioId: v.optional(v.id('usuarios')), acao: v.optional(v.string()), recurso: v.optional(v.string()), dataInicio: v.optional(v.number()), dataFim: v.optional(v.number()), limite: v.optional(v.number()) }, handler: async (ctx, args) => { let atividades; if (args.usuarioId) { atividades = await ctx.db .query('logsAtividades') .withIndex('by_usuario', (q) => q.eq('usuarioId', args.usuarioId!)) .order('desc') .take(args.limite || 100); } else if (args.acao) { atividades = await ctx.db .query('logsAtividades') .withIndex('by_acao', (q) => q.eq('acao', args.acao!)) .order('desc') .take(args.limite || 100); } else if (args.recurso) { atividades = await ctx.db .query('logsAtividades') .withIndex('by_recurso', (q) => q.eq('recurso', args.recurso!)) .order('desc') .take(args.limite || 100); } else { atividades = await ctx.db .query('logsAtividades') .withIndex('by_timestamp') .order('desc') .take(args.limite || 100); } // Filtrar por range de datas se fornecido if (args.dataInicio || args.dataFim) { atividades = atividades.filter((log) => { if (args.dataInicio && log.timestamp < args.dataInicio) return false; if (args.dataFim && log.timestamp > args.dataFim) return false; return true; }); } // Buscar informações dos usuários const atividadesComUsuarios = await Promise.all( atividades.map(async (atividade) => { const usuario = await ctx.db.get(atividade.usuarioId); let matricula = 'N/A'; if (usuario?.funcionarioId) { const funcionario = await ctx.db.get(usuario.funcionarioId); matricula = funcionario?.matricula || 'N/A'; } return { ...atividade, usuarioNome: usuario?.nome || 'Usuário Desconhecido', usuarioMatricula: matricula }; }) ); return atividadesComUsuarios; } }); /** * Obtém estatísticas de atividades */ export const obterEstatisticasAtividades = query({ args: { periodo: v.optional(v.number()) // dias (ex: 7, 30) }, handler: async (ctx, args) => { const periodo = args.periodo || 30; const dataInicio = Date.now() - periodo * 24 * 60 * 60 * 1000; const atividades = await ctx.db .query('logsAtividades') .withIndex('by_timestamp') .filter((q) => q.gte(q.field('timestamp'), dataInicio)) .collect(); // Agrupar por ação const porAcao: Record = {}; atividades.forEach((ativ) => { porAcao[ativ.acao] = (porAcao[ativ.acao] || 0) + 1; }); // Agrupar por recurso const porRecurso: Record = {}; atividades.forEach((ativ) => { porRecurso[ativ.recurso] = (porRecurso[ativ.recurso] || 0) + 1; }); // Agrupar por dia const porDia: Record = {}; atividades.forEach((ativ) => { const data = new Date(ativ.timestamp); const dia = data.toISOString().split('T')[0]; porDia[dia] = (porDia[dia] || 0) + 1; }); return { total: atividades.length, porAcao, porRecurso, porDia }; } }); /** * Obtém histórico de atividades de um recurso específico */ export const obterHistoricoRecurso = query({ args: { recurso: v.string(), recursoId: v.string() }, handler: async (ctx, args) => { const atividades = await ctx.db .query('logsAtividades') .withIndex('by_recurso_id', (q) => q.eq('recurso', args.recurso).eq('recursoId', args.recursoId) ) .order('desc') .collect(); // Buscar informações dos usuários const atividadesComUsuarios = await Promise.all( atividades.map(async (atividade) => { const usuario = await ctx.db.get(atividade.usuarioId); let matricula = 'N/A'; if (usuario?.funcionarioId) { const funcionario = await ctx.db.get(usuario.funcionarioId); matricula = funcionario?.matricula || 'N/A'; } return { ...atividade, usuarioNome: usuario?.nome || 'Usuário Desconhecido', usuarioMatricula: matricula }; }) ); return atividadesComUsuarios; } });