R-004 — Renovação de membro com carteira definitiva é aprovada automaticamente

TLDR: Quem já tem carteira definitiva emitida (users.issued_definitive_card = true) não reenvia documento ao renovar: a nova filiação nasce aprovada (card_status: auto_issued, admin_approved_* preenchidos pelo usuário de sistema “Automático”), o perfil é aprovado automaticamente e o e-mail enviado é o de renovação aprovada, não o de pedido de documentos.

Given / When / Then

Dado um usuário com issued_definitive_card = true Quando o webhook do gateway confirma o pagamento de uma nova filiação (WebhookMembershipService#initialize_new_membership) Então a nova filiação recebe card_status: auto_issued, admin_approved_at/admin_approved_by e card_issued_at/card_issued_by preenchidos com o usuário “Automático”; o user_profile é aprovado via automatic_approve!; nenhum onboarding novo é criado; e o e-mail disparado é MembershipMailer#membership_renewal_approved_email

Tabela de decisão

issued_definitive_card card_status da nova filiação admin_approved_* da filiação user_profile.approval_type Aprovação do perfil Onboarding novo E-mail enviado
true auto_issued preenchidos (“Automático”) automatic automatic_approve! — admin_approved_at = agora não é criado membership_renewal_approved_email (“Sua filiação ao CITRG foi renovada com sucesso”)
false not_issued (default) em branco manual manual_approve! — limpa admin_approved_at/admin_approved_by_id é criado request_documents_for_membership_email

Restrições

  • issued_definitive_card tem responsabilidade única: decidir se a próxima renovação é auto-aprovada/auto-emitida no webhook. Não é consultada em nenhum cálculo de status derivado.
  • issued_definitive_card é escrita em um único lugar: AdminMembershipsService#admin_issue_card, quando a filiação entra em remessa em data igual ou posterior a DATE_RELEASE_NEW_CITRG.
  • Além do webhook, a regra também é aplicada pela aprovação manual de documentos, via Membership::FutureApprove (app/models/membership/future_approve.rb): a filiação seguinte só é auto-aprovada quando o usuário já tem a flag; sem ela, permanece no fluxo manual. Como a flag ainda é false no momento da aprovação de documentos, a re-avaliação acontece na emissão da carteira — ver R-007. Esse caminho envia membership_renewal_approved_email para a filiação seguinte, com a ressalva de duplicidade descrita no R-007. O e-mail da tabela acima é o do webhook e é independente desse.
  • UserProfile#calculate_documentation_status deriva :ok de uma aprovação real do perfil (admin_approved_at), não da flag. O atalho return :ok if user.issued_definitive_card foi removido: a flag significa “a próxima renovação é automática”, e reusá-la no cálculo forçava :ok permanente e global no usuário, independente do estado real da filiação corrente.
  • Membership#automatic_approve! anexa a foto do perfil na carteira, igual a manual_approve! — os dois usam o mesmo attach_profile_picture_to_card. Ele nasceu sem o attach em 12/08/2026 e por isso as filiações auto-aprovadas até 14/09/2026 não têm card_picture. Essas filiações foram corrigidas no dado, por script pontual no console, anexando o blob da foto do perfil — a carteira digital não tem fallback de leitura: ela exibe o card_picture da filiação ou nada.
  • UserProfile#automatic_approve! é o espelho de manual_approve!: grava approval_type = :automatic, admin_approved_at = Time.current e admin_approved_by = o aprovador automático. Cuidado com o nome de manual_approve! — ele zera a aprovação, não aprova.
  • O usuário de sistema “Automático” é criado sob demanda via User.find_or_create_by!(email: "automatico@citrg.com.br") (name: "Automático", admin: true) e reusado nas renovações seguintes.
  • auto_issued conta como carteira efetivamente emitida em todo lugar em que :issued contava. Isso é centralizado em Membership::ISSUED_CARD_STATUSES = %i[issued auto_issued], usado por scope :card_issued (e portanto por active, via with_profile_approved_or_card_issued), scope :card_issued_or_processing e apolo_access_permitted?.
  • auto_issued aparece no filtro/formulário do Admin via AdminMembershipsService#card_statuses e tem label “Emitida Aut.” em config/locales/pt-BR.yml.
  • O enum documentation_status não tem valor approved_automatically. Ele existiu na proposta original e foi removido em 2026-07-15 — o caminho é :ok derivado da aprovação real.

Código

app/services/webhook_membership_service.rb — initialize_new_membership

```ruby if @user.issued_definitive_card @membership.card_status = :auto_issued @membership.admin_approved_at = Time.current @membership.admin_approved_by = automatic_approver @membership.card_issued_at = Time.current @membership.card_issued_by = automatic_approver end

…

if @user.issued_definitive_card user_profile.automatic_approve!(automatic_approver) send_membership_renewal_approved_email else user_profile.manual_approve! send_request_documents_for_membership_email end ```

Teste vinculado

test/services/webhook_membership_service_test.rb: - “sends renewal approved email and not documents email when user has issued definitive card” - “sends documents email and not renewal email when user does not have issued definitive card” - “sets card_status to auto_issued when user has issued definitive card” - “keeps card_status not_issued when user does not have issued definitive card” - “sets admin_approved_at to today and admin_approved_by to the automatic user on definitive card renewal” - “reuses the same automatic user across definitive card renewals” - “does not set membership admin_approved fields when user does not have issued definitive card” - “auto-approves the user_profile on definitive card renewal”

test/models/user_profile_test.rb — “calculate_documentation_status does not return :ok from issued_definitive_card alone without admin approval”

test/models/membership_test.rb: - “card_issued scope includes memberships with auto_issued card_status” - “card_issued_or_processing scope includes memberships with auto_issued card_status” - “apolo_access_permitted? returns true when card is auto_issued even without admin approval”

Relacionados