Pular para o conteúdo principal

Ticket Digital de Liberação (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/TicketScreen), gatein-server (app/api/public/tickets.py, app/api/mobile/activities.py)


1. Visão Geral e Arquitetura do Módulo

O Ticket Digital de Liberação é o comprovante oficial de autorização de entrada e atendimento emitido pelo Terminal para o motorista de aplicativo após a aprovação do check-in. Ele substitui fisicamente fichas de papel e senhas impressas, contendo um código QR óptico dinâmico, indicação de gate de entrada, número de doca, balança designada e instruções operacionais.

1.1 Diagrama de Sequência de Emissão e Leitura em Gate

sequenceDiagram
autonumber
actor T as Terminal / Painel Web
participant S as Gatein Server (FastAPI)
participant DB as PostgreSQL
participant FCM as Firebase Messaging
actor M as Motorista / App Mobile
participant SC as Scanner Óptico / Gate Físico

T->>S: POST /web/checkin/approve (Aprova Check-in do Motorista)
S->>DB: Busca TicketLayout ativo do Terminal
S->>S: Constrói JSONB snapshot dos dados operacionais (content)
S->>DB: Insere registro na tabela tickets
S->>DB: Atualiza Appointment.status -> IN_PROGRESS
S->>FCM: Dispara Push FCM (type: CHECKIN_APPROVED, ticket_id: Sqid)
FCM-->>M: Notificação: "Seu Ticket de Entrada foi emitido!"
M->>M: Toca na notificação -> Abre TicketScreen
M->>M: Ativa modo de Brilho Máximo do Visor (100% Brightness + KeepAwake)
M->>SC: Apresenta código QR no leitor do Gate
SC->>S: GET /public/tickets/verify/{qr_code}
S-->>SC: Confirma validade e libera cancela

2. Estruturas de Dados e Schemas Explícitos

2.1 Modelo Relacional no Banco de Dados (tickets e ticket_layouts)

Tabela tickets:

ColunaTipo SQLConstraintsDescrição / Regra
idUUIDPRIMARY KEY, Default gen_random_uuid()Identificador único interno do ticket
appointment_idUUIDFOREIGN KEY (appointments.id), NOT NULLAgendamento de origem
layout_refVARCHAR(64)NOT NULLReferência da versão de layout utilizada na renderização
contentJSONBNOT NULLSnapshot imutável dos dados impressos no ticket
created_atTIMESTAMPTZNOT NULL, Default now()Timestamp de emissão do ticket

Tabela ticket_layouts:

ColunaTipo SQLConstraintsDescrição / Regra
idUUIDPRIMARY KEY, Default gen_random_uuid()Identificador único do layout
terminal_idUUIDFOREIGN KEY (terminals.id), NOT NULLTerminal detentor da identidade visual
layout_refVARCHAR(64)NOT NULLNome de referência da versão (ex: v1_ticket_gate)
structureJSONBNOT NULLÁrvore de componentes UI do ticket em JSON

2.2 Schema de Resposta de Ticket na API (TicketResponseSchema)

{
"id": "z9y8x7w6",
"appointment_id": "w8x9k2m1",
"layout_ref": "v1_ticket_gate",
"content": {
"ticket_number": "TKT-994820",
"gate_entrada": "Gate 04",
"doca": "Doca 12",
"balanca": "Balança 02",
"codigo_qr": "984210492810",
"codigo_liberacao": "984210",
"peso_autorizado": "45.000 kg",
"instrucoes": "Mantenha os faróis acesos e respeite o limite de 20km/h."
},
"created_at": "2026-08-04T10:15:22Z"
}

3. Regras de Negócio Explícitas (RN-TKT-XXX)

RN-TKT-001: Imutabilidade Absoluta do Snapshot (content)

O campo content de um Ticket Digital é gerado no instante da aprovação do check-in e nunca é modificado. Alterações posteriores nos dados do agendamento, veículos ou motorista no ERP do terminal não afetam o snapshot gravado. Isso garante valor jurídico e auditabilidade à liberação de pátio.

RN-TKT-002: Motor Brilho Máximo do Visor (QR Scanner Mode)

Ao focar ou visualizar a tela TicketScreen no React Native:

  1. O aplicativo aciona o módulo de controle de hardware (expo-brightness / react-native-device-info) para elevar o brilho do visor para 100% (máximo).
  2. Ativa o sinalizador KeepAwake para impedir o bloqueio automático da tela enquanto o motorista aproxima o celular dos leitores ópticos das cancelas.
  3. Ao sair da tela, o brilho original do dispositivo é restaurado.

RN-TKT-003: Isolamento e Permissões por Tax ID (CPF)

O aplicativo mobile só renderiza tickets vinculados a agendamentos onde appointments.user_tax_id == current_user.tax_id. Requisições para consultar tickets de outros motoristas retornam HTTP 404 (TICKET_NOT_FOUND).

RN-TKT-004: Resiliência Offline e Cache Local

Devido ao sinal de celular frequentemente oscilar nas estruturas de concreto de pátios e coberturas de balança:

  • O ticket emitido é mantido em cache persistente local (AsyncStorage / Zustand store).
  • Uma vez baixado pelo aplicativo, o Ticket Digital pode ser aberto e exibido com seu código QR visual mesmo se o celular estiver sem conexão de rede.

RN-TKT-005: Regra de Resolução Fallback de Layout Dinâmico

Se a estrutura de layout indicada por layout_ref não estiver presente no cache do app ou no banco, o motor de renderização utiliza o componente universal StandardTicketCard para desenhar os campos básicos de content sem interromper a operação do motorista.


4. Detalhamento de Endpoints

4.1 GET /public/tickets/{ticket_id}

Consulta pública de bilhetes de liberação para validação rápida em totens e balanças.

4.2 GET /public/tickets/verify/{qr_code}

Valida a autenticidade de um código QR lido pelos leitores de gate.


5. Regras de Segurança e Tratamento de Erros

Código HTTPCódigo InternoCausa RaizAção Recomendada no App Mobile
404 Not FoundTICKET_NOT_FOUNDTicket inexistente ou pertencente a outro CPFNotificar motorista e atualizar lista
422 UnprocessableINVALID_TICKET_SQIDHash de ID malformadoRe-solicitar dados via pull-to-refresh