Entrar como:FuncionalidadesDoc
Pular para o conteúdo
← Voltar para a visão geral
✅ ConcluídoCard #12 · M3

Diário de Classe - Lançamento de Notas

Marco M3: Painel do Professor (PROFESSOR)

📅03 de agosto de 2026
👤Wellington Santiago (via ZCode)
🔧Commits: 3ebcba8

📄 Documento de Execução — Card 12: [M3] Diário de Classe - Lançamento de Notas

Campo Valor
Card Trello [12] [M3] Diário de Classe - Lançamento de Notas
URL Trello https://trello.com/c/yUIItvUQ
Marco M3 — Painel do Professor (PROFESSOR)
Data execução 04/08/2026
Responsável Wellington Santiago (via ZCode)
Doc anterior Card 11: Chat com Escola (M2)
Próximo card Card 13: Chamada Digital (4 status)
Commits 3ebcba8

🎯 1. O que foi implementado

Substituído o protótipo mock da página /professor/notas (que usava students de @/data/mock, média 6.0 errada e sem persistência) por uma implementação real e completa do Diário de Classe, conectada ao banco de dados via tRPC.

O professor agora pode lançar notas dos alunos por turma/disciplina/módulo, suportando os três sistemas de avaliação (NUMERIC 0-10, CONCEPT_3 Excelente/Bom/A Melhorar para Desenho, CONCEPT_5 A-E para matérias gerais), com cálculo de média ponderada automática, threshold de aprovação 7.0 (decisão confirmada pelo cliente, não 6.0), e fluxo de publicação (notas só ficam visíveis aos alunos/pais após publicar).

A grade é editável inline (clicar numa célula → editar → salvar automaticamente no blur), com estatísticas da turma em tempo real (média da turma, aprovados/reprovados), modal de entrada em lote (uma avaliação para todos alunos de uma vez), e auditoria completa (AuditLog em CREATE/UPDATE/PUBLISH).

Validação de segurança: o professor só consegue lançar notas em turmas/disciplinas onde foi formalmente vinculado via ClassTeacher (atribuição pedagógica). Tentativas de acesso a outras turmas retornam FORBIDDEN.

✅ Critérios de aceite validados

# Critério Status
1 Grid de alunos × avaliações
2 Notas 0-10 por avaliação (NUMERIC)
3 Pesos configuráveis por avaliação
4 Média ponderada automática
5 Aprovado/Reprovado (threshold 7.0)
6 Rota tRPC grade.listByClass
7 Rota tRPC grade.upsert
8 Rota tRPC grade.batchUpsert
9 Rota tRPC grade.publish / unpublish
10 Rota tRPC grade.calculateAverage
11 Página /professor/notas (seleção)
12 Página /professor/notas/[classId] (grid)
13 Componente GradeInput adaptativo
14 Componente AverageCell colorido
15 Filtro por turma/disciplina (via myClasses)
16 Validação: professor só em turmas atribuídas (ClassTeacher)
17 Validação: nota 0-10 (NUMERIC) OU conceito (CONCEPT)
18 Auditoria: AuditLog em CREATE/UPDATE/PUBLISH
19 Indicador "alterações não salvas"
20 Sistema dual: numérico E conceito por curso

📁 2. Arquivos criados/modificados

Criados

Arquivo Função
src/app/(dashboard)/professor/notas/[classId]/page.tsx Grade de lançamento de notas (grid alunos × avaliações, inline edit, publicar)
src/components/ui/GradeInput.tsx Input adaptativo: number 0-10 OU select conceito (3 ou 5 níveis) conforme gradingType
src/components/ui/AverageCell.tsx Célula de média com cor semântica (verde ≥7.0 / vermelho <7.0)

Modificados

Arquivo Mudança
src/server/trpc/routers/professor.ts +sub-router grade com 6 procedures (myClasses, listByClass, upsert, batchUpsert, publish, unpublish, calculateAverage); helpers computeAverage() e resolveTeacher(); constantes PASSING_AVERAGE=7.0 e CONCEPT_VALUE
src/app/(dashboard)/professor/notas/page.tsx Reescrita total: removeu mock, agora lista atribuições reais (ClassTeacher) e navega para o diário

🗄️ 3. Schema do banco (mudanças)

