Merge branch 'master' into call-audio-video-jitsi

This commit is contained in:
2025-11-21 19:54:01 -03:00
committed by GitHub
50 changed files with 5698 additions and 1630 deletions

View File

@@ -535,7 +535,7 @@ export default defineSchema({
ultimaTentativaLogin: v.optional(v.number()), // timestamp da última tentativa
// Campos de Chat e Perfil
avatar: v.optional(v.string()), // "avatar-1" até "avatar-15" ou storageId
fotoPerfil: v.optional(v.id("_storage")),
setor: v.optional(v.string()),
statusMensagem: v.optional(v.string()), // max 100 chars
@@ -761,7 +761,7 @@ export default defineSchema({
v.literal("sala_reuniao")
),
nome: v.optional(v.string()), // nome do grupo/sala
avatar: v.optional(v.string()), // avatar do grupo/sala
participantes: v.array(v.id("usuarios")), // IDs dos participantes
administradores: v.optional(v.array(v.id("usuarios"))), // IDs dos administradores (apenas para sala_reuniao)
ultimaMensagem: v.optional(v.string()),
@@ -1453,6 +1453,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()),
@@ -1487,6 +1506,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
@@ -1500,6 +1573,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(),