Sincronização de notas (Moodle → SGA)

Diferente da sincronização de envio (que empurra dados do SGA para o Moodle), este fluxo é o inverso: o SGA consulta o Moodle para obter as notas já lançadas em um diário (turma) específico.

Endpoint

sync_down_grades_service::do_call() (api/sync/down/index.php) responde a uma requisição identificando o diário pelo parâmetro de query string diario_id:

GET /admin/tool/sga/api/sync/down/?diario_id=20231.1.15806.1E.TEC.1386

Note

O comentário no topo do arquivo mostra esse formato de URL como exemplo, mas o mesmo aviso sobre inicialização do endpoint feito em Possível problema de inicialização do endpoint (na página Sincronização de envio (SGA → Moodle)) também se aplica aqui, já que este arquivo também inclui api/servicelib.php.

Consulta

A consulta SQL localiza, via course.idnumber LIKE '%#' || :diario_id, o curso cujo idnumber termina com #<diario_id> (convenção de nomenclatura usada pelos cursos criados via Sincronização de envio (SGA → Moodle)), lista todos os usuários matriculados com papel de arquétipo student nesse curso e, para cada um, monta um objeto JSON (jsonb_object_agg) mapeando o idnumber de cada grade_items — restrito à lista configurada em Notas a sincronizar (notes_to_sync, ver Instalação) — para a nota final lançada (grade_grades.finalgrade).

Warning

A consulta usa jsonb_object_agg, uma função específica do PostgreSQL. Como a esteira de CI (ci.yml) também testa contra MariaDB, este endpoint provavelmente falha em uma instalação Moodle rodando sobre MySQL/MariaDB — comportamento não verificado em ambiente real, apenas inferido da sintaxe SQL usada.

Resposta

Um array JSON, um objeto por aluno matriculado, ordenado por nome completo:

[
  {
    "matricula": "20231015806001",
    "nome_completo": "Fulano de Tal",
    "notas": {"N1": 8.5, "N2": 9.0}
  }
]

notas é null quando o aluno não tem nenhuma nota lançada nos itens configurados; quando presente, é um objeto {idnumber_do_item: nota} apenas com os itens que o aluno realmente possui em grade_grades.

Tratamento de erro

O bloco de tratamento é catch (Exception $ex) sem barra invertida inicial. Como o arquivo declara namespace tool_sga; no topo, esse nome não qualificado resolve para \tool_sga\Exception — classe que não existe neste plugin — e não para a \Exception global do PHP. Na prática, isso significa que o catch provavelmente nunca captura uma exceção real lançada pela camada de banco do Moodle (normalmente uma dml_exception ou similar, fora do namespace tool_sga): o erro tende a propagar como não capturado. Mesmo se o catch chegasse a capturar algo, o código dentro dele chama die("error") antes de qualquer outra linha — as linhas seguintes (http_response_code(500) e o echo json_encode(...) com a mensagem detalhada) ficam inalcançáveis. Ou seja, o tratamento de erro detalhado que o código parece ter sido escrito para produzir não é, de fato, alcançado por nenhum caminho de execução.