Merge remote-tracking branch 'origin' into feat-pedidos
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
import { v } from 'convex/values';
|
||||
import { mutation, query, internalMutation } from './_generated/server';
|
||||
import { internal } from './_generated/api';
|
||||
import type { Doc, Id } from './_generated/dataModel';
|
||||
import { internalMutation, mutation, query } from './_generated/server';
|
||||
import { Id, Doc } from './_generated/dataModel';
|
||||
import { verificarLicencaAtiva } from './atestadosLicencas';
|
||||
import { getCurrentUserFunction } from './auth';
|
||||
import { formatarDataBR } from './utils/datas';
|
||||
import { api } from './_generated/api';
|
||||
|
||||
// Validador para períodos
|
||||
const periodoValidator = v.object({
|
||||
@@ -46,7 +50,7 @@ function agruparPorSolicitacao(registros: Array<Doc<'ferias'>>): Array<{
|
||||
grupos.get(chave)!.push(registro);
|
||||
}
|
||||
|
||||
return Array.from(grupos.entries()).map(([_, periodos]) => {
|
||||
return Array.from(grupos.entries()).map(([, periodos]) => {
|
||||
// Ordenar por data de criação para manter ordem
|
||||
periodos.sort((a, b) => a._creationTime - b._creationTime);
|
||||
|
||||
@@ -137,7 +141,10 @@ export const listarTodas = query({
|
||||
|
||||
// Query: Listar solicitações do funcionário - períodos individuais
|
||||
export const listarMinhasSolicitacoes = query({
|
||||
args: { funcionarioId: v.id('funcionarios') },
|
||||
args: {
|
||||
funcionarioId: v.id('funcionarios'),
|
||||
_refresh: v.optional(v.number()) // Parâmetro para forçar atualização no frontend
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
const todasFerias = await ctx.db
|
||||
.query('ferias')
|
||||
@@ -205,6 +212,18 @@ export const listarSolicitacoesSubordinados = query({
|
||||
todasFerias.map(async (ferias) => {
|
||||
const funcionario = await ctx.db.get(ferias.funcionarioId);
|
||||
|
||||
// Buscar usuário do funcionário para obter fotoPerfilUrl
|
||||
let fotoPerfilUrl: string | null = null;
|
||||
if (funcionario) {
|
||||
const usuario = await ctx.db
|
||||
.query('usuarios')
|
||||
.withIndex('by_funcionarioId', (q) => q.eq('funcionarioId', funcionario._id))
|
||||
.first();
|
||||
if (usuario?.fotoPerfil) {
|
||||
fotoPerfilUrl = await ctx.storage.getUrl(usuario.fotoPerfil);
|
||||
}
|
||||
}
|
||||
|
||||
// Buscar time do funcionário
|
||||
const membroTime = await ctx.db
|
||||
.query('timesMembros')
|
||||
@@ -219,7 +238,12 @@ export const listarSolicitacoesSubordinados = query({
|
||||
|
||||
return {
|
||||
...ferias,
|
||||
funcionario,
|
||||
funcionario: funcionario
|
||||
? {
|
||||
...funcionario,
|
||||
fotoPerfilUrl
|
||||
}
|
||||
: null,
|
||||
time
|
||||
};
|
||||
})
|
||||
@@ -240,6 +264,19 @@ export const obterDetalhes = query({
|
||||
if (!ferias) return null;
|
||||
|
||||
const funcionario = await ctx.db.get(ferias.funcionarioId);
|
||||
|
||||
// Buscar usuário do funcionário para obter fotoPerfilUrl
|
||||
let fotoPerfilUrl: string | null = null;
|
||||
if (funcionario) {
|
||||
const usuario = await ctx.db
|
||||
.query('usuarios')
|
||||
.withIndex('by_funcionarioId', (q) => q.eq('funcionarioId', funcionario._id))
|
||||
.first();
|
||||
if (usuario?.fotoPerfil) {
|
||||
fotoPerfilUrl = await ctx.storage.getUrl(usuario.fotoPerfil);
|
||||
}
|
||||
}
|
||||
|
||||
let gestor = null;
|
||||
if (ferias.gestorId) {
|
||||
gestor = await ctx.db.get(ferias.gestorId);
|
||||
@@ -257,11 +294,31 @@ export const obterDetalhes = query({
|
||||
time = await ctx.db.get(membroTime.timeId);
|
||||
}
|
||||
|
||||
// Enriquecer histórico com nomes dos usuários
|
||||
let historicoComUsuarios = ferias.historicoAlteracoes;
|
||||
if (historicoComUsuarios && historicoComUsuarios.length > 0) {
|
||||
historicoComUsuarios = await Promise.all(
|
||||
historicoComUsuarios.map(async (hist) => {
|
||||
const usuario = await ctx.db.get(hist.usuarioId);
|
||||
return {
|
||||
...hist,
|
||||
usuarioNome: usuario?.nome || 'Usuário Desconhecido'
|
||||
};
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...ferias,
|
||||
funcionario,
|
||||
funcionario: funcionario
|
||||
? {
|
||||
...funcionario,
|
||||
fotoPerfilUrl
|
||||
}
|
||||
: null,
|
||||
gestor,
|
||||
time
|
||||
time,
|
||||
historicoAlteracoes: historicoComUsuarios
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -351,6 +408,10 @@ export const aprovar = mutation({
|
||||
|
||||
const funcionario = await ctx.db.get(registro.funcionarioId);
|
||||
|
||||
// Buscar nome do gestor para o histórico
|
||||
const gestorUsuario = await ctx.db.get(args.gestorId);
|
||||
const nomeGestor = gestorUsuario?.nome || 'Gestor';
|
||||
|
||||
// Atualizar o registro
|
||||
await ctx.db.patch(registro._id, {
|
||||
status: 'aprovado',
|
||||
@@ -361,7 +422,7 @@ export const aprovar = mutation({
|
||||
{
|
||||
data: Date.now(),
|
||||
usuarioId: args.gestorId,
|
||||
acao: 'Aprovado'
|
||||
acao: `Aprovado por ${nomeGestor}`
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -374,13 +435,58 @@ export const aprovar = mutation({
|
||||
.first();
|
||||
|
||||
if (usuario) {
|
||||
// Criar notificação in-app para funcionário
|
||||
await ctx.db.insert('notificacoesFerias', {
|
||||
destinatarioId: usuario._id,
|
||||
feriasId: registro._id,
|
||||
tipo: 'aprovado',
|
||||
lida: false,
|
||||
mensagem: `Período de férias de ${registro.diasFerias} dias foi aprovado!`
|
||||
mensagem: `Período de férias de ${formatarDataBR(registro.dataInicio)} até ${formatarDataBR(registro.dataFim)} (${registro.diasFerias} dias) foi aprovado por ${nomeGestor}!`
|
||||
});
|
||||
|
||||
// Enviar email ao funcionário usando template (agendado via scheduler)
|
||||
if (gestorUsuario) {
|
||||
// Obter URL do sistema
|
||||
let urlSistema = process.env.SITE_URL || 'http://localhost:5173';
|
||||
if (!urlSistema.match(/^https?:\/\//i)) {
|
||||
urlSistema = `http://${urlSistema}`;
|
||||
}
|
||||
|
||||
try {
|
||||
await ctx.scheduler.runAfter(0, api.email.enviarEmailComTemplate, {
|
||||
destinatario: usuario.email,
|
||||
destinatarioId: usuario._id,
|
||||
templateCodigo: 'ferias_aprovada',
|
||||
variaveis: {
|
||||
funcionarioNome: usuario.nome,
|
||||
gestorNome: gestorUsuario.nome,
|
||||
dataInicio: formatarDataBR(registro.dataInicio),
|
||||
dataFim: formatarDataBR(registro.dataFim),
|
||||
diasFerias: registro.diasFerias.toString(),
|
||||
urlSistema
|
||||
},
|
||||
enviadoPor: args.gestorId
|
||||
});
|
||||
} catch (error) {
|
||||
// Fallback para envio direto se houver erro ao agendar ou processar o template
|
||||
console.warn(
|
||||
'Erro ao agendar envio de email com template ferias_aprovada, usando envio direto:',
|
||||
error
|
||||
);
|
||||
await ctx.runMutation(api.email.enfileirarEmail, {
|
||||
destinatario: usuario.email,
|
||||
destinatarioId: usuario._id,
|
||||
assunto: 'Solicitação de Férias Aprovada',
|
||||
corpo: `<p>Olá ${usuario.nome},</p>
|
||||
<p>Sua solicitação de férias foi <strong>aprovada</strong> pelo gestor ${gestorUsuario.nome}:</p>
|
||||
<ul>
|
||||
<li><strong>Período:</strong> ${formatarDataBR(registro.dataInicio)} até ${formatarDataBR(registro.dataFim)}</li>
|
||||
<li><strong>Dias:</strong> ${registro.diasFerias} dias</li>
|
||||
</ul>`,
|
||||
enviadoPor: args.gestorId
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,6 +600,10 @@ export const ajustarEAprovar = mutation({
|
||||
]
|
||||
});
|
||||
|
||||
// Buscar nome do gestor
|
||||
const gestorUsuario = await ctx.db.get(args.gestorId);
|
||||
const nomeGestor = gestorUsuario?.nome || 'Gestor';
|
||||
|
||||
// Notificar funcionário
|
||||
if (funcionario) {
|
||||
const usuario = await ctx.db
|
||||
@@ -502,13 +612,58 @@ export const ajustarEAprovar = mutation({
|
||||
.first();
|
||||
|
||||
if (usuario) {
|
||||
// Criar notificação in-app para funcionário
|
||||
await ctx.db.insert('notificacoesFerias', {
|
||||
destinatarioId: usuario._id,
|
||||
feriasId: registroAntigo._id,
|
||||
tipo: 'data_ajustada',
|
||||
lida: false,
|
||||
mensagem: `Período de férias foi aprovado com ajuste de datas: ${args.novaDataInicio} a ${args.novaDataFim}`
|
||||
mensagem: `Período de férias foi aprovado com ajuste de datas: ${formatarDataBR(args.novaDataInicio)} a ${formatarDataBR(args.novaDataFim)} (${novosDias} dias) por ${nomeGestor}`
|
||||
});
|
||||
|
||||
// Enviar email ao funcionário usando template (agendado via scheduler)
|
||||
if (gestorUsuario) {
|
||||
// Obter URL do sistema
|
||||
let urlSistema = process.env.SITE_URL || 'http://localhost:5173';
|
||||
if (!urlSistema.match(/^https?:\/\//i)) {
|
||||
urlSistema = `http://${urlSistema}`;
|
||||
}
|
||||
|
||||
try {
|
||||
await ctx.scheduler.runAfter(0, api.email.enviarEmailComTemplate, {
|
||||
destinatario: usuario.email,
|
||||
destinatarioId: usuario._id,
|
||||
templateCodigo: 'ferias_aprovada',
|
||||
variaveis: {
|
||||
funcionarioNome: usuario.nome,
|
||||
gestorNome: gestorUsuario.nome,
|
||||
dataInicio: formatarDataBR(args.novaDataInicio),
|
||||
dataFim: formatarDataBR(args.novaDataFim),
|
||||
diasFerias: novosDias.toString(),
|
||||
urlSistema
|
||||
},
|
||||
enviadoPor: args.gestorId
|
||||
});
|
||||
} catch (error) {
|
||||
// Fallback para envio direto se houver erro ao agendar ou processar o template
|
||||
console.warn(
|
||||
'Erro ao agendar envio de email com template ferias_aprovada, usando envio direto:',
|
||||
error
|
||||
);
|
||||
await ctx.runMutation(api.email.enfileirarEmail, {
|
||||
destinatario: usuario.email,
|
||||
destinatarioId: usuario._id,
|
||||
assunto: 'Solicitação de Férias Aprovada (com Ajuste de Datas)',
|
||||
corpo: `<p>Olá ${usuario.nome},</p>
|
||||
<p>Sua solicitação de férias foi <strong>aprovada com ajuste de datas</strong> pelo gestor ${gestorUsuario.nome}:</p>
|
||||
<ul>
|
||||
<li><strong>Período:</strong> ${formatarDataBR(args.novaDataInicio)} até ${formatarDataBR(args.novaDataFim)}</li>
|
||||
<li><strong>Dias:</strong> ${novosDias} dias</li>
|
||||
</ul>`,
|
||||
enviadoPor: args.gestorId
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -646,6 +801,124 @@ export const atualizarStatus = mutation({
|
||||
await ctx.db.patch(registro._id, updateData);
|
||||
}
|
||||
|
||||
// Recalcular imediatamente o status de férias/licença do funcionário
|
||||
// para refletir o cancelamento (ou outra mudança) sem depender apenas do cron diário
|
||||
try {
|
||||
await ctx.runMutation(internal.ferias.atualizarStatusFuncionario, {
|
||||
funcionarioId: registro.funcionarioId
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(
|
||||
'[ferias.atualizarStatus] Erro ao atualizar statusFerias do funcionário:',
|
||||
error
|
||||
);
|
||||
}
|
||||
|
||||
// Se o status foi alterado para Cancelado_RH, notificar o funcionário
|
||||
if (args.novoStatus === 'Cancelado_RH') {
|
||||
const funcionario = await ctx.db.get(registro.funcionarioId);
|
||||
|
||||
if (funcionario) {
|
||||
const funcionarioUsuario = await ctx.db
|
||||
.query('usuarios')
|
||||
.withIndex('by_funcionarioId', (q) => q.eq('funcionarioId', funcionario._id))
|
||||
.first();
|
||||
|
||||
if (funcionarioUsuario) {
|
||||
// Buscar usuário do RH que está cancelando
|
||||
const usuarioRH = await ctx.db.get(args.usuarioId);
|
||||
const nomeRH = usuarioRH?.nome || 'Recursos Humanos';
|
||||
|
||||
// Criar notificação in-app para funcionário
|
||||
await ctx.db.insert('notificacoesFerias', {
|
||||
destinatarioId: funcionarioUsuario._id,
|
||||
feriasId: registro._id,
|
||||
tipo: 'cancelado',
|
||||
lida: false,
|
||||
mensagem: `Sua solicitação de férias de ${formatarDataBR(registro.dataInicio)} até ${formatarDataBR(registro.dataFim)} (${registro.diasFerias} dias) foi cancelada pelo setor de Recursos Humanos.`
|
||||
});
|
||||
|
||||
// Obter URL do sistema
|
||||
let urlSistema = process.env.SITE_URL || 'http://localhost:5173';
|
||||
if (!urlSistema.match(/^https?:\/\//i)) {
|
||||
urlSistema = `http://${urlSistema}`;
|
||||
}
|
||||
|
||||
// Enviar email ao funcionário usando template (agendado via scheduler)
|
||||
try {
|
||||
await ctx.scheduler.runAfter(0, api.email.enviarEmailComTemplate, {
|
||||
destinatario: funcionarioUsuario.email,
|
||||
destinatarioId: funcionarioUsuario._id,
|
||||
templateCodigo: 'ferias_cancelada_rh',
|
||||
variaveis: {
|
||||
funcionarioNome: funcionarioUsuario.nome,
|
||||
dataInicio: formatarDataBR(registro.dataInicio),
|
||||
dataFim: formatarDataBR(registro.dataFim),
|
||||
diasFerias: registro.diasFerias.toString(),
|
||||
urlSistema
|
||||
},
|
||||
enviadoPor: args.usuarioId
|
||||
});
|
||||
} catch (error) {
|
||||
// Fallback para envio direto se houver erro ao agendar ou processar o template
|
||||
console.warn(
|
||||
'Erro ao agendar envio de email com template ferias_cancelada_rh, usando envio direto:',
|
||||
error
|
||||
);
|
||||
await ctx.runMutation(api.email.enfileirarEmail, {
|
||||
destinatario: funcionarioUsuario.email,
|
||||
destinatarioId: funcionarioUsuario._id,
|
||||
assunto: 'Solicitação de Férias Cancelada',
|
||||
corpo: `<p>Olá ${funcionarioUsuario.nome},</p>
|
||||
<p>Sua solicitação de férias foi <strong>cancelada</strong> pelo setor de Recursos Humanos:</p>
|
||||
<ul>
|
||||
<li><strong>Período:</strong> ${formatarDataBR(registro.dataInicio)} até ${formatarDataBR(registro.dataFim)}</li>
|
||||
<li><strong>Dias:</strong> ${registro.diasFerias} dias</li>
|
||||
</ul>
|
||||
<p>Para mais informações, entre em contato com o setor de Recursos Humanos.</p>`,
|
||||
enviadoPor: args.usuarioId
|
||||
});
|
||||
}
|
||||
|
||||
// Criar ou obter conversa entre RH e funcionário
|
||||
const conversasExistentes = await ctx.db
|
||||
.query('conversas')
|
||||
.filter((q) => q.eq(q.field('tipo'), 'individual'))
|
||||
.collect();
|
||||
|
||||
let conversaId: Id<'conversas'> | null = null;
|
||||
for (const conversa of conversasExistentes) {
|
||||
if (
|
||||
conversa.participantes.length === 2 &&
|
||||
conversa.participantes.includes(args.usuarioId) &&
|
||||
conversa.participantes.includes(funcionarioUsuario._id)
|
||||
) {
|
||||
conversaId = conversa._id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!conversaId) {
|
||||
conversaId = await ctx.db.insert('conversas', {
|
||||
tipo: 'individual',
|
||||
participantes: [args.usuarioId, funcionarioUsuario._id],
|
||||
criadoPor: args.usuarioId,
|
||||
criadoEm: Date.now()
|
||||
});
|
||||
}
|
||||
|
||||
// Criar mensagem de chat (texto simples)
|
||||
await ctx.db.insert('mensagens', {
|
||||
conversaId,
|
||||
remetenteId: args.usuarioId,
|
||||
tipo: 'texto',
|
||||
conteudo: `Sua solicitação de férias de ${formatarDataBR(registro.dataInicio)} até ${formatarDataBR(registro.dataFim)} (${registro.diasFerias} dias) foi cancelada pelo setor de Recursos Humanos. Para mais informações, entre em contato conosco.`,
|
||||
enviadaEm: Date.now()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@@ -762,7 +1035,15 @@ export const atualizarStatusTodosFuncionarios = internalMutation({
|
||||
}
|
||||
}
|
||||
|
||||
const novoStatus = emFerias ? 'em_ferias' : 'ativo';
|
||||
// Determinar o status: férias tem prioridade sobre licença
|
||||
let novoStatus: 'ativo' | 'em_ferias' | 'em_licenca';
|
||||
if (emFerias) {
|
||||
novoStatus = 'em_ferias';
|
||||
} else {
|
||||
// Se não está em férias, verificar se está em licença
|
||||
const emLicenca = await verificarLicencaAtiva(ctx, func._id, hoje);
|
||||
novoStatus = emLicenca ? 'em_licenca' : 'ativo';
|
||||
}
|
||||
|
||||
if (func.statusFerias !== novoStatus) {
|
||||
await ctx.db.patch(func._id, { statusFerias: novoStatus });
|
||||
@@ -772,3 +1053,146 @@ export const atualizarStatusTodosFuncionarios = internalMutation({
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Internal Mutation: Atualizar status de um funcionário específico
|
||||
export const atualizarStatusFuncionario = internalMutation({
|
||||
args: {
|
||||
funcionarioId: v.id('funcionarios')
|
||||
},
|
||||
returns: v.null(),
|
||||
handler: async (ctx, args) => {
|
||||
const func = await ctx.db.get(args.funcionarioId);
|
||||
if (!func) return null;
|
||||
|
||||
const hoje = new Date();
|
||||
hoje.setHours(0, 0, 0, 0);
|
||||
|
||||
// Buscar todos os registros de férias que podem estar em férias
|
||||
const feriasAprovadas = await ctx.db
|
||||
.query('ferias')
|
||||
.withIndex('by_funcionario_and_status', (q) =>
|
||||
q.eq('funcionarioId', func._id).eq('status', 'aprovado')
|
||||
)
|
||||
.collect();
|
||||
|
||||
const feriasAjustadas = await ctx.db
|
||||
.query('ferias')
|
||||
.withIndex('by_funcionario_and_status', (q) =>
|
||||
q.eq('funcionarioId', func._id).eq('status', 'data_ajustada_aprovada')
|
||||
)
|
||||
.collect();
|
||||
|
||||
const feriasEmFerias = await ctx.db
|
||||
.query('ferias')
|
||||
.withIndex('by_funcionario_and_status', (q) =>
|
||||
q.eq('funcionarioId', func._id).eq('status', 'EmFérias')
|
||||
)
|
||||
.collect();
|
||||
|
||||
const idsAprovados = new Set(feriasAprovadas.map((f) => f._id));
|
||||
const idsAjustados = new Set(feriasAjustadas.map((f) => f._id));
|
||||
const statusAnteriorPorId = new Map<Id<'ferias'>, 'aprovado' | 'data_ajustada_aprovada'>();
|
||||
|
||||
for (const ferias of feriasEmFerias) {
|
||||
if (ferias.historicoAlteracoes && ferias.historicoAlteracoes.length > 0) {
|
||||
const historico = ferias.historicoAlteracoes;
|
||||
for (let i = historico.length - 1; i >= 0; i--) {
|
||||
const entrada = historico[i];
|
||||
if (entrada.acao.includes('Aprovado') || entrada.acao.includes('aprovado')) {
|
||||
statusAnteriorPorId.set(ferias._id, 'aprovado');
|
||||
break;
|
||||
} else if (entrada.acao.includes('Data ajustada') || entrada.acao.includes('ajustada')) {
|
||||
statusAnteriorPorId.set(ferias._id, 'data_ajustada_aprovada');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!statusAnteriorPorId.has(ferias._id)) {
|
||||
statusAnteriorPorId.set(ferias._id, 'aprovado');
|
||||
}
|
||||
}
|
||||
|
||||
const todasFerias = [...feriasAprovadas, ...feriasAjustadas, ...feriasEmFerias];
|
||||
|
||||
let emFerias = false;
|
||||
for (const ferias of todasFerias) {
|
||||
const inicio = new Date(ferias.dataInicio);
|
||||
const fim = new Date(ferias.dataFim);
|
||||
inicio.setHours(0, 0, 0, 0);
|
||||
fim.setHours(23, 59, 59, 999);
|
||||
|
||||
if (hoje >= inicio && hoje <= fim) {
|
||||
emFerias = true;
|
||||
|
||||
if (ferias.status !== 'EmFérias') {
|
||||
await ctx.db.patch(ferias._id, {
|
||||
status: 'EmFérias'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (ferias.status === 'EmFérias') {
|
||||
let statusAnterior: 'aprovado' | 'data_ajustada_aprovada';
|
||||
|
||||
if (idsAprovados.has(ferias._id)) {
|
||||
statusAnterior = 'aprovado';
|
||||
} else if (idsAjustados.has(ferias._id)) {
|
||||
statusAnterior = 'data_ajustada_aprovada';
|
||||
} else {
|
||||
statusAnterior = statusAnteriorPorId.get(ferias._id) || 'aprovado';
|
||||
}
|
||||
|
||||
await ctx.db.patch(ferias._id, {
|
||||
status: statusAnterior
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determinar o status: férias tem prioridade sobre licença
|
||||
let novoStatus: 'ativo' | 'em_ferias' | 'em_licenca';
|
||||
if (emFerias) {
|
||||
novoStatus = 'em_ferias';
|
||||
console.log(`[atualizarStatusFuncionario] Funcionário ${func._id} está em férias`);
|
||||
} else {
|
||||
// Se não está em férias, verificar se está em licença
|
||||
console.log(
|
||||
`[atualizarStatusFuncionario] Verificando licença ativa para funcionário ${func._id}, data: ${hoje.toISOString()}`
|
||||
);
|
||||
const emLicenca = await verificarLicencaAtiva(ctx, func._id, hoje);
|
||||
novoStatus = emLicenca ? 'em_licenca' : 'ativo';
|
||||
console.log(
|
||||
`[atualizarStatusFuncionario] Funcionário ${func._id}: emLicenca=${emLicenca}, statusAtual=${func.statusFerias}, novoStatus=${novoStatus}`
|
||||
);
|
||||
}
|
||||
|
||||
if (func.statusFerias !== novoStatus) {
|
||||
console.log(
|
||||
`[atualizarStatusFuncionario] ⚠️ ATUALIZANDO status de "${func.statusFerias}" para "${novoStatus}"`
|
||||
);
|
||||
await ctx.db.patch(func._id, { statusFerias: novoStatus });
|
||||
console.log(`[atualizarStatusFuncionario] ✅ Status atualizado com sucesso!`);
|
||||
} else {
|
||||
console.log(`[atualizarStatusFuncionario] Status já está correto: ${novoStatus}`);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Mutation pública para atualizar status do funcionário atual (útil para debug/teste)
|
||||
export const atualizarMeuStatus = mutation({
|
||||
args: {},
|
||||
returns: v.null(),
|
||||
handler: async (ctx) => {
|
||||
const usuario = await getCurrentUserFunction(ctx);
|
||||
if (!usuario || !usuario.funcionarioId) {
|
||||
throw new Error('Usuário não encontrado ou não possui funcionário associado');
|
||||
}
|
||||
|
||||
await ctx.runMutation(internal.ferias.atualizarStatusFuncionario, {
|
||||
funcionarioId: usuario.funcionarioId
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user