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:
| Coluna | Tipo SQL | Constraints | Descrição / Regra |
|---|---|---|---|
id | UUID | PRIMARY KEY, Default gen_random_uuid() | Identificador único interno do ticket |
appointment_id | UUID | FOREIGN KEY (appointments.id), NOT NULL | Agendamento de origem |
layout_ref | VARCHAR(64) | NOT NULL | Referência da versão de layout utilizada na renderização |
content | JSONB | NOT NULL | Snapshot imutável dos dados impressos no ticket |
created_at | TIMESTAMPTZ | NOT NULL, Default now() | Timestamp de emissão do ticket |
Tabela ticket_layouts:
| Coluna | Tipo SQL | Constraints | Descrição / Regra |
|---|---|---|---|
id | UUID | PRIMARY KEY, Default gen_random_uuid() | Identificador único do layout |
terminal_id | UUID | FOREIGN KEY (terminals.id), NOT NULL | Terminal detentor da identidade visual |
layout_ref | VARCHAR(64) | NOT NULL | Nome de referência da versão (ex: v1_ticket_gate) |
structure | JSONB | NOT 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:
- 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). - Ativa o sinalizador
KeepAwakepara impedir o bloqueio automático da tela enquanto o motorista aproxima o celular dos leitores ópticos das cancelas. - 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 HTTP | Código Interno | Causa Raiz | Ação Recomendada no App Mobile |
|---|---|---|---|
404 Not Found | TICKET_NOT_FOUND | Ticket inexistente ou pertencente a outro CPF | Notificar motorista e atualizar lista |
422 Unprocessable | INVALID_TICKET_SQID | Hash de ID malformado | Re-solicitar dados via pull-to-refresh |