import { query, mutation } from './_generated/server'; import { v } from 'convex/values'; import { getCurrentUserFunction } from './auth'; /** * Listar todos os setores */ export const list = query({ args: {}, returns: v.array( v.object({ _id: v.id('setores'), _creationTime: v.number(), nome: v.string(), sigla: v.string(), criadoPor: v.id('usuarios'), createdAt: v.number() }) ), handler: async (ctx) => { const setores = await ctx.db.query('setores').order('asc').collect(); return setores; } }); /** * Obter um setor pelo ID */ export const getById = query({ args: { id: v.id('setores') }, returns: v.union( v.object({ _id: v.id('setores'), _creationTime: v.number(), nome: v.string(), sigla: v.string(), criadoPor: v.id('usuarios'), createdAt: v.number() }), v.null() ), handler: async (ctx, args) => { const setor = await ctx.db.get(args.id); return setor; } }); /** * Criar um novo setor */ export const create = mutation({ args: { nome: v.string(), sigla: v.string() }, returns: v.id('setores'), handler: async (ctx, args) => { const usuario = await getCurrentUserFunction(ctx); if (!usuario) { throw new Error('Usuário não autenticado'); } // Verificar se já existe setor com mesmo nome ou sigla const existenteNome = await ctx.db .query('setores') .withIndex('by_nome', (q) => q.eq('nome', args.nome)) .first(); if (existenteNome) { throw new Error('Já existe um setor com este nome'); } const existenteSigla = await ctx.db .query('setores') .withIndex('by_sigla', (q) => q.eq('sigla', args.sigla)) .first(); if (existenteSigla) { throw new Error('Já existe um setor com esta sigla'); } const setorId = await ctx.db.insert('setores', { nome: args.nome, sigla: args.sigla.toUpperCase(), criadoPor: usuario._id, createdAt: Date.now() }); return setorId; } }); /** * Atualizar um setor existente */ export const update = mutation({ args: { id: v.id('setores'), nome: v.string(), sigla: v.string() }, returns: v.null(), handler: async (ctx, args) => { const usuario = await getCurrentUserFunction(ctx); if (!usuario) { throw new Error('Usuário não autenticado'); } const setor = await ctx.db.get(args.id); if (!setor) { throw new Error('Setor não encontrado'); } // Verificar se já existe outro setor com mesmo nome const existenteNome = await ctx.db .query('setores') .withIndex('by_nome', (q) => q.eq('nome', args.nome)) .first(); if (existenteNome && existenteNome._id !== args.id) { throw new Error('Já existe um setor com este nome'); } // Verificar se já existe outro setor com mesma sigla const existenteSigla = await ctx.db .query('setores') .withIndex('by_sigla', (q) => q.eq('sigla', args.sigla)) .first(); if (existenteSigla && existenteSigla._id !== args.id) { throw new Error('Já existe um setor com esta sigla'); } await ctx.db.patch(args.id, { nome: args.nome, sigla: args.sigla.toUpperCase() }); return null; } }); /** * Obter funcionários de um setor específico */ export const getFuncionariosBySetor = query({ args: { setorId: v.id('setores') }, returns: v.array( v.object({ _id: v.id('funcionarios'), _creationTime: v.number(), nome: v.string(), matricula: v.optional(v.string()), email: v.string(), cpf: v.string() }) ), handler: async (ctx, args) => { // Buscar todas as relações funcionarioSetores para este setor const funcionarioSetores = await ctx.db .query('funcionarioSetores') .withIndex('by_setorId', (q) => q.eq('setorId', args.setorId)) .collect(); // Buscar os funcionários correspondentes const funcionarios = []; for (const relacao of funcionarioSetores) { const funcionario = await ctx.db.get(relacao.funcionarioId); if (funcionario) { funcionarios.push({ _id: funcionario._id, _creationTime: funcionario._creationTime, nome: funcionario.nome, matricula: funcionario.matricula, email: funcionario.email, cpf: funcionario.cpf }); } } return funcionarios; } }); /** * Obter setores de um funcionário */ export const getSetoresByFuncionario = query({ args: { funcionarioId: v.id('funcionarios') }, returns: v.array( v.object({ _id: v.id('setores'), _creationTime: v.number(), nome: v.string(), sigla: v.string(), criadoPor: v.id('usuarios'), createdAt: v.number() }) ), handler: async (ctx, args) => { // Buscar todas as relações funcionarioSetores para este funcionário const funcionarioSetores = await ctx.db .query('funcionarioSetores') .withIndex('by_funcionarioId', (q) => q.eq('funcionarioId', args.funcionarioId)) .collect(); // Buscar os setores correspondentes const setores = []; for (const relacao of funcionarioSetores) { const setor = await ctx.db.get(relacao.setorId); if (setor) { setores.push(setor); } } return setores; } }); /** * Atualizar setores de um funcionário */ export const atualizarSetoresFuncionario = mutation({ args: { funcionarioId: v.id('funcionarios'), setorIds: v.array(v.id('setores')) }, returns: v.null(), handler: async (ctx, args) => { const usuario = await getCurrentUserFunction(ctx); if (!usuario) { throw new Error('Usuário não autenticado'); } // Verificar se o funcionário existe const funcionario = await ctx.db.get(args.funcionarioId); if (!funcionario) { throw new Error('Funcionário não encontrado'); } // Verificar se todos os setores existem for (const setorId of args.setorIds) { const setor = await ctx.db.get(setorId); if (!setor) { throw new Error(`Setor ${setorId} não encontrado`); } } // Remover todas as relações existentes do funcionário const funcionarioSetoresExistentes = await ctx.db .query('funcionarioSetores') .withIndex('by_funcionarioId', (q) => q.eq('funcionarioId', args.funcionarioId)) .collect(); for (const relacao of funcionarioSetoresExistentes) { await ctx.db.delete(relacao._id); } // Criar novas relações para os setores selecionados const now = Date.now(); for (const setorId of args.setorIds) { // Verificar se já existe relação (evitar duplicatas) const existe = await ctx.db .query('funcionarioSetores') .withIndex('by_funcionarioId_and_setorId', (q) => q.eq('funcionarioId', args.funcionarioId).eq('setorId', setorId) ) .first(); if (!existe) { await ctx.db.insert('funcionarioSetores', { funcionarioId: args.funcionarioId, setorId, createdAt: now }); } } return null; } }); /** * Excluir um setor */ export const remove = mutation({ args: { id: v.id('setores') }, returns: v.null(), handler: async (ctx, args) => { const usuario = await getCurrentUserFunction(ctx); if (!usuario) { throw new Error('Usuário não autenticado'); } const setor = await ctx.db.get(args.id); if (!setor) { throw new Error('Setor não encontrado'); } // Verificar se há funcionários vinculados const funcionariosVinculados = await ctx.db .query('funcionarioSetores') .withIndex('by_setorId', (q) => q.eq('setorId', args.id)) .first(); if (funcionariosVinculados) { throw new Error('Não é possível excluir um setor com funcionários vinculados'); } // Verificar se há passos de fluxo vinculados const passosVinculados = await ctx.db .query('flowSteps') .collect(); const temPassosVinculados = passosVinculados.some((p) => p.setorId === args.id); if (temPassosVinculados) { throw new Error('Não é possível excluir um setor vinculado a passos de fluxo'); } await ctx.db.delete(args.id); return null; } });