Skip to main content

Comentários — visão geral

O módulo de Comentários cobre duas capacidades independentes que aparecem juntas na worklist e no laudário, mas não têm relação técnica entre si: comentar um exame (texto livre, sem efeito clínico) e sinalizar um achado crítico (uma marcação booleana do exame, com justificativa obrigatória). Não existe uma tela própria de "comentários" — as duas capacidades vivem dentro de componentes embutidos, abertos a partir de ícones da linha da worklist e da grade de ícones do laudário.

Este levantamento cobre a interface (Angular) do repositório mm-pacs-portal-main-interface, branch integration/with-fixlaudo, pastas src/app/features/exam-comments e src/app/features/exam-critical-finding, testado no ambiente https://task4.srv1812538.hstgr.cloud/. O contrato de API correspondente já está documentado em Comment — visão geral (back); esta seção documenta a experiência de tela.

:::caution Atualização (24/09/2026) — bug de bundle confirmado e corrigido; novo bloqueio distinto Este levantamento inicial (mais cedo em 24/09/2026) foi feito contra um build do ambiente task4 desatualizado (branch integration/all-features, ~100 commits atrás de develop/with-fixlaudo), que causava HTTP 400 "The GraphQL operation is invalid." ao salvar um comentário — o bundle antigo ainda enviava os argumentos legados isCriticalFinding/isTechnicalSuspicion que o código-fonte atual não declara mais.

Depois de atualizar o task4 para develop (front e API), repeti o teste: o erro de schema desapareceu — a mutation AddExamComment é aceita normalmente (confirmado pelo payload real, examId/description, sem as flags legadas). Ou seja, aquele 400 era mesmo um artefato do ambiente de teste desatualizado, não um bug do código documentado nesta página.

Salvar um comentário agora falha por um motivo diferente e novo: a mutation retorna HTTP 200 com um erro GraphQL UPSTREAM_UNAVAILABLE ("A required service is temporarily unavailable.", statusCode: 503) — reproduzido duas vezes seguidas. Não investiguei a causa raiz (é depuração de infraestrutura de um serviço a jusante, fora do escopo desta documentação de tela) — audit-api e RabbitMQ compartilhado estavam com status saudável quando verifiquei, então a causa provável é outro serviço downstream específico da mutation de comentário. A confirmar — responsável: time de backend; data: 24/09/2026: identificar qual serviço a jusante da mutation addExamComment está indisponível.

Por causa disso, as capturas abaixo ainda mostram o formulário preenchido e um estado de erro — não foi possível capturar um comentário efetivamente salvo e listado neste levantamento. :::

:::caution Pendência deste levantamento — sem exame concluído para achado crítico O único exame de teste da unidade ("Paciente Teste Docs Portal2") está no status Recebido, não Concluído. A política canFlagCriticalFinding (src/app/entities/exam/lib/exam-policy.ts:440) exige isExamConcluded(exam.status), então o botão Sinalizar achado crítico simplesmente não aparece na barra de ações da linha, para nenhum perfil — confirmado navegando com administrator. O laudário, que também hospeda esse gatilho, continua inacessível de fato: o botão Abrir Laudário está habilitado (comportamento atualizado — ver Laudário), mas abri-lo falha com o bug real de schema GraphQL documentado lá (PreviousExamsFilter/ ReportVariables), então não dá para chegar à tela de achado crítico dentro do laudário. A confirmar — responsável: time de frontend; data: 24/09/2026: repetir este levantamento com um exame concluído (laudo assinado) e o bug de laudário corrigido, para capturar o diálogo de achado crítico e a matriz de permissões completa. :::

As duas capacidades, na tela​

Páginas deste módulo​

PáginaCobre
Comentários do examePopover app-exam-comments: listar, adicionar, apagar comentário; e os atalhos combinados Pendente/Reconvocar/Retornar para laudar que gravam um comentário e trocam o status numa única ação
Achado críticoDiálogo app-exam-critical-finding-dialog: sinalizar ou remover a flag de achado crítico do exame, com justificativa obrigatória

Onde cada capacidade vive​

Nenhuma das duas é uma rota própria — não há entrada em app.routes.ts para nenhuma delas (confirmado por busca em todo src/app). Os dois componentes são hospedados por dois pontos de entrada cada:

CapacidadeComponenteHospedeiro 1Hospedeiro 2
Comentar exameExamCommentsComponent (features/exam-comments)Ícone de balão na linha da worklist — exam-worklist.component.html:639-644 e 664-697Ícone pi-comments da grade de ícones do laudário — exam-report-page.component.html:672-677, acionado por report-quick-icons.component.ts:162-166
Achado críticoExamCriticalFindingDialogComponent (features/exam-critical-finding)Botão Sinalizar achado crítico da barra de ações expandida da linha — exam-actions-bar.component.ts:229-231, exam-worklist.component.ts:1481-1482Ícone pi-exclamation-triangle da grade do laudário — report-quick-icons.component.ts:181-185, exam-report-page.component.ts:1393-1395

O código do próprio diálogo de achado crítico documenta que ele foi unificado: existiam dois componentes com o mesmo nome de classe e o mesmo seletor em slices diferentes do projeto (um sabia remover a sinalização, o outro não; o mínimo de caracteres do comentário divergia entre eles) — hoje há um só, parametrizado por examId para servir tanto a worklist (que tem o Exam inteiro) quanto o laudário (que só tem o id) (exam-critical-finding-dialog.component.ts:48-53).

Permissões usadas neste módulo​

CamadaO que decideOnde
Front — mostrar/ocultar o ícone de comentáriocanCommentExam(exam, user): !exam.isDeleted && (user.canAddComment || isPlatformAdmin), com canAddComment vindo de exam:add-comment em qualquer escopo do IAMexam-policy.ts:171-173, exam-user-context.factory.ts:42
Front — desabilitar (não ocultar) o ícone quando falta a permissãocommentDenied(exam), tooltip EXAM.ACAO.SEM_PERMISSAO_COMENTARexam-worklist.component.ts:940-941
Front — apagar um comentárioSó ownership local: comment.userId === currentUserId() — não há checagem de exam:delete-comment no front; o backend segue sendo a fonte de verdadeexam-comments.component.ts:170-173
Front — mostrar o botão de achado crítico na worklistcanFlagCriticalFinding(exam, user): !exam.isDeleted && isExamConcluded(exam.status) && isExamOperator(user), onde isExamOperator é isPlatformAdmin || canUpdate || canSign — não uma permissão dedicadaexam-policy.ts:440-443, exam-policy.ts:148-150
Front — mostrar o ícone de achado crítico no laudárioQuery GraphQL própria ExamCriticalFindingPermission → examPermissions.canFlagCriticalFinding, calculada pelo servidor para aquele exame específico — política diferente da usada na worklistexam-actions.service.ts:880-887, exam.graphql.ts:480-485
Back — todas as rotasexam:add-comment, exam:list-comment, exam:delete-comment, exam:flag-critical-finding, exam:flag-technical-suspicion, escopo RLS por unidadever Comment — visão geral (back)

:::info Achado de código: nenhuma permissão granular de flag é lida em produção no front As strings exam:flag-critical-finding e exam:flag-technical-suspicion — que o backend exige nas rotas PUT/DELETE /exams/:id/critical-finding e /technical-suspicion — só aparecem no catálogo de personas de mock (personas.ts:19-20) usado pelos testes locais; nenhuma política de produção lê essas strings. O front decide se mostra o botão com uma aproximação própria (isExamOperator: platform admin, ou exam:update, ou exam:sign), não com a permissão granular da flag. Isso significa que a visibilidade do botão no front e a autorização real da mutation no backend podem divergir para um usuário no limite (ex.: alguém com exam:flag-critical-finding mas sem exam:update/exam:sign veria o botão oculto, mesmo podendo executar a ação no servidor). A confirmar — responsável: time de frontend; data: 24/09/2026. :::

Lendo o catálogo de papéis do backend (mm-pacs-portal-main-api/package/identity/authorization/core/models/identity-system-role.ts), dos 9 perfis de teste deste levantamento (docs-usuarios.md):

PermissãoQuem tem no catálogoObservação
exam:add-comment / exam:list-comment / exam:delete-commentadministrator, manager (ver nota abaixo)doctor, technician, resident, read_only, typist, requestor, financial não têm essas três no catálogo (DOCTOR_PERMISSIONS, identity-system-role.ts:179-192, não lista nenhuma)
exam:flag-critical-finding / exam:mark-clinical / exam:flag-technical-suspicionadministrator, managermesmos ausentes acima

:::caution Discrepância confirmada entre catálogo e comportamento observado O catálogo acima diz que doctor não tem exam:add-comment. Mas navegando com docs.doctor@mobilemed.test neste ambiente, o ícone Inserir comentário aparece habilitado (não desabilitado, sem tooltip de bloqueio) na linha do exame de teste — o mesmo padrão observado com administrator. Isso sugere que o tenant "Clínica Docs Portal 2" foi provisionado com um conjunto de permissões por papel diferente do catálogo hardcoded lido acima (possivelmente por um caminho de reconciliação de papéis análogo ao já documentado para manager no módulo de Exames (ver o quadro "Achado de código" na seção "Quem acessa o quê — visão rápida"). Não foi possível confirmar a causa raiz dentro do escopo deste levantamento. A confirmar — responsável: time de backend/IAM; data: 24/09/2026. :::

Contexto de negócio (legado) — Bitrix​

Os cards abaixo (funil de features do sistema legado, entityTypeId 1320) descrevem a intenção de produto original deste módulo. Eles não são fonte de comportamento atual — várias regras do legado (prefixo de texto no comentário, exclusão mútua achado crítico/suspeita técnica, motivo obrigatório configurável por empresa) não foram portadas, como já detalhado nas ressalvas da doc de backend. Listamos aqui só id e título, como contexto histórico:

CardTítulo
672F-001 — Comentar exame (criar e listar comentários) - Front
680F-003 — Comentar achado crítico / suspeita técnica (com sinalização do exame) - Front

Relacionado​