Menuabrir
EstávelAtualizado em 14 de mai. de 2026, 00:06

Este módulo depende de

1
  • crmSync automático de lifecycle_stage via _sync_crm_lifecycle()

Módulos que dependem deste

5
  • councilcross_module.business_snapshot (membros ativos, plano)
  • diaryFK obrigatório — cada entry é de um membro específico
  • billingSync de plano após payment paid — atualiza member.plan_type
  • meetingsLista de alunos para envio de lembretes automáticos
  • programsValidar matrícula do aluno e resolve member_id para progresso

Members

Status: 🟢 Estável (mirror leve) Code: backend/app/modules/members UI: frontend/src/app/(admin)/[slug]/admin/members + frontend/src/app/(member) Última revisão deste doc: 2026-05-13 por Felipe + Claude Dependências fortes: crm (sync lifecycle), identity (end_user_id)


1. Identidade

O que faz (uma frase)

Define membros (alunos/clientes ativos do tenant), programas (cursos/produtos) e enrollments (matrículas) — gate de acesso à área restrita do aluno + sync automático com CRM lifecycle.

Por que existe (negócio)

CRM tem todos contatos (lead/customer/vendor). Members tem só quem tem acesso ativo ao produto. Separação importante porque:

  • Acesso à área /clube exige members_member ativo (não basta ser CrmContact).
  • Plano (basic/pro) determina features.
  • Status (active/paused/canceled) afeta cobrança e dunning.

Status atual

Estável. Mirror leve de Members v1 legacy (32 tabelas) — agora 3 tabelas enxutas no Suite.


2. Cases de uso reais

Case 1: Cliente compra acesso

Hotmart webhook → CRM cria/atualiza contato → Members create_member_sync_crm_lifecycle() atualiza crm_contact.lifecycle_stage=customer.

Case 2: Cliente cancela

UI admin → PATCH /members/{id} {status: canceled} → Members atualiza → CRM lifecycle volta pra subscriber (perde acesso).


3. Oportunidades de negócio

  • Member portal whitelabel: vender área do aluno como tema customizável.
  • Multi-program access: member com múltiplos enrollments → cobrança bundle.
  • Engagement-driven pricing: plan dinâmico baseado em engagement (intelligence).

4. Arquitetura interna

Arquivos

Tasks

Sem Celery próprio.


5. Tabelas (3)

members_member

ColunaNotas
tenant_id
legacy_idMembers v1 backfill
end_user_idIdentity Service
email / full_name / preferred_name
planbasic/pro/etc.
statusactive / paused / canceled
avatar_url / bio / profession / birth_date / interests (JSONB)
crm_contact_idBackref sync
churn_risk_scoreCache
joined_at / last_active_at

UNIQUE (tenant_id, email), (tenant_id, legacy_id). Índice (tenant_id, status).

members_program

ColunaNotas
slug / title / description / cover_url
is_active

UNIQUE (tenant_id, slug).

members_enrollment

ColunaNotas
member_id / program_idFK CASCADE
statusactive / completed / paused
enrolled_at / completed_at

UNIQUE (member_id, program_id).

Relacionamentos cross-módulo

DireçãoOutro móduloComo
↘ Escrevecrm_contact_sync_crm_lifecycle em create/patch (status→lifecycle_stage). Fire-and-recover.
↗ Lêidentityend_user_id mapeia ao Identity Service (não validado no Suite)

6. API / Endpoints (9)

MétodoRotaO que faz
GET/members?q=&status=&limit&offsetLista paginada com search
POST/membersCriar (trigger CRM sync)
GET/members/statsContagem por status
GET/members/{id}Detalhe
PATCH/members/{id}Atualizar (status change → CRM sync)
POST/members/{id}/enrollmentsMatricular
DELETE/members/{id}/enrollments/{program_id}Desmatricular
GET/programsListar ativos
POST/programsCriar

7. Configuração

Sem env vars próprias. Reutiliza MANDIR_DEFAULT_TENANT_ID.


8. Operações + Troubleshooting

Sintoma: CRM lifecycle não muda quando member muda status

Causa: _sync_crm_lifecycle é fire-and-recover (não bloqueia). Diagnóstico: logs members.crm_sync.error. Fix: rerun manual via API.


9. Limitações e débitos técnicos

#Item
1CRM sync best-effort — falhas não retornam erro
2Sem validação de pré-requisitos em enrollment
3Hard-delete — sem deleted_at
4end_user_id não validado contra Identity

10. Histórico

Em prod desde absorção do Members legacy (2026-05-04).