autocensup/ESPECIFICACOES.md
Rogério Lima 36d3386d2d feat: protect manual edits from API overwrite, fix pending situacao, sort CRUD lists
- Add Pessoa/Vinculo.atualizado_manualmente flag, set automatically on web CRUD
  save; all Gennera/txt import paths now skip records flagged this way instead
  of overwriting them
- Vinculo import: finalize step corrects leftover "situacao nao informada"
  vinculos to "Desvinculado", pulling carga horaria from censup_carga_horaria
- Generic CRUD list view: click a column header to sort (asc/desc), persists
  through pagination; FK columns sort by their related display field
- Rename GENNERA_API_BASE_URL setting to GENNERA_LOCAL_BASE_URL

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 15:39:36 -03:00

9.7 KiB

Especificacoes do Projeto Autocensup

Visao geral

O Autocensup e uma aplicacao web Django para apoiar a preparacao, conferencia e processamento de dados do Censo da Educacao Superior. O sistema centraliza cadastros de pessoas, cursos, vinculos, instituicoes, polos e tabelas auxiliares, permitindo importar dados locais e da API Gennera, revisar pendencias e operar os registros por ano de censo.

Objetivos

  • Manter uma base local de dados necessarios ao Censo Superior.
  • Importar pessoas e vinculos a partir da API Gennera.
  • Importar o Arquivo Aluno exportado do sistema Censup.
  • Conferir vinculos por curso, situacao e pendencias cadastrais.
  • Permitir ajustes cadastrais via telas CRUD autenticadas.
  • Processar situacoes de vinculos em lote por matricula.

Stack tecnica

  • Linguagem: Python 3.12+.
  • Framework web: Django 5.2.
  • Banco de dados: PostgreSQL 16.
  • Driver PostgreSQL: psycopg 3.
  • Gerenciador de dependencias: uv.
  • Infra local: Docker Compose para o servico db.
  • Templates: Django Templates com Bootstrap/Tabler.
  • Autenticacao: autenticacao padrao do Django, com views protegidas por login.

Configuracao de ambiente

Variaveis principais:

  • DJANGO_DEBUG: habilita ou desabilita modo debug.
  • DJANGO_SECRET_KEY: chave secreta da aplicacao.
  • DJANGO_ALLOWED_HOSTS: hosts permitidos.
  • POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST, POSTGRES_PORT: conexao PostgreSQL.
  • DATABASE_URL: alternativa para configurar o banco por URL.
  • GENNERA_LOCAL_BASE_URL: URL base da API Gennera.
  • API_TOKEN: token Bearer usado nas chamadas a API Gennera.

Comandos basicos:

cp .env.example .env
UV_CACHE_DIR=/tmp/uv-cache uv sync
docker compose up -d db
UV_CACHE_DIR=/tmp/uv-cache uv run python manage.py migrate
UV_CACHE_DIR=/tmp/uv-cache uv run python manage.py loaddata ufs municipios
UV_CACHE_DIR=/tmp/uv-cache uv run python manage.py runserver

Modulos principais

  • config/settings.py: configuracao Django e leitura de variaveis de ambiente.
  • core/models.py: modelos de dominio.
  • core/views.py: dashboard, selecao de ano, importacoes, processamento em lote e CRUD generico.
  • core/importers.py: importacao de arquivos, CSVs e API Gennera.
  • core/validation.py: validacoes de curso, pessoa e vinculo.
  • core/year.py: ano de censo selecionado na sessao.
  • templates/: layout e telas da aplicacao.
  • docs/: insumos e regras de leiaute do Censo Superior.

Modelo de dados

AnoCenso

Representa o ano de referencia do censo. O campo ano e chave primaria. A propriedade ano_execucao retorna ano + 1.

UF, Pais e Municipio

Tabelas auxiliares usadas nos cadastros de pessoa. Municipio pertence a uma UF.

Curso

