A base do sistema. Uma plataforma como Hotmart ou Kiwify geralmente tem dois papéis principais: Produtor (criador) e Aluno (comprador). Muitas vezes, uma mesma pessoa pode ser ambos.
Tabela: usuarios
id (UUID ou SERIAL) - PKnome_completo (VARCHAR)email (VARCHAR) - Unique Indexsenha_hash (VARCHAR) - Para armazenar hash da senhacpf_cnpj (VARCHAR) - Opcional, para questões fiscaisavatar_url (TEXT) - Link para a fotodata_cadastro (TIMESTAMP)ultimo_acesso (TIMESTAMP)status (ENUM: 'ativo', 'bloqueado', 'pendente')Tabela: produtores (Estende o usuário com dados específicos de quem vende)
id (UUID) - PK e FK para usuarios.idbio (TEXT)url_personalizada (VARCHAR) - Ex: https://escola.dominio/professor.joaocomissao_padrao (DECIMAL) - % padrão de comissão que a plataforma retém dele?chave_pix (VARCHAR)conta_bancaria (TEXT) - JSON com dados bancáriosstatus_verificacao (ENUM: 'pendente', 'verificado', 'reprovado')Aqui é onde mora o "produto". Em plataformas modernas, o conceito de produto é abstrato. Pode ser um curso, um ebook, uma assinatura, um webinar.
Tabela: produtos (O "esqueleto" do curso)
id (UUID) - PKprodutor_id (UUID) - FK para produtores.idtipo (ENUM: 'curso', 'ebook', 'comunidade', 'mentoria', 'assinatura')titulo (VARCHAR)subtitulo (VARCHAR)descricao (TEXT)imagem_capa_url (TEXT)preco (DECIMAL)preco_promocional (DECIMAL)data_criacao (TIMESTAMP)status (ENUM: 'rascunho', 'publicado', 'arquivado')Tabela: modulos (Divide o curso em partes, usado se tipo = 'curso')
id (UUID) - PKproduto_id (UUID) - FK para produtos.idordem (INTEGER) - Para ordenar os módulos (ex: 1, 2, 3)titulo (VARCHAR)descricao (TEXT)Tabela: aulas (O conteúdo em si)
id (UUID) - PKmodulo_id (UUID) - FK para modulos.idordem (INTEGER)titulo (VARCHAR)descricao (TEXT)tipo_conteudo (ENUM: 'video', 'texto', 'quiz', 'arquivo')conteudo (TEXT) - Para textos longos ou HTML.conteudo_url (TEXT) - Para link do vídeo (Vimeo, Youtube, AWS S3).duracao_segundos (INTEGER) - Importante para analytics.pontuacao_quiz (INT) - Se for um quiz, quantos pontos vale.Gerencia a compra, o acesso e os pagamentos.
Tabela: pedidos
id (UUID) - PKusuario_id (UUID) - FK para usuarios.id (Quem comprou)data_pedido (TIMESTAMP)valor_total (DECIMAL)desconto (DECIMAL)cupom_id (UUID) - FK para cupons.id (opcional)status (ENUM: 'pendente', 'pago', 'cancelado', 'reembolsado')metodo_pagamento (ENUM: 'cartao', 'pix', 'boleto')Tabela: itens_pedido (Liga o pedido aos produtos, pois um pedido pode ter mais de um curso)
id (UUID) - PKpedido_id (UUID) - FK para pedidos.idproduto_id (UUID) - FK para produtos.idpreco_unitario (DECIMAL)comissao_aplicada (DECIMAL) - Quanto o produtor ganhou nessa venda.Tabela: matriculas (Corresponde à "Liberação de Acesso")
id (UUID) - PKusuario_id (UUID) - FK para usuarios.id (Aluno)produto_id (UUID) - FK para produtos.iddata_aquisicao (TIMESTAMP)data_expiracao (TIMESTAMP) - NULL se for vitalício.status (ENUM: 'ativo', 'expirado', 'cancelado')progresso_percentual (INTEGER) - Cache para evitar calcular toda hora.Aqui é o coração da experiência do aluno.
Tabela: progresso_aulas
id (UUID) - PKusuario_id (UUID) - FKaula_id (UUID) - FKstatus (ENUM: 'nao_iniciado', 'assistindo', 'concluido')ultimo_segundo_assistido (INTEGER)data_ultimo_acesso (TIMESTAMP)concluido_em (TIMESTAMP)usuario_id, aula_id) - Para garantir que não haja duplicidade.Tabela: anotacoes
id (UUID) - PKusuario_id (UUID) - FKaula_id (UUID) - FKtexto (TEXT)timestamp_video (INTEGER) - Em que minuto da aula ele fez a anotação.data_criacao (TIMESTAMP)Tabela: duvidas (Fórum)
id (UUID) - PKusuario_id (UUID) - FK (Quem perguntou)aula_id (UUID) - FK (Dúvida vinculada a uma aula específica)titulo (VARCHAR)descricao (TEXT)data_criacao (TIMESTAMP)status (ENUM: 'aberto', 'respondido', 'resolvido')Tabela: respostas_duvidas
id (UUID) - PKduvida_id (UUID) - FKusuario_id (UUID) - FK (Quem respondeu: pode ser aluno ou produtor)texto (TEXT)data_criacao (TIMESTAMP)resposta_oficial (BOOLEAN) - Para destacar a resposta do professor.Essencial em plataformas como Hotmart.
Tabela: afiliados
id (UUID) - PK e FK para usuarios.idcodigo_indicacao (VARCHAR) - Ex: @joao123data_cadastro (TIMESTAMP)Tabela: comissoes_afiliados (Configuração: qual produto cada afiliado promove)
id (UUID) - PKafiliado_id (UUID) - FK para afiliados.idproduto_id (UUID) - FK para produtos.idtaxa_comissao (DECIMAL) - % que o afiliado ganha nesse produto.status (ENUM: 'ativo', 'bloqueado')Tabela: vendas_afiliados (Registro de cada vaga atribuída a um afiliado)
id (UUID) - PKitem_pedido_id (UUID) - FK para itens_pedido.id (De qual venda veio)afiliado_id (UUID) - FK para afiliados.idcomissao_ganha (DECIMAL) - Valor calculado.status_pagamento (ENUM: 'a_pagar', 'pago', 'cancelado')Tabela: cupons
id (UUID) - PKprodutor_id (UUID) - FK para produtores.idcodigo (VARCHAR) - Ex: BLACKFRIDAY20tipo_desconto (ENUM: 'percentual', 'fixo')valor_desconto (DECIMAL)data_inicio (TIMESTAMP)data_fim (TIMESTAMP)uso_maximo (INTEGER) - Limite total de usos.afiliado_exclusivo_id (UUID) - FK para afiliados.id (opcional, para cupons de afiliados).Para visualizar como essas tabelas se conectam:
email, produto_id, usuario_id, e chaves estrangeiras.deleted_at (TIMESTAMP) para manter o histórico.JSONB (no PostgreSQL) pode ser uma boa prática para evitar muitas colunas esparsas.progresso_aulas podem ser "shardeadas" por usuario_id ou movidas para um banco de dados NoSQL (como DynamoDB ou Cassandra) devido à alta taxa de escrita.Este modelo cobre 80% das features de uma plataforma como Hotmart ou Kiwify. A partir daqui, você pode expandir para áreas como comunidade (posts, likes) ou certificados.