Nenhuma mudança de schema — reutilizado o model Grade existente (com campos value, concept, weight, evaluationType, description, isPublished, publishedAt, periodType, periodNumber, year) e o relacionamento ClassTeacher (validação de acesso pedagógico).

  • Enum GradingSystem { NUMERIC, CONCEPT_3, CONCEPT_5 } já existente (definido no M1.5, decisão #26)
  • Enum PeriodType { MODULE, BIMESTER, TRIMESTER, SEMESTER } — período default: MODULE (decisão do cliente: ano letivo por módulo)

🔌 4. Handoff para o próximo card

Procedures tRPC disponíveis (professor.grade.*)

  • myClasses{ assignments: [{ id, class_: {id,name,code,year,branch}, subject: {id,name,course:{gradingType}} }] }
  • listByClass({classId, subjectId, year, periodNumber}){ classInfo, subjectInfo, gradingType, students[], grades[], passingAverage }
  • upsert({studentId, classId, subjectId, year, periodNumber, value?, concept?, weight, evaluationType?, description?, gradeId?}){id}
  • batchUpsert({classId, subjectId, year, periodNumber, entries[], ...}){created, updated, total}
  • publish({classId, subjectId, year, periodNumber}){published} (+notifica alunos)
  • unpublish(...){unpublished}
  • calculateAverage({studentId, subjectId, year, periodNumber}){average, isApproved}

Padrões reutilizáveis

  • resolveTeacher(prisma, userId) — helper que resolve Teacher.id do usuário logado (reusar em Card 13/14/15/16)
  • computeAverage(grades[]) — cálculo ponderado com tabela de conversão conceito→valor (reusar em relatórios/boletins)
  • GradeInput — componente adaptativo que serve para qualquer lugar que precise entrada de nota
  • AverageCell — célula de exibição de média (reusar em boletim do aluno, painel do pai, relatórios)

Decisões de implementação (defaults adotados)

# Pendência do cliente Default adotado
1 Média: simples ou ponderada? Ponderada (com pesos por avaliação)
2 Pesos: quem define? Professor define ao criar cada avaliação (default peso 1)
3 Tabela conceito→numérico EXCELENTE=10, BOM=7.5, A_MELHORAR=4.0, A=9.5, B=8.0, C=6.5, D=4.0, E=1.0
4 Aluno vê nota imediatamente ou após publish? Após publish (notas são rascunho até publicar)
5 Pais recebem push ao publicar? Alunos recebem notificação in-app (push Web ficará para M6)
6 Professor pode despublicar? Sim (botão Despublicar disponível)
7 Recuperação? Default: alunos <7.0 = "Reprovado" (sem fluxo de recuperação automático ainda)

⚠️ Esses defaults estão marcados em decisoes.md para confirmação do cliente. Se discordar de algum, é só ajustar a tabela CONCEPT_VALUE ou o fluxo.

📋 5. Checklist do Trello — status por item

Entregas (5/5)

  • Grid de alunos × avaliações
  • Notas 0-10 por avaliação
  • Pesos configuráveis
  • Média ponderada automática
  • Aprovado/Reprovado (7.0 — corrigido de 6.0)

Especificação Técnica (20/27 implementados)

Itens de Socket.io live (grade:published via WebSocket) e export Excel não foram implementados nesta iteração (ficam para refinamento futuro, quando Socket.io for adicionado no projeto). Auto-save de rascunho a cada 30s também ficou como melhoria futura (atualmente salva on-blur por célula, que é mais simples e igualmente eficaz).

🚀 6. Deploy DEV

🧠 7. Contexto gerado para próximas etapas

  1. resolveTeacher() + ClassTeacher access check são o padrão de autorização para TODOS os procedures do professor (Cards 13-16). Reusar.
  2. GradeInput é o componente canônico de entrada de nota — qualquer tela que precise editar nota (boletim do aluno com edição, painel do pai com revisão) deve usá-lo.
  3. Tabela CONCEPT_VALUE está duplicada em professor.ts (backend) e na página [classId]/page.tsx (frontend). Se o cliente alterar a tabela de conversão, mudar nos dois lugares. Considerar mover para um lib/grading.ts compartilhado no futuro.
  4. Fluxo publish cria Notification para cada aluno. Quando Socket.io for adicionado (M6 ou futuro), substituir por evento grade:published em tempo real.
  5. Período: UI atual mostra "Módulo 1" fixo (hardcoded periodNumber=1). Para suportar navegação entre módulos, adicionar seletor de módulo no header (melhoria pequena).

🎯 8. Próximo card

Card 13 [M3] Chamada Digital (4 status)

  • Spec: docs/execucao/13-m3-chamada-digital.md
  • Foco: registro de frequência pelo professor (4 status: PRESENT, ABSENT, LATE, JUSTIFIED)
  • Reuso: ProfessorShell, resolveTeacher(), model Attendance, validação ClassTeacher
  • Decisão confirmada pelo cliente: SEM botão "marcar todos presentes" (marcar um por um)
← Voltar para a visão geral