Versão: 1.1
Contexto: módulo Academy existente (AcademyClass com venue_id, coach_user_id, schedule_label; roster; presenças; arquivamento).
Implementação (fases 1–5 do plano): ver código e 2026-04-10_academy-venue-coach-schedule-enrollment-invites; fluxo de uso: academy-enrollment-user-flow.md.
| Já existe | Lacuna para a estratégia |
|---|---|
Turma com venue_id + coach_user_id |
Vínculo coach ↔ venue não é entidade própria; coach só aparece por turma |
schedule_label (string) |
Não há recorrência (dias/horas) queryável |
| Dono cria turma; coach gere roster; add por email/user | Não há capacidade máxima, vagas, nem pedido de entrada do aluno |
| E-mail em fila em nova inscrição | Extender para convites e respostas a pedidos, se desejado |
Tabela sugerida: venue_coach (ou venue_staff se no futuro incluir outros papéis).
venue_id, user_id (coach), timestampsstatus (active, suspended), invited_by_user_id, notesvenue_id presente neste vínculo (ou o coach é super_admin com exceção documentada).Quem atribui: dono da arena (e/ou super_admin). O professor não auto-associa sem aprovação (evita abuso), salvo política de negócio explícita.
Duas abordagens; recomendação híbrida:
A — Recorrência normalizada (recomendada)
Tabela academy_class_schedule_slots:
academy_class_idweekday (0–6 ou ISO)starts_at / ends_at como time (ou minutos desde meia-noite no TZ da venue)effective_from / effective_until para fériasB — Label humano
Manter schedule_label como denormalizado gerado para UI (“Seg e Qua, 19h–20h30”) ou preenchido pelo coach.
Sessões pontuais (AcademyClassSession) continuam alinhadas a datas concretas; os slots definem a “oferta” semanal.
Em academy_classes (ou tabela de configuração 1:1):
max_members (nullable = ilimitado, se produto permitir)max_members - count(membros ativos) (computed; não persistir salvo cache).Tabela: academy_class_enrollment_requests
academy_class_id, user_id (player), status (pending, approved, rejected, cancelled)message opcional (aluno), resolved_by_user_id, resolved_atacademy_class_id, user_id) onde status = pending (ou histórico com estados finais)Transição:
pending se houver vaga ou política “lista de espera” (definir produto).approve → executa a mesma lógica que AddAcademyClassMemberAction (transação + e-mail se novo membro).reject / aluno cancel sem efeito no roster.Interpretação recomendada no MVP: convite direto (equivalente a pré-aprovacao).
Opção 1 — Reutilizar pedido invertido
Tabela academy_class_invitations:
academy_class_id, invitee_user_id, invited_by_user_id, status (pending, accepted, declined, expired)Opção 2 — Só notificação + CTA
Notificação/in-app “Foste convidado” que chama accept → AddAcademyClassMemberAction.
“Chamar” em tempo real (ex.: aula já a começar): pode ser evento Reverb + notificação, fora do MVP de dados acima, ou fase posterior.
| Ação | Quem |
|---|---|
Gerir vínculos venue_coach |
venue_owner da arena, super_admin |
| Criar turma na arena | Manter: dono cria e escolhe coach vinculado à mesma arena; ou permitir coach criar só se venue_coach ativo e permissão nova academy.class.create_as_coach |
| Editar slots / capacidade | Coach atribuído à turma + policy existente; dono pode override conforme matriz |
| Listar turmas “abertas a pedidos” | Player autenticado; escopo: arenas públicas / coaches vinculados / só turmas com accepts_enrollment_requests = true |
| Pedir entrada | role:player; não ser já membro; respeitar vaga ou lista de espera |
| Aprovar/rejeitar pedidos | Coach da turma e/ou venue_owner (cravar uma fonte de verdade) |
| Convidar aluno (“chamar”) | Coach da turma (e mesmas guards de arquivo/capacidade) |
Documentar decisão única: aprovação de pedido é só coach, só dono, ou ambos (either).
flowchart LR
subgraph arena
VO[Venue owner]
VC[venue_coach]
VO --> VC
end
subgraph turma
C[Coach]
T[AcademyClass + slots]
VC --> C
C --> T
end
P[Player]
T -->|vagas| P
P -->|pedido| ER[enrollment_request]
ER -->|aprovar| C
C -->|convite| INV[invitation]
INV -->|aceitar| P
max_members, flag accepts_enrollment_requests.| Fase | Entrega | Risco / nota |
|---|---|---|
| 1 | venue_coach + UI dono “Professores da arena” + validação em CreateAcademyClassAction / policies |
Base para tudo o resto |
| 2 | academy_class_schedule_slots + UI criar/editar horários; manter schedule_label sync |
Migração + seeds |
| 3 | max_members + cálculo de vagas + listagem pública/restrita de turmas |
Performance: índices em membros |
| 4 | enrollment_requests + UI aluno + UI coach aprovar/rejeitar |
Integrar com AddAcademyClassMemberAction |
| 5 | Convites “chamar aluno” + e-mail em fila + opcional Reverb | Reutilizar padrão de mail já existente |
| 6 | Lista de espera, convites por token anónimo, calendário | Pós-MVP |
enrollment_requests e invitations.docs/changes/... por fase; atualizar matriz ACL e kolos_registro-de-rotas.md.Documento de estratégia; implementação incremental no módulo Kolos\Modules\Academy e Venue.