Files
sgse-app/packages/backend/convex/setores.ts
killer-cf 6128c20da0 feat: implement sub-steps management in workflow editor
- Added functionality for creating, updating, and deleting sub-steps within the workflow editor.
- Introduced a modal for adding new sub-steps, including fields for name and description.
- Enhanced the UI to display sub-steps with status indicators and options for updating their status.
- Updated navigation links to reflect changes in the workflow structure, ensuring consistency across the application.
- Refactored related components to accommodate the new sub-steps feature, improving overall workflow management.
2025-11-25 14:14:43 -03:00

319 lines
7.6 KiB
TypeScript

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;
}
});