Ir para o conteúdo

Sincronizar alunos ​

Objetivo: manter os alunos de uma turma do Presente iguais aos do seu sistema acadêmico. A forma recomendada é a importação CSV, que é idempotente e valida antes de gravar.

Você precisa de: uma conta com CADASTRAR na turma (por exemplo, COORDENADOR da disciplina; veja Permissões) e o identificador (id) da turma.

Visão geral ​

  1. Entrar e achar a turma (GET /turmas).
  2. Montar o CSV com os alunos do seu sistema.
  3. Simular (modo: "simular"): nada é gravado; o relatório diz o que aconteceria.
  4. Conferir o relatório e aplicar (modo: "aplicar").
  5. Desativar quem saiu da turma no seu sistema (a importação nunca remove ninguém).

1. Achar a turma ​

GET /turmas lista as turmas que a conta enxerga (cada item tem id, nome, disciplinaId, instituicaoId). Para uma disciplina específica: GET /disciplinas/{disciplinaId}/turmas. Guarde o id da turma junto ao identificador dela no seu sistema.

2. O CSV ​

csv
nome,email
Ana Exemplo,ana@exemplo.org
Bruno Exemplo,bruno@exemplo.org
  • Colunas obrigatórias: nome e email. Os nomes de coluna aceitam apelidos em português, espanhol e inglês (por exemplo name, nombre, correo), sem diferenciar maiúsculas nem acentos.
  • Separador: vírgula, ponto e vírgula ou tabulação (detectado pelo cabeçalho). Aspas duplas para valores com separador; "" para aspas dentro do valor. Aceita CRLF ou LF e BOM do Excel.
  • Limites: 500 linhas e 90 000 caracteres por arquivo. Acima disso, divida em vários arquivos e envie um por vez.
  • O mesmo e-mail duas vezes no arquivo: a segunda ocorrência vira erro (duplicate).

3. Simular ​

POST /turmas/{turmaId}/importacoes/alunos, com o CSV como texto no corpo JSON:

bash
curl -X POST "$API/turmas/$TURMA/importacoes/alunos" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile csv alunos.csv '{csv: $csv, modo: "simular"}')"
js
import { readFileSync } from "node:fs"

const csv = readFileSync("alunos.csv", "utf8")
const r = await fetch(`${API}/turmas/${TURMA}/importacoes/alunos`, {
  method: "POST",
  headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
  body: JSON.stringify({ csv, modo: "simular" }),
})
const relatorio = await r.json()
python
csv = open("alunos.csv", encoding="utf-8").read()
r = requests.post(f"{API}/turmas/{TURMA}/importacoes/alunos",
                  headers={"Authorization": f"Bearer {token}"},
                  json={"csv": csv, "modo": "simular"})
relatorio = r.json()

A resposta é 200 (mesmo quando há linhas com erro: erro de linha é conteúdo do relatório, não da chamada):

json
{
  "tipo": "alunos",
  "modo": "simular",
  "aplicado": false,
  "erroArquivo": null,
  "colunaAusente": null,
  "resumo": { "VALIDA": 1, "JA_EXISTE": 1 },
  "linhas": [
    { "linha": 2, "situacao": "VALIDA", "rotulo": "ana@exemplo.org" },
    { "linha": 3, "situacao": "JA_EXISTE", "rotulo": "bruno@exemplo.org" }
  ],
  "convites": null
}

Situações de cada linha:

SituaçãoSignificado
VALIDA(só no simular) seria criada ou vinculada.
CRIADAConta nova criada e matriculada; a pessoa recebe um convite por e-mail.
VINCULADAO e-mail já tinha conta na plataforma; a pessoa foi matriculada nesta turma.
REATIVADAA matrícula estava inativa e voltou.
JA_EXISTEJá estava matriculada: nada a fazer. Repetir a importação não duplica nem reenvia convite.
ERROA linha impede a importação; campo e codigo dizem o motivo.

codigo pode ser required, invalid, too_long, out_of_range, duplicate ou not_found. erroArquivo indica problema do arquivo todo: empty, too_many_lines, unterminated_quote, too_large ou missing_column (com colunaAusente).

