Pular para o conteúdo principal

Eventos e Ciclo de Vida de Agendamentos (Appointments)

Pilar: 04 — Banco de Dados e Eventos / Eventos
Status: 🟢 Implementado
Última Revisão Técnica: 2026-08-03
Módulos Conectados: gatein-server (app/core/scheduler.py, app/api/web/appointments.py, app/api/public/appointments.py), gatein-app (src/screens/Home)


1. Visão Geral dos Eventos de Agendamento

O módulo de Appointments é a entidade operacional primária do ecossistema Gatein. Qualquer criação, alteração de janela temporal, cancelamento, notificação agendada ou auditoria de engajamento do motorista gera um evento registrado na tabela appointments_logs e dispara reações em tempo real ou agendadas.

sequenceDiagram
autonumber
actor ERP as Terminal / ERP (API Key / Web App)
participant S as Gatein Server (FastAPI)
participant SCHED as APScheduler Engine
participant DB as PostgreSQL
participant FCM as Firebase Messaging
actor M as Motorista (Mobile App)

ERP->>S: POST /web/appointments (Cria Agendamento com Ref + Janela + Driver TaxID)
S->>DB: Inserção do Appointment (Status: PLANNED ou ACTIVE)
S->>DB: Registra AppointmentLog (event: CREATED)
S->>FCM: notify_user_by_tax_id(type: APPOINTMENT_CREATED)
FCM-->>M: Notificação Push: "Novo Agendamento Criado!"

note over SCHED, DB: Jobs de Background Recorrentes
SCHED->>DB: Executa check_1day_reminders() (23h a 25h antes)
SCHED->>FCM: Push Batch (type: REMINDER_1DAY)
SCHED->>DB: Executa check_12h_reminders() (12h antes)
SCHED->>FCM: Push Batch (type: COUNTDOWN)
SCHED->>DB: Executa check_window_open() (Janela Aberta)
SCHED->>FCM: Push (type: WINDOW_OPEN)

M->>S: POST /mobile/activities/log-events (Visualizou / Clicou)
S->>DB: Registra AppointmentLog (event: VIEWED / CLICKED)

ERP->>S: POST /web/appointments/cancel (Cancela Agendamento)
S->>DB: Atualiza status -> CANCELLED
S->>DB: Registra AppointmentLog (event: DELETED / CHECKIN_CANCELLED)
S->>FCM: Push: "Agendamento Cancelado"

2. Dicionário de Eventos (AppointmentEvent)

Enum AppointmentEventOrigem da InvocaçãoDescrição do EventoEfeitos Colaterais / Notificações
createdWeb App / API PúblicaAgendamento criado pelo Terminal/TransportadorInjeta log em appointments_logs e envia Push FCM APPOINTMENT_CREATED
updatedWeb App / API PúblicaAlteração de janela, placa, carga ou layout_refAtualiza o banco, grava log em JSON e envia Push APPOINTMENT_UPDATED
deletedWeb App / API PúblicaCancelamento ou soft-delete do agendamentoTransiciona status para CANCELLED/DELETED, cancela jobs e envia Push APPOINTMENT_CANCELLED
notification_sentAPSchedulerSucesso no envio de um lembrete em backgroundGrava em appointments_logs com json = {"push_type": "..."} para garantir idempotência
checkin_cancelledEndpoint /mobile/checkin/cancelReversão do check-in pelo motorista ou operadorReverte status de CHECKED-IN para ACTIVE, registra justificativa e notifica motorista
viewedMobile App (log-events)Motorista expandiu o card do agendamento na telaRegistra telemetria do motorista (bateria, horário) sem enviar Push
clickedMobile App (log-events)Motorista clicou na ação principal do cardRegistra telemetria de engajamento do motorista
auto_deactivatedAPScheduler (check_in_progress)Agendamento mantido em IN_PROGRESS por > 24hMarca status como COMPLETED/PAUSED por estouro de tempo limite

3. Eventos Disparados por Background Jobs (APScheduler)

Os 4 jobs de background operam com verificação de idempotência baseada na tabela appointments_logs:

3.1 Evento REMINDER_1DAY

  • Target SQL: Agendamentos com status == 'ACTIVE' e window_start entre now() + 23h e now() + 25h.
  • Idempotência: Ignora agendamentos que já possuem um log em appointments_logs com event == 'notification_sent' e json->>'push_type' == 'REMINDER_1DAY'.

3.2 Evento COUNTDOWN (12 Horas)

  • Target SQL: Agendamentos com status == 'ACTIVE' e window_start entre now() + 11h52m30s e now() + 12h07m30s.
  • Idempotência: Ignora agendamentos que já contêm log de push_type == 'COUNTDOWN'. Envia payload com target_timestamp para a contagem regressiva local no app.

3.3 Evento WINDOW_OPEN

  • Target SQL: Agendamentos ativos dentro da janela permitida ((window_start - start_tolerance) <= now() <= (window_end + end_tolerance)).
  • Idempotência: Envia uma única notificação informando a abertura da janela e libera a ação de check-in remoto via GPS.

4. Regras de Negócio de Eventos de Agendamento (RN-EVT-APT-XXX)

RN-EVT-APT-001: Idempotência de Disparo em Lote

Antes de cada envio em massa de lembretes, o APScheduler consulta em lote os registros de appointments_logs. Agendamentos cujos lembretes já foram disparados anteriormente são filtrados antes da invocação da API do Firebase FCM, reduzindo o consumo de cota.

RN-EVT-APT-002: Gravação Auditável de Payload de Alteração

Sempre que o evento updated for disparado pela API, o campo json do log em appointments_logs gravará a diferença (diff) entre os atributos antigos e novos (ex: {"old_window_start": "...", "new_window_start": "..."}).

RN-EVT-APT-003: Cancelamento Cascata de Agendamentos e Check-ins

A ocorrência do evento deleted (cancelamento) em um agendamento forçará a invalidação imediata de qualquer solicitação de check-in pendente associada em checkins, enviando notificação Push com o motivo do cancelamento para o motorista.