Cadastro de cursos identificados por codigo_mec. Campos relevantes:

  • descricao.
  • situacao de funcionamento.
  • indicador de licenciatura.
  • indicador de EaD.
  • carga horaria total.
  • polo vinculado, quando aplicavel.

FallbackCurso

Mapeia textos divergentes entre dados externos e cursos locais para uso cadastral/manual. A importacao de vinculos da API Gennera nao usa fallback por nome: o curso deve ser identificado exclusivamente por course_code.

Instituicao e Polo

Representam instituicoes INEP e locais de oferta. Polos podem ser vinculados a cursos EaD.

Pessoa

Cadastro do aluno/pessoa com CPF unico, dados de nascimento, nacionalidade, cor/raca, pais de origem, deficiencias, tipo de escola do ensino medio e anos de censo associados.

Vinculo

Relaciona pessoa, curso e ano de censo. Regras estruturais:

  • ano_censo referencia AnoCenso.
  • curso referencia Curso.codigo_mec.
  • uma pessoa pode ter apenas um vinculo para o mesmo curso no mesmo ano de censo.
  • uma pessoa pode ter mais de um vinculo no mesmo ano de censo quando os cursos forem diferentes.
  • a regra acima e garantida por restricao unica em pessoa, curso e ano de censo.
  • vinculos sao filtrados pelo ano de trabalho selecionado em telas de consulta.

Situacoes suportadas:

  • Nao informada.
  • Cursando.
  • Matricula trancada.
  • Desvinculado do curso.
  • Transferencia interna.
  • Formado.
  • Falecido.

Funcionalidades web

Dashboard

Rota: /

Exibe vinculos agregados por curso para o ano selecionado, com contadores por situacao e quantidade de registros pendentes.

Selecao de ano de censo

Rota: /ano-censo/

Atualiza na sessao o ano de trabalho. Esse ano e usado para filtrar vinculos em dashboard, listagens e processamento de situacao.

Importacao do Arquivo Aluno

Rota: /importar/alunos/

Recebe arquivo .txt do Censup e processa registros:

  • 40: cabecalho.
  • 41: dados cadastrais de pessoa.
  • 42: vinculo do aluno com curso.

O resultado informa pessoas criadas/atualizadas, vinculos criados/atualizados, registros ignorados e erros.

Importacao de pessoas Gennera

Rota: /importar/pessoas-gennera/

Consulta a API Gennera por ano de referencia e cria pessoas ainda nao existentes na base local.

Importacao de vinculos Gennera

Rota: /importar/vinculos-gennera/

Consulta a API Gennera por CPF e ano selecionado, criando ou atualizando vinculos locais conforme regras de situacao.

Endpoint esperado:

GET /vinculo/?ano=<ano>&cpf=<cpf>

O curso do vinculo deve ser resolvido exclusivamente pelo campo course_code, correspondente a Curso.codigo_mec. Se course_code nao vier na resposta ou nao existir em cursos locais, o registro deve ser rejeitado com erro.

Processamento de situacao em lote

Rota: /processar/situacao/

Recebe uma lista de matriculas e uma situacao alvo. Atualiza vinculos do ano selecionado e informa matriculas nao encontradas.

Pendencias

Rota: /pendencias/

Lista registros com campos obrigatorios ou regras de consistencia pendentes, usando as validacoes de core/validation.py.

CRUD generico

Rotas:

  • /cadastros/<slug>/
  • /cadastros/<slug>/novo/
  • /cadastros/<slug>/<pk>/
  • /cadastros/<slug>/<pk>/editar/
  • /cadastros/<slug>/<pk>/excluir/

Cadastros disponiveis:

  • anos do censo.
  • UFs.
  • paises.
  • municipios.
  • cursos.
  • fallbacks de curso.
  • instituicoes.
  • polos.
  • pessoas.
  • vinculos.

Regras de validacao

Curso

  • Codigo MEC e descricao sao obrigatorios.
  • Situacao de funcionamento e obrigatoria.
  • Carga horaria total deve ser maior que zero.
  • Curso EaD deve ter polo vinculado.

