Pular para o conteúdo principal

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)

ColunaTipo SQLConstraintsDescrição / Regra
idUUIDPRIMARY KEY, Default gen_random_uuid()Identificador único interno
terminal_idUUIDFOREIGN KEY (terminals.id), NOT NULLTerminal responsável pelo atendimento
user_tax_idVARCHAR(14)NOT NULL, INDEXCPF do motorista (apenas números)
refVARCHAR(64)NULLABLECódigo da Ordem de Carga/NF (ERP externo)
statusVARCHAR(32)NOT NULL, Default 'ACTIVE'Estado no ciclo de vida (PLANNED, ACTIVE, CHECKED-IN, IN_PROGRESS, COMPLETED, CANCELLED)
window_startTIMESTAMPTZNOT NULLInício da janela agendada de chegada
window_endTIMESTAMPTZNOT NULLTérmino da janela agendada
start_toleranceINTEGERDEFAULT 0Minutos de tolerância antes de window_start
end_toleranceINTEGERDEFAULT 0Minutos de tolerância depois de window_end
custom_dataJSONBNULLABLEObjeto 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 users ou drivers, o agendamento é associado diretamente.
  • Se não existir, o agendamento é criado em estado PLANNED aguardando 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:

  1. É obrigatório preencher o campo reason (mínimo 5 caracteres).
  2. O agendamento retorna do estado CHECKED-IN para o estado ACTIVE.
  3. 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 HTTPCódigo InternoCausa RaizAção no Web App
400 Bad RequestCANNOT_CANCEL_APPOINTMENT_WITH_TICKETAgendamento possui ticket emitido e não pode ser canceladoDesabilitar botão de cancelamento na UI
400 Bad RequestREASON_REQUIREDTentativa de rejeitar check-in sem informar motivoExibir campo de texto obrigatório
409 ConflictOVERLAPPING_APPOINTMENT_WINDOWMotorista já possui agendamento no mesmo horárioNotificar o operador sobre o conflito de agenda