Pular para o conteúdo principal

Triggers e Eventos de Notificação

Pilar: 03 — Notificações
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/web/checkin.py), gatein-app (src/services/notifications)


1. Mapeamento Completo de Triggers e Eventos

A tabela abaixo lista todos os disparadores do ecossistema Gatein, sua origem, canal, timing e regras de idempotência:

EventoTrigger / OrigemDestinatárioCanalTimingPayload data.typeIdempotência / Trava
Check-in AprovadoOperador Terminal no Web AppMotoristaPush FCM (Canal checkin)ImediatoCHECKIN_APPROVED1 por Check-in aprovado
Check-in RejeitadoOperador Terminal no Web AppMotoristaPush FCM (Canal checkin)ImediatoCHECKIN_REJECTED1 por Check-in rejeitado
Lembrete de 1 DiaAPScheduler (check_1day_reminders)MotoristaPush FCM (Canal appointment)Hourly (+23h a +25h)REMINDER_1DAYLog em appointment_logs
Lembrete de 12 HorasAPScheduler (check_12h_reminders)MotoristaPush FCM (Canal appointment)Every 15m (+12h ± 7.5m)COUNTDOWNLog em appointment_logs
Abertura de JanelaAPScheduler (check_window_open)MotoristaPush FCM (Canal appointment)Every 5m (Janela Ativa)WINDOW_OPENLog em appointment_logs
Nova Viagem AtribuídaDespachante no Web App / APIMotoristaPush FCM (Canal trip)ImediatoTRIP_ASSIGNED1 por Trip criada
Novo AnúncioAdmin de Comunicação no Web AppMotoristas da EmpresaPush FCM (Canal announcement)Imediato / AgendadoANNOUNCEMENT_PUBLISHED1 por Anúncio publicado
Alerta de SegurançaMotorista aciona botão SOS ou SistemaMotorista + CentralPush FCM (Canal security)Imediato (Priority MAX)SECURITY_ALERTSem trava (Reenviável)

2. Detalhamento Técnico dos Triggers de Agendamento

2.1 Trigger REMINDER_1DAY

  • Condição SQL: status == 'ACTIVE' AND window_start BETWEEN (now + 23h) AND (now + 25h).
  • Comportamento: Se o motorista possuir apenas 1 agendamento, exibe a hora exata ("Você possui um agendamento em Terminal Santos às 14:00"). Se possuir múltiplos, consolida a quantidade ("Você possui 3 agendamentos amanhã").

2.2 Trigger COUNTDOWN (12 Horas)

  • Condição SQL: status == 'ACTIVE' AND window_start BETWEEN (now + 11h52m30s) AND (now + 12h07m30s).
  • Comportamento: Injeta no payload o atributo target_timestamp contendo o timestamp ISO exato do window_start. O aplicativo mobile utiliza esse atributo para iniciar um timer/countdown na interface local do card.

2.3 Trigger WINDOW_OPEN

  • Condição SQL: status == 'ACTIVE' AND (window_start - start_tolerance) <= now <= (window_end + end_tolerance).
  • Comportamento: Alerta o motorista que o veículo já pode entrar na fila física ou realizar o check-in remoto via GPS/Geofence.

3. Fluxo de Disparo Reativo no Backend (Código de Exemplo)

Quando o operador clica em "Aprovar Check-in" no Web App, o handler executa:

# app/api/web/checkin.py
@router.post("/checkin/{checkin_id}/approve")
def approve_checkin(checkin_id: str, db: Session = Depends(get_db)):
checkin = db.query(Checkin).get(decode_id(checkin_id))
checkin.status = "APPROVED"

# Emite o Ticket Digital
ticket = create_ticket_for_checkin(db, checkin)
db.commit()

# Dispara a notificação Push de forma síncrona/reativa
notify_user_by_tax_id(
db=db,
tax_id=checkin.appointment.user_tax_id,
title="Check-in Aprovado!",
body=f"Seu check-in em {checkin.terminal.name} foi aprovado. Clique para ver seu Ticket.",
data={
"type": "CHECKIN_APPROVED",
"appointment_id": encode_id(checkin.appointment_id),
"ticket_id": encode_id(ticket.id)
}
)

4. Regras de Supressão e Condições de Guarda

  1. Guarda de Exclusão Lógica (deleted_at): Nenhuma notificação é disparada para agendamentos, viagens ou motoristas com deleted_at IS NOT NULL.
  2. Guarda de Precedência de Cancelamento: Se um agendamento for transicionado para CANCELLED antes da execução dos jobs do APScheduler, a checagem em AppointmentLog ou no status do banco interrompe o envio imediatamente.
  3. Guarda de Permissão do Sistema Operacional: Se o motorista revogou a permissão de notificações push nas configurações do Android/iOS, o Firebase retém o status, mas a notificação local do Notifee não é exibida.