import { v } from "convex/values"; import { mutation, query, QueryCtx, MutationCtx } from "./_generated/server"; import { Doc, Id } from "./_generated/dataModel"; /** * 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; }, });