Skip to content

[Janela Simulado] Cards 01+02 · ms-simulado · schema + availability + PATCH/gate - #164

Merged
FernandoAlmeidaPinto merged 8 commits into
developfrom
feature/simulado-janela-disponibilidade-card02
Aug 1, 2026
Merged

[Janela Simulado] Cards 01+02 · ms-simulado · schema + availability + PATCH/gate#164
FernandoAlmeidaPinto merged 8 commits into
developfrom
feature/simulado-janela-disponibilidade-card02

Conversation

@FernandoAlmeidaPinto

Copy link
Copy Markdown
Member

[Janela Simulado] Cards 01 + 02 · ms-simulado

Etapa 5 (Janela Simulado). Adiciona janela de disponibilidade temporal opcional por simulado (disponivelDe / disponivelAte), complementar ao bloqueado atual. Retrocompatível: simulados legados ficam null/null e continuam disponíveis como hoje.

Este PR reúne os dois cards de ms-simulado da etapa (Card 01 é pré-requisito do 02).

Card 01 — schema + funções de availability + índice

  • Campos disponivelDe / disponivelAte (Date | null, default null) no schema Simulado.
  • helpers/availability.ts: funções puras isSimuladoAvailable e getAvailabilityStatus (enum disponivel | bloqueado | antes_da_janela | depois_da_janela) — fonte única de verdade.
  • Índice composto { categoria, bloqueado, disponivelDe, disponivelAte } (via SimuladoSchema.index, criado no boot por autoIndex).

Card 02 — endpoint + filtro + gate

  • PATCH /v1/simulado/:id/disponibilidade (DTO UpdateDisponibilidadeDTO) com semântica parcial: campo omitido = inalterado, null explícito = limpa. Validação cross-field (disponivelDe >= disponivelAte → 400) feita sobre os valores finais (existente + payload).
  • Filtro de janela em getAvailable: aluno só vê simulados dentro da janela (ou null/null).
  • Gate em getToAnswer: 403 com payload { message, status } quando fora da janela (ou bloqueado). O status detalhado permite ao frontend exibir mensagem específica.
  • POST /v1/simulado/answer não é gated — grace period intencional (aluno que abriu dentro da janela pode submeter fora).

Notas de implementação (divergências corrigidas vs spec original)

  • Gate lançado antes do try/catch de getToAnswer — o try/catch existente engolia erros e retornava null, então o 403 precisava propagar de fora dele.
  • Método de repositório updateDisponibilidade em vez de acessar model (protected em BaseRepository) direto do service.
  • Leitura projetada getAvailabilityById no gate para evitar o getById pesado (populate aninhado) duplicado no hot path.

Testes

  • Funções puras: matriz completa (bloqueado/antes/dentro/depois × sem janela/com janela + limites inclusivos + 4 status).
  • Repo: updateDisponibilidade ($set parcial + null), getAvailable (shape do filtro de janela), getAvailabilityById (projeção sem populate).
  • Service: gate 403 (bloqueado/antes/depois), not-found, validação cross-field (inclusive merge), persistência parcial e clear.
  • 30 testes verdes no módulo simulado. Build e lint dos arquivos tocados ok.

Deploy

Sem migration SQL. Documentos legados nascem null/null automaticamente; índice criado no boot.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant