Check-in Antecipado e Remoto (App Mobile)
Pilar: 02 — Funcionalidades Core / App Mobile
Status: 🟢 Implementado
Última Revisão Técnica: 2026-08-03
Módulos Conectados:gatein-app(src/screens/CheckinProcessing,src/screens/CheckinFail),gatein-server(app/api/mobile/checkin.py,app/api/sockets/handlers/checkin.py)
1. Visão Geral da Funcionalidade
O Check-in Antecipado e Remoto é a funcionalidade responsável por permitir que o motorista solicite sua autorização de entrada e recepção em pátio através do aplicativo mobile antes mesmo de se aproximar dos gates físicos ou totens de atendimento.
O acionamento pode ocorrer de duas formas:
- Automático via Geofence (Cerca Virtual): O aplicativo detecta a entrada do veículo no raio/polígono de coordenadas do terminal e apresenta um prompt de confirmação proativo.
- Manual no Card de Agendamento: O motorista aciona manualmente o botão "Realizar Check-in" no card do agendamento ativo.
2. Diagrama de Sequência e Handshake Socket.IO
sequenceDiagram
autonumber
actor M as Motorista (Mobile App)
participant S as Gatein Server (FastAPI)
participant SIO as Socket.IO (/checkin namespace)
participant HW as Hardware / Totem Terminal (Physical)
participant DB as PostgreSQL
participant FCM as Firebase Messaging
M->>S: POST /mobile/checkin/{terminal_id} (REST Request)
S->>S: Decodifica Sqid do terminal_id
S->>SIO: Consulta dicionário em memória active_terminals
alt Terminal Offline
S-->>M: HTTP 503 ("Terminal encontra-se offline")
else Terminal Online (SID Ativo)
S-->>M: HTTP 200 ("Check-in solicitado, aguarde notificação")
S->>S: Inicia BackgroundTask: run_async_checkin()
S->>SIO: sio.call('request_checkin', payload={tax_id}, timeout=15s)
SIO->>HW: Dispara sinal para totem / automação de pátio
alt Handshake Timeout (> 15,0s) ou Erro de Comunicação
HW--xSIO: Sem resposta / Exceção no hardware
S->>FCM: notify_user_by_tax_id(type: CHECKIN_FAILED)
FCM-->>M: Push + Notifee: "Tempo limite excedido no terminal. Tente novamente."
else Resposta Válida do Hardware (List of Tickets)
HW-->>SIO: Retorna JSON de tickets + dados de liberação
S->>DB: Validação Fail-Fast: checa se ticket_layout_ref existe
S->>DB: Transiciona Appointment.status -> CHECKED-IN
S->>DB: Persiste snapshot na tabela tickets
S->>FCM: notify_user_by_tax_id(type: CHECKED-IN)
FCM-->>M: Push + Notifee: "Acesso liberado! Toque para ver seu Ticket."
end
end
3. Detalhamento de Endpoints
3.1 Disparar Check-in Remoto (POST /mobile/checkin/{terminal_id})
Inicia a sequência assíncrona de comunicação com o terminal físico.
- Path Parameters:
terminal_id(string, obrigatório): Identificador em formato Sqid do terminal.
- Headers:
Authorization: Bearer <jwt_token>
Lógica de Execução no Servidor (Step-by-Step):
- Decodificação de Sqid: Converte
terminal_id(hash Sqid) para oBigIntegerinterno do PostgreSQL viadecode_id(). - Checagem de Presença Socket.IO: Inspeciona o dicionário singleton em memória
active_terminalsno namespace/checkin. - Rejeição Fail-Fast: Se o terminal não possuir conexão Socket.IO ativa, encerra imediatamente retornando HTTP 503 (
TERMINAL_OFFLINE). - Agendamento Assíncrono: Agenda o método corrotina
run_async_checkin()através doBackgroundTasksdo FastAPI e responde HTTP 200 imediatamente com o payload{ "success": true, "message": "Check-in em processamento." }.
3.2 Cancelar Check-in (POST /mobile/checkin/cancel/{appointment_id})
Reverte um check-in pendente ou liberado de volta ao estado inicial agendado (ACTIVE).
- Path Parameters:
appointment_id(string, obrigatório): Hash Sqid do agendamento.
- Payload de Requisição (
CancelCheckinRequest):
{
"reason": "Problema mecânico na carreta durante aguardo na fila"
}
Lógica de Processamento:
- Valida se o
appointment_iddecodificado existe e pertence aouser_tax_idautenticado. - Verifica se o
statusatual éCHECKED-INouON_GOING. Caso contrário, retorna HTTP 400 (INVALID_STATUS_FOR_CANCELLATION). - Reverte o status do agendamento para
ACTIVE. - Insere registro de auditoria na tabela
appointment_logscom o eventoCHECKIN_CANCELLEDe a justificativa fornecida. - Dispara Push FCM informando o cancelamento ao aplicativo.
4. Regras de Negócio Explícitas (RN-CHK-XXX)
RN-CHK-001: Validação Rígida da Janela Temporal com Tolerâncias
O aplicativo mobile e o backend autorizam o disparo do check-in se, e somente se, a hora atual do servidor satisfizer a equação:
(window_start - start_tolerance) <= now() <= (window_end + end_tolerance)
Caso o motorista acione o check-in fora dessa janela, o servidor retorna erro HTTP 400 (OUT_OF_WINDOW_TOLERANCE).
RN-CHK-002: Handshake de Hardware com Timeout de 15,0 Segundos
A chamada RPC via Socket.IO (sio.call('request_checkin')) emitida pelo servidor FastAPI em direção ao hardware local do terminal possui um tempo limite incondicional de 15,0 segundos. Excedido esse tempo:
- A corrotina captura a exceção
TimeoutError. - O status do agendamento não é alterado.
- Um Push FCM de erro com
type: "CHECKIN_FAILED"é despachado para o celular do motorista.
RN-CHK-003: Fail-Fast de Layouts de Ticket
Antes de persistir a liberação e transicionar o estado do agendamento no PostgreSQL, o backend verifica se os códigos de layout (layout_ref) retornados pelo hardware existem na tabela ticket_layouts. Se qualquer layout retornado for inexistente ou inválido, a transação do banco sofre rollback e o check-in é abortado.
RN-CHK-004: Inibição por Integração de Segurança Pendente
Se a empresa Terminal possuir a configuração safety_integration_blocks_checkin = True e o motorista possuir pendência na tabela safety_integrations (is_safety_integration_pending == True), a interface do app oculta/desabilita o botão de check-in. O backend rejeita requisições diretas com HTTP 403 (SAFETY_INTEGRATION_REQUIRED).
RN-CHK-005: Desduplicação de Check-in em Andamento (Concurrency Control)
É proibido disparar requisições concorrentes de check-in para o mesmo agendamento. Se já houver uma tarefa assíncrona em processamento para aquele appointment_id, o backend retorna HTTP 409 (CHECKIN_ALREADY_IN_PROGRESS).
5. Regras de Segurança e Tratamento de Erros
| Código HTTP | Código Interno | Motivo / Causa Raiz | Ação Recomendada no App Mobile |
|---|---|---|---|
400 Bad Request | OUT_OF_WINDOW_TOLERANCE | Tentativa de check-in fora da janela agendada | Exibir modal com horários permitidos |
403 Forbidden | SAFETY_INTEGRATION_REQUIRED | Integração de segurança pendente | Redirecionar para o módulo de Segurança |
409 Conflict | CHECKIN_ALREADY_IN_PROGRESS | Requisição idêntica já sendo processada | Manter tela de carregamento ativada |
503 Service Unavailable | TERMINAL_OFFLINE | Terminal sem conexão Socket.IO ativa | Exibir alerta de terminal temporariamente indisponível |