R-007 — A filiação seguinte é re-avaliada na emissão da carteira

TLDR: A aprovação de documentos, isolada, não basta para auto-aprovar a filiação seguinte: naquele momento issued_definitive_card ainda é false. Quem re-avalia a filiação seguinte é a emissão da carteira (AdminMembershipsService#admin_issue_card), que é onde a flag passa a valer true.

Given / When / Then

Dado um usuário sem carteira definitiva, com a filiação vigente aprovada e uma filiação seguinte paga, pendente e not_issued Quando o atendente emite a carteira da filiação vigente pelo Admin, em data igual ou posterior a DATE_RELEASE_NEW_CITRG Então users.issued_definitive_card vira true e, na mesma chamada, Membership::FutureApprove é executado de novo: a filiação seguinte recebe card_status: auto_issued, admin_approved_* e card_issued_* do usuário “Automático” — e o membro recebe membership_renewal_approved_email referente à filiação seguinte, que neste caminho é o único e-mail da ação

Por que existe

A ordem dos eventos na primeira filiação é fixa:

  1. AdminUserProfilesService#admin_approve_user_profile aprova a filiação vigente e chama Membership::FutureApprove. Nesse instante a flag ainda é false, então a filiação seguinte cai no ramo manual de R-004 e fica not_issued / documentation_status: pending, sem aprovação.
  2. AdminMembershipsService#admin_issue_card grava issued_definitive_card = true.

Sem uma segunda avaliação no passo 2, a filiação seguinte ficava pendente para sempre: a fila de emissão só olha filiações em processing, então ninguém a via para aprovar ou emitir, e quando ela entrasse em vigência apolo_access_permitted? recusaria o acesso ao Apolo por falta de admin_approved_by_id e de carteira emitida.

Restrições

  • A chamada fica no fim de admin_issue_card, fora de transação e depois de a flag e o card_status estarem persistidos. Se ela falhar, a carteira continua emitida e na remessa.
  • O argumento é current_membership: user.current_membership, nunca o resource recebido. User#next_membership devolve a própria vigente quando não existe filiação posterior, e o guard next_membership != current_membership só neutraliza esse fallback se o argumento vier de current_membership. Passando resource, uma reimpressão de carteira de filiação vencida auto-aprovaria a filiação vigente pendente, sem análise de documento.
  • Vale para qualquer shipment_kind (first_time, resend, reprint). Não há retrabalho: o guard do use case bloqueia uma filiação seguinte já aprovada ou já emitida.
  • A re-avaliação envia membership_renewal_approved_email para a filiação seguinte. O envio chegou a ser removido em 2026-09-08 e foi restaurado em 2026-09-09 — ver o adendo da spec.
  • Dois envios na moderação, com conteúdos distintos. O e-mail usa o mesmo template dos outros dois remetentes, e o corpo renderiza @user.name, register_number_pad_dot e a vigência da filiação (valid_since/valid_until) — esta última desde o adendo de 2026-09-09. O register_number é compartilhado pela filiação vigente e pela seguinte, porque WebhookMembershipService#create_or_return_register_number reusa o do usuário, então a vigência é o único dado que difere entre os dois envios. O assunto continua igual nos três remetentes, e o metadata também não distingue (grava @user.id, não o da filiação). Efeito por chamador:

    Chamador O chamador já envia e-mail? Resultado
    AdminUserProfilesService#admin_approve_user_profile sim, sempre (fire_approved_user_profile_email) 2 e-mails — mesmo assunto, vigências diferentes
    AdminMembershipsService#admin_issue_card não, nenhum 1 e-mail, o único aviso da aprovação da filiação seguinte

    No primeiro caso o envio duplo é determinístico: para existir filiação seguinte distinta o usuário tem duas ou mais filiações, logo is_renewal? (user.memberships.count > 1) é sempre true e o chamador já disparou o mesmo e-mail. Com a vigência no corpo eles deixaram de ser idênticos, mas continuam sendo dois — reduzir para um único envio não foi decidido.

  • Se DATE_RELEASE_NEW_CITRG estiver no futuro, a flag não é escrita e a filiação seguinte permanece no fluxo manual.

Código

app/services/admin_memberships_service.rb — fim de admin_issue_card

ruby user = resource.user # ... issued_definitive_card = true, card_status = :issued Membership::FutureApprove.call(user: user, current_membership: user.current_membership)

O user é o mesmo objeto que recebeu update(issued_definitive_card: true) algumas linhas acima, então a flag já vale true em memória e no banco quando o use case é chamado.

Relacionadas

  • R-004 — a regra de auto-aprovação que esta re-avaliação faz valer também no fluxo de primeira filiação.