Pular para o conteúdo principal

Anúncios — Gestão pelo Admin (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/admin/Announcements), gatein-server (app/api/web/announcements.py, app/models.py), gatein-app (src/screens/AnnouncementsScreen, FCM Push Notifications)


1. Visão Geral e Integração com o App Mobile

O módulo de Gestão de Anúncios e Comunicados no Web App permite que Administradores de Terminais criem, editem, agendem e publiquem avisos operacionais, alertas de segurança em pátio e informativos institucionais direcionados aos motoristas de aplicativo.

Quando um anúncio é publicado ou atinge sua data de agendamento (start_at), o servidor FastAPI aceita a publicação e pode disparar automaticamente Notificações Push via Firebase Cloud Messaging (FCM) contendo um Deep Link (announcement_id) que abre o comunicado em tela cheia no aplicativo mobile.

1.1 Diagrama de Sequência de Publicação e Notificação FCM Batch

sequenceDiagram
autonumber
actor A as Admin do Terminal (Web App)
participant S as Gatein Server (FastAPI)
participant ST as Cloud Storage (S3/Firebase)
participant DB as PostgreSQL
participant FCM as Firebase Messaging
actor M as Motorista (App Mobile)

A->>S: POST /web/uploads (Upload do Banner de Imagem)
S->>ST: Envia imagem para o Bucket
ST-->>S: Retorna URL pública da imagem

A->>S: POST /web/announcements (title, description, image_url, start_at: now())
S->>DB: Insere registro na tabela announcements (is_active = True)
S->>FCM: Envia Push FCM em lote para motoristas elegíveis (payload: announcement_id)
S-->>A: HTTP 201 (Anúncio publicado com sucesso)

FCM-->>M: Notificação Push: "Novo Comunicado do Terminal"
M->>M: Toca na notificação -> Deep Link abre o Anúncio no App

2. Estruturas de Dados e Schemas Explícitos

2.1 Modelo Relacional no Banco de Dados (announcements)

ColunaTipo SQLConstraintsDescrição / Regra
idUUIDPRIMARY KEY, Default gen_random_uuid()Identificador único interno
company_idUUIDFOREIGN KEY (companies.id), NOT NULLEmpresa criadora do comunicado
titleVARCHAR(255)NOT NULLTítulo do anúncio
subtitleVARCHAR(255)NULLABLESubtítulo ou resumo explicativo
descriptionTEXTNULLABLECorpo do texto completo em Markdown/HTML
image_urlVARCHAR(512)NULLABLEURL da imagem do banner
image_positionJSONBDEFAULT '{"x": 50, "y": 50}'Coordenadas de ajuste de corte da imagem na UI
urlVARCHAR(512)NULLABLELink externo para navegação ao clicar
is_activeBOOLEANNOT NULL, Default TrueStatus de ativação
start_atTIMESTAMPTZNULLABLEData/hora programada de início da exibição
end_atTIMESTAMPTZNULLABLEData/hora de expiração e expulso

2.2 Schemas de Requisição do Web App (CreateAnnouncementPayload)

{
"title": "Interdição do Gate 02 para Obras de Asfalto",
"subtitle": "Manutenção preventiva na pista interna de triagem",
"description": "Informamos a todos os motoristas que o Gate 02 estará fechado. Utilize exclusivamente o Gate 04.",
"image_url": "https://cdn.gatein.app/announcements/manutencao_gate2.jpg",
"image_position": { "x": 50, "y": 50 },
"url": "https://terminal-santos.com.br/comunicados/gate2",
"is_active": true,
"start_at": "2026-08-04T08:00:00Z",
"end_at": "2026-08-06T18:00:00Z"
}

3. Regras de Negócio Explícitas (RN-ANC-ADM-XXX)

RN-ANC-ADM-001: Anúncios sem Data de Expiração (end_at == NULL)

Se o Administrador deixar o campo end_at como nulo (NULL), o anúncio permanecerá ativo e elegível para exibição por tempo indeterminado, desde que respeitadas a flag is_active == True e a regra de concorrência da janela deslizante do app mobile (máximo de 3 anúncios simultâneos por empresa).

RN-ANC-ADM-002: Preservação Histórica e Soft-Delete

Anúncios que expirarem (end_at < now()) ou que forem desativados pelo Administrador não são deletados do banco de dados. O histórico é preservado na tabela announcements para fins de auditoria de comunicados e logs de visualização dos motoristas (announcement_logs).

RN-ANC-ADM-003: Agendamento Futuro (start_at > now())

Se a data start_at for configurada para um timestamp no futuro, o anúncio é gravado com status agendado. Ele não será retornado pela API mobile nem gerará notificações FCM até que a data/hora programada seja atingida.

RN-ANC-ADM-004: Disparo Único de Notificação Push FCM na Publicação

A notificação Push FCM em massa para os motoristas da empresa é disparada uma única vez no momento em que o anúncio é publicado ativamente (start_at <= now() e is_active == True). Edições subsequentes em textos ou títulos de um anúncio já publicado não disparam novas notificações em massa aos motoristas para evitar spam.


4. Detalhamento de Endpoints

4.1 GET /web/announcements

Retorna a listagem de todos os anúncios criados pela empresa do administrador, com filtros por status (active, scheduled, expired).

4.2 POST /web/announcements

Cria e publica/agenda um novo anúncio, efetuando o upload da imagem e disparando Push FCM em batch se ativo.

4.3 PUT /web/announcements/{id}

Atualiza os campos de texto, imagem, links e datas do anúncio.

4.4 DELETE /web/announcements/{id}

Marca o anúncio como desativado (is_active = False).


5. Regras de Segurança e Tabela de Erros

Código HTTPCódigo InternoCausa RaizAção no Web App
400 Bad RequestINVALID_EXPIRATION_DATEData end_at é anterior à data start_atCorrigir o intervalo de datas no formulário
400 Bad RequestMISSING_BANNER_IMAGETipo do anúncio exige imagem e a URL não foi fornecidaRealizar upload da imagem antes de salvar
404 Not FoundANNOUNCEMENT_NOT_FOUNDAnúncio informado não pertence à empresa do adminAtualizar a lista de comunicados na UI