Pular para o conteúdo principal

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:

  1. 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.
  2. 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):

  1. Decodificação de Sqid: Converte terminal_id (hash Sqid) para o BigInteger interno do PostgreSQL via decode_id().
  2. Checagem de Presença Socket.IO: Inspeciona o dicionário singleton em memória active_terminals no namespace /checkin.
  3. Rejeição Fail-Fast: Se o terminal não possuir conexão Socket.IO ativa, encerra imediatamente retornando HTTP 503 (TERMINAL_OFFLINE).
  4. Agendamento Assíncrono: Agenda o método corrotina run_async_checkin() através do BackgroundTasks do 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:

  1. Valida se o appointment_id decodificado existe e pertence ao user_tax_id autenticado.
  2. Verifica se o status atual é CHECKED-IN ou ON_GOING. Caso contrário, retorna HTTP 400 (INVALID_STATUS_FOR_CANCELLATION).
  3. Reverte o status do agendamento para ACTIVE.
  4. Insere registro de auditoria na tabela appointment_logs com o evento CHECKIN_CANCELLED e a justificativa fornecida.
  5. 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 HTTPCódigo InternoMotivo / Causa RaizAção Recomendada no App Mobile
400 Bad RequestOUT_OF_WINDOW_TOLERANCETentativa de check-in fora da janela agendadaExibir modal com horários permitidos
403 ForbiddenSAFETY_INTEGRATION_REQUIREDIntegração de segurança pendenteRedirecionar para o módulo de Segurança
409 ConflictCHECKIN_ALREADY_IN_PROGRESSRequisição idêntica já sendo processadaManter tela de carregamento ativada
503 Service UnavailableTERMINAL_OFFLINETerminal sem conexão Socket.IO ativaExibir alerta de terminal temporariamente indisponível