# 10. Duplicação de questão com rastreamento de linhagem #62
FernandoAlmeidaPinto
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Status: 🔒 Bloqueado por:
docs/categoria-simulado.md— modelo Categoria estabilizado.docs/questoes-em-multiplas-provas.md(doc 9) —Questaojá perdeuprovaenumero; criar umaQuestaoindependente "órfã" (sem vínculo a prova ainda) virou natural após o refactor. Doc 10 é uma evolução conceitual em cima do doc 9.Recomendação de execução: após doc 9 estar completo (Fase 5 do §9 do doc 9). Não conflita com docs 4-8.
Serviços afetados:
ms-simulado(schema + endpoint + service),api-vcnafacul(proxy),client-vcnafacul(botão de duplicar + badges de linhagem).Autor: Fernando Almeida
Última atualização: 2026-05-26
1. Contexto
Após o doc 9, a mesma
Questaopode estar em N provas com numerações independentes (Prova.questoes[i].numero). Isso cobre o caso "questão exata é reutilizável", mas não cobre "quero uma variante levemente modificada".Cenário real: admin tem uma questão excelente de Matemática (Q1) na prova ENEM 2023. Quer criar uma variação dela — mesmo conceito, mas com números diferentes nas alternativas — pra usar numa prova nova (Personalizada Cursinho X). Hoje (e após doc 9) ele precisa:
Questaonova do zero, copiando o texto manualmente.Doc 10 introduz a primitiva "duplicar com lastro": a partir de uma questão existente, o admin gera uma cópia editável que registra sua origem e a original passa a saber quais cópias existem dela.
2. Objetivo
Questaoeditável independentemente.origem).copias).3. Escopo
Dentro do escopo
origem: ref<Questao> | nullemQuestao.copias: ref<Questao>[]emQuestao.POST /v1/questao/:id/duplicarno ms-simulado.Permissions.criarQuestao(já existente).Fora do escopo
criarQuestao.4. Decisões de design
_id(novo),createdAt(now),status(= Pending),acertos(= 0),quantidadeResposta(= 0),quantidadeSimulado(= 0),origem(= sourceId),copias(= [])Pending(precisa nova validação por admin)criarQuestaoorigem.origemapontando pra ID soft-deleted. UI mostra "Copiada de [questão excluída]"copiasarray em questão muito copiadanumeromora emProva.questoes[i]. Cópia órfã não tem número até ser adicionada.5. Modelo de dados
5.1 Acréscimos em
Questao5.2 Índices
{ origem: 1 }emQuestao— pra reverse lookup eficiente (encontrar todas as cópias de uma questão). Mas comocopiasarray já vive no documento da original, esse índice é menos crítico. Adicionar só se análise de performance pedir.5.3 Migration
Sem migração de dados necessária. Os dois campos novos têm defaults (
nulle[]); documentos existentes continuam válidos.6. Endpoint de duplicação
6.1
POST /v1/questao/:id/duplicarBody: vazio (
{}).Response 201:
{ "_id": "new_questao_id", "textoQuestao": "... (copiado da original)", "pergunta": "...", "textoAlternativaA": "...", // ... todas as alternativas + imagens (mesmas refs) "alternativa": "B", "enemArea": "Matemática", "frente1": "...", "materia": "...", "status": "Pending", "acertos": 0, "quantidadeResposta": 0, "quantidadeSimulado": 0, "origem": "source_questao_id", "copias": [], "createdAt": "<now>", "updatedAt": "<now>" }Erros possíveis:
404se a questão original não existir.403se o caller não temcriarQuestao.6.2 Implementação no
QuestaoService.duplicar(sourceId)6.3 Controller
6.4 Proxy em api-vcnafacul
POST /mssimulado/questao/:id/duplicar, autenticado, permissãocriarQuestao. Sem lógica de domínio — só proxy.7. Frontend
7.1 Botão "Duplicar"
No modal de visualização da questão (ou na listagem), adicionar botão:
Fluxo do
handleDuplicar:/mssimulado/questao/:id/duplicar.7.2 Badge "Cópia de"
No header da questão (modal ou card), quando
origem != null:7.3 Contador de cópias na original
Quando
copias.length > 0:O botão abre um sub-modal ou drawer com a lista de cópias (cards compactos), permitindo navegar pra qualquer uma.
7.4 Tela / drawer "Ver cópias"
Layout simples, lista de cards:
"Em provas" lista as provas que contêm essa cópia — combina com lookup reverso introduzido no doc 9 (
questoes.questao: id).7.5 Tipo TypeScript
IQuestaoganha:8. Casos especiais
8.1 Questão original soft-deletada
Se a admin deletar (soft) a questão original, a cópia continua existindo. O
origemcontinua apontando pro ID antigo.Frontend: ao tentar abrir a original pelo botão "Ver original", o backend responde 410/404. UI mostra mensagem:
8.2 Cópia da cópia (cadeia)
Q1 → Q2 → Q3:
O lastro é só "pai imediato" — não tem campo "ancestral original". Pra visualizar a cadeia completa, o frontend faz traversal: começa em Q3, segue
origemrecursivamente até chegar em uma questão comorigem == null(a original raiz).8.3 Estatísticas
Cada cópia tem
acertos,quantidadeResposta,quantidadeSimuladopróprios. Não há agregação pela linhagem na primeira release.Item futuro: endpoint
GET /v1/questao/:id/lineage-statsque soma stats da família.8.4 Aprovação independente
Cópia começa em
Pending. Admin precisa aprovar (mesmo fluxo de qualquer questão nova). Aprovação da original não propaga pra cópias — cada uma é independente.8.5 Edição da original
Editar Q1 (texto, alternativas, etc.) não afeta Q2 (que é cópia). As duas são instâncias independentes.
9. Plano de implementação
Backend ms-simulado
origemecopiasno schemaQuestao.QuestaoService.duplicar(sourceId)com transação Mongo.POST /v1/questao/:id/duplicarnoQuestaoController.copiasatualizado).Backend api-vcnafacul
POST /mssimulado/questao/:id/duplicarcom guardcriarQuestao.QuestaoDTO(output) pra incluirorigemecopias.Frontend client-vcnafacul
IQuestaocom novos campos.duplicarQuestao.ts.criarQuestao).Testes
10. Lacunas e itens em aberto
10.1 Visualização em árvore genealógica
Primeira release mostra só pai e filhos diretos. Pra entender "Q5 veio de Q4 que veio de Q3 que veio de Q2 que veio de Q1", admin precisa navegar manualmente.
Como resolveria: tela dedicada de "árvore de linhagem" mostrando o grafo. Doc futuro.
10.2 Diff visual entre original e cópia
Pra admin entender O QUE mudou entre Q1 e Q2 (texto da pergunta, qual alternativa, etc.), faltaria um lado-a-lado com diffs destacados.
Como resolveria: componente de diff que recebe duas questões e compara campo a campo.
10.3 Permissão dedicada "duplicarQuestao"
Hoje reaproveita
criarQuestao. Se algum dia surgir caso "esse cargo pode duplicar mas não criar do zero", separa.10.4 Estatísticas agregadas pela linhagem
Q1.acertos = 50,Q2.acertos = 30(Q2 é cópia). Métrica "família Q1: 80 acertos" não existe nativamente.Como resolveria: endpoint agregado ou cálculo on-demand no frontend (sum em todas da linhagem).
10.5 Merge de questões (juntar Q2 em Q1)
Caso reverso: admin tem duas questões e quer "fundir" em uma. Não suportado.
10.6 Auto-duplicação por trigger
Caso: "questão com taxa de erro > 80% gera cópia automática pra revisão". Não suportado.
10.7 Provas em que a cópia foi inserida
A UI de "Ver cópias" mostra "Em provas: X, Y". Isso depende do lookup reverso do doc 9 (
Prova.questoes.questao).Se o doc 10 for shippado antes do doc 9 finalizar (improvável, dado o status de bloqueio), essa parte da UI fica vazia. Sequência correta evita problema.
11. Riscos
copiasarray crescer demais: improvável > 100. Se acontecer, paginar essa visualização.12. Itens futuros
duplicarQuestao.Beta Was this translation helpful? Give feedback.
All reactions