Achado crítico
O diálogo Achado crítico deixa quem opera o exame (médico, gestor ou administrador) sinalizar
que um exame concluído tem um resultado que exige atenção imediata — ou remover essa
sinalização depois. Diferente do comentário de texto livre, esta é uma marcação booleana do exame
(isCriticalFinding), sempre acompanhada de uma justificativa obrigatória quando se está
sinalizando (a remoção é só uma confirmação simples).
:::caution Pendência deste levantamento — sem captura de tela deste diálogo
O único exame de teste da unidade ("Paciente Teste Docs Portal2") está no status Recebido, não
Concluído. A regra canFlagCriticalFinding (exam-policy.ts:440-443) exige
isExamConcluded(exam.status) para sequer mostrar o botão que abre este diálogo — confirmado
navegando com administrator: a barra de ações expandida da linha não lista "Sinalizar achado
crítico" nesse exame, para nenhum perfil. O segundo ponto de entrada (a grade de ícones do
laudário) está bloqueado pelo mesmo motivo documentado no módulo de
Exames: sem estudo PACS por trás, o botão Abrir Laudário fica
desabilitado. Por isso, todo o conteúdo abaixo (comportamento, validação, textos de tela) foi
confirmado lendo o código-fonte de
src/app/features/exam-critical-finding/ui/exam-critical-finding-dialog.component.ts e .html, não
por navegação real. A confirmar — responsável: time de frontend; data: 24/09/2026: repetir este
levantamento com um exame concluído para capturar as telas reais e confirmar visualmente o
comportamento descrito.
:::

