R-005 — Vencimento de filiação notifica o trg-club

TLDR: Quando uma filiação vence, o citrg-api empurra um webhook para o trg-club para que o perfil PRO seja rebaixado mesmo que a pessoa nunca mais faça login. O citrg-api é o iniciador do evento, e o webhook é autoritativo: só é enviado depois da guarda de renovação, e o trg-club rebaixa direto ao recebê-lo, sem reconsultar o citrg-api.

Given / When / Then

Dado uma filiação cujo valid_until foi ontem, e cujo usuário não tem nenhuma filiação paga com valid_until posterior Quando o cron diário Notifications::Memberships::Expiration::ExpiredYesterdayJob roda (GoodJob, 0 8 * * *) Então além do e-mail de lembrete, é enfileirado um NotifyTrgClubJob para aquela filiação, que faz POST de { email, register_number } para citrg/memberships/expired no trg-club

Tabela de decisão

Situação da filiação vencida ontem E-mail de lembrete Notificação ao trg-club
sem renovação paga posterior enviado enviada
com renovação paga de valid_until maior não enviado não enviada
filiação apagada antes do job rodar — job descartado (discard_on ActiveRecord::RecordNotFound)
trg-club fora do ar enviado retry até 10 tentativas (~4h)

Restrições

  • A guarda de renovação vive em BaseExpirationJob#perform e é anterior tanto ao e-mail quanto à notificação: se existe qualquer filiação paga com valid_until maior, a filiação é pulada por completo. A guarda não exige aprovação de admin.
  • O loop do cron nunca faz HTTP. notify_external apenas enfileira um NotifyTrgClubJob por filiação vencida — e-mail e notificação falham de forma independente, e a falha de um membro não afeta os demais.
  • TrgClubService levanta TrgClubService::Error em qualquer falha (erro de conexão, timeout, resposta não-2xx). O NotifyTrgClubJob declara retry_on TrgClubService::Error, wait: :polynomially_longer, attempts: 10 — janela de aproximadamente 4 horas, persistida pelo GoodJob no Postgres, então sobrevive a restart e é visível/re-executável em /good_job.
  • O webhook é autoritativo por decisão de projeto: reconsultar o citrg-api no recebimento perderia o evento sempre que o citrg-api estivesse momentaneamente indisponível. Um rebaixamento indevido se auto-corrige no próximo login do membro (auto_subscribe_pro no trg-club).
  • O e-mail de lembrete de vencimento não teve o comportamento alterado por esta regra.

Configuração

Variável Papel
TRG_CLUB_API_URL URL base do trg-club. Default https://api.trgclub.com/; staging https://staging-api.trg.club/
APOLO_ACCESS_TOKEN token da integração trg-club↔citrg já existente (o mesmo validado na entrada como apolo-access-token), enviado no header X-Security-Signature-Token. Não há segredo novo a configurar

Contrato com o trg-club

  • Transporte: POST JSON para citrg/memberships/expired.
  • Autenticação: segredo compartilhado no header X-Security-Signature-Token.
  • Corpo: { "email": "<e-mail do membro>", "register_number": <bigint> }. O e-mail vai em minúsculas.
  • Chave de match: email.
  • Resposta: o trg-club devolve 200 para aceito/conhecido/desconhecido-mas-processado e 401 para token inválido. O citrg-api não depende do corpo da resposta.

Código

  • app/services/trg_club_service.rb
  • app/jobs/notifications/memberships/expiration/base_expiration_job.rb — hook notify_external
  • app/jobs/notifications/memberships/expiration/expired_yesterday_job.rb
  • app/jobs/notifications/memberships/expiration/notify_trg_club_job.rb
  • config/initializers/good_job.rb — cron 0 8 * * *

Teste vinculado

test/services/trg_club_service_test.rb, test/jobs/notifications/memberships/expiration/expired_yesterday_job_test.rb, test/jobs/notifications/memberships/expiration/notify_trg_club_job_test.rb

Relacionados