Pular para o conteúdo principal

Regras de Exclusão

O DokStamp é projetado para preservar a integridade dos certificados emitidos. Uma vez que um certificado tenha sido emitido, as entidades que ele referencia são protegidas contra exclusão. Esta página explica as regras e os padrões recomendados para integrações.

Exclusão lógica

Todas as entidades no DokStamp usam exclusão lógica: quando você chama DELETE /resource/{uuid}, o registro não é removido fisicamente do banco de dados. Em vez disso, um timestamp deleted_at é definido. Registros com exclusão lógica:
  • São excluídos de todas as respostas de listagem via GET
  • Não podem ser referenciados por novos recursos
  • Retêm todos os seus dados e relacionamentos intactos
  • Podem ser restaurados pelo administrador da plataforma, se necessário
Isso significa que nenhum dado é perdido permanentemente através da API de exclusão padrão.

Regras de proteção contra exclusão

Tentar excluir uma entidade que possua certificados emitidos dependentes resultará em erro. A proteção é aplicada no nível do banco de dados via restrições de chave estrangeira.
EntidadeNão pode ser excluída quando…
InstituiçãoPossui cursos, módulos ou certificados que a referenciam
CursoPossui turmas, matrículas ou certificados que o referenciam
MóduloEstá vinculado a algum curso (relacionamento course_modules existe)
TurmaPossui matrículas ou certificados que a referenciam
EstudantePossui certificados, matrículas ou um snapshot de dados cadastrais

Por que isso importa para integrações

Quando o seu sistema de terceiros exclui ou desativa uma entidade, você não deve espelhar essa exclusão cegamente no DokStamp se certificados já foram emitidos. A abordagem recomendada:

1. Verifique se há certificados antes de excluir

async function canDelete(entityType, uuid) {
  const certs = await api.get('/certificates', {
    params: { [`where[${entityType}_uuid]`]: uuid, per_page: 1 }
  });
  return certs.data.meta.total === 0;
}

// Exemplo para um curso
if (await canDelete('course', courseUuid)) {
  await api.delete(`/courses/${courseUuid}`);
} else {
  // Arquive em vez de excluir
  await api.patch(`/courses/${courseUuid}`, { status: 'archived' });
}

2. Arquive em vez de excluir

Para cursos e instituições, prefira atualizar o campo status para archived ou inactive em vez de excluir:
// Em vez de DELETE /courses/{uuid}
await api.patch(`/courses/${courseUuid}`, { status: 'archived' });
Isso preserva todos os relacionamentos enquanto marca claramente a entidade como não mais ativa.

3. Trate o erro adequadamente

Se uma tentativa de exclusão falhar devido a uma dependência existente, a API retorna um erro. Sempre trate isso na sua integração:
try {
  await api.delete(`/courses/${courseUuid}`);
} catch (err) {
  if (err.response?.status === 500) {
    // Provavelmente um erro de integridade referencial — registre e arquive
    logger.warn(`Não é possível excluir o curso ${courseUuid} — possui registros dependentes. Arquivando.`);
    await api.patch(`/courses/${courseUuid}`, { status: 'archived' });
  } else {
    throw err;
  }
}

Imutabilidade do certificado

Uma vez que um certificado é emitido, todos os dados associados a ele são preservados:
  • Identidade do estudante (nome, email, documento de identificação, data de nascimento, país) — capturada em um snapshot imutável no momento da emissão
  • Dados do curso, da instituição, da turma e da matrícula — todos preservados pelas regras de integridade referencial acima
Isso garante que a URL de verificação pública de um certificado sempre exiba informações precisas e completas, independentemente de quaisquer alterações futuras nas entidades subjacentes.

Desvinculação de módulos vs exclusão

Módulos podem ser desvinculados de um curso sem serem excluídos:
DELETE /courses/{course_uuid}/detach/modules
Isso remove a associação course_modules, mas deixa tanto o curso quanto o módulo intactos. Esta é a operação preferida ao reorganizar um currículo, pois permite que o módulo seja vinculado novamente a um curso diferente. A exclusão definitiva de um módulo (via DELETE /modules/{uuid}) só é possível após ele ter sido desvinculado de todos os cursos.

Resumo: prefira arquivar em vez de excluir

CenárioAção recomendada
Curso descontinuadoPATCH /courses/{uuid}{ "status": "archived" }
Instituição inativaPATCH /institutions/{uuid}{ "status": "inactive" }
Registro de estudante a ser desativadoNão exclua; mantenha o registro intacto
Módulo que não é mais ministradoDesvincule do curso; não exclua o módulo
Turma encerradaNenhuma ação necessária; turmas são registros históricos