Database Schema — Plataforma OLP
Documentação completa do schema PostgreSQL (Supabase). Última atualização: Abr/2026.
Índice
- Visão Geral
- Categorias de Tabelas
- Tabelas — Detalhamento
- Enums
- Database Functions
- Triggers
- Storage Buckets
Visão Geral
| Métrica | Valor |
|---|---|
| Total de Tabelas | 73 |
| Enums | 23 |
| Database Functions | 18 |
| Storage Buckets | 4 |
Convenções
- PK: Todas as tabelas usam
id UUID DEFAULT gen_random_uuid()(exceto tabelas de junção com PK composta eportal_alert_cooldown) - Timestamps:
criado_emeatualizado_emcomDEFAULT now() - Soft Delete: Usamos campo
ativo BOOLEAN DEFAULT trueao invés de exclusão física - FK Naming:
<tabela>_<coluna>_fkey - FK Deletion Rules:
CASCADE: Dados operacionais sem valor histórico (alunos, turmas, inscrições ao deletar escola)SET NULL: Referências ausuariosem campos de autoria/responsabilidade (preserva registros históricos ao deletar usuário)NO ACTION/RESTRICT: Bloqueio intencional (raro)
- Idioma: Nomes de tabelas e colunas em português
Categorias de Tabelas
| Categoria | Tabelas | Descrição |
|---|---|---|
| Estrutura | 2 | Configuração base do sistema |
| Escolas | 5 | Dados institucionais (inclui anotações) |
| Usuários | 6 | Identidade, permissões, sub-permissões e vínculos |
| Olimpíadas | 8 | Competições e cronogramas |
| Alunos | 6 | Estudantes, responsáveis e solicitações de vínculo |
| Inscrições e Resultados | 5 | Participação, resultados e importação |
| Comunicação | 9 | Mensagens, mural, templates, snapshots, personalizações |
| Conteúdo | 8 | Cursos, vídeos, tutoriais, banners, progresso |
| Financeiro | 4 | Planos, assinaturas, faturas, billing (twilio_billing_log legado) |
| Sistema | 18 | Auth, logs, cache, cron, config, feature flags, canary, segurança, presença |
| Agenda | 2 | Tarefas e eventos da escola |
Tabelas — Detalhamento
1. Estrutura
papeis
Catálogo fixo de papéis do sistema.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
nome | TEXT | Nome do papel (unique) |
descricao | TEXT | Descrição do papel |
Valores inseridos: administrador, especialista, escola, escola_trial, coordenador, coordenador_olimpiadas, coordenador_pedagogico, diretor, pedagogico, professor, marketing, aluno, responsavel
series_escolares
Catálogo fixo de séries/anos escolares.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
label | TEXT | Ex: "6º EF", "1ª EM" |
grupo | TEXT | "fundamental" ou "medio" |
ordem | INT | Para ordenação |
2. Escolas
escolas
Tabela principal de escolas parceiras.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
nome | TEXT | Nome da escola |
cnpj | TEXT | CNPJ (opcional) |
codigo_inep | TEXT | Código INEP (8 dígitos) |
tipo | ENUM tipo_escola | publica, privada, rede, sistema_ensino |
status | ENUM status_escola | em_analise, ativa, suspensa, encerrada |
cidade | TEXT | Cidade |
estado | TEXT | UF (2 letras) |
email_contato | TEXT | Email institucional |
telefone_contato | TEXT | Telefone principal |
ano_letivo_atual | INT | Ano letivo vigente (default: 2026) |
incremento_ano_automatico | BOOL | Se true, incrementa em jan |
alunos_contratados | INT | Qtd contratada no plano |
limite_alunos | INT | Limite calculado (com margem 10%) |
alunos_idade_olimpica | INT | Faixa etária olímpica |
gateway_customer_id | TEXT | ID no MercadoPago |
rede_ou_mantenedora | TEXT | Rede ou mantenedora |
endereco_escola
Endereço da escola (1:1 com escolas).
| Coluna | Tipo | Descrição |
|---|---|---|
escola_id | UUID (FK → escolas) | UNIQUE |
cep, logradouro, numero, complemento, bairro, cidade, estado | TEXT | Campos do endereço |
escola_mural_config
Configuração do Mural Olímpico aluno/responsável (1:1 com escolas).
| Coluna | Tipo | Descrição |
|---|---|---|
escola_id | UUID (FK → escolas) | UNIQUE |
mural_ativo | BOOL | Se mural está habilitado |
mural_slug | TEXT | URL amigável (ex: "colegio-abc") |
metodo_acesso_por_serie | JSONB | Ex: {"6_ef":"A","8_ef":"B"} |
escola_anotacoes
Anotações livres da escola (1:1 com escolas). Usada na Agenda do coordenador.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | UNIQUE |
conteudo | TEXT | Conteúdo da anotação (default: '') |
atualizado_por | UUID (FK → usuarios) | Quem editou por último |
atualizado_por_nome | TEXT | Nome (desnormalizado) |
3. Usuários
usuarios
Tabela central de usuários do sistema (admin, especialista, escola, coordenador, etc.).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
nome_completo | TEXT | Nome completo |
codigo | TEXT | CPF, CNPJ ou INEP (normalizado, sem máscara) |
tipo_codigo | TEXT | "cpf", "cnpj" ou "inep" |
telefone | TEXT | Telefone para OTP |
email | TEXT | Email (opcional) |
escola_id | UUID (FK → escolas) | Escola vinculada (null para admin/especialista) |
ativo | BOOL | Se usuário está ativo |
auth_user_id | UUID | ID no Supabase Auth (legado, não utilizado ativamente) |
usuario_papeis
Tabela de junção N:N entre usuários e papéis. Um usuário pode ter múltiplos papéis.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
usuario_id | UUID (FK → usuarios) | Usuário |
papel_id | UUID (FK → papeis) | Papel |
escola_id | UUID (FK → escolas) | Escola do contexto do papel |
ativo | BOOL | Se vínculo está ativo |
Trigger: fn_validar_escola_usuario_papel — valida consistência escola_id ↔ papel.
usuarios_escola_permissoes
Permissões granulares por usuário × escola × papel. Desde Abr/2026, escopadas por papel_id para isolar permissões de papéis distintos na mesma escola.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
usuario_id | UUID (FK → usuarios) | Usuário |
escola_id | UUID (FK → escolas) | Escola |
papel_id | UUID (FK → papeis) | Papel do vínculo (adicionado Abr/2026) |
permissao | TEXT | Nome da permissão granular |
UNIQUE: (usuario_id, escola_id, papel_id, permissao)
usuarios_escola_sub_permissoes
Sub-permissões granulares (tabs/funcionalidades) por usuário × escola × papel. Controlam visibilidade de sub-features dentro de uma seção (ex: alunos.importacao).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
usuario_id | UUID (FK → usuarios) | Usuário |
escola_id | UUID (FK → escolas) | Escola |
papel_id | UUID (FK → papeis) | Papel do vínculo |
sub_permissao | TEXT | Chave dot-notation (ex: alunos.lista) |
UNIQUE: (usuario_id, escola_id, papel_id, sub_permissao)
solicitacoes_vinculo
Solicitações de vínculo de usuário a escola (convite para novo papel).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola alvo |
solicitante_id | UUID (FK → usuarios) | Quem solicitou |
destinatario_id | UUID (FK → usuarios) | Usuário alvo |
papel_id | UUID (FK → papeis) | Papel proposto |
permissoes | TEXT[] | Permissões a conceder |
status | ENUM solicitacao_vinculo_status | pendente, aceita, recusada |
respondida_em | TIMESTAMPTZ | Quando respondeu |
ADR: Responsáveis × Escolas — Relação Implícita (sem tabela de junção)
Status: Aceita | Data: Mar/2026 | Contexto: Modelagem de dados
Modelo Atual
A relação entre responsaveis e escolas é implícita, derivada pela cadeia:
responsaveis → aluno_responsaveis → alunos.escola_idNão existe uma tabela responsavel_escolas. A visibilidade de um responsável em uma escola depende inteiramente da existência de pelo menos um aluno ativo vinculado àquela escola.
Campo Legado: responsaveis.escola_id
A coluna responsaveis.escola_id é um campo legado de referência — indica a escola onde o responsável foi cadastrado pela primeira vez. Ela não é usada para controle de acesso nem para determinar visibilidade. A RLS ignora esse campo e usa exclusivamente a cadeia de JOINs.
JOINs Indiretos em Uso
O sistema já realiza esses JOINs em 4 pontos principais:
| Local | Cadeia de JOINs | Propósito |
|---|---|---|
gestao-responsaveis (action list) | responsaveis → aluno_responsaveis → alunos → turmas → series_escolares (4 níveis) | Listar responsáveis com dados dos filhos |
portal-escola (dashboard responsável) | aluno_responsaveis → alunos → escolas | Montar lista de filhos com nome da escola |
RLS responsaveis_escola_select | responsavel_tem_aluno_na_escola(id) → aluno_responsaveis → alunos | Determinar visibilidade por row |
RLS aluno_resp_escola_select | aluno_pertence_escola(aluno_id) | Validar vínculo aluno ↔ escola |
Justificativa
- SSOT (Single Source of Truth): A escola de um aluno é definida em
alunos.escola_id. Duplicar essa informação em uma tabelaresponsavel_escolascriaria risco de inconsistência. - Simplicidade: O responsável só tem sentido no contexto dos seus filhos. Se não tem filhos em uma escola, não há razão para ter acesso a ela.
- Bloqueio granular: O campo
bloqueado_escolaemaluno_responsaveispermite bloquear vínculos individualmente, o que é mais preciso que um bloqueio por escola.
Trade-offs Conhecidos
| Trade-off | Impacto | Mitigação |
|---|---|---|
| Query indireta | Para saber "quais escolas este responsável acessa", é necessário agregar DISTINCT alunos.escola_id via aluno_responsaveis | Aceitável — essa query é rara e ocorre apenas no portal |
| Perda silenciosa de visibilidade | Se todos os alunos de uma escola forem desativados (ativo = false), o responsável perde acesso àquela escola sem notificação | Aceitável no contexto atual — aluno desativado = responsável não precisa mais acessar |
| Bloqueio por escola | Não há como bloquear um responsável "na escola inteira" sem bloquear cada vínculo aluno_responsaveis individualmente | Mitigado pelo fato de que escolas geralmente têm poucos filhos por responsável (1-3) |
| Performance RLS | A função responsavel_tem_aluno_na_escola() executa JOIN em cada row avaliada pela policy | Aceitável — volume de responsáveis por escola é limitado (centenas, não milhões) |
Quando Revisitar
Criar uma tabela explícita responsavel_escolas seria justificado se:
- Surgir necessidade de metadados no nível escola (ex: data de cadastro na escola, status por escola)
- O volume de responsáveis crescer a ponto de impactar performance das queries RLS
- For necessário bloquear responsáveis por escola sem iterar vínculos individuais
- O responsável precisar ter acesso a uma escola sem filhos ativos (ex: histórico)
4. Olimpíadas
olimpiadas
Tabela principal de olimpíadas/competições científicas.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
sigla | TEXT | Ex: "OBM", "OBF" |
nome | TEXT | Nome completo |
area_conhecimento | ENUM | matematica, fisica, quimica, etc. |
abrangencia | ENUM | nacional, internacional, regional, estadual |
tipo_aplicacao | ENUM | presencial, online, hibrido, online_na_escola, por_fase |
tipo_inscricao | ENUM | individual, por_equipe, por_escola, pelo_professor |
custo_inscricao | ENUM | gratuita, paga |
status_inscricao | ENUM | abertas, encerradas, em_breve, suspensas |
edicao_atual | INT | Ano da edição corrente |
ativo | BOOL | Se olimpíada está ativa (soft delete) |
criado_por | UUID | Especialista que criou |
icone_customizado | TEXT | Nome do ícone Lucide |
config_arquivo_inscricao | JSONB | Configuração do arquivo de inscrição |
modo_config_fases | TEXT | 'uniforme' ou 'por_nivel' — modo de configuração de fases |
fases_por_nivel | JSONB | Mapa nível→fases participantes (modo por_nivel) |
cronograma_configurado | BOOL | Flag de status |
links_configurados | BOOL | Flag de status |
olimpiada_edicoes
Controla edições anuais de cada olimpíada.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
olimpiada_id | UUID (FK → olimpiadas) | Olimpíada |
ano_edicao | INT | Ano da edição |
status | TEXT | "ativa", "encerrada" |
fases_olimpiada
Fases dentro de uma edição.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
olimpiada_id | UUID (FK → olimpiadas) | Olimpíada |
nome_fase | TEXT | Ex: "Fase 1", "Semifinal" |
ordem | INT | Ordem sequencial |
data | DATE | Data início |
data_fim | DATE | Data fim |
ano_edicao | INT | Filtro por edição |
tempo_maximo_minutos | INT | Tempo máximo global (modo uniforme) |
questoes_por_nivel | JSONB | Nº questões por nível: {"Nível 0": 10, ...} |
tempo_por_nivel | JSONB | Tempo por nível em minutos: {"Nível 0": 60, ...} (modo por_nivel) |
pontuacao_maxima_por_nivel | JSONB | Pontuação máxima por nível |
tipo_aplicacao | ENUM tipo_aplicacao_olimpiada | Tipo de aplicação da fase (nullable — só preenchido quando olimpíada.tipo_aplicacao = 'por_fase') |
atividades_cronograma
Eventos e atividades do cronograma de uma edição.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
olimpiada_id | UUID (FK) | Olimpíada |
fase_id | UUID (FK → fases_olimpiada) | Fase associada (opcional) |
titulo | TEXT | Título do evento |
descricao | TEXT | Descrição |
data | DATE | Data do evento |
data_fim | DATE | Data fim (range) |
tipo_atividade | ENUM tipo_atividade_cronograma | inicio_prazo, fim_prazo, atividade, marco, prova, resultado, inscricao, pagamento, documento |
ordem | INT | Ordenação |
ano_edicao | INT | Filtro por edição |
niveis_competicao
Níveis dentro de uma olimpíada (ex: Nível 1, Nível 2).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
olimpiada_id | UUID (FK) | Olimpíada |
titulo | TEXT | Nome do nível |
descricao | TEXT | Descrição |
ordem | INT | Ordenação |
niveis_competicao_series
Junção N:N entre níveis e séries escolares.
| Coluna | Tipo | PK |
|---|---|---|
nivel_id | UUID (FK → niveis_competicao) | Composta |
serie_id | UUID (FK → series_escolares) | Composta |
olimpiada_series_participantes
Séries que participam de uma olimpíada.
| Coluna | Tipo | PK |
|---|---|---|
olimpiada_id | UUID (FK → olimpiadas) | Composta |
serie_id | UUID (FK → series_escolares) | Composta |
olimpiada_links
Links externos de uma olimpíada (1:1).
| Coluna | Tipo | Descrição |
|---|---|---|
olimpiada_id | UUID (FK, PK) | UNIQUE |
site_oficial | TEXT | URL do site |
link_regulamento | TEXT | URL do regulamento |
link_provas_anteriores | TEXT | URL de provas |
5. Alunos
alunos
Cadastro de alunos vinculados a escolas.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
turma_id | UUID (FK → turmas) | Turma atual |
nome_completo | TEXT | Nome |
matricula | TEXT | Matrícula escolar |
data_nascimento | DATE | Data de nascimento |
cpf | TEXT | CPF (opcional) |
sexo | TEXT | M/F |
cor_raca | TEXT | branca, preta, parda, etc. |
email | TEXT | Email (opcional) |
telefone | TEXT | Telefone (opcional) |
ativo | BOOL | Status ativo |
turmas
Turmas escolares por ano letivo.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
serie_id | UUID (FK → series_escolares) | Série/ano |
identificador | TEXT | Ex: "A", "B", "C" |
ano_letivo | INT | Ano letivo |
ativo | BOOL | Status |
UNIQUE: (escola_id, serie_id, identificador, ano_letivo)
aluno_turma_historico
Histórico de turmas de cada aluno (transferências).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
aluno_id | UUID (FK → alunos) | Aluno |
turma_id | UUID (FK → turmas) | Turma |
escola_id | UUID (FK → escolas) | Escola |
ano_letivo | INT | Ano letivo |
data_entrada | DATE | Quando entrou |
data_saida | DATE | Quando saiu (null = ativo) |
status | TEXT | "ativo", "transferido" |
responsaveis
Responsáveis pelos alunos (pais, tutores).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola de referência |
nome_completo | TEXT | Nome |
cpf | TEXT | CPF (obrigatório, para login mural) |
telefone | TEXT | Telefone (obrigatório, para OTP) |
telefone_secundario | TEXT | Telefone alternativo |
email | TEXT | |
ativo | BOOL | Status |
aluno_responsaveis
Junção N:N entre alunos e responsáveis.
| Coluna | Tipo | PK |
|---|---|---|
aluno_id | UUID (FK → alunos) | Composta |
responsavel_id | UUID (FK → responsaveis) | Composta |
parentesco | TEXT | "responsavel", "pai", "mae", etc. |
principal | BOOL | Se é responsável principal |
bloqueado_escola | BOOL | Se escola bloqueou o vínculo |
bloqueado_por | UUID | Quem bloqueou |
6. Inscrições e Resultados
escola_olimpiadas
Adesão de uma escola a uma olimpíada (por edição).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
olimpiada_id | UUID (FK → olimpiadas) | Olimpíada |
ano_edicao | INT | Edição |
status | TEXT | "ativa", "encerrada" |
criado_por | UUID | Coordenador que aderiu |
inscricoes_olimpiada
Inscrição de um aluno em uma olimpíada.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
aluno_id | UUID (FK → alunos) | Aluno |
olimpiada_id | UUID (FK → olimpiadas) | Olimpíada |
escola_id | UUID (FK → escolas) | Escola |
nivel_id | UUID (FK → niveis_competicao) | Nível |
ano_edicao | INT | Edição |
status | TEXT | "pendente", "confirmada", "cancelada" |
inscrito_por | UUID | Quem inscreveu |
autorizado_responsavel | BOOL | Se responsável autorizou |
autorizado_por | UUID (FK → responsaveis) | Responsável que autorizou |
dados_extras | JSONB | Dados adicionais da inscrição |
resultados_aluno
Resultados/notas de alunos em fases de olimpíadas.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
inscricao_id | UUID (FK → inscricoes_olimpiada) | Inscrição |
fase_id | UUID (FK → fases_olimpiada) | Fase |
nota | NUMERIC | Nota obtida |
classificacao | INT | Posição/ranking |
premiacao | TEXT | "ouro", "prata", "bronze", "mencao_honrosa" |
presente | BOOL | Se compareceu |
escola_id | UUID (FK → escolas) | Escola |
configuracoes_fase_nivel
Faixas de premiação por fase × nível × escola.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
fase_id | UUID (FK → fases_olimpiada) | Fase |
nivel_id | UUID (FK → niveis_competicao) | Nível |
escola_id | UUID (FK → escolas) | Escola |
nota_corte | NUMERIC | Nota mínima |
faixa_ouro_min/max | NUMERIC | Faixa para ouro |
faixa_prata_min/max | NUMERIC | Faixa para prata |
faixa_bronze_min/max | NUMERIC | Faixa para bronze |
faixa_mencao_min/max | NUMERIC | Faixa para menção honrosa |
7. Comunicação
mural_publicacoes
Publicações no mural da escola (notícias, avisos).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
olimpiada_id | UUID (FK → olimpiadas) | Olimpíada (opcional) |
titulo | TEXT | Título |
conteudo | TEXT | Conteúdo (Markdown) |
descricao | TEXT | Resumo/subtítulo |
tipo | TEXT | "noticia", "aviso", "resultado" |
imagem_url | TEXT | URL da imagem |
video_url | TEXT | URL do vídeo |
link_externo | TEXT | Link externo |
destaque | BOOL | Se está em destaque |
ativa | BOOL | Se está visível |
ordem | INT | Ordenação |
criado_por | UUID (FK → usuarios) | Autor |
mural_liberacoes
Controle de liberação de resultados para o Mural Olímpico.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
escola_olimpiada_id | UUID (FK → escola_olimpiadas) | Adesão |
fase_id | UUID (FK) | Fase (opcional) |
nivel_id | UUID (FK) | Nível (opcional) |
liberar_notas | BOOL | Mostra pontuação |
liberar_resultados | BOOL | Mostra resultados/premiações |
config_notas | JSONB | Config granular de notas |
config_resultados | JSONB | Config granular de resultados |
mural_dados_publicados
Snapshots materializados de dados de resultados para o Mural. Evita queries complexas em tempo real no portal público.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
escola_olimpiada_id | UUID (FK → escola_olimpiadas) | Adesão |
inscricao_id | UUID (FK → inscricoes_olimpiada) | Inscrição |
aluno_id | UUID (FK → alunos) | Aluno |
fase_id | UUID (FK → fases_olimpiada) | Fase |
nivel_id | UUID (FK → niveis_competicao) | Nível (opcional) |
tipo | TEXT | Tipo do snapshot (ex: "resultado") |
dados | JSONB | Dados materializados |
mensagens_enviadas
Histórico de mensagens enviadas (WhatsApp/SMS/notificações).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
enviado_por | UUID (FK → usuarios) | Remetente |
assunto | TEXT | Assunto |
conteudo | TEXT | Corpo da mensagem |
destinatarios | TEXT[] | Array de identificadores |
template_id | UUID (FK → templates_mensagem) | Template usado |
olimpiada_id | UUID (FK) | Olimpíada relacionada |
status | TEXT | "enviada", "erro" |
templates_mensagem
Templates de mensagens reutilizáveis.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
hub_id | UUID (FK → template_hubs) | Hub de templates |
titulo | TEXT | Nome do template |
conteudo | TEXT | Corpo com variáveis |
tipo | TEXT | "sms", "notificacao" |
template_hubs
Agrupamento de templates por olimpíada.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
tipo | ENUM template_hub_tipo | institucional, olimpiada |
olimpiada_id | UUID (FK → olimpiadas) | Olimpíada (opcional) |
criado_por | UUID | Especialista |
ativo | BOOL | Status |
template_personalizacoes
Personalizações de templates por escola.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
template_id | UUID (FK → templates_mensagem) | Template base |
escola_id | UUID (FK → escolas) | Escola |
conteudo_personalizado | TEXT | Versão customizada |
notificacoes
Notificações in-app para usuários.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
usuario_id | UUID (FK → usuarios) | Destinatário |
escola_id | UUID (FK → escolas) | Escola (opcional) |
titulo | TEXT | Título |
mensagem | TEXT | Corpo |
tipo | ENUM notification_type | Tipo da notificação |
dados | JSONB | Dados extras |
lida | BOOL | Se foi lida |
lida_em | TIMESTAMPTZ | Quando foi lida |
expira_em | TIMESTAMPTZ | Expiração |
8. Conteúdo
cursos
Cursos de capacitação.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
titulo | TEXT | Nome do curso |
descricao | TEXT | Descrição |
categoria_visual | ENUM categoria_visual_curso | azul_claro, verde, vermelho, roxo, amarelo, cinza |
tipo_curso | TEXT | "curso", "trilha" |
ativo | BOOL | Status |
criado_por | UUID | Especialista |
cursos_videos
Vídeos dentro de um curso.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
curso_id | UUID (FK → cursos) | Curso |
titulo | TEXT | Título do vídeo |
descricao | TEXT | Descrição |
detalhes | TEXT | Detalhes adicionais |
url_video | TEXT | URL do vídeo |
thumbnail_url | TEXT | Thumbnail |
ordem | INT | Ordenação |
status | ENUM status_video_curso | rascunho, publicado |
nivel | TEXT | iniciante, intermediario, avancado |
tags | TEXT[] | Tags de categorização |
duracao_segundos | INT | Duração |
visualizacoes | INT | Contador |
avaliacao_media | NUMERIC | Média de avaliações |
total_avaliacoes | INT | Total de avaliações |
criado_por | UUID | Autor |
usuario_progresso_video
Progresso do usuário em vídeos de cursos.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
usuario_id | UUID (FK → usuarios) | Usuário |
video_id | UUID (FK → cursos_videos) | Vídeo |
concluido | BOOL | Se completou (default: false) |
concluido_em | TIMESTAMPTZ | Quando concluiu |
avaliacao | INT | Nota dada (1-5) |
avaliado_em | TIMESTAMPTZ | Quando avaliou |
video_comentarios
Comentários/dúvidas em vídeos de cursos.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
video_id | UUID (FK → cursos_videos) | Vídeo |
usuario_id | UUID (FK → usuarios) | Quem comentou |
tipo | TEXT | "duvida" (default) |
minuto_video | TEXT | Timestamp no vídeo |
conteudo | TEXT | Texto do comentário |
status | TEXT | "pendente" (default) |
respondido_por | UUID (FK → usuarios) | Quem respondeu |
resposta | TEXT | Texto da resposta |
respondido_em | TIMESTAMPTZ | Quando respondeu |
video_materiais
Materiais complementares de vídeos (PDFs, links).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
video_id | UUID (FK → cursos_videos) | Vídeo |
nome | TEXT | Nome do material |
descricao | TEXT | Descrição |
arquivo_url | TEXT | URL do arquivo |
tipo_arquivo | TEXT | Tipo MIME |
tamanho_bytes | INT | Tamanho em bytes |
criado_por | UUID (FK → usuarios) | Quem enviou |
tutoriais
Tutoriais da plataforma.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
titulo | TEXT | Título |
descricao | TEXT | Descrição |
url_video | TEXT | URL do vídeo |
thumbnail_url | TEXT | Thumbnail |
categoria | TEXT | Categoria |
ordem | INT | Ordenação |
ativo | BOOL | Status |
criado_por | UUID | Autor |
banners_login
Banners do carrossel na tela de login.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
titulo | TEXT | Título |
descricao | TEXT | Descrição |
imagem_url | TEXT | URL da imagem (bucket: banners-login) |
link | TEXT | Link do banner |
horario | TEXT | Horário exibido |
ativo | BOOL | Se está ativo |
activated_at | TIMESTAMPTZ | Quando foi ativado |
ordem_no_carrossel | INT | Posição |
visualizacoes | INT | Contador |
cliques | INT | Contador |
criado_por | UUID | Especialista |
headers_novidades
Cards de novidades no header do dashboard.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
titulo | TEXT | Título |
descricao | TEXT | Descrição |
cor_fundo | TEXT | Classe CSS (ex: "bg-[#fd2f55]") |
tag | TEXT | Tag de categoria |
link | TEXT | Link |
ativo | BOOL | Se está ativo |
activated_at | TIMESTAMPTZ | Quando ativou |
ordem_no_carrossel | INT | Posição |
criado_por | UUID | Especialista |
9. Financeiro
planos
Planos de assinatura disponíveis.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
nome | TEXT | Nome do plano |
descricao | TEXT | Descrição |
preco_mensal | NUMERIC | Preço mensal base |
preco_anual | NUMERIC | Preço anual (desconto) |
alunos_minimo | INT | Mínimo contratável |
alunos_maximo | INT | Máximo contratável |
valor_por_aluno_extra | NUMERIC | Valor por aluno excedente |
tipo_cobranca | TEXT | "mensal", "anual" |
trial_dias | INT | Dias de trial |
is_trial | BOOL | Se é plano de trial |
features | JSONB | Features habilitadas |
ativo | BOOL | Status |
escola_assinaturas
Assinatura ativa de cada escola.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
plano_id | UUID (FK → planos) | Plano |
status_assinatura | ENUM status_assinatura | trial, ativa, suspensa, cancelada |
data_inicio | DATE | Início |
data_fim | DATE | Fim (opcional) |
trial_ate | DATE | Expiração do trial |
valor_atual | NUMERIC | Valor atual mensal |
proximo_vencimento | DATE | Próxima cobrança |
dia_vencimento | INT | Dia fixo de vencimento |
intervalo_cobranca | TEXT | "mensal", "anual" |
meses_contratados | INT | Total contratado |
data_fim_contrato | DATE | Fim do contrato |
renovacao_automatica | BOOL | Se renova automaticamente |
permite_cancelamento_antecipado | BOOL | Se permite cancelar |
multa_cancelamento_percentual | NUMERIC | % de multa |
gateway_subscription_id | TEXT | ID no gateway |
gateway_customer_id | TEXT | ID do cliente no gateway |
escola_faturas
Faturas mensais geradas para escolas.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
plano_id | UUID (FK → planos) | Plano na geração |
numero_fatura | TEXT | Ex: "OLP-2026-0001" (trigger) |
referencia_mes | DATE | Mês de referência |
valor | NUMERIC | Valor da fatura |
desconto | NUMERIC | Desconto aplicado |
taxas | NUMERIC | Taxas adicionais |
status_pagamento | ENUM status_pagamento | pendente, pago, vencido, cancelado |
vencimento_em | DATE | Data de vencimento |
pago_em | DATE | Data do pagamento |
tipo_fatura | TEXT | "mensal", "setup" |
metodo_pagamento | TEXT | "pix", "boleto", "cartao" |
link_pagamento | TEXT | URL de pagamento |
gateway_preference_id | TEXT | ID da preference (MercadoPago) |
gateway_payment_id | TEXT | ID do pagamento |
pix_qrcode | TEXT | QR Code PIX |
pix_copia_cola | TEXT | PIX copia e cola |
pix_expiracao | TIMESTAMPTZ | Expiração do PIX |
boleto_pdf_url | TEXT | URL do boleto |
codigo_barras | TEXT | Código de barras |
sms_enviado_em | TIMESTAMPTZ | Quando lembrete de mensagem enviado |
lembrete_d5_enviado_em | TIMESTAMPTZ | Lembrete D-5 |
migrada | BOOL | Se foi migrada de sistema antigo |
twilio_billing_log ⚠️ LEGADO/DESCONTINUADO
Tabela legada do antigo provedor Twilio. Não é mais utilizada ativamente. Mantida apenas por histórico de dados.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
saldo | NUMERIC | Saldo em USD |
moeda | TEXT | "usd" (default) |
consultado_por | UUID (FK → usuarios) | Quem consultou (null = cron) |
10. Sistema
login_otps
OTPs para login do sistema admin.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
usuario_id | UUID (FK → usuarios) | Usuário |
codigo_otp_hash | TEXT | Hash SHA-256 do OTP |
expira_em | TIMESTAMPTZ | Expiração (5 min) |
usado_em | TIMESTAMPTZ | Quando foi usado |
tentativas_falhas | INT | Contador (max 3) |
ip_origem | TEXT | IP do solicitante |
user_agent | TEXT | User agent |
portal_otps
OTPs para login do Mural Olímpico (aluno/responsável).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
entidade_id | UUID | ID do aluno ou responsável |
tipo_entidade | TEXT | "aluno" ou "responsavel" |
escola_id | UUID (FK → escolas) | Escola |
codigo_otp_hash | TEXT | Hash SHA-256 |
expira_em | TIMESTAMPTZ | Expiração |
usado_em | TIMESTAMPTZ | Quando usado |
tentativas_falhas | INT | Contador |
ip_origem | TEXT | IP |
user_agent | TEXT | User agent |
portal_login_tentativas
Rate limiting do Mural Olímpico público.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
ip | TEXT | IP do cliente |
tipo_tentativa | TEXT | "lookup", "login_aluno_a", etc. |
identificador | TEXT | Identificador (matrícula, CPF) |
escola_id | UUID (FK) | Escola |
sucesso | BOOL | Se foi sucesso |
portal_alert_cooldown
Cooldown de alertas ntfy para evitar spam (sem PK UUID — usa alert_key como PK).
| Coluna | Tipo | Descrição |
|---|---|---|
alert_key | TEXT (PK) | Chave do alerta |
last_sent | TIMESTAMPTZ | Última vez enviado |
portal_rate_metrics
Métricas agregadas de rate limiting do Mural por janela temporal.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
janela_inicio | TIMESTAMPTZ | Início da janela (por minuto) |
tipo_acao | TEXT | Tipo de ação (lookup, login, otp, etc.) |
escola_id | UUID (FK → escolas) | Escola (nullable — null = global) |
contagem | INT | Total de requisições na janela |
contagem_bloqueada | INT | Total bloqueado na janela |
UNIQUE: (janela_inicio, tipo_acao, COALESCE(escola_id, '00000000-...'))
token_blacklist
Tokens JWT invalidados (logout, troca de perfil).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
jti | TEXT | JWT ID (claim jti do token) |
usuario_id | UUID (FK → usuarios) | Dono do token |
motivo | TEXT | "logout" (default) |
expira_em | TIMESTAMPTZ | Expiração original do token |
senha_historico
Histórico de senhas (hashes) para impedir reutilização.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
usuario_id | UUID (FK → usuarios) | Usuário |
senha_hash | TEXT | Hash Argon2 da senha |
sms_log
Log unificado de todas as mensagens enviadas (WhatsApp + SMS fallback).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
provider | TEXT | "wasender" (default). Valor "twilio" é legado. |
provider_msg_id | TEXT | ID da mensagem no provider |
origem | TEXT | Módulo que enviou (ex: "otp", "faturamento") |
tipo | TEXT | Tipo da mensagem (ex: "otp_login", "lembrete_fatura") |
destinatario | TEXT | Telefone do destinatário |
status | TEXT | "sent" (default), "delivered", "failed", etc. |
delivery_status | TEXT | Status de entrega (webhook) |
delivery_updated_at | TIMESTAMPTZ | Última atualização de entrega |
erro_codigo | TEXT | Código de erro (se falhou) |
erro_mensagem | TEXT | Mensagem de erro |
custo | NUMERIC | Custo da mensagem |
moeda | TEXT | "USD" (default) |
usuario_id | UUID (FK → usuarios) | Usuário associado |
escola_id | UUID (FK → escolas) | Escola associada |
metadata | JSONB | Dados extras |
twilio_sid | TEXT | SID Twilio (legado — campo mantido por compatibilidade) |
logs_transacoes
Log de auditoria para operações de escrita (CREATE, UPDATE, DELETE).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
usuario_id | UUID (FK → usuarios) | Quem executou |
nome_usuario | TEXT | Nome (desnormalizado) |
papel_principal | TEXT | Papel no momento |
acao | TEXT | Ex: "escola.create", "usuario.update" |
detalhes | JSONB | Diff, resumo, etc. |
ip | TEXT | IP do cliente |
cidade | TEXT | Geolocalização |
estado | TEXT | Geolocalização |
pais | TEXT | Geolocalização |
incidentes_resolucoes
Resoluções de incidentes vinculadas a logs de transação.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
log_id | UUID (FK → logs_transacoes) | UNIQUE — Log do incidente |
resolvido_por | UUID (FK → usuarios) | Quem resolveu |
resolvido_em | TIMESTAMPTZ | Quando resolveu |
nota | TEXT | Nota de resolução |
cron_status
Monitoramento de jobs agendados.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
job_name | TEXT | Nome do job |
status | TEXT | "operacional", "erro", "critico" |
ultima_execucao | TIMESTAMPTZ | Última execução |
ultima_execucao_sucesso | TIMESTAMPTZ | Última com sucesso |
ultimo_erro | TEXT | Mensagem do último erro |
ultimo_erro_em | TIMESTAMPTZ | Quando ocorreu |
tentativas_consecutivas | INT | Erros consecutivos |
proximo_retry | TIMESTAMPTZ | Próximo retry |
sms_critico_enviado_em | TIMESTAMPTZ | Alerta enviado |
cadastro_tokens
Tokens para auto-cadastro de escolas trial.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
token | TEXT | Token de cadastro |
tipo | TEXT | "trial" |
escola_id | UUID (FK → escolas) | Escola associada |
criado_por | UUID (FK → usuarios) | Quem gerou |
expira_em | TIMESTAMPTZ | Expiração |
usado | BOOL | Se foi usado |
usado_em | TIMESTAMPTZ | Quando foi usado |
configuracoes_plataforma
Configurações globais key-value.
| Coluna | Tipo | Descrição |
|---|---|---|
chave | TEXT (PK) | Chave da configuração |
valor | JSONB | Valor |
atualizado_por | UUID (FK → usuarios) | Quem atualizou |
coordenador_cores
Cores de identificação de coordenadores na Agenda.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
usuario_id | UUID (FK → usuarios) | Coordenador |
escola_id | UUID (FK → escolas) | Escola |
cor | VARCHAR | Cor hexadecimal |
feature_flags
Feature flags globais para controle de funcionalidades.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
chave | TEXT | Chave da flag (unique) |
nome | TEXT | Nome legível |
descricao | TEXT | Descrição |
ativa_global | BOOL | Se está ativa globalmente (default: true) |
parent_chave | TEXT | Chave da flag pai (para hierarquia) |
canary_groups
Grupos canary para rollout gradual de features.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
nome | TEXT | Nome do grupo |
descricao | TEXT | Descrição |
ativo | BOOL | Se está ativo (default: true) |
canary_group_escolas
Junção N:N entre grupos canary e escolas.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
canary_group_id | UUID (FK → canary_groups) | Grupo |
escola_id | UUID (FK → escolas) | Escola |
adicionada_em | TIMESTAMPTZ | Quando adicionada |
canary_group_usuarios
Junção N:N entre grupos canary e usuários.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
canary_group_id | UUID (FK → canary_groups) | Grupo |
usuario_id | UUID (FK → usuarios) | Usuário |
adicionado_em | TIMESTAMPTZ | Quando adicionado |
feature_flag_canary
Junção N:N entre feature flags e grupos canary.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
feature_flag_id | UUID (FK → feature_flags) | Flag |
canary_group_id | UUID (FK → canary_groups) | Grupo canary |
11. Agenda
tarefas
Sistema de tarefas internas da escola.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
titulo | TEXT | Título |
descricao | TEXT | Descrição |
prioridade | TEXT | "baixa", "media", "alta", "urgente" |
status | TEXT | "pendente", "em_andamento", "concluida" |
prazo | DATE | Data limite |
responsavel_id | UUID (FK → usuarios, SET NULL) | Responsável (nullable — SET NULL ao deletar usuário) |
criado_por | UUID (FK → usuarios, SET NULL) | Criador (nullable — SET NULL ao deletar usuário) |
eventos_manuais_escola
Eventos customizados criados pela escola no calendário.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
criado_por | UUID (FK → usuarios) | Criador |
titulo | TEXT | Título |
descricao | TEXT | Descrição |
data | DATE | Data |
hora | TEXT | Horário |
local | TEXT | Local |
tipo | TEXT | "manual" |
olimpiada_id | UUID (FK → olimpiadas) | Olimpíada (opcional) |
12. Importação
importacao_alunos_sessoes
Sessões de importação em lote de alunos (via XLSX).
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
usuario_id | UUID (FK → usuarios) | Quem importou |
status | TEXT | "pendente", "processando", "concluida", "erro" |
total_alunos | INT | Total a processar |
alunos_processados | INT | Processados |
alunos_sucesso | INT | Com sucesso |
alunos_erro | INT | Com erro |
alunos_ignorados | INT | Ignorados |
progresso | INT | % de progresso |
dados_importacao | JSONB | Dados do XLSX |
resultados | JSONB | Resultados detalhados |
mensagem | TEXT | Mensagem de status |
importacao_resultados_sessoes
Sessões de importação em lote de resultados/notas (via XLSX). Mesmo padrão arquitetural da importacao_alunos_sessoes.
| Coluna | Tipo | Descrição |
|---|---|---|
id | UUID (PK) | Identificador |
escola_id | UUID (FK → escolas) | Escola |
usuario_id | UUID (FK → usuarios) | Quem importou |
olimpiada_id | UUID (FK → olimpiadas) | Olimpíada alvo |
fase_id | UUID (FK → fases_olimpiada) | Fase alvo |
nivel_id | UUID (FK → niveis_competicao) | Nível (opcional) |
status | TEXT | "pendente", "processando", "concluida", "falha", "cancelada" |
total_resultados | INT | Total a processar |
resultados_processados | INT | Processados |
resultados_sucesso | INT | Com sucesso |
resultados_erro | INT | Com erro |
resultados_atualizados | INT | Atualizados (upsert) |
inscricoes_auto_criadas | INT | Inscrições criadas automaticamente |
matriculas_nao_encontradas | TEXT[] | Matrículas não localizadas |
progresso | INT | % de progresso |
dados_importacao | JSONB | Dados do XLSX |
resultados_detalhes | JSONB | Detalhes (success, errors, updated) |
Enums
| Enum | Valores |
|---|---|
tipo_escola | publica, privada, rede, sistema_ensino |
status_escola | em_analise, ativa, suspensa, encerrada |
area_conhecimento_olimpiada | matematica, fisica, quimica, biologia, informatica, geografia, historia, portugues, astronomia, robotica, filosofia, multidisciplinar |
abrangencia_olimpiada | nacional, internacional, regional, estadual |
tipo_aplicacao_olimpiada | presencial, online, hibrido, online_na_escola, por_fase |
tipo_inscricao_olimpiada | individual, por_equipe, por_escola, pelo_professor |
tipo_custo_inscricao | gratuita, paga |
status_inscricao_olimpiada | abertas, encerradas, em_breve, suspensas |
tipo_atividade_cronograma | inicio_prazo, fim_prazo, atividade, marco, prova, resultado, inscricao, pagamento, documento |
status_assinatura | trial, ativa, suspensa, cancelada |
status_pagamento | pendente, pago, vencido, cancelado |
status_video_curso | rascunho, publicado |
categoria_visual_curso | azul_claro, verde, vermelho, roxo, amarelo, cinza |
notification_type | fatura_proxima, fatura_vencida, pagamento_confirmado, inscricao, resultado, mensagem, sistema, cron_falha, equipe_olp, solicitacao_vinculo |
grupo_serie_escolar | fundamental_iniciais, fundamental_finais, medio |
permissao_area | gestao_olimpiadas, resultados, comunicacao, inscricoes, videos, mural, relatorios, painel_controle, calendario, olimpiadas_coord, dashboard_gestor, alunos, usuarios, pagamentos, configuracoes, painel_geral, uso_plataforma, projeto_olimpico, financeiro, agenda, dashboard_escola, formacao |
solicitacao_vinculo_status | pendente, aceita, recusada |
template_hub_tipo | institucional, olimpiada |
template_mensagem_tipo | abertura_turma, lembrete_encontro, anuncio_resultado, sessao_fotos, anuncio_simulado, lembrete_simulado, aplicacao_prova_interna, aplicacao_prova_externa |
tipo_codigo | cpf, cnpj, inep |
tipo_planos | Básico, Enterprise, Profissional, Essencial |
tutorial_secao | dashboard, olimpiadas, calendario, resultados, comunicacao, inscricoes, videos, jornal_olimpico, perfil, esp_dashboard, esp_banners, esp_headers, esp_olimpiadas, esp_templates, esp_cursos, esp_cursos_videos, esp_tutoriais, esp_configuracoes, gestor_dashboard, gestor_alunos, gestor_turmas, gestor_usuarios, gestor_responsaveis, gestor_pagamentos, gestor_configuracoes, gestor_portal, coord_painel, coord_calendario, coord_olimpiadas, coord_inscricoes, coord_resultados, coord_comunicacao, coord_videos, coord_videos_player, coord_mural, dir_painel, dir_uso, dir_projeto, dir_financeiro, escola_dashboard, escola_alunos, escola_usuarios, escola_pagamentos, escola_configuracoes, coord_resultados_olimpiada |
tutorial_status | ativo, inativo |
Database Functions
| Função | Tipo | Descrição |
|---|---|---|
aluno_pertence_escola(p_aluno_id) | SECURITY DEFINER | Verifica se aluno pertence à escola do JWT. Evita recursão RLS. |
get_alunos_responsavel() | SECURITY DEFINER | Retorna IDs dos alunos vinculados ao responsável do JWT. |
responsavel_vinculado_aluno(p_aluno_id) | SECURITY DEFINER | Verifica se responsável do JWT está vinculado ao aluno. |
responsavel_tem_aluno_na_escola(p_responsavel_id) | SECURITY DEFINER | Verifica se responsável tem aluno na escola do JWT. |
usuario_na_mesma_escola(p_usuario_id, p_escola_id) | SECURITY DEFINER | Verifica se usuário tem papel ativo na escola. Usada em RLS. |
update_updated_at_column() | TRIGGER | Atualiza atualizado_em = now() antes de UPDATE. |
gerar_numero_fatura() | TRIGGER | Gera numero_fatura sequencial (ex: OLP-2026-0001). |
calcular_proximo_vencimento() | TRIGGER | Calcula proximo_vencimento ao criar assinatura. |
fn_validar_escola_usuario_papel() | TRIGGER | Valida consistência escola_id ao inserir em usuario_papeis. |
limpar_otps_expirados() | Utility | Remove OTPs expirados há mais de 24h. |
increment_video_view(p_video_id) | SECURITY DEFINER | Incrementa visualizacoes em cursos_videos. |
increment_banner_metric(p_id, p_campo) | SECURITY DEFINER | Incrementa visualizacoes ou cliques em banners_login. |
portal_check_guards(p_escola_id, p_ip, p_identificador, p_tipo, ...) | SECURITY DEFINER | Query atômica de rate limit do Mural (count_escola, count_ip, failed_24h). 2 overloads (com e sem p_window_minutes_ip). |
portal_increment_metric(p_tipo, p_escola_id, p_blocked) | SECURITY DEFINER | Incrementa métricas de rate limit em portal_rate_metrics com UPSERT. |
portal_check_alert_cooldown(p_key, p_minutes) | SECURITY DEFINER | Verifica e registra cooldown de alertas ntfy. Retorna TRUE se pode enviar. |
admin_list_canary_groups_with_counts() | SECURITY DEFINER | Lista grupos canary com contagem de escolas, usuários e flags. |
validar_tarefa_titulo() | TRIGGER | Valida que título da tarefa não excede 120 caracteres. |
trigger_set_updated_at_import_resultados() | TRIGGER | Preserva criado_em original ao atualizar importacao_resultados_sessoes. |
Triggers
| Trigger | Tabela | Evento | Função |
|---|---|---|---|
update_*_updated_at | Múltiplas tabelas | BEFORE UPDATE | update_updated_at_column() |
trigger_gerar_numero_fatura | escola_faturas | BEFORE INSERT | gerar_numero_fatura() |
trigger_calcular_vencimento | escola_assinaturas | BEFORE INSERT | calcular_proximo_vencimento() |
trigger_validar_escola_papel | usuario_papeis | BEFORE INSERT/UPDATE | fn_validar_escola_usuario_papel() |
trigger_validar_tarefa_titulo | tarefas | BEFORE INSERT/UPDATE | validar_tarefa_titulo() |
trigger_set_updated_at_import_resultados | importacao_resultados_sessoes | BEFORE UPDATE | trigger_set_updated_at_import_resultados() |
Storage Buckets
| Bucket | Público | Uso |
|---|---|---|
banners-login | ✅ Sim | Imagens dos banners na tela de login |
curso-thumbnails | ✅ Sim | Thumbnails de cursos/vídeos |
tutoriais-thumbnails | ✅ Sim | Thumbnails de tutoriais |
mural-imagens | ✅ Sim | Imagens de publicações do mural |
Nota: Todos os buckets são públicos para leitura. O upload é controlado via Edge Functions (não há policies de storage client-side).