Merge remote-tracking branch 'origin' into feat-licitacoes-contratos

This commit is contained in:
2025-11-19 09:29:30 -03:00
22 changed files with 5943 additions and 128 deletions

View File

@@ -1392,5 +1392,122 @@ export default defineSchema({
criadoEm: v.number(),
atualizadoEm: v.number(),
})
.index("by_criadoEm", ["criadoEm"])
.index("by_criadoEm", ["criadoEm"]),
// Sistema de Controle de Ponto
registrosPonto: defineTable({
funcionarioId: v.id("funcionarios"),
tipo: v.union(
v.literal("entrada"),
v.literal("saida_almoco"),
v.literal("retorno_almoco"),
v.literal("saida")
),
data: v.string(), // YYYY-MM-DD
hora: v.number(),
minuto: v.number(),
segundo: v.number(),
timestamp: v.number(), // Timestamp completo para ordenação
imagemId: v.optional(v.id("_storage")),
sincronizadoComServidor: v.boolean(),
toleranciaMinutos: v.number(),
dentroDoPrazo: v.boolean(),
// Informações de Rede
ipAddress: v.optional(v.string()),
ipPublico: v.optional(v.string()),
ipLocal: v.optional(v.string()),
// Informações do Navegador
userAgent: v.optional(v.string()),
browser: v.optional(v.string()),
browserVersion: v.optional(v.string()),
engine: v.optional(v.string()),
// Informações do Sistema
sistemaOperacional: v.optional(v.string()),
osVersion: v.optional(v.string()),
arquitetura: v.optional(v.string()),
plataforma: v.optional(v.string()),
// Informações de Localização
latitude: v.optional(v.number()),
longitude: v.optional(v.number()),
precisao: v.optional(v.number()),
endereco: v.optional(v.string()),
cidade: v.optional(v.string()),
estado: v.optional(v.string()),
pais: v.optional(v.string()),
timezone: v.optional(v.string()),
// Informações do Dispositivo
deviceType: v.optional(v.string()),
deviceModel: v.optional(v.string()),
screenResolution: v.optional(v.string()),
coresTela: v.optional(v.number()),
idioma: v.optional(v.string()),
// Informações Adicionais
isMobile: v.optional(v.boolean()),
isTablet: v.optional(v.boolean()),
isDesktop: v.optional(v.boolean()),
connectionType: v.optional(v.string()),
memoryInfo: v.optional(v.string()),
// Justificativa opcional para o registro
justificativa: v.optional(v.string()),
criadoEm: v.number(),
})
.index("by_funcionario_data", ["funcionarioId", "data"])
.index("by_data", ["data"])
.index("by_dentro_prazo", ["dentroDoPrazo", "data"])
.index("by_funcionario_timestamp", ["funcionarioId", "timestamp"]),
configuracaoPonto: defineTable({
horarioEntrada: v.string(), // HH:mm
horarioSaidaAlmoco: v.string(), // HH:mm
horarioRetornoAlmoco: v.string(), // HH:mm
horarioSaida: v.string(), // HH:mm
toleranciaMinutos: v.number(),
// Nomes personalizados dos tipos de registro
nomeEntrada: v.optional(v.string()), // Padrão: "Entrada 1"
nomeSaidaAlmoco: v.optional(v.string()), // Padrão: "Saída 1"
nomeRetornoAlmoco: v.optional(v.string()), // Padrão: "Entrada 2"
nomeSaida: v.optional(v.string()), // Padrão: "Saída 2"
// Ajuste de fuso horário (GMT offset em horas)
gmtOffset: v.optional(v.number()), // Padrão: 0 (UTC)
ativo: v.boolean(),
atualizadoPor: v.id("usuarios"),
atualizadoEm: v.number(),
})
.index("by_ativo", ["ativo"]),
configuracaoRelogio: defineTable({
servidorNTP: v.optional(v.string()),
portaNTP: v.optional(v.number()),
usarServidorExterno: v.boolean(),
fallbackParaPC: v.boolean(),
ultimaSincronizacao: v.optional(v.number()),
offsetSegundos: v.optional(v.number()),
// Ajuste de fuso horário (GMT offset em horas)
gmtOffset: v.optional(v.number()), // Padrão: 0 (UTC)
atualizadoPor: v.id("usuarios"),
atualizadoEm: v.number(),
})
.index("by_ativo", ["usarServidorExterno"]),
// Banco de Horas - Saldo diário de horas trabalhadas
bancoHoras: defineTable({
funcionarioId: v.id("funcionarios"),
data: v.string(), // YYYY-MM-DD
cargaHorariaDiaria: v.number(), // Horas esperadas do dia (em minutos)
horasTrabalhadas: v.number(), // Horas realmente trabalhadas (em minutos)
saldoMinutos: v.number(), // Saldo do dia (positivo = horas extras, negativo = déficit)
registrosPontoIds: v.array(v.id("registrosPonto")), // IDs dos registros do dia
calculadoEm: v.number(),
})
.index("by_funcionario_data", ["funcionarioId", "data"])
.index("by_funcionario", ["funcionarioId"])
.index("by_data", ["data"]),
});