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_cardtem 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 aDATE_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 éfalseno momento da aprovação de documentos, a re-avaliação acontece na emissão da carteira — ver R-007. Esse caminho enviamembership_renewal_approved_emailpara 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_statusderiva:okde uma aprovação real do perfil (admin_approved_at), não da flag. O atalhoreturn :ok if user.issued_definitive_cardfoi removido: a flag significa “a próxima renovação é automática”, e reusá-la no cálculo forçava:okpermanente e global no usuário, independente do estado real da filiação corrente.Membership#automatic_approve!anexa a foto do perfil na carteira, igual amanual_approve!— os dois usam o mesmoattach_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êmcard_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 ocard_pictureda filiação ou nada.UserProfile#automatic_approve!é o espelho demanual_approve!: gravaapproval_type = :automatic,admin_approved_at = Time.currenteadmin_approved_by= o aprovador automático. Cuidado com o nome demanual_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_issuedconta como carteira efetivamente emitida em todo lugar em que:issuedcontava. Isso é centralizado emMembership::ISSUED_CARD_STATUSES = %i[issued auto_issued], usado porscope :card_issued(e portanto poractive, viawith_profile_approved_or_card_issued),scope :card_issued_or_processingeapolo_access_permitted?.auto_issuedaparece no filtro/formulário do Admin viaAdminMembershipsService#card_statusese tem label “Emitida Aut.” emconfig/locales/pt-BR.yml.- O enum
documentation_statusnão tem valorapproved_automatically. Ele existiu na proposta original e foi removido em 2026-07-15 — o caminho é:okderivado 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”