feat: enhance point registration and location validation features
- Refactored the RegistroPonto component to improve the layout and user experience, including a new section for displaying standard hours. - Updated RelogioSincronizado to include GMT offset adjustments for accurate time display. - Introduced new location validation logic in the backend to ensure point registrations are within allowed geofenced areas. - Enhanced the device information schema to capture additional GPS data, improving the reliability of location checks. - Added new endpoints for managing allowed marking addresses, facilitating better control over where points can be registered.
This commit is contained in:
@@ -1367,6 +1367,25 @@ export default defineSchema({
|
||||
latitude: v.optional(v.number()),
|
||||
longitude: v.optional(v.number()),
|
||||
precisao: v.optional(v.number()),
|
||||
altitude: v.optional(v.union(v.number(), v.null())),
|
||||
altitudeAccuracy: v.optional(v.union(v.number(), v.null())),
|
||||
heading: v.optional(v.union(v.number(), v.null())),
|
||||
speed: v.optional(v.union(v.number(), v.null())),
|
||||
confiabilidadeGPS: v.optional(v.number()), // 0-1 (frontend)
|
||||
scoreConfiancaBackend: v.optional(v.number()), // 0-1 (backend)
|
||||
suspeitaSpoofing: v.optional(v.boolean()),
|
||||
motivoSuspeita: v.optional(v.string()),
|
||||
avisosValidacao: v.optional(v.array(v.string())), // Array de avisos detalhados da validação
|
||||
distanciaIPvsGPS: v.optional(v.number()), // Distância em metros entre IP geolocation e GPS
|
||||
velocidadeUltimoRegistro: v.optional(v.number()), // Velocidade em km/h do último registro
|
||||
distanciaUltimoRegistro: v.optional(v.number()), // Distância em metros do último registro
|
||||
tempoDecorridoHoras: v.optional(v.number()), // Tempo em horas desde o último registro
|
||||
// Informações de Geofencing
|
||||
enderecoMarcacaoEsperado: v.optional(v.id("enderecosMarcacao")), // Endereço mais próximo esperado
|
||||
distanciaEnderecoEsperado: v.optional(v.number()), // Distância em metros do endereço esperado
|
||||
dentroRaioPermitido: v.optional(v.boolean()), // Se está dentro do raio permitido
|
||||
enderecoMarcacaoUsado: v.optional(v.id("enderecosMarcacao")), // Qual endereço foi usado na validação
|
||||
raioToleranciaUsado: v.optional(v.number()), // Raio usado na validação em metros
|
||||
endereco: v.optional(v.string()),
|
||||
cidade: v.optional(v.string()),
|
||||
estado: v.optional(v.string()),
|
||||
@@ -1401,6 +1420,60 @@ export default defineSchema({
|
||||
.index("by_dentro_prazo", ["dentroDoPrazo", "data"])
|
||||
.index("by_funcionario_timestamp", ["funcionarioId", "timestamp"]),
|
||||
|
||||
// Endereços de Marcação - Locais permitidos para registro de ponto
|
||||
enderecosMarcacao: defineTable({
|
||||
nome: v.string(), // Ex: "Sede Principal", "Home Office João Silva", "Cliente ABC"
|
||||
descricao: v.optional(v.string()), // Descrição opcional
|
||||
// Coordenadas (obrigatórias)
|
||||
latitude: v.number(),
|
||||
longitude: v.number(),
|
||||
// Endereço físico (para exibição)
|
||||
endereco: v.string(), // Ex: "Rua Exemplo, 123"
|
||||
bairro: v.optional(v.string()), // Bairro do endereço
|
||||
cep: v.optional(v.string()),
|
||||
cidade: v.string(),
|
||||
estado: v.string(),
|
||||
pais: v.optional(v.string()), // Padrão: "Brasil"
|
||||
// Configurações
|
||||
raioMetros: v.number(), // Raio de tolerância em metros (ex: 100m, 500m, 1000m)
|
||||
ativo: v.boolean(),
|
||||
// Tipos de uso
|
||||
tipo: v.union(
|
||||
v.literal("sede"), // Sede principal (para todos)
|
||||
v.literal("home_office"), // Home office específico
|
||||
v.literal("deslocamento"), // Deslocamento temporário
|
||||
v.literal("cliente") // Local de cliente
|
||||
),
|
||||
// Metadados
|
||||
criadoPor: v.id("usuarios"),
|
||||
criadoEm: v.number(),
|
||||
atualizadoPor: v.optional(v.id("usuarios")),
|
||||
atualizadoEm: v.optional(v.number()),
|
||||
})
|
||||
.index("by_ativo", ["ativo"])
|
||||
.index("by_tipo", ["tipo"])
|
||||
.index("by_cidade", ["cidade"]),
|
||||
|
||||
// Associação Funcionário ↔ Endereço de Marcação
|
||||
funcionarioEnderecosMarcacao: defineTable({
|
||||
funcionarioId: v.id("funcionarios"),
|
||||
enderecoMarcacaoId: v.id("enderecosMarcacao"),
|
||||
// Configurações específicas do funcionário
|
||||
raioMetrosPersonalizado: v.optional(v.number()), // Pode ter raio diferente do padrão
|
||||
// Período de validade (para deslocamentos temporários)
|
||||
dataInicio: v.optional(v.string()), // YYYY-MM-DD
|
||||
dataFim: v.optional(v.string()), // YYYY-MM-DD
|
||||
// Status
|
||||
ativo: v.boolean(),
|
||||
// Metadados
|
||||
criadoPor: v.id("usuarios"),
|
||||
criadoEm: v.number(),
|
||||
})
|
||||
.index("by_funcionario", ["funcionarioId"])
|
||||
.index("by_endereco", ["enderecoMarcacaoId"])
|
||||
.index("by_funcionario_ativo", ["funcionarioId", "ativo"])
|
||||
.index("by_endereco_ativo", ["enderecoMarcacaoId", "ativo"]),
|
||||
|
||||
configuracaoPonto: defineTable({
|
||||
horarioEntrada: v.string(), // HH:mm
|
||||
horarioSaidaAlmoco: v.string(), // HH:mm
|
||||
@@ -1414,6 +1487,9 @@ export default defineSchema({
|
||||
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)
|
||||
// Configurações de geofencing
|
||||
validarLocalizacao: v.optional(v.boolean()), // Habilitar/desabilitar validação de localização
|
||||
toleranciaDistanciaMetros: v.optional(v.number()), // Raio padrão global em metros
|
||||
ativo: v.boolean(),
|
||||
atualizadoPor: v.id("usuarios"),
|
||||
atualizadoEm: v.number(),
|
||||
|
||||
Reference in New Issue
Block a user