O simular não revela se um e-mail já tem conta na plataforma (por privacidade); por isso convites vem null e linhas novas aparecem como VALIDA.

4. Aplicar ​

Repita a chamada com "modo": "aplicar". Por padrão é tudo ou nada: se alguma linha tiver ERRO, aplicado vem false e nada é gravado. Corrija o arquivo e envie de novo. Com sucesso, aplicado é true e convites diz quantos e-mails de convite saíram.

Atenção: aplicar com e-mails reais envia convites reais. Teste o seu código na demonstração, com dados fictícios, antes de apontar para produção.

Modo parcial ​

Para importar só as linhas válidas e deixar as outras para depois, use "parcial": true com uma trava de conteúdo:

  1. simular com parcial: true: a resposta traz hashConteudo (SHA-256 do conteúdo) e contagens (importadas, ignoradas).
  2. aplicar com parcial: true e o mesmo hashConteudo, com o mesmo arquivo. Se o arquivo mudou, a resposta é 409 CONFLICT.

A resposta do aplicar parcial traz ignoradas: as linhas que ficaram de fora. Elas existem só nessa resposta (não ficam guardadas), então registre-as no seu lado.

5. Quem saiu da turma ​

A importação só acrescenta ou reativa. Para refletir saídas, leia as matrículas e desative quem não está mais no seu sistema:

bash
# todas as matrículas, inclusive inativas (paginar: veja "Paginação e limites")
curl "$API/turmas/$TURMA/matriculas?limite=200&inativos=true" -H "Authorization: Bearer $TOKEN"

# desativar uma matrícula
curl -X PATCH "$API/turmas/$TURMA/matriculas/$MATRICULA" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"ativo": false}'

Cada item da lista de matrículas tem id (a matrícula), usuarioId, nome, email, ativo e status da conta (CONVIDADO, ATIVO ou SUSPENSO). Compare por email com a lista do seu sistema. Desativar uma matrícula mantém o histórico de presença do aluno; para voltar, importe de novo (REATIVADA) ou envie {"ativo": true}.

Exemplo completo (JavaScript) ​

js
const auth = { Authorization: `Bearer ${token}` }
const json = { ...auth, "Content-Type": "application/json" }

async function importa(csv, modo, extra = {}) {
  const r = await fetch(`${API}/turmas/${TURMA}/importacoes/alunos`, { method: "POST", headers: json, body: JSON.stringify({ csv, modo, ...extra }) })
  if (!r.ok) throw new Error(`HTTP ${r.status} ${(await r.json()).code}`)
  return r.json()
}

const simulacao = await importa(csv, "simular")
const erros = simulacao.linhas.filter((l) => l.situacao === "ERRO")
if (simulacao.erroArquivo || erros.length) {
  console.error("Corrija o arquivo:", simulacao.erroArquivo ?? erros)
} else {
  const aplicado = await importa(csv, "aplicar")
  console.info(aplicado.resumo, `convites: ${aplicado.convites}`)
}

Pessoas com papel (equipe) ​

Para criar professores, coordenadores, preceptores e auxiliares em lote, e também alunos de várias turmas de uma vez, use POST /instituicoes/{instituicaoId}/importacoes/pessoas. Exige ADMINISTRAR na instituição (CURADOR). O funcionamento é o mesmo; as colunas são:

ColunaObrigatóriaValores
nome, emailsimComo acima.
papelsimALUNO, PROFESSOR, COORDENADOR, AUXILIAR, PRECEPTOR, CURADOR.
disciplinaconforme o papelA sigla da disciplina.
turmaconforme o papelO nome da turma (dentro da disciplina).
avalia, cadastranãosim/não (aceita s, n, yes, true, 1...): marcas podeAvaliar e podeCadastrar.

Escopo exigido por papel: ALUNO e PROFESSOR pedem disciplina e turma; COORDENADOR pede disciplina; AUXILIAR pede disciplina (e pode ter turma); CURADOR e PRECEPTOR não têm disciplina nem turma. Disciplina ou turma que não existem viram ERRO com not_found.

contato@presente.app.br