Questionário respondido
Questionário respondido
Um questionário aplicado a um paciente — de adesão ao tratamento, de sintomas, de triagem — gera, quando respondido, um registro com as perguntas e as respostas dadas. É esse registro que este recurso devolve: o conteúdo do que foi respondido, não o formulário em si.
No FHIR isso é a
QuestionnaireResponse. O questionário
que serviu de base é um recurso separado, apontado pelo campo questionnaire.
Este recurso é somente leitura. Não existe POST /fhir/resources/QuestionnaireResponse —
questionários são aplicados e respondidos dentro do NiloCare, ou pelo link que o paciente
recebe. Veja O que a integração não cobre para o que acontece
se você tentar enviá-lo mesmo assim.
Só existe quando há resposta
Um questionário sem nenhuma resposta preenchida não existe neste recurso. Não é um recurso
vazio, nem um 404 explicado: ele simplesmente nunca é criado, e a criação é abandonada em
silêncio, sem erro em lugar nenhum.
Vale para o questionário que ninguém abriu, para o que expirou sem resposta, e para o que só tem respostas em branco — resposta vazia ou composta apenas de espaços é descartada antes da contagem. Uma resposta cuja pergunta não é mais localizável é descartada do mesmo jeito, e também em silêncio. Se você espera um registro por questionário aplicado, vai contar menos do que a tela mostra.
Para saber quais questionários foram atribuídos a um paciente, incluindo os que ele não respondeu, o recurso é Tarefa.
Campos
A coluna No NiloCare traz o rótulo com que o dado aparece para a equipe; são rótulos, não caminhos de navegação: a tela pode ser reorganizada, o rótulo é o que permite conferir se o dado é o que você esperava. São os rótulos da tela atual de questionários do paciente — uma implantação que ainda não a recebeu mostra outra tela, com outros rótulos.
Todos os campos são de resposta — nenhum deles é enviado por você.
Situação
status só assume três dos valores do FHIR, e a redução perde informação:
in-progress reúne três situações diferentes, e a API não distingue entre elas: não há como
saber se o questionário ainda não foi enviado ao paciente, se foi enviado e não aberto, ou se
está em preenchimento. Não trate in-progress como “o paciente está respondendo”.
Na prática você raramente verá as duas primeiras: um questionário que ninguém começou a responder não existe neste recurso.
Um questionário concluído fora do prazo aparece como completed, não como stopped. A
conclusão vence o vencimento do prazo na plataforma, e é a conclusão que chega aqui. stopped
descreve o questionário que expirou sem ser concluído.
E stopped pode nunca aparecer: a situação de expirado é calculada pela passagem do prazo, não
por alguém alterar o registro, e este recurso só é reescrito
quando o questionário respondido muda. Um
questionário parcialmente respondido cujo prazo venceu continua sendo devolvido como
in-progress até que algo mais aconteça com ele — e mesmo então, uma gravação em que nada do que
esta API expõe mudou pode não ser reescrita.
Não conte com stopped para detectar vencimento. E não há como calcular o vencimento por
aqui: o prazo de resposta não é exposto em nenhum recurso desta API — nem neste, nem na
Tarefa, cuja origem de questionário vem sem restriction.
Quem respondeu e a quem foi aplicado
São dois campos diferentes, e confundi-los é o erro mais comum deste recurso:
subjecté a quem o questionário foi aplicado.authoré quem registrou as respostas — o próprio paciente, quando ele respondeu pelo link que recebeu, ou o profissional que as preencheu por ele.typena referência diz qual dos dois é.
Sem registro de quem submeteu, author repete o subject: a leitura fica com os dois
campos iguais. Isso não significa que o paciente respondeu sozinho — significa que a plataforma
não guardou quem submeteu.
source traz sempre o mesmo valor de author. Ele existe porque o FHIR o prevê, e não
acrescenta informação nenhuma.
subject é normalmente o paciente, mas nem sempre: um questionário aplicado dentro de um
atendimento pode ter o atendimento como subject, e nesse caso a referência vem com
type: Encounter. Confira o type antes de tratar subject como paciente — e veja
Buscar, porque isso muda qual parâmetro encontra o registro.
As respostas
Cada pergunta respondida vira um item de item[], com o enunciado em text, o identificador da
pergunta em linkId e as respostas em answer[]. Uma pergunta de múltipla escolha traz uma
entrada de answer por opção marcada.
linkId é o elo com o questionário. É o mesmo identificador que o item correspondente
carrega no recurso do questionário — é por ele que você liga a resposta à pergunta original,
com o tipo dela e as opções possíveis.
Toda resposta chega como texto. answer[].valueString é o único campo de valor produzido:
data, número e sim/não saem como a mesma string que a tela mostra. Não há valueDate,
valueInteger, valueBoolean nem valueCoding — e também não há code nem system na opção
marcada, só o rótulo dela. Para tipar a resposta, o caminho é o tipo da pergunta no questionário,
alcançado pelo linkId.
Opção marcada e texto digitado na mesma resposta: quando os dois chegam gravados juntos, só o
texto vem em valueString — a tela mostra os dois, separados por ·, e aqui aparece um. Uma
resposta do tipo Outros — dor no ombro esquerdo chega então apenas como
dor no ombro esquerdo.
Não é o caso comum. Normalmente o rótulo e o texto são duas respostas distintas, e viram duas
entradas de answer[] no mesmo item, sem perda. O caso acima aparece em registros gravados pelo
fluxo de resposta mais antigo — se você compara o que lê aqui com o que a tela mostra, é o
primeiro lugar onde os dois divergem.
A lista de itens é plana e não está na ordem do questionário. As seções em que as perguntas
estão organizadas não são representadas, e a ordem de item[] acompanha a ordem em que a
plataforma devolve as respostas — não a ordem das perguntas. Para exibir na ordem original,
ordene pelo questionário, casando os linkId.
Perguntas não respondidas não aparecem. A ausência de um linkId em item[] significa “sem
resposta”, não “pergunta inexistente”.
O questionário respondido
questionnaire traz a URL canônica do questionário, no formato
{host}/fhir/resources/Questionnaire/{id}.
A canônica não é versionada. Ela vem sem sufixo |versão, então aponta para o questionário
como ele está hoje — e o questionário pode ter mudado depois de o paciente responder:
perguntas reescritas, opções acrescentadas, perguntas removidas.
E item[].text também não é uma cópia congelada. Ele é o enunciado lido do questionário na
última vez que este recurso foi gravado — a plataforma permite reescrever o enunciado de uma
pergunta já respondida, e a reescrita chega aqui na gravação seguinte. O mesmo vale para o
rótulo de uma opção, que é o valueString das respostas de escolha.
Na prática o texto fica estável enquanto o questionário respondido não muda, mas não trate
item[].text como registro do que o paciente viu. Esta API não tem esse dado.
Para ler o questionário em si — os enunciados, os tipos de pergunta e as opções —, use a URL
que veio em questionnaire, tal como ela veio; não monte o caminho a partir de outro
identificador. Veja Questionário:
Cadastrar ou atualizar
Não existe. Este recurso não tem caminho de escrita nesta API — nem para criar, nem para atualizar, nem para apagar. Respostas de questionário nascem no NiloCare, ou no link que o paciente recebe, e chegam aqui já prontas.
Um POST /fhir/resources/QuestionnaireResponse não é uma operação suportada e não devolve
um erro de validação tratável: com um corpo válido, a chamada falha com erro inesperado do
servidor (500). Não escreva tratamento em cima desse comportamento — ele não é contrato, e
nada é gravado na plataforma de qualquer forma. Um corpo malformado responde 400 antes disso,
pela validação do recurso — não conclua daí que a operação existe.
Dentro de uma carga em lote o erro é limpo, e
igualmente definitivo: a entrada é recusada com
Resource QuestionnaireResponse not supported.
Buscar
A resposta é sempre um Bundle do tipo searchset.
Busca sem resultados não é erro: volta 200 com um Bundle cujo entry é uma lista vazia — a
chave vem sempre, e link também. Trate a ausência de resultados pela lista vazia, não esperando
um 404.
Parâmetros de busca suportados
Os questionários respondidos de um paciente pelo identificador dele — a busca mais usada deste recurso:
As quatro referências deste recurso — subject, patient, author e source — trazem
reference e identifier, então as duas formas de busca por referência estão disponíveis em
todas: patient=Patient/{id}, com o id Nilo FHIR, e patient:identifier=system|valor, com o
identificador do paciente. A segunda é a prática, porque dispensa conhecer o id do store.
Isso não vale para todos os recursos desta API — em
Avaliação clínica, por exemplo, as referências saem sem
reference e só a forma com :identifier encontra algo.
patient e subject não são intercambiáveis aqui. No FHIR, patient é o mesmo campo
subject restrito a pacientes — e o subject deste recurso
nem sempre é um paciente. Um questionário cujo
subject é o atendimento não é encontrado por patient, e é por subject que ele aparece. Se a
sua contagem por paciente vem menor do que a tela mostra, é o primeiro lugar a conferir.
Qual identificador do paciente o subject carrega depende da sua implantação. Na
configuração que usa identificadores externos nas referências, é o identificador do seu sistema
— e o filtro acima funciona como está. Sem ela, o subject traz o identificador Nilo do
paciente (…/NamingSystem/hippocrates-api--patient), e é esse system que você tem de usar no
filtro. Confira numa resposta de leitura qual dos dois está lá antes de montar a busca em
volume. O mesmo vale para author e source.
E quando o subject é um atendimento, o identificador é o do atendimento, com o system
correspondente — nem o do seu sistema nem o do paciente. Filtrar esses registros por identificador
de paciente não os encontra de forma nenhuma.
Alguns parâmetros canônicos da QuestionnaireResponse existem e não encontram nada aqui,
porque a plataforma não preenche o campo correspondente: based-on, part-of e encounter.
Repare em encounter: mesmo o questionário aplicado dentro de um atendimento não preenche esse
campo — o atendimento, quando aparece, aparece em subject.
Não há parâmetro que procure dentro das respostas: nem pelo texto de item[].text, nem pelo
valor de answer[].valueString, nem pelo linkId. Filtrar por conteúdo respondido é trabalho
do seu lado, depois de ler o recurso.
A paginação é por _count e _page_token; havendo página seguinte, o Bundle traz a URL pronta
em link.
Ler por ID
Diferente da busca, esta leitura não devolve um Bundle — mas também não devolve o recurso
nu. A resposta é um envelope com fullUrl, search e resource, e o questionário respondido
está em resource. Ler status ou item na raiz da resposta não encontra nada.
A leitura por ID responde 404 quando o id não existe — inclusive quando o registro existia e
foi apagado na plataforma.
Quando o registro muda, e quando não muda
É a seção mais importante desta página depois da primeira, porque o que se lê aqui pode estar atrasado em relação à plataforma — e o motivo não é latência.
Este recurso é reescrito quando o questionário respondido muda — não quando uma resposta muda. O que dispara a regravação são os acontecimentos do questionário como um todo: ele ser enviado ao paciente, ser iniciado, ser concluído, ser apagado. Editar ou apagar respostas sem que nada disso aconteça não reescreve nada aqui.
Consequência prática: entre duas dessas mudanças, o conteúdo de item[] é o da última
gravação, não o que está na plataforma agora. Uma correção feita numa resposta já dada só
aparece quando o questionário respondido mudar de novo — o que, num questionário já concluído,
pode ser nunca.
Nem toda mudança do questionário respondido chega a reescrever o recurso: uma gravação em que
nada do que esta API expõe mudou é dispensada. Você não precisa fazer nada com isso — é a razão
pela qual meta.lastUpdated pode ficar para trás da última alteração feita na plataforma.
Apagar o questionário respondido no NiloCare remove o recurso do store. Não há mudança de
status nem marca de exclusão: o id que você leu com sucesso passa a responder 404, sem
aviso. Se você guarda o conteúdo de uma resposta, guarde o conteúdo — não o id.
Esvaziar todas as respostas nunca apaga o que já foi gravado. Se uma regravação chegar a acontecer com todas as respostas em branco, ela é abandonada — um questionário sem resposta válida não é sincronizado — e o que estava gravado permanece, com as respostas antigas. Para fazer o registro desaparecer, o caminho é apagar o questionário respondido, não esvaziá-lo.
Isso vale para o conjunto vazio, não para uma resposta a menos: numa regravação em que sobrou pelo
menos uma resposta, item[] é substituído inteiro e o item apagado desaparece.
Nos campos fora de item[], a gravação preserva o valor anterior quando o novo é vazio — então
author, source e authored não voltam a ficar em branco depois de preenchidos uma vez.
Removido o registro de quem submeteu, a leitura continua devolvendo o author antigo
indefinidamente.
Erros
Este recurso só tem leitura, então a lista é curta:
Os erros de busca deste recurso vêm do store, não de validação de negócio: não há regra de
domínio a violar numa leitura. Uma busca bem formada que não encontra nada responde 200 com
Bundle vazio, nunca um erro.
O que a integração não cobre
Não há escrita: nem criar, nem atualizar, nem apagar uma resposta, nem responder um questionário por integração.
E vários dados que a plataforma guarda não têm campo aqui:
- a pontuação e a classificação do questionário respondido — o que a tela mostra em Classificação é calculado pela plataforma e não é exposto, nem por resposta nem no total;
- os resultados e condutas derivados das respostas, que a tela mostra em Resultados e condutas;
- quem aplicou o questionário, que a tela mostra em Aplicado por. Não confunda com
author, que é quem registrou as respostas; - a data em que o questionário foi aplicado (a tela mostra Aplicado em), o momento em que
o paciente começou a responder, e o prazo de resposta. Só a conclusão é exposta, em
authored; - a versão do questionário que o paciente respondeu — a canônica em
questionnaireaponta para a versão atual; - as seções do questionário, e a ordem original das perguntas;
- o tipo de cada pergunta e as opções possíveis — isso está no questionário, alcançável
pelo
linkId; - o código da opção marcada: só o rótulo dela chega, em texto.
Para saber quais questionários foram atribuídos a um paciente — inclusive os não respondidos — o
recurso é Tarefa: o output[] dela aponta para o questionário e para a
resposta dele. O prazo de resposta não está lá tampouco: a origem de questionário da Task
vem sem restriction.

