Fix: status “Documentação pendente” após renovação com carteira definitiva

TLDR: Membros com carteira definitiva emitida deixam de ver “Documentação pendente” após renovar — o dashboard passa a mostrar “Carteira emitida” (último onboarding aprovado) e o Admin passa a mostrar a documentação como aprovada.

Atualização (2026-07-15): status approved_automatically removido. O valor approved_automatically do enum documentation_status foi removido. Membros com carteira definitiva passaram a resolver para :ok em UserProfile#calculate_documentation_status. Removidos também a label user_profile_documentation_statuses.APPROVED_AUTOMATICALLY (pt-BR) e a chave approved_automatically de Membership#public_serialize. Como documentation_status é coluna string sem migration, não houve mudança de schema nem migração de dados — o valor antigo nunca chegou a existir em produção.

Estado final (ver R-004): o :ok não vem mais da flag issued_definitive_card e sim de uma aprovação real do perfil (admin_approved_at), gravada por user_profile.automatic_approve! na renovação.

Contexto

Membros cuja carteira definitiva já foi emitida (users.issued_definitive_card = true, marcada a partir da remessa 205 / DATE_RELEASE_NEW_CITRG) passavam a ver “Documentação pendente” na Área do Membro após renovar, mesmo não podendo (nem precisando) reenviar documentos.

Causa raiz: na renovação, WebhookMembershipService#initialize_new_membership não criava novo onboarding para esses membros (guard em create_new_onboarding) e zerava user_profile.admin_approved_at. Com isso, as duas fontes derivadas de status ficavam “pendentes”:

Superfície Lê o status de Por que quebrava
A) Card do dashboard GET /api/v2/user/onboarding → current_onboarding current_onboarding ficava nil → serializer retornava {} → frontend usava fallback PENDING
B) Admin + /me user_profile.documentation_status → calculate_documentation_status admin_approved_at zerado → caía no default :pending

Objetivos

  • Área do Membro exibe “Carteira emitida” (onboarding approved) após a renovação de membro com carteira definitiva
  • Admin exibe a documentação como aprovada para membros com carteira definitiva
  • Não resetar o user_profile na renovação de membro com carteira definitiva
  • Correção derivada, cobrindo membros já renovados e renovações futuras, sem migração de dados

Fora de escopo

  • Nenhuma mudança no citrg-memberarea. O label do card vem do useStatusCard da área do membro e o Ponto 1 se resolve apenas pela API.

Mudanças

app/models/user.rb

  • Novo método last_onboarding → onboardings.approved.order(created_at: :desc).first. Completa o fallback do controller; retorna nil quando não há onboarding aprovado (mantém OnboardingSerializer.new(nil) => {}).

app/controllers/api/v2/onboarding_controller.rb

  • onboarding usa current_onboarding || last_onboarding — corrige a superfície A.

app/services/webhook_membership_service.rb

  • Em initialize_new_membership, não resetar o user_profile quando @user.issued_definitive_card.

app/models/user_profile.rb

  • calculate_documentation_status passa a resolver para :ok no caso de carteira definitiva — corrige a superfície B para existentes e futuros.

config/locales/pt-BR.yml

  • Label de status de documentação exibido no Admin.

app/models/membership.rb

  • public_serialize exposto sem label nulo na API pública.

Testes

  • test/models/user_test.rb — last_onboarding retorna o último onboarding aprovado (mais recente por created_at), ignorando não aprovados; retorna nil sem onboarding aprovado.
  • test/controllers/api/v2/onboarding_controller_test.rb — fallback: usuário sem current_onboarding mas com onboarding aprovado → resposta status == "approved" com o id correto; regressão: "user without onboarding" continua retornando "{}".
  • test/services/webhook_membership_service_test.rb — renovação com issued_definitive_card = true não zera admin_approved_at/admin_approved_by_id.
  • test/models/user_profile_test.rb — calculate_documentation_status para membro com carteira definitiva.

Como verificar

bash make test test=test/models/user_test.rb make test test=test/models/user_profile_test.rb make test test=test/services/webhook_membership_service_test.rb make test test=test/controllers/api/v2/onboarding_controller_test.rb

  1. Todos verdes, incluindo as regressões ("user without onboarding", reset com issued_definitive_card = false).
  2. Console: usuário com issued_definitive_card = true + onboarding aprovado no histórico + nova filiação sem onboarding →
    • user.current_onboarding → nil; user.last_onboarding → onboarding aprovado
    • OnboardingSerializer.new(user.current_onboarding || user.last_onboarding).as_json → status: "approved" (dashboard mostra “Carteira emitida”)
    • user.user_profile.calculate_documentation_status → :ok
  3. Suíte completa antes do PR.

Decisão — label do dashboard

O label do card vem do useStatusCard (área do membro): com onboarding approved, quando há next_afiliation.status ele usa o label da filiação. Mapeamento:

  • active / payment_issues / sem filiação → “Carteira emitida” (entregue pelo fix da API)
  • expire_soon / suspended / expired → mostram sempre o estado real da filiação (CTAs de renovar/suporte), independente de issued_definitive_card

A flag não deve mascarar estados de vencimento/suspensão.

Documentação