Para quem é
| Persona | Quem é | O que faz aqui |
|---|---|---|
| Médico / radiologista | Assina laudos | Sinaliza um achado que precisa chegar a alguém com urgência, ou remove uma sinalização feita por engano |
| Gestor / administrador da unidade | Opera a unidade | Mesma ação, via isPlatformAdmin ou nível gestor (canUpdate/canSign) |
Demais perfis (technician, resident, read_only, typist, requestor) | Consultam ou preparam o exame | Não veem o botão — a política local (isExamOperator) não inclui esses perfis |
Como acessar
Não é uma tela própria — é um diálogo modal (app-exam-critical-finding-dialog), com dois pontos
de entrada:
| Onde | Gatilho | Condição para aparecer |
|---|---|---|
| Barra de ações expandida da linha da worklist | Ícone ⚠️ Sinalizar achado crítico | Exame concluído e usuário operador (isExamOperator) — exam-actions-bar.component.ts:229-231 |
| Grade de ícones do laudário | Ícone pi-exclamation-triangle | Permissão calculada pelo servidor por exame (canFlagCriticalFinding da query ExamCriticalFindingPermission) — exam-report-page.component.ts:1393-1395 |
Permissões que liberam a ação
| Ação | Elemento | O que decide | Onde |
|---|---|---|---|
| Ver o botão na worklist | Ícone ⚠️ da barra de ações | canFlagCriticalFinding(exam, user): exame não excluído, concluído, e isExamOperator (isPlatformAdmin || canUpdate || canSign) | exam-policy.ts:440-443, exam-policy.ts:148-150 |
| Ver o ícone no laudário | pi-exclamation-triangle da grade | Query GraphQL própria por exame, calculada pelo servidor — política diferente da usada na worklist | exam-actions.service.ts:880-887, exam.graphql.ts:480-485 |
| Confirmar (sinalizar) | Botão de confirmação do diálogo | Formulário válido (comentário 10–400 caracteres) e não estar no estado "negado" | exam-critical-finding-dialog.component.ts:167-172 |
| Confirmar (remover) | Botão de confirmação do diálogo | Sem validação de comentário — é uma confirmação simples | exam-critical-finding-dialog.component.ts:145-153 |
:::info Duas políticas diferentes para o mesmo botão
A worklist decide se mostra o botão com uma aproximação local (isExamOperator), enquanto o
laudário consulta o servidor via ExamCriticalFindingPermission para o mesmo exame. Nenhuma das
duas usa a permissão granular exam:flag-critical-finding diretamente no front — essa string só
existe em fixtures de mock (personas.ts:19), nunca é lida por uma política de produção. Isso pode
fazer o botão aparecer/desaparecer de forma diferente na worklist e no laudário para o mesmo
usuário e o mesmo exame. A confirmar — responsável: time de frontend; data: 24/09/2026.
:::
Passo a passo (lido no código — sem captura real, ver pendência acima)
1. Abrir o diálogo
No exame concluído, clique no ícone ⚠️ Sinalizar achado crítico (worklist) ou no ícone de
exclamação da grade de ícones (laudário). O diálogo abre já no modo certo:
Sinalizar se exam.isCriticalFinding ainda é false, Remover se já é true
(isRemoving, exam-critical-finding-dialog.component.ts:110).
2. Preencher a justificativa (só no modo Sinalizar)
O campo de comentário exige entre 10 e 400 caracteres — Validators.required,
Validators.minLength(10), Validators.maxLength(400), aplicados só quando não se está
removendo (exam-critical-finding-dialog.component.ts:145-153). Essa exigência é uma regra do
front, não do backend: o comentário do próprio código registra que "o servidor aceita reason
vazio" e que a obrigatoriedade foi decidida pelo time, porque uma flag que dispara escalação sem
descrição não é acionável (exam-critical-finding-dialog.component.ts:42-46). O modo Remover não
tem campo de comentário.
3. Confirmar
O rótulo do botão de confirmação muda conforme o modo e uma decisão deliberada de seguir o
protótipo Figma: no modo Sinalizar, o botão diz "Sinalizar Urgência" (chave
EXAM.DIALOG.CRITICAL_FINDING_FLAG_ACTION), mesmo o diálogo e o gatilho que o abre chamando a ação
de "achado crítico" em todo o resto da tela; no modo Remover, o botão diz "Confirmar"
(confirmLabelKey, exam-critical-finding-dialog.component.ts:112-121).
Estados de erro tratados
| Estado | Quando ocorre | O que a pessoa vê |
|---|---|---|
| Negado | Resposta 403/401 do servidor | Diálogo entra em estado "negado": o botão de confirmar fica desabilitado — tentar de novo não ajuda, porque é falta de permissão |
| Parcial (marcação salvou, comentário falhou) | O setCriticalFinding internamente grava a flag e depois tenta o comentário; se só o comentário falhar (ex.: 403 vindo da chamada de comentário), a flag já mudou no servidor | O diálogo mostra o erro de justificativa, mas ao fechar emite changed mesmo assim, para a linha da worklist refletir que o achado já está marcado |
| Outro erro (404, erro comum) | Exame não encontrado ou falha genérica | Diálogo continua aberto e o comentário digitado é preservado — a pessoa não perde o texto já escrito |
A composição "marcar a flag + gravar o comentário" não é transacional — divergência conhecida
em relação à v1, que fazia isso numa única chamada. Isso é o que torna o estado "parcial" acima
possível (exam-finding-comment.ts, comentário de topo do arquivo).
Regras de negócio
| ID | Regra | O que a tela faz |
|---|---|---|
| — | Só exame concluído libera o botão na worklist | canFlagCriticalFinding exige isExamConcluded |
| — | Comentário obrigatório (10–400 chars) só ao sinalizar; remover não pede comentário | Validadores condicionais no effect() do componente |
| — | Falha de permissão desabilita o confirmar; falha comum preserva o texto e permite tentar de novo | showFailure, exam-critical-finding-dialog.component.ts:209-226 |
| — | O diálogo de achado crítico é único — foi consolidado a partir de dois componentes duplicados com regras divergentes (mínimo de 10 vs. 1 caractere) | Comentário de topo do componente, exam-critical-finding-dialog.component.ts:48-53 |
| — | LGPD: a mensagem de erro nunca repete o conteúdo do comentário digitado | exam-critical-finding-dialog.component.ts:199-202 |
Rotas e contratos relacionados
| Operação GraphQL (front) | Equivale à rota REST (back) | Quando é chamada |
|---|---|---|
mutation setExamCriticalFinding | PUT /v1/exams/:id/critical-finding | Confirmar no modo Sinalizar |
mutation removeExamCriticalFinding | DELETE /v1/exams/:id/critical-finding | Confirmar no modo Remover |
query ExamCriticalFindingPermission | GET /v1/exams/:id/capabilities | Ao abrir a grade de ícones do laudário, para decidir se mostra o ícone |
→ Detalhe das rotas, regras de idempotência e a divergência de permissão entre capabilities e a
rota de escrita: Achado crítico e suspeita técnica — API.
Fora do escopo desta página
A suspeita técnica (a segunda flag clínica do exame, documentada no mesmo módulo de backend)
tem um diálogo próprio no front — ExamTechnicalSuspicionDialogComponent, em
src/app/features/exam-quick-actions/, fora da pasta exam-critical-finding — e só está
conectado à worklist (via o fluxo de preparo do exame), sem gatilho equivalente no laudário. Por
não fazer parte do escopo de código pedido para este levantamento, não foi detalhado aqui; ver
Achado crítico e suspeita técnica — API para o
contrato de backend correspondente.