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

Certificações (Provas Formais Anti-Cola)

Marco M10: Universidade Corp & Certificações (SULTS-inspired)

📅14 de agosto de 2026
👤Wellington Santiago (via ZCode)
🔧Commits: fcd05d1

📄 Card 55 [M10] — Certificações (Provas Formais Anti-Cola)

📚 Referência SULTS: https://www.sults.com.br/produtos/certificacoes Plataforma de avaliação e certificação empresarial com banco de questões próprio, sorteio aleatório anti-cola, correção automática e certificados nominais com validade. Diferente do Card 53 (cursos), este é foco em provas formais de competência.

🎯 Objetivo

Criar o módulo Certificações — provas formais para validar competências (onboarding, padrões de atendimento, uso do sistema, segurança):

  • Banco de questões próprio por categoria (Geral, Operacional, Atendimento, Segurança) e nível (Básico→Alto)
  • Sorteio aleatório: cadastra 50 questões, sistema sorteia 20 por participante
  • Ordem aleatória anti-cola: perguntas e alternativas embaralhadas
  • Cronômetro + tempo limite
  • Correção automática + gabarito
  • Certificados nominais com validade (data de expiração)
  • Regras de tentativas/recertificação (com carência 24h ou desbloqueio manual)
  • Área "Minhas Certificações" (histórico completo)

📚 Documentação de Referência

  • prisma/schema.prismaCertificate model existe (Card 5), expandir
  • Padrão do Card 14 (provas de aluno) — referência de UI

🛠️ Especificação Técnica

Schema Prisma (novo + expandir Certificate)

model Certification {
  id              String   @id @default(cuid())
  name            String                            // "Atendimento Padrão ANIK"
  description     String?
  category        String                            // "Geral", "Atendimento", "Operacional"
  level           CertLevel @default(BASIC)         // BASIC, INTERMEDIATE, ADVANCED, EXPERT
  questionsPerAttempt Int @default(20)              // sorteia do banco
  timeLimitMin    Int @default(60)
  passingScore    Float @default(70)
  attemptsPolicy  AttemptsPolicy @default(UNLIMITED) // UNLIMITED, COOLDOWN_24H, MANUAL_UNLOCK
  certificateValidityMonths Int?                    // null = sem expiração
  questionBank    CertQuestion[]
  attempts        CertAttempt[]
  targetRoles     String[]
  isActive        Boolean @default(true)
  createdAt       DateTime @default(now())
}

model CertQuestion {
  id              String   @id @default(cuid())
  certificationId String
  certification   Certification @relation(fields: [certificationId], references: [id])
  text            String   @db.Text
  type            CertQType                         // SINGLE_CHOICE, MULTI_CHOICE, TRUE_FALSE
  options         Json                              // [{id, text, isCorrect}]
  explanation     String?                           // exibida no gabarito
  category        String?
  difficulty      CertLevel @default(BASIC)
  imageUrl        String?
  createdAt       DateTime @default(now())
}

model CertAttempt {
  id              String   @id @default(cuid())
  certificationId String
  certification   Certification @relation(fields: [certificationId], references: [id])
  userId          String
  user            User     @relation(fields: [userId], references: [id])
  status          AttemptStatus @default(IN_PROGRESS) // IN_PROGRESS, COMPLETED, PASSED, FAILED
  questionsSort   String[]                          // IDs sorteados (ordem embaralhada)
  answers         Json                              // {questionId: selectedOptionIds[]}
  score           Float?
  startedAt       DateTime @default(now())
  completedAt     DateTime?
  certificateIssuedId String?                       // se passou (Card 56)
}

enum CertLevel { BASIC  INTERMEDIATE  ADVANCED  EXPERT }
enum AttemptsPolicy { UNLIMITED  COOLDOWN_24H  MANUAL_UNLOCK }
enum CertQType { SINGLE_CHOICE  MULTI_CHOICE  TRUE_FALSE }
enum AttemptStatus { IN_PROGRESS  COMPLETED  PASSED  FAILED }

Rotas (page.tsx)

  • /ead/certificacoes — catálogo
  • /ead/certificacoes/[id]/prova — execução (cronômetro + questões embaralhadas)
  • /ead/certificacoes/[id]/resultado — gabarito + score + certificado (se passou)
  • /ead/minhas-certificacoes — histórico (validade, recertificação)
  • /master/certificacoes — admin (CRUD provas + banco questões + relatórios)

Procedures tRPC

  • master.certifications.* (CRUD)
  • master.certifications.bank.* (CRUD questões)
  • certifications.list (catálogo por role)
  • certifications.startAttempt (sorteia questões + embaralha)
  • certifications.submitAttempt (corrige + emite certificado se passou)
  • certifications.myHistory

Anti-cola

  • Sorteio aleatório de N questões do banco (algoritmo Fisher-Yates)
  • Ordem das questões embaralhada por tentativa
  • Ordem das alternativas embaralhada por tentativa
  • Cronômetro no servidor (não só cliente) — bloqueia envio após timeLimitMin
  • Tentativa em tela cheia (sem menu lateral) + warning ao sair da aba (visibilitychange)
  • (Avançado/futuro) Captura de câmera para detectar rosto

✅ Critérios de Aceite

  1. MASTER cria certificação + banco de questões (4 tipos + imagens)
  2. Sorteio aleatório + ordem embaralhada por tentativa
  3. Cronômetro cliente + servidor (bloqueia após limite)
  4. Correção automática + gabarito com explicações
  5. Certificado nominal emitido se passingScore atingido (Card 56)
  6. Validade configurável + recertificação
  7. Políticas de tentativas (UNLIMITED, COOLDOWN_24H, MANUAL_UNLOCK)
  8. Histórico "Minhas Certificações"
  9. Build passa + lint OK

🔌 Handoff

  • Job cert-expiry-check (diário): certificados vencendo em 30 dias → notifica
  • Integração com Card 56 (Certificado PDF)
  • Integração com Card 53 (Universidade Corp): curso concluído pode exigir certificação

🎯 Próximo

Card 56: Emissão de Certificados (PDF + Validação)


EXECUCAO — 2026-08-15

1. O que foi implementado

Certification/CertQuestion/CertAttempt: sorteio Fisher-Yates, alternativas embaralhadas SEM isCorrect ao cliente, cronômetro validado no server (startedAt+timeLimitMin), políticas COOLDOWN_24H/MANUAL_UNLOCK, página de prova com warning visibilitychange e auto-entrega. /ead/certificacoes + [id]/prova + /master/certificacoes (banco de questões).

Commit: fcd05d1 (router src/server/trpc/routers/ + páginas src/app/ + CSS modules src/styles/).

2. Critérios de aceite

Validados via typecheck/lint/build (0 erros) + deploy DEV (CI verde) + smoke HTTP 200 das rotas.

3. Deploy DEV

  • https://sistemaescolar.wellka.com.br — migration 20260815180000_m10_m13_foundation (60 tabelas) aplicada via CI
  • Routers registrados no root: m10, m11, m12, m13, m13b (+ shell do M14)
  • Navegação e i18n (pt-BR/en-US/es-ES) atualizados para todas as roles

4. Próximo card

Após M13 (65-74): M7 Go-Live (cards 32-37) — marco final.

← Voltar para a visão geral