Pessoa

  • Nome, CPF, data de nascimento, cor/raca, nacionalidade, pais de origem, indicador de deficiencia e tipo de escola do ensino medio sao obrigatorios.
  • CPF deve conter 11 digitos numericos.
  • Brasileira nata deve ter pais BRA e UF de nascimento.
  • Brasileira naturalizada ou estrangeira nao pode ter pais BRA nem UF/municipio de nascimento.
  • Municipio de nascimento exige UF e deve pertencer a UF informada.
  • Quando o indicador de deficiencia for Sim, todos os tipos de deficiencia devem estar preenchidos e ao menos um deve estar marcado.

Vinculo

  • Ano do censo e situacao sao obrigatorios.
  • Semestre de ingresso deve seguir o formato 01AAAA ou 02AAAA.
  • Curso presencial exige turno do aluno.
  • Curso EaD exige polo no vinculo ou no curso.
  • Curso de licenciatura exige informacoes de Aluno PARFOR e segunda licenciatura/formacao pedagogica.
  • Carga horaria total do aluno deve vir do curso.
  • Vinculo formado exige carga horaria integralizada maior ou igual a carga horaria total.
  • Indicadores de financiamento, apoio social, atividade extracurricular e acao afirmativa devem ter os tipos correspondentes preenchidos conforme a opcao principal.

Regras de importacao de vinculos

  • A decisao de situacao e feita por pessoa, curso e ano de censo.
  • Registros retornados pela API para outro ano sao ignorados na decisao do ano selecionado.
  • Se a carga horaria acumulada for maior ou igual a carga horaria total do curso, a situacao deve ser Formado.
  • Vinculo ja Formado nao deve ser rebaixado por outra regra de importacao.
  • Se houver registro no segundo semestre do ano selecionado, a situacao deve ser Cursando.
  • Se houver registro apenas no primeiro semestre do ano selecionado, a situacao deve ser Desvinculado.
  • Se nao houver vinculo retornado para pessoa que ja possui vinculo local no ano, a situacao local deve ser Desvinculado, exceto quando ja estiver Formado.
  • A carga horaria acumulada retornada pela API deve atualizar a carga horaria integralizada mesmo quando a situacao Formado for preservada.
  • O campo semestre_ingresso deve ser atualizado a partir do registro mais antigo do grupo de vinculos, considerando ano e semestre. O formato gravado e AAYYYY, por exemplo 012026 para primeiro semestre de 2026.

Dados de apoio

Arquivos relevantes em docs/:

  • REGRAS_ARQUIVO_ALUNO.md: regras do leiaute do Arquivo Aluno.
  • aluno_exportacao.txt: exemplo ou insumo de arquivo aluno.
  • cursos.csv e cursos_locais.csv: insumos de cursos.
  • leiaute_aluno_2025.xlsx: leiaute oficial usado como referencia.
  • tabela_municipio_2025.xlsx, tabela_paises_2025.xlsx, tabela_uf_2025.xlsx: tabelas auxiliares.

Fluxo operacional sugerido

  1. Conferir e atualizar cadastros de cursos.
  2. Exportar aluno_exportacao.txt no sistema Censup.
  3. Importar o Arquivo Aluno no Autocensup.
  4. Importar pessoas e vinculos da API Gennera quando necessario.
  5. Revisar dashboard e pendencias.
  6. Processar ajustes de situacao por matricula, se aplicavel.
  7. Corrigir cadastros pendentes via CRUD.

Testes

Executar a suite:

UV_CACHE_DIR=/tmp/uv-cache uv run python manage.py test

Verificar migracoes pendentes:

UV_CACHE_DIR=/tmp/uv-cache uv run python manage.py makemigrations --check --dry-run

Observacoes de schema

O campo Vinculo.ano_censo e uma ForeignKey para AnoCenso, mas usa explicitamente a coluna fisica ano_censo no banco por compatibilidade com dados existentes. Essa decisao evita perda de dados e mantem o ORM alinhado ao schema atual.