Envio segmentado por plataforma
TLDR: Adiciona o campo
platform_targetemNotificationpara permitir ao admin enviar uma push diretamente para o tópicoplatform_iosouplatform_androidvia Firebase, reutilizando oNotificationService.
Contexto
A spec anterior (20260522145722_notifications_platform_topics.md) criou a infraestrutura de tópicos platform_ios / platform_android (campo topics, service, backfill). Agora o admin precisa poder usar esses tópicos: criar uma Notification no Django Admin e marcar que ela deve ir para todos os iOS ou todos os Android.
Hoje o NotificationService._get_target só conhece duas formas de rotear: send_to_all (broadcast em all_<env>) e push_device (token único). Falta o caso intermediário: broadcast por plataforma.
Objetivos
- Adicionar o campo
platform_targetemNotification(choicesios/android, opcional) - Atualizar
_get_targetpara priorizarplatform_targetquando preenchido - Quando
platform_targetestá preenchido, a notificação vai para o tópicoplatform_<choice>independente desend_to_alloupush_device - Sem alterações no payload
datapor padrão (o admin preenche manualmente se quiser) - Mostrar
platform_targetna lista do Django Admin - Validar no admin que
platform_targetesend_to_allsão mutuamente exclusivos
Fora de escopo
— (não registrado na spec original)
Mudanças
apps/notifications/models.py
Adicionar em Notification:
python
PLATFORM_CHOICES = (("ios", "iOS"), ("android", "Android"))
platform_target = models.CharField(
blank=True, null=True, max_length=20, choices=PLATFORM_CHOICES,
verbose_name="Plataforma alvo",
help_text="Se preenchido, envia para todos os dispositivos da plataforma escolhida (ignora 'Enviar para todos?' e dispositivo específico).",
)
apps/notifications/migrations/0018_notification_platform_target.py (novo)
Schema migration adicionando platform_target como nullable.
apps/notifications/services/notification.py
Atualizar _get_target:
python
def _get_target(self) -> _NotificationTarget:
if self.notification.platform_target:
return _NotificationTarget(kind="topic", value=f"platform_{self.notification.platform_target}")
if self.notification.send_to_all:
return _NotificationTarget(kind="topic", value=self.all_topic())
token = getattr(self.notification.push_device, "token", None)
if token:
return _NotificationTarget(kind="token", value=token)
return _NotificationTarget(kind="none", value=None)
Precedência: platform_target > send_to_all > push_device.
apps/notifications/admin.py
list_displaydoNotificationAdminpassa a incluirplatform_target- Adicionar
NotificationAdminFormcom validação emclean()que levantaValidationErrorquandoplatform_targetesend_to_allvêm juntos; associar viaform = NotificationAdminForm
tests/notifications/test_notification_service.py
Testes Triple-A com messaging.send mockado:
- platform_target='ios' → mensagem enviada com topic="platform_ios"
- platform_target='android' → topic="platform_android"
- platform_target='ios' + send_to_all=True → platform_target vence
- platform_target='ios' + push_device definido → platform_target vence
- platform_target vazio + send_to_all=True → comportamento existente preservado (all_<env>)
tests/notifications/test_notification_admin.py (novo)
Testes de validação do form do admin, cobrindo as combinações válidas e inválidas de platform_target e send_to_all.
Como verificar
python manage.py migrate notifications— verificar0018aplicada- Django Admin → Notifications → criar nova com
platform_target='ios'e salvar - Confirmar no log/banco que a mensagem FCM foi enviada com
topic="platform_ios"e que apenas devices iOS recebem - Criar outra com
platform_target='android'esend_to_all=Trueao mesmo tempo — deve exibir erro de validação impedindo o save - Criar outra com
send_to_all=Trueeplatform_targetvazio — deve continuar indo paraall_<env>(regressão) pytest tests/notifications/— todos passam
Documentação
- reference/notifications/platform_topics.md — seção “Enviar pelo Admin”