feat: Introduce structured table definitions in convex/tables for various entities and remove the todos example table.
This commit is contained in:
@@ -1,200 +1,198 @@
|
||||
import { mutation, query } from "./_generated/server";
|
||||
import { v } from "convex/values";
|
||||
import { situacaoContrato } from "./schema";
|
||||
import { getCurrentUserFunction } from "./auth";
|
||||
import { internal } from "./_generated/api";
|
||||
import { mutation, query } from './_generated/server';
|
||||
import { v } from 'convex/values';
|
||||
import { situacaoContrato } from './tables/contratos';
|
||||
import { getCurrentUserFunction } from './auth';
|
||||
import { internal } from './_generated/api';
|
||||
|
||||
export const listar = query({
|
||||
args: {
|
||||
responsavelId: v.optional(v.id("funcionarios")),
|
||||
dataInicio: v.optional(v.string()),
|
||||
dataFim: v.optional(v.string()),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
|
||||
recurso: "contratos",
|
||||
acao: "listar",
|
||||
});
|
||||
args: {
|
||||
responsavelId: v.optional(v.id('funcionarios')),
|
||||
dataInicio: v.optional(v.string()),
|
||||
dataFim: v.optional(v.string())
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
|
||||
recurso: 'contratos',
|
||||
acao: 'listar'
|
||||
});
|
||||
|
||||
let q = ctx.db.query("contratos");
|
||||
let q = ctx.db.query('contratos');
|
||||
|
||||
if (args.responsavelId) {
|
||||
q = q.withIndex("by_responsavel", (q) =>
|
||||
q.eq("responsavelId", args.responsavelId!)
|
||||
) as typeof q;
|
||||
}
|
||||
if (args.responsavelId) {
|
||||
q = q.withIndex('by_responsavel', (q) =>
|
||||
q.eq('responsavelId', args.responsavelId!)
|
||||
) as typeof q;
|
||||
}
|
||||
|
||||
const contratos = await q.collect();
|
||||
const contratos = await q.collect();
|
||||
|
||||
// Filtros em memória para datas (já que Convex não tem filtro de range nativo eficiente combinado com outros índices sem setup complexo)
|
||||
// Se o volume for muito grande, ideal seria criar índices específicos ou usar search.
|
||||
let resultado = contratos;
|
||||
// Filtros em memória para datas (já que Convex não tem filtro de range nativo eficiente combinado com outros índices sem setup complexo)
|
||||
// Se o volume for muito grande, ideal seria criar índices específicos ou usar search.
|
||||
let resultado = contratos;
|
||||
|
||||
if (args.dataInicio) {
|
||||
resultado = resultado.filter(
|
||||
(c) => c.dataInicioVigencia >= args.dataInicio!
|
||||
);
|
||||
}
|
||||
if (args.dataInicio) {
|
||||
resultado = resultado.filter((c) => c.dataInicioVigencia >= args.dataInicio!);
|
||||
}
|
||||
|
||||
if (args.dataFim) {
|
||||
resultado = resultado.filter((c) => c.dataFimVigencia <= args.dataFim!);
|
||||
}
|
||||
if (args.dataFim) {
|
||||
resultado = resultado.filter((c) => c.dataFimVigencia <= args.dataFim!);
|
||||
}
|
||||
|
||||
// Enriquecer com dados relacionados
|
||||
const contratosEnriquecidos = await Promise.all(
|
||||
resultado.map(async (c) => {
|
||||
const contratada = await ctx.db.get(c.contratadaId);
|
||||
const responsavel = await ctx.db.get(c.responsavelId);
|
||||
return {
|
||||
...c,
|
||||
contratada,
|
||||
responsavel,
|
||||
};
|
||||
})
|
||||
);
|
||||
// Enriquecer com dados relacionados
|
||||
const contratosEnriquecidos = await Promise.all(
|
||||
resultado.map(async (c) => {
|
||||
const contratada = await ctx.db.get(c.contratadaId);
|
||||
const responsavel = await ctx.db.get(c.responsavelId);
|
||||
return {
|
||||
...c,
|
||||
contratada,
|
||||
responsavel
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
return contratosEnriquecidos;
|
||||
},
|
||||
return contratosEnriquecidos;
|
||||
}
|
||||
});
|
||||
|
||||
export const obter = query({
|
||||
args: { id: v.id("contratos") },
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
|
||||
recurso: "contratos",
|
||||
acao: "ver",
|
||||
});
|
||||
const contrato = await ctx.db.get(args.id);
|
||||
if (!contrato) return null;
|
||||
args: { id: v.id('contratos') },
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
|
||||
recurso: 'contratos',
|
||||
acao: 'ver'
|
||||
});
|
||||
const contrato = await ctx.db.get(args.id);
|
||||
if (!contrato) return null;
|
||||
|
||||
const contratada = await ctx.db.get(contrato.contratadaId);
|
||||
const responsavel = await ctx.db.get(contrato.responsavelId);
|
||||
const contratada = await ctx.db.get(contrato.contratadaId);
|
||||
const responsavel = await ctx.db.get(contrato.responsavelId);
|
||||
|
||||
return {
|
||||
...contrato,
|
||||
contratada,
|
||||
responsavel,
|
||||
};
|
||||
},
|
||||
return {
|
||||
...contrato,
|
||||
contratada,
|
||||
responsavel
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
export const criar = mutation({
|
||||
args: {
|
||||
contratadaId: v.id("empresas"),
|
||||
objeto: v.string(),
|
||||
numeroNotaEmpenho: v.string(),
|
||||
responsavelId: v.id("funcionarios"),
|
||||
departamento: v.string(),
|
||||
situacao: situacaoContrato,
|
||||
numeroProcessoLicitatorio: v.string(),
|
||||
modalidade: v.string(),
|
||||
numeroContrato: v.string(),
|
||||
anoContrato: v.number(),
|
||||
dataInicioVigencia: v.string(),
|
||||
dataFimVigencia: v.string(),
|
||||
nomeFiscal: v.string(),
|
||||
valorTotal: v.string(),
|
||||
dataAditivoPrazo: v.optional(v.string()),
|
||||
diasAvisoVencimento: v.number(),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
|
||||
recurso: "contratos",
|
||||
acao: "criar",
|
||||
});
|
||||
args: {
|
||||
contratadaId: v.id('empresas'),
|
||||
objeto: v.string(),
|
||||
numeroNotaEmpenho: v.string(),
|
||||
responsavelId: v.id('funcionarios'),
|
||||
departamento: v.string(),
|
||||
situacao: situacaoContrato,
|
||||
numeroProcessoLicitatorio: v.string(),
|
||||
modalidade: v.string(),
|
||||
numeroContrato: v.string(),
|
||||
anoContrato: v.number(),
|
||||
dataInicioVigencia: v.string(),
|
||||
dataFimVigencia: v.string(),
|
||||
nomeFiscal: v.string(),
|
||||
valorTotal: v.string(),
|
||||
dataAditivoPrazo: v.optional(v.string()),
|
||||
diasAvisoVencimento: v.number()
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
|
||||
recurso: 'contratos',
|
||||
acao: 'criar'
|
||||
});
|
||||
|
||||
const usuario = await getCurrentUserFunction(ctx);
|
||||
if (!usuario) throw new Error("Não autenticado");
|
||||
const usuario = await getCurrentUserFunction(ctx);
|
||||
if (!usuario) throw new Error('Não autenticado');
|
||||
|
||||
const id = await ctx.db.insert("contratos", {
|
||||
...args,
|
||||
criadoPor: usuario._id,
|
||||
criadoEm: Date.now(),
|
||||
});
|
||||
const id = await ctx.db.insert('contratos', {
|
||||
...args,
|
||||
criadoPor: usuario._id,
|
||||
criadoEm: Date.now()
|
||||
});
|
||||
|
||||
return id;
|
||||
},
|
||||
return id;
|
||||
}
|
||||
});
|
||||
|
||||
export const editar = mutation({
|
||||
args: {
|
||||
id: v.id("contratos"),
|
||||
contratadaId: v.optional(v.id("empresas")),
|
||||
objeto: v.optional(v.string()),
|
||||
numeroNotaEmpenho: v.optional(v.string()),
|
||||
responsavelId: v.optional(v.id("funcionarios")),
|
||||
departamento: v.optional(v.string()),
|
||||
situacao: v.optional(situacaoContrato),
|
||||
numeroProcessoLicitatorio: v.optional(v.string()),
|
||||
modalidade: v.optional(v.string()),
|
||||
numeroContrato: v.optional(v.string()),
|
||||
anoContrato: v.optional(v.number()),
|
||||
dataInicioVigencia: v.optional(v.string()),
|
||||
dataFimVigencia: v.optional(v.string()),
|
||||
nomeFiscal: v.optional(v.string()),
|
||||
valorTotal: v.optional(v.string()),
|
||||
dataAditivoPrazo: v.optional(v.string()),
|
||||
diasAvisoVencimento: v.optional(v.number()),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
|
||||
recurso: "contratos",
|
||||
acao: "editar",
|
||||
});
|
||||
args: {
|
||||
id: v.id('contratos'),
|
||||
contratadaId: v.optional(v.id('empresas')),
|
||||
objeto: v.optional(v.string()),
|
||||
numeroNotaEmpenho: v.optional(v.string()),
|
||||
responsavelId: v.optional(v.id('funcionarios')),
|
||||
departamento: v.optional(v.string()),
|
||||
situacao: v.optional(situacaoContrato),
|
||||
numeroProcessoLicitatorio: v.optional(v.string()),
|
||||
modalidade: v.optional(v.string()),
|
||||
numeroContrato: v.optional(v.string()),
|
||||
anoContrato: v.optional(v.number()),
|
||||
dataInicioVigencia: v.optional(v.string()),
|
||||
dataFimVigencia: v.optional(v.string()),
|
||||
nomeFiscal: v.optional(v.string()),
|
||||
valorTotal: v.optional(v.string()),
|
||||
dataAditivoPrazo: v.optional(v.string()),
|
||||
diasAvisoVencimento: v.optional(v.number())
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
|
||||
recurso: 'contratos',
|
||||
acao: 'editar'
|
||||
});
|
||||
|
||||
const { id, ...campos } = args;
|
||||
const { id, ...campos } = args;
|
||||
|
||||
await ctx.db.patch(id, {
|
||||
...campos,
|
||||
atualizadoEm: Date.now(),
|
||||
});
|
||||
},
|
||||
await ctx.db.patch(id, {
|
||||
...campos,
|
||||
atualizadoEm: Date.now()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export const excluir = mutation({
|
||||
args: { id: v.id("contratos") },
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
|
||||
recurso: "contratos",
|
||||
acao: "excluir",
|
||||
});
|
||||
await ctx.db.delete(args.id);
|
||||
},
|
||||
args: { id: v.id('contratos') },
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.runQuery(internal.permissoesAcoes.assertPermissaoAcaoAtual, {
|
||||
recurso: 'contratos',
|
||||
acao: 'excluir'
|
||||
});
|
||||
await ctx.db.delete(args.id);
|
||||
}
|
||||
});
|
||||
|
||||
export const verificarVencimentos = query({
|
||||
args: {},
|
||||
handler: async (ctx) => {
|
||||
// Esta query pode ser usada por um componente de notificação ou cron job
|
||||
// Retorna contratos que estão próximos do vencimento baseados no diasAvisoVencimento
|
||||
args: {},
|
||||
handler: async (ctx) => {
|
||||
// Esta query pode ser usada por um componente de notificação ou cron job
|
||||
// Retorna contratos que estão próximos do vencimento baseados no diasAvisoVencimento
|
||||
|
||||
const hoje = new Date();
|
||||
const hojeStr = hoje.toISOString().split("T")[0];
|
||||
const hoje = new Date();
|
||||
const hojeStr = hoje.toISOString().split('T')[0];
|
||||
|
||||
// Buscar contratos ativos (em execução ou aguardando assinatura)
|
||||
const contratos = await ctx.db
|
||||
.query("contratos")
|
||||
.filter((q) =>
|
||||
q.or(
|
||||
q.eq(q.field("situacao"), "em_execucao"),
|
||||
q.eq(q.field("situacao"), "aguardando_assinatura")
|
||||
)
|
||||
)
|
||||
.collect();
|
||||
// Buscar contratos ativos (em execução ou aguardando assinatura)
|
||||
const contratos = await ctx.db
|
||||
.query('contratos')
|
||||
.filter((q) =>
|
||||
q.or(
|
||||
q.eq(q.field('situacao'), 'em_execucao'),
|
||||
q.eq(q.field('situacao'), 'aguardando_assinatura')
|
||||
)
|
||||
)
|
||||
.collect();
|
||||
|
||||
const proximosVencimento = contratos.filter((c) => {
|
||||
if (!c.dataFimVigencia) return false;
|
||||
const proximosVencimento = contratos.filter((c) => {
|
||||
if (!c.dataFimVigencia) return false;
|
||||
|
||||
const dataFim = new Date(c.dataFimVigencia);
|
||||
const dataAviso = new Date(dataFim);
|
||||
dataAviso.setDate(dataAviso.getDate() - c.diasAvisoVencimento);
|
||||
const dataFim = new Date(c.dataFimVigencia);
|
||||
const dataAviso = new Date(dataFim);
|
||||
dataAviso.setDate(dataAviso.getDate() - c.diasAvisoVencimento);
|
||||
|
||||
const dataAvisoStr = dataAviso.toISOString().split("T")[0];
|
||||
const dataAvisoStr = dataAviso.toISOString().split('T')[0];
|
||||
|
||||
// Se hoje for maior ou igual a data de aviso e menor que a data fim
|
||||
return hojeStr >= dataAvisoStr && hojeStr <= c.dataFimVigencia;
|
||||
});
|
||||
// Se hoje for maior ou igual a data de aviso e menor que a data fim
|
||||
return hojeStr >= dataAvisoStr && hojeStr <= c.dataFimVigencia;
|
||||
});
|
||||
|
||||
return proximosVencimento;
|
||||
},
|
||||
return proximosVencimento;
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user