Gestão e Configuração de Appointments (Web App)
Pilar: 02 — Funcionalidades Core / Web App
Status: 🟢 Implementado
Última Revisão Técnica: 2026-08-03
Módulos Conectados:gatein-web(src/screens/AppointmentsPage,src/screens/CheckinApprovalModal),gatein-server(app/api/web/appointments.py,app/models.py),gatein-app(src/screens/Home,src/screens/TicketScreen)
1. Visão Geral e Conectividade com o App Mobile
O módulo de Gestão de Appointments (Agendamentos) no Web App é o painel de controle operacional de Terminais e Transportadoras. Através desta interface, os operadores criam agendamentos vinculados ao CPF do motorista, definem janelas de atendimento, monitoram o status em tempo real do pátio e realizam a aprovação ou rejeição de check-ins iniciados pelos motoristas via aplicativo mobile.
1.1 Diagrama do Ciclo Bidirecional Web ↔ Mobile
sequenceDiagram
autonumber
actor T as Operador de Terminal (Web App)
participant S as Gatein Server (FastAPI)
participant DB as PostgreSQL
participant FCM as Firebase Messaging
actor M as Motorista (App Mobile)
T->>S: POST /web/appointments (CPF: "12345678901", janela, carga)
S->>DB: Insere registro em appointments (status: ACTIVE)
S->>FCM: Envia Push Notification (type: NEW_APPOINTMENT)
FCM-->>M: Notificação: "Você possui um novo agendamento no Terminal!"
note over M, S: Motorista aproxima-se do pátio e realiza o Check-in no App Mobile
M->>S: POST /mobile/checkin/{terminal_id}
S->>DB: Atualiza Appointment.status -> CHECKED_IN
S-->>T: Atualiza painel do Web App em tempo real via WebSocket
T->>S: POST /web/checkin/approve (appointment_id)
S->>DB: Cria registro na tabela tickets (Snapshot JSONB)
S->>DB: Transiciona status -> IN_PROGRESS
S->>FCM: Envia Push Notification (type: CHECKIN_APPROVED)
FCM-->>M: Notificação: "Acesso Liberado! Veja seu Ticket Digital."
2. Estrutura dos Dados e Schemas Explícitos
2.1 Modelo Relacional no Banco de Dados (appointments)
| Coluna | Tipo SQL | Constraints | Descrição / Regra |
|---|---|---|---|
id | UUID | PRIMARY KEY, Default gen_random_uuid() | Identificador único interno |
terminal_id | UUID | FOREIGN KEY (terminals.id), NOT NULL | Terminal responsável pelo atendimento |
user_tax_id | VARCHAR(14) | NOT NULL, INDEX | CPF do motorista (apenas números) |
ref | VARCHAR(64) | NULLABLE | Código da Ordem de Carga/NF (ERP externo) |
status | VARCHAR(32) | NOT NULL, Default 'ACTIVE' | Estado no ciclo de vida (PLANNED, ACTIVE, CHECKED-IN, IN_PROGRESS, COMPLETED, CANCELLED) |
window_start | TIMESTAMPTZ | NOT NULL | Início da janela agendada de chegada |
window_end | TIMESTAMPTZ | NOT NULL | Término da janela agendada |
start_tolerance | INTEGER | DEFAULT 0 | Minutos de tolerância antes de window_start |
end_tolerance | INTEGER | DEFAULT 0 | Minutos de tolerância depois de window_end |
custom_data | JSONB | NULLABLE | Objeto de chave-valor para preenchimento de layouts dinâmicos |
2.2 Schemas de Requisição do Web App
Payload de Criação de Agendamento (CreateAppointmentWebPayload):
{
"user_tax_id": "12345678901",
"ref": "ORD-2026-9948",
"window_start": "2026-08-04T10:00:00Z",
"window_end": "2026-08-04T12:00:00Z",
"start_tolerance": 60,
"end_tolerance": 30,
"layout_ref": "v2_standard_card",
"custom_data": {
"peso_estimado": "45.000 kg",
"tipo_carroceria": "Graneleiro",
"gate_entrada": "Gate 03"
}
}
Payload de Rejeição de Check-in (RejectCheckinPayload):
{
"reason": "Docas de grãos temporariamente sem energia elétrica. Retorne em 30 min."
}
3. Regras de Negócio Explícitas (RN-APT-WEB-XXX)
RN-APT-WEB-001: Validação de Vínculo de CPF do Motorista
Ao criar um agendamento no Web App, o sistema verifica se o CPF informado (user_tax_id) já possui cadastro na plataforma:
- Se o motorista existir na tabela
usersoudrivers, o agendamento é associado diretamente. - Se não existir, o agendamento é criado em estado
PLANNEDaguardando que o motorista conclua o onboarding no app mobile com aquele mesmo CPF.
RN-APT-WEB-002: Regra de Imutabilidade Pós-Emissão de Ticket
Um agendamento que teve seu check-in aprovado (status == "IN_PROGRESS" ou "COMPLETED") e que já possui um Ticket Digital gerado não pode ser cancelado ou excluído pelo operador Web. Qualquer tentativa retornará HTTP 400 (CANNOT_CANCEL_APPOINTMENT_WITH_TICKET).
RN-APT-WEB-003: Motivo Obrigatório em Rejeição de Check-in
Se o operador do terminal optar por rejeitar um check-in pendente no painel Web:
- É obrigatório preencher o campo
reason(mínimo 5 caracteres). - O agendamento retorna do estado
CHECKED-INpara o estadoACTIVE. - Um Push FCM com
type: "CHECKIN_REJECTED"é enviado instantaneamente para o motorista contendo a justificativa informada pelo operador.
RN-APT-WEB-004: Prevenção de Conflito de Janela (Overlapping Booking)
O servidor rejeita a criação de agendamentos duplicados para o mesmo motorista (user_tax_id) e mesmo terminal onde as janelas temporais se sobreponham totalmente, evitando múltiplos compromissos simultâneos no mesmo gate.
4. Detalhamento de Endpoints
4.1 POST /web/appointments
Cria um novo agendamento para o CPF do motorista e notifica o dispositivo mobile.
4.2 GET /web/appointments
Retorna a listagem paginada de agendamentos da empresa com filtros de status (active, checked_in, history).
4.3 POST /web/checkin/approve/{appointment_id}
Aprova o check-in do motorista, altera o status para IN_PROGRESS e emite o Ticket Digital.
4.4 POST /web/checkin/reject/{appointment_id}
Rejeita o check-in solicitando justificativa e reverte o estado do agendamento.
5. Regras de Segurança e Tabela de Erros
| Código HTTP | Código Interno | Causa Raiz | Ação no Web App |
|---|---|---|---|
400 Bad Request | CANNOT_CANCEL_APPOINTMENT_WITH_TICKET | Agendamento possui ticket emitido e não pode ser cancelado | Desabilitar botão de cancelamento na UI |
400 Bad Request | REASON_REQUIRED | Tentativa de rejeitar check-in sem informar motivo | Exibir campo de texto obrigatório |
409 Conflict | OVERLAPPING_APPOINTMENT_WINDOW | Motorista já possui agendamento no mesmo horário | Notificar o operador sobre o conflito de agenda |