feat: enhance dashboard functionality by adding user statistics, improving data filtering for dispensas, and refining timestamp handling to ensure accurate time zone management
This commit is contained in:
@@ -7,10 +7,12 @@ export const getStats = query({
|
||||
returns: v.object({
|
||||
totalFuncionarios: v.number(),
|
||||
totalSimbolos: v.number(),
|
||||
totalUsuarios: v.number(),
|
||||
funcionariosAtivos: v.number(),
|
||||
funcionariosDesligados: v.number(),
|
||||
cargoComissionado: v.number(),
|
||||
funcaoGratificada: v.number()
|
||||
funcaoGratificada: v.number(),
|
||||
totalCadastros: v.number()
|
||||
}),
|
||||
handler: async (ctx) => {
|
||||
// Contar funcionários
|
||||
@@ -36,41 +38,22 @@ export const getStats = query({
|
||||
const simbolos = await ctx.db.query('simbolos').collect();
|
||||
const totalSimbolos = simbolos.length;
|
||||
|
||||
// Contar usuários cadastrados
|
||||
const usuarios = await ctx.db.query('usuarios').collect();
|
||||
const totalUsuarios = usuarios.length;
|
||||
|
||||
// Calcular total de cadastros (funcionários + símbolos + usuários)
|
||||
const totalCadastros = totalFuncionarios + totalSimbolos + totalUsuarios;
|
||||
|
||||
return {
|
||||
totalFuncionarios,
|
||||
totalSimbolos,
|
||||
totalUsuarios,
|
||||
funcionariosAtivos,
|
||||
funcionariosDesligados,
|
||||
cargoComissionado,
|
||||
funcaoGratificada
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Obter atividades recentes (últimas 24 horas)
|
||||
export const getRecentActivity = query({
|
||||
args: {},
|
||||
returns: v.object({
|
||||
funcionariosCadastrados24h: v.number(),
|
||||
simbolosCadastrados24h: v.number()
|
||||
}),
|
||||
handler: async (ctx) => {
|
||||
const now = Date.now();
|
||||
const last24h = now - 24 * 60 * 60 * 1000;
|
||||
|
||||
// Funcionários cadastrados nas últimas 24h
|
||||
const funcionarios = await ctx.db.query('funcionarios').collect();
|
||||
const funcionariosCadastrados24h = funcionarios.filter(
|
||||
(f) => f._creationTime >= last24h
|
||||
).length;
|
||||
|
||||
// Símbolos cadastrados nas últimas 24h
|
||||
const simbolos = await ctx.db.query('simbolos').collect();
|
||||
const simbolosCadastrados24h = simbolos.filter((s) => s._creationTime >= last24h).length;
|
||||
|
||||
return {
|
||||
funcionariosCadastrados24h,
|
||||
simbolosCadastrados24h
|
||||
funcaoGratificada,
|
||||
totalCadastros
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -847,224 +847,3 @@ export const obterHistoricoAlertas = query({
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Status consolidado do sistema para o dashboard
|
||||
*/
|
||||
export const getStatusSistema = query({
|
||||
args: {},
|
||||
returns: v.object({
|
||||
usuariosOnline: v.number(),
|
||||
totalRegistros: v.number(),
|
||||
tempoMedioResposta: v.number(),
|
||||
cpuUsada: v.number(),
|
||||
memoriaUsada: v.number(),
|
||||
ultimaAtualizacao: v.number()
|
||||
}),
|
||||
handler: async (ctx) => {
|
||||
try {
|
||||
// Última métrica, se existir
|
||||
const ultimaMetrica = (await ctx.db.query('systemMetrics').order('desc').first()) ?? null;
|
||||
|
||||
// Usuários online: usar métrica se disponível, senão derivar de usuários
|
||||
let usuariosOnline = 0;
|
||||
if (ultimaMetrica?.usuariosOnline !== undefined) {
|
||||
usuariosOnline = ultimaMetrica.usuariosOnline;
|
||||
} else {
|
||||
const usuarios = await ctx.db.query('usuarios').collect();
|
||||
usuariosOnline = usuarios.filter((u) => u.statusPresenca === 'online').length;
|
||||
}
|
||||
|
||||
// Total de registros (estimativa baseada em tabelas principais)
|
||||
const [usuarios, funcionarios, simbolos, alertas, metricas] = await Promise.all([
|
||||
ctx.db.query('usuarios').collect(),
|
||||
ctx.db.query('funcionarios').collect(),
|
||||
ctx.db.query('simbolos').collect(),
|
||||
ctx.db.query('alertConfigurations').collect(),
|
||||
ctx.db.query('systemMetrics').take(100) // não precisa contar tudo
|
||||
]);
|
||||
const totalRegistros =
|
||||
usuarios.length + funcionarios.length + simbolos.length + alertas.length + metricas.length;
|
||||
|
||||
// Métricas de performance com fallbacks seguros
|
||||
const tempoMedioResposta = ultimaMetrica?.tempoRespostaMedio ?? 0;
|
||||
const cpuUsada = Math.max(
|
||||
0,
|
||||
Math.min(100, Math.round((ultimaMetrica?.cpuUsage ?? 0) * 100) / 100)
|
||||
);
|
||||
const memoriaUsada = Math.max(
|
||||
0,
|
||||
Math.min(100, Math.round((ultimaMetrica?.memoryUsage ?? 0) * 100) / 100)
|
||||
);
|
||||
const ultimaAtualizacao = ultimaMetrica?.timestamp ?? Date.now();
|
||||
|
||||
return {
|
||||
usuariosOnline,
|
||||
totalRegistros,
|
||||
tempoMedioResposta,
|
||||
cpuUsada,
|
||||
memoriaUsada,
|
||||
ultimaAtualizacao
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Erro em getStatusSistema:', error);
|
||||
// Retornar valores padrão em caso de erro
|
||||
return {
|
||||
usuariosOnline: 0,
|
||||
totalRegistros: 0,
|
||||
tempoMedioResposta: 0,
|
||||
cpuUsada: 0,
|
||||
memoriaUsada: 0,
|
||||
ultimaAtualizacao: Date.now()
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Atividade do banco no último minuto (agregada em buckets)
|
||||
* Usa logsAtividades e systemMetrics para calcular atividade real.
|
||||
*/
|
||||
export const getAtividadeBancoDados = query({
|
||||
args: {},
|
||||
returns: v.object({
|
||||
historico: v.array(
|
||||
v.object({
|
||||
entradas: v.number(),
|
||||
saidas: v.number()
|
||||
})
|
||||
)
|
||||
}),
|
||||
handler: async (ctx) => {
|
||||
try {
|
||||
const agora = Date.now();
|
||||
const haUmMinuto = agora - 60 * 1000;
|
||||
|
||||
// Buscar atividades reais do sistema
|
||||
const atividadesRecentes = await ctx.db
|
||||
.query('logsAtividades')
|
||||
.withIndex('by_timestamp', (q) => q.gte('timestamp', haUmMinuto))
|
||||
.order('asc')
|
||||
.collect();
|
||||
|
||||
// Buscar métricas também (para mensagens se houver)
|
||||
const metricasRecentes = await ctx.db
|
||||
.query('systemMetrics')
|
||||
.withIndex('by_timestamp', (q) => q.gte('timestamp', haUmMinuto))
|
||||
.order('asc')
|
||||
.collect();
|
||||
|
||||
// Bucketizar em 30 pontos (~2s cada) para visualização
|
||||
const numBuckets = 30;
|
||||
const bucketSizeMs = Math.ceil(60_000 / numBuckets);
|
||||
const historico: Array<{ entradas: number; saidas: number }> = [];
|
||||
|
||||
for (let i = 0; i < numBuckets; i++) {
|
||||
const inicio = haUmMinuto + i * bucketSizeMs;
|
||||
const fim = inicio + bucketSizeMs;
|
||||
|
||||
// Contar atividades de criação/inserção (entradas)
|
||||
const atividadesBucket = atividadesRecentes.filter(
|
||||
(a) => a.timestamp >= inicio && a.timestamp < fim
|
||||
);
|
||||
const entradasAtividades = atividadesBucket.filter(
|
||||
(a) => a.acao === 'criar' || a.acao === 'inserir' || a.acao === 'cadastrar'
|
||||
).length;
|
||||
|
||||
// Contar atividades de exclusão/remoção (saídas)
|
||||
const saidasAtividades = atividadesBucket.filter(
|
||||
(a) => a.acao === 'excluir' || a.acao === 'remover' || a.acao === 'deletar'
|
||||
).length;
|
||||
|
||||
// Usar mensagensPorMinuto como adicional se disponível
|
||||
const bucketMetricas = metricasRecentes.filter(
|
||||
(m) => m.timestamp >= inicio && m.timestamp < fim
|
||||
);
|
||||
const somaMensagens =
|
||||
bucketMetricas.reduce((acc, m) => acc + (m.mensagensPorMinuto ?? 0), 0) || 0;
|
||||
|
||||
// Combinar atividades reais com métricas de mensagens
|
||||
const entradas = Math.max(0, Math.round(entradasAtividades + somaMensagens * 0.3));
|
||||
const saidas = Math.max(0, Math.round(saidasAtividades + somaMensagens * 0.2));
|
||||
|
||||
historico.push({ entradas, saidas });
|
||||
}
|
||||
|
||||
return { historico };
|
||||
} catch (error) {
|
||||
console.error('Erro em getAtividadeBancoDados:', error);
|
||||
// Retornar histórico vazio em caso de erro
|
||||
return { historico: Array(30).fill({ entradas: 0, saidas: 0 }) };
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Distribuição de operações (calculada a partir de logsAtividades e métricas)
|
||||
*/
|
||||
export const getDistribuicaoRequisicoes = query({
|
||||
args: {},
|
||||
returns: v.object({
|
||||
queries: v.number(),
|
||||
mutations: v.number(),
|
||||
leituras: v.number(),
|
||||
escritas: v.number()
|
||||
}),
|
||||
handler: async (ctx) => {
|
||||
try {
|
||||
const umaHoraAtras = Date.now() - 60 * 60 * 1000;
|
||||
|
||||
// Buscar atividades reais do sistema
|
||||
const atividades = await ctx.db
|
||||
.query('logsAtividades')
|
||||
.withIndex('by_timestamp', (q) => q.gte('timestamp', umaHoraAtras))
|
||||
.collect();
|
||||
|
||||
// Buscar métricas também
|
||||
const metricas = await ctx.db
|
||||
.query('systemMetrics')
|
||||
.withIndex('by_timestamp', (q) => q.gte('timestamp', umaHoraAtras))
|
||||
.order('desc')
|
||||
.take(100);
|
||||
|
||||
// Contar operações de leitura (consultas, visualizações)
|
||||
const leituras = atividades.filter(
|
||||
(a) =>
|
||||
a.acao === 'consultar' ||
|
||||
a.acao === 'visualizar' ||
|
||||
a.acao === 'listar' ||
|
||||
a.acao === 'buscar'
|
||||
).length;
|
||||
|
||||
// Contar operações de escrita (criar, editar, excluir)
|
||||
const escritas = atividades.filter(
|
||||
(a) =>
|
||||
a.acao === 'criar' ||
|
||||
a.acao === 'editar' ||
|
||||
a.acao === 'excluir' ||
|
||||
a.acao === 'inserir' ||
|
||||
a.acao === 'atualizar' ||
|
||||
a.acao === 'deletar' ||
|
||||
a.acao === 'cadastrar' ||
|
||||
a.acao === 'remover'
|
||||
).length;
|
||||
|
||||
// Adicionar estimativa baseada em mensagens se disponível
|
||||
const totalMensagens = Math.max(
|
||||
0,
|
||||
Math.round(metricas.reduce((acc, m) => acc + (m.mensagensPorMinuto ?? 0), 0))
|
||||
);
|
||||
|
||||
// Queries são leituras + parte das mensagens (como consultas de chat)
|
||||
const queries = leituras + Math.round(totalMensagens * 0.5);
|
||||
|
||||
// Mutations são escritas + parte das mensagens (como envio de mensagens)
|
||||
const mutations = escritas + Math.round(totalMensagens * 0.3);
|
||||
|
||||
return { queries, mutations, leituras, escritas };
|
||||
} catch (error) {
|
||||
console.error('Erro em getDistribuicaoRequisicoes:', error);
|
||||
// Retornar valores padrão em caso de erro
|
||||
return { queries: 0, mutations: 0, leituras: 0, escritas: 0 };
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -636,45 +636,59 @@ export const registrarPonto = mutation({
|
||||
.filter((q) => q.eq(q.field('ativo'), true))
|
||||
.collect();
|
||||
|
||||
const dataConsulta = new Date(data);
|
||||
// Helper para criar timestamp UTC a partir de data (YYYY-MM-DD), hora e minuto em GMT-3
|
||||
// A hora informada está em GMT-3, então precisamos adicionar 3 horas para obter UTC
|
||||
const offsetGMT3ParaUTC = 3 * 60 * 60 * 1000; // 3 horas em milissegundos
|
||||
function criarTimestampUTCDeGMT3(data: string, hora: number, minuto: number): number {
|
||||
const [ano, mes, dia] = data.split('-').map(Number);
|
||||
return Date.UTC(ano, mes - 1, dia, hora, minuto, 0, 0) + offsetGMT3ParaUTC;
|
||||
}
|
||||
|
||||
// Helper para criar timestamp UTC a partir de data (YYYY-MM-DD), hora e minuto que já estão em UTC
|
||||
function criarTimestampUTC(data: string, horaUTC: number, minutoUTC: number): number {
|
||||
const [ano, mes, dia] = data.split('-').map(Number);
|
||||
return Date.UTC(ano, mes - 1, dia, horaUTC, minutoUTC, 0, 0);
|
||||
}
|
||||
|
||||
// Obter timestamp atual em UTC
|
||||
const agoraUTC = new Date();
|
||||
const agoraTimestampUTC = agoraUTC.getTime();
|
||||
|
||||
// Timestamp da consulta (registro sendo feito) em UTC
|
||||
// hora/minuto já estão em UTC (extraídos com getUTCHours/getUTCMinutes)
|
||||
const timestampConsultaUTC = criarTimestampUTC(data, hora, minuto);
|
||||
|
||||
for (const dispensa of dispensas) {
|
||||
// Se for isento, sempre está dispensado
|
||||
if (dispensa.isento) {
|
||||
throw new Error('Registro dispensado pelo gestor: Isento de registro (caso excepcional)');
|
||||
}
|
||||
|
||||
// Verificar se está no período
|
||||
const dataInicio = new Date(dispensa.dataInicio);
|
||||
const dataFim = new Date(dispensa.dataFim);
|
||||
// Calcular timestamps de início e fim da dispensa em UTC
|
||||
const timestampInicioUTC = criarTimestampUTCDeGMT3(
|
||||
dispensa.dataInicio,
|
||||
dispensa.horaInicio,
|
||||
dispensa.minutoInicio
|
||||
);
|
||||
const timestampFimUTC = criarTimestampUTCDeGMT3(
|
||||
dispensa.dataFim,
|
||||
dispensa.horaFim,
|
||||
dispensa.minutoFim
|
||||
);
|
||||
|
||||
if (dataConsulta >= dataInicio && dataConsulta <= dataFim) {
|
||||
// Verificar hora e minuto se necessário
|
||||
const timestampConsulta = new Date(
|
||||
`${data}T${hora.toString().padStart(2, '0')}:${minuto.toString().padStart(2, '0')}:00`
|
||||
).getTime();
|
||||
const timestampInicio = new Date(
|
||||
`${dispensa.dataInicio}T${dispensa.horaInicio.toString().padStart(2, '0')}:${dispensa.minutoInicio.toString().padStart(2, '0')}:00`
|
||||
).getTime();
|
||||
const timestampFim = new Date(
|
||||
`${dispensa.dataFim}T${dispensa.horaFim.toString().padStart(2, '0')}:${dispensa.minutoFim.toString().padStart(2, '0')}:00`
|
||||
).getTime();
|
||||
|
||||
if (timestampConsulta >= timestampInicio && timestampConsulta <= timestampFim) {
|
||||
throw new Error(`Registro dispensado pelo gestor: ${dispensa.motivo}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Verificar se expirou (desativar na mutation de registro)
|
||||
const agora = new Date();
|
||||
const dataFimTimestamp = new Date(
|
||||
`${dispensa.dataFim}T${dispensa.horaFim.toString().padStart(2, '0')}:${dispensa.minutoFim.toString().padStart(2, '0')}:00`
|
||||
).getTime();
|
||||
|
||||
if (agora.getTime() > dataFimTimestamp && !dispensa.isento) {
|
||||
// Desativar dispensa expirada (mutation pode fazer isso)
|
||||
// Desativar dispensa expirada ANTES de verificar bloqueio (após o fim)
|
||||
// Verificar se AGORA já passou do horário de fim da dispensa
|
||||
if (agoraTimestampUTC > timestampFimUTC) {
|
||||
await ctx.db.patch(dispensa._id, {
|
||||
ativo: false
|
||||
});
|
||||
continue; // Pular verificação de bloqueio se já expirou
|
||||
}
|
||||
|
||||
// Verificar se AGORA está dentro do período da dispensa (não o horário do registro)
|
||||
// Se o momento atual está dentro do período, bloqueia qualquer tentativa de registro
|
||||
if (agoraTimestampUTC >= timestampInicioUTC && agoraTimestampUTC <= timestampFimUTC) {
|
||||
throw new Error(`Registro dispensado pelo gestor: ${dispensa.motivo}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2883,10 +2897,7 @@ export const excluirHomologacao = mutation({
|
||||
};
|
||||
|
||||
// Se a homologação tem valores anteriores, restaurar
|
||||
if (
|
||||
homologacao.horaAnterior !== undefined &&
|
||||
homologacao.minutoAnterior !== undefined
|
||||
) {
|
||||
if (homologacao.horaAnterior !== undefined && homologacao.minutoAnterior !== undefined) {
|
||||
patchData.hora = homologacao.horaAnterior;
|
||||
patchData.minuto = homologacao.minutoAnterior;
|
||||
}
|
||||
@@ -3033,10 +3044,8 @@ export const removerDispensaRegistro = mutation({
|
||||
throw new Error('Você não tem permissão para remover esta dispensa');
|
||||
}
|
||||
|
||||
// Desativar dispensa
|
||||
await ctx.db.patch(args.dispensaId, {
|
||||
ativo: false
|
||||
});
|
||||
// Deletar dispensa do banco de dados
|
||||
await ctx.db.delete(args.dispensaId);
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
@@ -3117,14 +3126,49 @@ export const listarDispensas = query({
|
||||
}
|
||||
}
|
||||
|
||||
// Verificar se expirou (se não for isento)
|
||||
// Verificar se está ativa ou expirada (considerando data, hora e minuto em GMT-3)
|
||||
let expirada = false;
|
||||
|
||||
// GMT-3 está 3 horas ATRÁS do UTC
|
||||
// Offset: +3 horas para converter GMT-3 para UTC
|
||||
const offsetGMT3ParaUTC = 3 * 60 * 60 * 1000; // 3 horas em milissegundos
|
||||
|
||||
// Obter data/hora atual em UTC
|
||||
const agoraUTC = new Date();
|
||||
const agoraTimestampUTC = agoraUTC.getTime();
|
||||
|
||||
// Helper para criar timestamp UTC a partir de data (YYYY-MM-DD), hora e minuto em GMT-3
|
||||
// A hora informada está em GMT-3, então precisamos adicionar 3 horas para obter UTC
|
||||
// Exemplo: 08:00 GMT-3 = 11:00 UTC
|
||||
function criarTimestampUTCDeGMT3(data: string, hora: number, minuto: number): number {
|
||||
const [ano, mes, dia] = data.split('-').map(Number);
|
||||
// Date.UTC cria timestamp UTC
|
||||
// Se a hora está em GMT-3, adicionamos 3 horas para obter o equivalente UTC
|
||||
return Date.UTC(ano, mes - 1, dia, hora, minuto, 0, 0) + offsetGMT3ParaUTC;
|
||||
}
|
||||
|
||||
if (!d.isento) {
|
||||
const agora = new Date();
|
||||
const dataFimTimestamp = new Date(
|
||||
`${d.dataFim}T${d.horaFim.toString().padStart(2, '0')}:${d.minutoFim.toString().padStart(2, '0')}:00`
|
||||
).getTime();
|
||||
expirada = agora.getTime() > dataFimTimestamp;
|
||||
// Para dispensas não isentas, verificar se está dentro do período
|
||||
const dataInicioTimestamp = criarTimestampUTCDeGMT3(
|
||||
d.dataInicio,
|
||||
d.horaInicio,
|
||||
d.minutoInicio
|
||||
);
|
||||
const dataFimTimestamp = criarTimestampUTCDeGMT3(d.dataFim, d.horaFim, d.minutoFim);
|
||||
|
||||
// Está expirada se estiver antes do início OU depois do fim
|
||||
// Está ativa se: dataInicioTimestamp <= agoraTimestampUTC <= dataFimTimestamp
|
||||
expirada =
|
||||
agoraTimestampUTC < dataInicioTimestamp || agoraTimestampUTC > dataFimTimestamp;
|
||||
} else {
|
||||
// Se for isento, verificar apenas se já passou do início
|
||||
const dataInicioTimestamp = criarTimestampUTCDeGMT3(
|
||||
d.dataInicio,
|
||||
d.horaInicio,
|
||||
d.minutoInicio
|
||||
);
|
||||
// Se ainda não começou, está expirada (não ativa ainda)
|
||||
expirada = agoraTimestampUTC < dataInicioTimestamp;
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -3349,7 +3393,16 @@ export const verificarDispensaAtiva = query({
|
||||
.filter((q) => q.eq(q.field('ativo'), true))
|
||||
.collect();
|
||||
|
||||
const dataConsulta = new Date(args.data);
|
||||
// Helper para criar timestamp UTC a partir de data (YYYY-MM-DD), hora e minuto em GMT-3
|
||||
const offsetGMT3ParaUTC = 3 * 60 * 60 * 1000; // 3 horas em milissegundos
|
||||
function criarTimestampUTCDeGMT3(data: string, hora: number, minuto: number): number {
|
||||
const [ano, mes, dia] = data.split('-').map(Number);
|
||||
return Date.UTC(ano, mes - 1, dia, hora, minuto, 0, 0) + offsetGMT3ParaUTC;
|
||||
}
|
||||
|
||||
// Obter timestamp atual em UTC
|
||||
const agoraUTC = new Date();
|
||||
const agoraTimestampUTC = agoraUTC.getTime();
|
||||
|
||||
for (const dispensa of dispensas) {
|
||||
// Se for isento, sempre está dispensado
|
||||
@@ -3361,33 +3414,39 @@ export const verificarDispensaAtiva = query({
|
||||
};
|
||||
}
|
||||
|
||||
// Verificar se está no período
|
||||
const dataInicio = new Date(dispensa.dataInicio);
|
||||
const dataFim = new Date(dispensa.dataFim);
|
||||
// Calcular timestamps de início e fim da dispensa em UTC
|
||||
const timestampInicioUTC = criarTimestampUTCDeGMT3(
|
||||
dispensa.dataInicio,
|
||||
dispensa.horaInicio,
|
||||
dispensa.minutoInicio
|
||||
);
|
||||
const timestampFimUTC = criarTimestampUTCDeGMT3(
|
||||
dispensa.dataFim,
|
||||
dispensa.horaFim,
|
||||
dispensa.minutoFim
|
||||
);
|
||||
|
||||
// Se a data está dentro do período
|
||||
if (dataConsulta >= dataInicio && dataConsulta <= dataFim) {
|
||||
// Se hora e minuto foram fornecidos, verificar também
|
||||
if (args.hora !== undefined && args.minuto !== undefined) {
|
||||
const timestampConsulta = new Date(
|
||||
`${args.data}T${args.hora.toString().padStart(2, '0')}:${args.minuto.toString().padStart(2, '0')}:00`
|
||||
).getTime();
|
||||
const timestampInicio = new Date(
|
||||
`${dispensa.dataInicio}T${dispensa.horaInicio.toString().padStart(2, '0')}:${dispensa.minutoInicio.toString().padStart(2, '0')}:00`
|
||||
).getTime();
|
||||
const timestampFim = new Date(
|
||||
`${dispensa.dataFim}T${dispensa.horaFim.toString().padStart(2, '0')}:${dispensa.minutoFim.toString().padStart(2, '0')}:00`
|
||||
).getTime();
|
||||
// Verificar se AGORA já passou do horário de fim da dispensa
|
||||
// Se já expirou, não está mais dispensado
|
||||
if (agoraTimestampUTC > timestampFimUTC) {
|
||||
// Dispensa expirada, continuar para próxima
|
||||
continue;
|
||||
}
|
||||
|
||||
if (timestampConsulta >= timestampInicio && timestampConsulta <= timestampFim) {
|
||||
return {
|
||||
dispensado: true,
|
||||
dispensa,
|
||||
motivo: dispensa.motivo
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// Apenas verificar data
|
||||
// Se hora e minuto foram fornecidos, verificar timestamp completo
|
||||
if (args.hora !== undefined && args.minuto !== undefined) {
|
||||
const timestampConsultaUTC = criarTimestampUTCDeGMT3(args.data, args.hora, args.minuto);
|
||||
if (timestampConsultaUTC >= timestampInicioUTC && timestampConsultaUTC <= timestampFimUTC) {
|
||||
return {
|
||||
dispensado: true,
|
||||
dispensa,
|
||||
motivo: dispensa.motivo
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// Se apenas data foi fornecida, verificar se AGORA está dentro do período
|
||||
// (não apenas a data, mas também o horário)
|
||||
if (agoraTimestampUTC >= timestampInicioUTC && agoraTimestampUTC <= timestampFimUTC) {
|
||||
return {
|
||||
dispensado: true,
|
||||
dispensa,
|
||||
|
||||
Reference in New Issue
Block a user