<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://ohcnwiki.tellmey.fyi/index.php?action=history&amp;feed=atom&amp;title=References%2FQuestionnaire</id>
	<title>References/Questionnaire - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://ohcnwiki.tellmey.fyi/index.php?action=history&amp;feed=atom&amp;title=References%2FQuestionnaire"/>
	<link rel="alternate" type="text/html" href="https://ohcnwiki.tellmey.fyi/index.php?title=References/Questionnaire&amp;action=history"/>
	<updated>2026-07-06T05:18:44Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.4</generator>
	<entry>
		<id>https://ohcnwiki.tellmey.fyi/index.php?title=References/Questionnaire&amp;diff=391&amp;oldid=prev</id>
		<title>Admin: Automated edit (via update-page on MediaWiki MCP Server)</title>
		<link rel="alternate" type="text/html" href="https://ohcnwiki.tellmey.fyi/index.php?title=References/Questionnaire&amp;diff=391&amp;oldid=prev"/>
		<updated>2026-07-06T04:01:38Z</updated>

		<summary type="html">&lt;p&gt;Automated edit (via update-page on MediaWiki MCP Server)&lt;/p&gt;
&lt;a href=&quot;https://ohcnwiki.tellmey.fyi/index.php?title=References/Questionnaire&amp;amp;diff=391&amp;amp;oldid=153&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://ohcnwiki.tellmey.fyi/index.php?title=References/Questionnaire&amp;diff=153&amp;oldid=prev</id>
		<title>Admin: OHC identity seed</title>
		<link rel="alternate" type="text/html" href="https://ohcnwiki.tellmey.fyi/index.php?title=References/Questionnaire&amp;diff=153&amp;oldid=prev"/>
		<updated>2026-07-04T22:44:49Z</updated>

		<summary type="html">&lt;p&gt;OHC identity seed&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Doc header&lt;br /&gt;
|type=reference&lt;br /&gt;
|domain=definitions&lt;br /&gt;
|title=Questionnaire&lt;br /&gt;
|order=1&lt;br /&gt;
|introduced=3.0&lt;br /&gt;
|model=Questionnaire&lt;br /&gt;
|reference=References/Activity Definition&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;Questionnaire&amp;lt;/code&amp;gt; is a versioned, FHIR-inspired form: a tree of questions answered about a patient or an encounter. You touch it whenever you define a data-collection form, render one for filling, or submit answers — which can flow back out as [[References/Observation|Observations]]. It captures both clinical data and arbitrary non-clinical structured data.&lt;br /&gt;
&lt;br /&gt;
The Django model is only the storage layer. The API schema you code against lives in the Pydantic resource specs under &amp;lt;code&amp;gt;care/emr/resources/questionnaire*&amp;lt;/code&amp;gt;: enums, the nested shape of the JSON fields, validation, and the split between read and write contracts.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Source (model):&amp;#039;&amp;#039;&amp;#039; [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/models/questionnaire.py &amp;lt;code&amp;gt;care/emr/models/questionnaire.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Source (specs):&amp;#039;&amp;#039;&amp;#039; [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/questionnaire/spec.py &amp;lt;code&amp;gt;resources/questionnaire/spec.py&amp;lt;/code&amp;gt;] · [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/questionnaire/utils.py &amp;lt;code&amp;gt;resources/questionnaire/utils.py&amp;lt;/code&amp;gt;] · [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/questionnaire/questionnaire_organization.py &amp;lt;code&amp;gt;resources/questionnaire/questionnaire_organization.py&amp;lt;/code&amp;gt;] · [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/questionnaire_response/spec.py &amp;lt;code&amp;gt;resources/questionnaire_response/spec.py&amp;lt;/code&amp;gt;] · [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/questionnaire_response_template/spec.py &amp;lt;code&amp;gt;resources/questionnaire_response_template/spec.py&amp;lt;/code&amp;gt;] · [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/form_submission/spec.py &amp;lt;code&amp;gt;resources/form_submission/spec.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== Models ==&lt;br /&gt;
&lt;br /&gt;
Six models back the forms feature. The &amp;lt;code&amp;gt;Questionnaire&amp;lt;/code&amp;gt; is the definition; everything else records submissions, answers, organization scope, or reusable prefill.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Model&lt;br /&gt;
! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Questionnaire&amp;lt;/code&amp;gt;&lt;br /&gt;
| A versioned form definition: questions, styling, subject type, and status&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FormSubmission&amp;lt;/code&amp;gt;&lt;br /&gt;
| A submission of a questionnaire against a patient (and optional encounter)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
| A stored set of answers for a subject, optionally tied to a submission&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireOrganization&amp;lt;/code&amp;gt;&lt;br /&gt;
| Scopes a questionnaire to an instance-level &amp;lt;code&amp;gt;Organization&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireFacilityOrganization&amp;lt;/code&amp;gt;&lt;br /&gt;
| Scopes a questionnaire to a &amp;lt;code&amp;gt;FacilityOrganization&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireResponseTemplate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Reusable prefill template for questionnaire responses&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
All extend [[References/Base models &amp;amp;amp; conventions|&amp;lt;code&amp;gt;EMRBaseModel&amp;lt;/code&amp;gt;]], which supplies &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt;, audit fields, and soft-delete semantics.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;code&amp;gt;Questionnaire&amp;lt;/code&amp;gt; fields ==&lt;br /&gt;
&lt;br /&gt;
=== Definition ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Req&lt;br /&gt;
! Notes&lt;br /&gt;
{{Field|model=Questionnaire|section=Definition|name=version|type=CharField(255)|notes=yes}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Definition|name=slug|type=CharField(255)|notes=yes}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Definition|name=title|type=CharField(255)|notes=yes}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Definition|name=description|type=TextField|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Definition|name=subject_type|type=CharField(255)|notes=yes}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Definition|name=status|type=CharField(255)|notes=yes}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Definition|name=styling_metadata|type=JSONField|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Definition|name=questions|type=JSONField|notes=yes}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Definition|name=organization_cache|type=ArrayField[int]|notes=—}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Definition|name=internal_organization_cache|type=ArrayField[int]|notes=—}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The write spec also carries a &amp;lt;code&amp;gt;type: str&amp;lt;/code&amp;gt; field (default &amp;lt;code&amp;gt;&amp;amp;quot;custom&amp;amp;quot;&amp;lt;/code&amp;gt;) that has no backing model column.&lt;br /&gt;
&lt;br /&gt;
==== Organization scope caches ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;organization_cache&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;internal_organization_cache&amp;lt;/code&amp;gt; hold flattened organization IDs so access filtering can run without deep joins. The through-models below own them; clients never write them directly.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Maintained by&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;organization_cache&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireOrganization.sync_questionnaire_cache()&amp;lt;/code&amp;gt; — instance &amp;lt;code&amp;gt;Organization&amp;lt;/code&amp;gt; IDs plus each org&amp;#039;s &amp;lt;code&amp;gt;parent_cache&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;internal_organization_cache&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireFacilityOrganization.sync_questionnaire_cache()&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;FacilityOrganization&amp;lt;/code&amp;gt; IDs plus each org&amp;#039;s &amp;lt;code&amp;gt;parent_cache&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Enum values ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;QuestionnaireStatus&amp;lt;/code&amp;gt; values ===&lt;br /&gt;
&lt;br /&gt;
The lifecycle state of the definition, modeled on FHIR publication-status. Once a questionnaire is &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt;, edit and delete are off the table — move it to &amp;lt;code&amp;gt;retired&amp;lt;/code&amp;gt; instead.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;retired&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;draft&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;SubjectType&amp;lt;/code&amp;gt; values ===&lt;br /&gt;
&lt;br /&gt;
What kind of resource the form is about. This drives whether an encounter is required at submit time.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;patient&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;encounter&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;QuestionType&amp;lt;/code&amp;gt; values ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; of each question (&amp;lt;code&amp;gt;Question.type&amp;lt;/code&amp;gt;). The commented-out members &amp;lt;code&amp;gt;open_choice&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;attachment&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;reference&amp;lt;/code&amp;gt; are not implemented.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt;&lt;br /&gt;
| Container; must have ≥1 sub-question&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt;&lt;br /&gt;
| Validated against &amp;lt;code&amp;gt;true/false/1/0&amp;lt;/code&amp;gt; on submit&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;decimal&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;integer&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt;&lt;br /&gt;
| Length capped by &amp;lt;code&amp;gt;settings.MAX_QUESTIONNAIRE_TEXT_RESPONSE_SIZE&amp;lt;/code&amp;gt; on submit&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;display&amp;lt;/code&amp;gt;&lt;br /&gt;
| Display-only, no answer&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;date&amp;lt;/code&amp;gt;&lt;br /&gt;
| ISO date&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;dateTime&amp;lt;/code&amp;gt;&lt;br /&gt;
| Must include timezone on submit&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;time&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;%H:%M:%S&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;choice&amp;lt;/code&amp;gt;&lt;br /&gt;
| Requires &amp;lt;code&amp;gt;answer_option&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;answer_value_set&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt;&lt;br /&gt;
| Must have scheme + netloc&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt;&lt;br /&gt;
| Requires &amp;lt;code&amp;gt;answer_option&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;answer_value_set&amp;lt;/code&amp;gt;; answers need a &amp;lt;code&amp;gt;unit&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;structured&amp;lt;/code&amp;gt;&lt;br /&gt;
| Skipped by response validation&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;EnableOperator&amp;lt;/code&amp;gt; values ===&lt;br /&gt;
&lt;br /&gt;
The comparison for an &amp;lt;code&amp;gt;enable_when&amp;lt;/code&amp;gt; condition (&amp;lt;code&amp;gt;EnableWhen.operator&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;exists&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;equals&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;not_equals&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;greater&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;less&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;greater_or_equals&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;less_or_equals&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;EnableBehavior&amp;lt;/code&amp;gt; values ===&lt;br /&gt;
&lt;br /&gt;
How multiple &amp;lt;code&amp;gt;enable_when&amp;lt;/code&amp;gt; conditions combine (&amp;lt;code&amp;gt;Question.enable_behavior&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;all&amp;lt;/code&amp;gt;&lt;br /&gt;
| Enable only if all conditions pass (default on submit)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;&lt;br /&gt;
| Enable if any condition passes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;DisabledDisplay&amp;lt;/code&amp;gt; values ===&lt;br /&gt;
&lt;br /&gt;
How a disabled question renders (&amp;lt;code&amp;gt;Question.disabled_display&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hidden&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;AnswerConstraint&amp;lt;/code&amp;gt; values ===&lt;br /&gt;
&lt;br /&gt;
Whether free input outside the options is allowed (&amp;lt;code&amp;gt;Question.answer_constraint&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;required&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;optional&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;QuestionnaireResponseStatusChoices&amp;lt;/code&amp;gt; values ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;QuestionnaireResponse.status&amp;lt;/code&amp;gt; (model default &amp;lt;code&amp;gt;&amp;amp;quot;completed&amp;amp;quot;&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;completed&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;entered_in_error&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;FormSubmissionStatusChoices&amp;lt;/code&amp;gt; values ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;FormSubmission.status&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;draft&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;submitted&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;entered_in_error&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; nested shape ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Questionnaire.questions&amp;lt;/code&amp;gt; is an opaque &amp;lt;code&amp;gt;JSONField&amp;lt;/code&amp;gt;, but the API contract is a recursive list of &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;QuestionnaireBaseSpec&amp;lt;/code&amp;gt;). Fields, with their real types and validation:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Req&lt;br /&gt;
! Default&lt;br /&gt;
! Notes&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=link_id|type=str|notes=yes}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=id|type=UUID4 | UUID5|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=code|type=Coding bound to value set system-observation|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=collect_time|type=bool|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=collect_performer|type=bool|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=text|type=str|notes=yes}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=description|type=str | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=type|type=QuestionType|notes=yes}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=structured_type|type=str | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=enable_when|type=list[EnableWhen] | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=enable_behavior|type=EnableBehavior | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=disabled_display|type=DisabledDisplay | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=collect_body_site|type=bool | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=collect_method|type=bool | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=required|type=bool | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=repeats|type=bool | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=read_only|type=bool | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=max_length|type=int | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=answer_constraint|type=AnswerConstraint | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=answer_option|type=list[AnswerOption] | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=answer_value_set|type=str | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=is_observation|type=bool | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=unit|type=Coding bound to value set system-ucum-units|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=questions|type=list[Question]|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=formula|type=str | None|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=styling_metadata|type=dict|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=templates|type=list[TemplateConfig]|notes=no}}&lt;br /&gt;
{{Field|model=Questionnaire|section=Question nested shape|name=is_component|type=bool|notes=no}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;model_validator&amp;lt;/code&amp;gt; (mode &amp;lt;code&amp;gt;after&amp;lt;/code&amp;gt;) enforces three rules:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;choice&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; types must have &amp;lt;code&amp;gt;answer_option&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;answer_value_set&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt; types must have at least one sub-question.&lt;br /&gt;
* &amp;lt;code&amp;gt;answer_value_set&amp;lt;/code&amp;gt;, when set, must reference an existing &amp;lt;code&amp;gt;ValueSet&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Sub-specs of &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Spec&lt;br /&gt;
! Shape&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;EnableWhen&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ question: str (link_id), operator: EnableOperator, answer: Any }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AnswerOption&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ value: Any (non-blank, stripped), initial_selected: bool = false }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Performer&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ performer_type: str, performer_id: str | None, text: str | None }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TemplateConfig&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ name: str, content: str, structured_content: dict | None, meta: dict | None }&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Resource specs (API schema) ==&lt;br /&gt;
&lt;br /&gt;
Every spec builds on &amp;lt;code&amp;gt;EMRResource&amp;lt;/code&amp;gt;, which provides &amp;lt;code&amp;gt;serialize&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;de_serialize&amp;lt;/code&amp;gt;. Read specs run &amp;lt;code&amp;gt;perform_extra_serialization&amp;lt;/code&amp;gt;; write specs run &amp;lt;code&amp;gt;perform_extra_deserialization&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Questionnaire ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Spec&lt;br /&gt;
! Role&lt;br /&gt;
! Key fields / behaviour&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireBaseSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| shared&lt;br /&gt;
| &amp;lt;code&amp;gt;__model__ = Questionnaire&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireWriteSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write (base)&lt;br /&gt;
| &amp;lt;code&amp;gt;version&amp;lt;/code&amp;gt; (frozen &amp;lt;code&amp;gt;&amp;amp;quot;1.0&amp;amp;quot;&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;slug&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;SlugType&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;&amp;amp;quot;custom&amp;amp;quot;&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;subject_type&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;styling_metadata&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;questions&amp;lt;/code&amp;gt;. Validates slug uniqueness and that it doesn&amp;#039;t shadow internal types, a non-empty title, and unique &amp;lt;code&amp;gt;link_id&amp;lt;/code&amp;gt;s and &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt;s across the whole tree&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · create&lt;br /&gt;
| Extends the write spec with &amp;lt;code&amp;gt;organizations: list[UUID4]&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;min_length=1&amp;lt;/code&amp;gt;). &amp;lt;code&amp;gt;perform_extra_deserialization&amp;lt;/code&amp;gt; stashes them on &amp;lt;code&amp;gt;obj._organizations&amp;lt;/code&amp;gt;; the view then links them through &amp;lt;code&amp;gt;QuestionnaireOrganization&amp;lt;/code&amp;gt;, which rebuilds &amp;lt;code&amp;gt;organization_cache&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireUpdateSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · update&lt;br /&gt;
| Same as &amp;lt;code&amp;gt;QuestionnaireWriteSpec&amp;lt;/code&amp;gt;, minus &amp;lt;code&amp;gt;organizations&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireReadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · list/detail&lt;br /&gt;
| &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; (= &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;slug&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;version&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;subject_type&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;styling_metadata&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;questions&amp;lt;/code&amp;gt; (raw list), &amp;lt;code&amp;gt;created_by&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;updated_by&amp;lt;/code&amp;gt; (resolved via &amp;lt;code&amp;gt;serialize_audit_users&amp;lt;/code&amp;gt;)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Value sets bound on questions: &amp;lt;code&amp;gt;code&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;system-observation&amp;lt;/code&amp;gt; (LOINC), &amp;lt;code&amp;gt;unit&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;system-ucum-units&amp;lt;/code&amp;gt; (UCUM). &amp;lt;code&amp;gt;answer_value_set&amp;lt;/code&amp;gt; references any [[References/Value Set|&amp;lt;code&amp;gt;ValueSet&amp;lt;/code&amp;gt;]] by slug.&lt;br /&gt;
&lt;br /&gt;
=== Questionnaire response ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Spec&lt;br /&gt;
! Role&lt;br /&gt;
! Key fields / behaviour&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;EMRQuestionnaireResponseBase&amp;lt;/code&amp;gt;&lt;br /&gt;
| shared&lt;br /&gt;
| &amp;lt;code&amp;gt;__model__ = QuestionnaireResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireResponseUpdate&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · update&lt;br /&gt;
| &amp;lt;code&amp;gt;status: QuestionnaireResponseStatusChoices&amp;lt;/code&amp;gt; (default &amp;lt;code&amp;gt;completed&amp;lt;/code&amp;gt;) — the only handle for voiding a response by marking it &amp;lt;code&amp;gt;entered_in_error&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireResponseReadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · detail&lt;br /&gt;
| &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;questionnaire&amp;lt;/code&amp;gt; (nested &amp;lt;code&amp;gt;QuestionnaireReadSpec&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;subject_id&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;responses&amp;lt;/code&amp;gt; (raw list), &amp;lt;code&amp;gt;encounter&amp;lt;/code&amp;gt; (external id or &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;structured_responses&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;structured_response_type&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;created_by&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;updated_by&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;created_date&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;modified_date&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Submit request schema (not a DB write spec) ====&lt;br /&gt;
&lt;br /&gt;
The submit endpoint (&amp;lt;code&amp;gt;/questionnaire/&amp;amp;lt;slug&amp;amp;gt;/submit/&amp;lt;/code&amp;gt;) takes a plain Pydantic request, which &amp;lt;code&amp;gt;handle_response()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;utils.py&amp;lt;/code&amp;gt; validates and persists:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Spec&lt;br /&gt;
! Shape&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireSubmitRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ resource_id: UUID4, encounter: UUID4 | None, patient: UUID4, results: list[QuestionnaireSubmitResult], form_submission: UUID4 | None }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireSubmitResult&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ question_id: UUID4|UUID5, body_site: Coding | None, method: Coding | None, taken_at: datetime | None, values: list[QuestionnaireSubmitResultValue], note: str | None, sub_results: list[list[QuestionnaireSubmitResult]] }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireSubmitResultValue&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ value: str | None, unit: Coding | None, coding: Coding | None }&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Form submission ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Spec&lt;br /&gt;
! Role&lt;br /&gt;
! Key fields / behaviour&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;BaseFormSubmissionSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| shared&lt;br /&gt;
| &amp;lt;code&amp;gt;__model__ = FormSubmission&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;id: UUID4 | None&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FormSubmissionUpdateSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · update&lt;br /&gt;
| &amp;lt;code&amp;gt;status: FormSubmissionStatusChoices&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;response_dump: dict&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FormSubmissionWriteSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · create&lt;br /&gt;
| Adds &amp;lt;code&amp;gt;questionnaire: str&amp;lt;/code&amp;gt; (slug), &amp;lt;code&amp;gt;patient: UUID4&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;encounter: UUID4 | None&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;perform_extra_deserialization&amp;lt;/code&amp;gt; resolves the questionnaire by slug and the patient/encounter by &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt;; when an encounter is given it overrides &amp;lt;code&amp;gt;patient&amp;lt;/code&amp;gt; with the encounter&amp;#039;s patient&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FormSubmissionReadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · detail&lt;br /&gt;
| &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;response_dump&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;created_date&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;modified_date&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;created_by&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;updated_by&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt;)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Questionnaire response template ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Spec&lt;br /&gt;
! Role&lt;br /&gt;
! Key fields / behaviour&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireResponseTemplateBaseSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| shared&lt;br /&gt;
| &amp;lt;code&amp;gt;__model__ = QuestionnaireResponseTemplate&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;id: UUID4 | None&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;template_data: TemplateData&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;name: str&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;description: str = &amp;amp;quot;&amp;amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireResponseTemplateCreateSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · create&lt;br /&gt;
| Adds &amp;lt;code&amp;gt;questionnaire: str | None&amp;lt;/code&amp;gt; (slug), &amp;lt;code&amp;gt;facility: UUID4 | None&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;users: list[str]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;facility_organizations: list[UUID4]&amp;lt;/code&amp;gt;. Requires &amp;lt;code&amp;gt;facility&amp;lt;/code&amp;gt; whenever &amp;lt;code&amp;gt;facility_organizations&amp;lt;/code&amp;gt; is set. Resolves questionnaire/facility and recomputes &amp;lt;code&amp;gt;available_keys&amp;lt;/code&amp;gt; from the non-empty keys of &amp;lt;code&amp;gt;template_data&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireResponseTemplateUpdateSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · update&lt;br /&gt;
| &amp;lt;code&amp;gt;users&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;facility_organizations&amp;lt;/code&amp;gt;; recomputes &amp;lt;code&amp;gt;available_keys&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireResponseTemplateReadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · list&lt;br /&gt;
| &amp;lt;code&amp;gt;created_date&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;modified_date&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;QuestionnaireResponseTemplateRetrieveSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · detail&lt;br /&gt;
| Extends the read spec with resolved &amp;lt;code&amp;gt;users: list[dict]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;facility_organizations: list[dict]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;created_by&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;updated_by&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;template_data&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;TemplateData&amp;lt;/code&amp;gt;) shape ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;QuestionnaireResponseTemplate.template_data&amp;lt;/code&amp;gt; is an opaque &amp;lt;code&amp;gt;JSONField&amp;lt;/code&amp;gt; that the spec validates as:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Notes&lt;br /&gt;
{{Field|model=Questionnaire|section=template_data (TemplateData) shape|name=medication_request|type=list[MedicationRequestTemplateSpec] | None|notes=Extends the [[References/Medication Request}}&lt;br /&gt;
{{Field|model=Questionnaire|section=template_data (TemplateData) shape|name=questionnaire|type=list[QuestionnaireAnswer] | None|notes=&amp;lt;code&amp;gt;QuestionnaireAnswer = { question_id: str, answer: dict, meta: dict }&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=Questionnaire|section=template_data (TemplateData) shape|name=activity_definition|type=list[ActivityDefinitionTemplateSpec] | None|notes=&amp;lt;code&amp;gt;{ slug (validated against ActivityDefinition), service_request: ServiceRequestUpdateSpec }&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=Questionnaire|section=template_data (TemplateData) shape|name=meta|type=dict | None|notes=}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;available_keys&amp;lt;/code&amp;gt; (model &amp;lt;code&amp;gt;ArrayField&amp;lt;/code&amp;gt;) is server-maintained: on create/update it is set to the &amp;lt;code&amp;gt;template_data&amp;lt;/code&amp;gt; keys whose value is truthy.&lt;br /&gt;
&lt;br /&gt;
== Related models ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;FormSubmission&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
A submission event linking a questionnaire to a patient and, optionally, an encounter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;questionnaire → FK Questionnaire (CASCADE)&lt;br /&gt;
patient       → FK emr.Patient (CASCADE)&lt;br /&gt;
encounter     → FK emr.Encounter (CASCADE, nullable)&lt;br /&gt;
status        → CharField(255)         # FormSubmissionStatusChoices&lt;br /&gt;
response_dump → JSONField (default {})&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== &amp;lt;code&amp;gt;QuestionnaireResponse&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The answers for a subject. The &amp;lt;code&amp;gt;questionnaire&amp;lt;/code&amp;gt; FK is nullable, so a response can outlive or detach from its definition.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;questionnaire            → FK Questionnaire (CASCADE, nullable)&lt;br /&gt;
subject_id               → UUIDField&lt;br /&gt;
responses                → JSONField (default [])  # raw submitted results&lt;br /&gt;
structured_responses     → JSONField (default {})  # extracted/structured data&lt;br /&gt;
structured_response_type → CharField (nullable)&lt;br /&gt;
patient                  → FK emr.Patient (CASCADE)&lt;br /&gt;
encounter                → FK emr.Encounter (CASCADE, nullable)&lt;br /&gt;
form_submission          → FK FormSubmission (CASCADE, nullable)&lt;br /&gt;
status                   → CharField(255), default &amp;quot;completed&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== &amp;lt;code&amp;gt;QuestionnaireOrganization&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;QuestionnaireFacilityOrganization&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Through-models that scope a questionnaire to organizations — the first to an instance-level &amp;lt;code&amp;gt;Organization&amp;lt;/code&amp;gt;, the second to a &amp;lt;code&amp;gt;FacilityOrganization&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;questionnaire → FK Questionnaire (CASCADE)&lt;br /&gt;
organization  → FK Organization | FacilityOrganization (CASCADE)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Each overrides &amp;lt;code&amp;gt;save()&amp;lt;/code&amp;gt; to recompute the matching cache on the parent &amp;lt;code&amp;gt;Questionnaire&amp;lt;/code&amp;gt; (see [[#organization-cache-sync|Methods &amp;amp;amp; save behaviour]]). Their specs (&amp;lt;code&amp;gt;questionnaire_organization.py&amp;lt;/code&amp;gt;) exclude both FKs from serialization (&amp;lt;code&amp;gt;__exclude__ = [&amp;amp;quot;questionnaire&amp;amp;quot;, &amp;amp;quot;organization&amp;amp;quot;]&amp;lt;/code&amp;gt;): the write spec accepts &amp;lt;code&amp;gt;organization: UUID4&amp;lt;/code&amp;gt;, the read spec returns &amp;lt;code&amp;gt;organization: dict&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;QuestionnaireResponseTemplate&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
A reusable template that prefills questionnaire responses, optionally scoped to a facility and to specific facility organizations or users.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;facility               → FK facility.Facility (CASCADE, nullable)&lt;br /&gt;
name                   → CharField(255)&lt;br /&gt;
description            → TextField (default &amp;quot;&amp;quot;)&lt;br /&gt;
template_data          → JSONField (default {})   # TemplateData shape&lt;br /&gt;
questionnaire          → FK Questionnaire (CASCADE, nullable, default None)&lt;br /&gt;
facility_organizations → ArrayField[int] (default [])&lt;br /&gt;
users                  → ArrayField[int] (default [])&lt;br /&gt;
available_keys         → ArrayField[CharField(255)] (default [])  # server-maintained&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Methods &amp;amp;amp; save behaviour ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;Questionnaire.get_questions_by_id()&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Walks the &amp;lt;code&amp;gt;questions&amp;lt;/code&amp;gt; tree, recursing into nested &amp;lt;code&amp;gt;questions&amp;lt;/code&amp;gt;, and returns a &amp;lt;code&amp;gt;{ str(question_id): question }&amp;lt;/code&amp;gt; dict. The result is memoized on the instance via &amp;lt;code&amp;gt;_questions_by_id_cache&amp;lt;/code&amp;gt;. If &amp;lt;code&amp;gt;questions&amp;lt;/code&amp;gt; is not a list, it returns an empty dict.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;QuestionnaireResponse.render_responses()&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Joins stored &amp;lt;code&amp;gt;responses&amp;lt;/code&amp;gt; against the live questionnaire definition. For each answer it looks up the question through &amp;lt;code&amp;gt;questionnaire.get_questions_by_id()&amp;lt;/code&amp;gt; and returns a list of &amp;lt;code&amp;gt;{ &amp;amp;quot;answer&amp;amp;quot;: ..., &amp;amp;quot;question&amp;amp;quot;: ... }&amp;lt;/code&amp;gt;. It returns an empty list when there are no responses or no linked questionnaire, and skips any answer whose &amp;lt;code&amp;gt;question_id&amp;lt;/code&amp;gt; is no longer in the definition.&lt;br /&gt;
&lt;br /&gt;
=== Submission handling — &amp;lt;code&amp;gt;handle_response()&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;resources/questionnaire/utils.py&amp;lt;/code&amp;gt; runs this server-side on every submission:&lt;br /&gt;
&lt;br /&gt;
# Rejects the submission if the questionnaire &amp;lt;code&amp;gt;status != &amp;amp;quot;active&amp;amp;quot;&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;questionnaire_inactive&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Resolves &amp;lt;code&amp;gt;encounter&amp;lt;/code&amp;gt; (required when &amp;lt;code&amp;gt;subject_type == &amp;amp;quot;encounter&amp;amp;quot;&amp;lt;/code&amp;gt;) and &amp;lt;code&amp;gt;patient&amp;lt;/code&amp;gt; by &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Rejects empty submissions (&amp;lt;code&amp;gt;questionnaire_empty&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Prunes the question tree by &amp;lt;code&amp;gt;enable_when&amp;lt;/code&amp;gt; rules; answers to disabled questions raise &amp;lt;code&amp;gt;enable_when_failed&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Validates each answer against its &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; (type checks per [[#questiontype-values|QuestionType]]), &amp;lt;code&amp;gt;required&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;answer_value_set&amp;lt;/code&amp;gt; (the coding must belong to the value set), and &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; units. Any failure aborts with an &amp;lt;code&amp;gt;errors&amp;lt;/code&amp;gt; payload.&lt;br /&gt;
# Builds &amp;lt;code&amp;gt;ObservationSpec&amp;lt;/code&amp;gt; objects for coded/group questions and creates a &amp;lt;code&amp;gt;QuestionnaireResponse&amp;lt;/code&amp;gt; (raw &amp;lt;code&amp;gt;responses&amp;lt;/code&amp;gt; = the dumped results).&lt;br /&gt;
# When an encounter is present, bulk-creates the derived [[References/Observation|Observations]], linked back to the response.&lt;br /&gt;
&lt;br /&gt;
=== Organization cache sync ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;QuestionnaireOrganization.save()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;QuestionnaireFacilityOrganization.save()&amp;lt;/code&amp;gt; call &amp;lt;code&amp;gt;super().save()&amp;lt;/code&amp;gt;, then &amp;lt;code&amp;gt;sync_questionnaire_cache()&amp;lt;/code&amp;gt;, which:&lt;br /&gt;
&lt;br /&gt;
# Loads all through-rows for the parent questionnaire.&lt;br /&gt;
# Collects each linked organization&amp;#039;s &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; plus its &amp;lt;code&amp;gt;parent_cache&amp;lt;/code&amp;gt; (ancestor chain).&lt;br /&gt;
# De-duplicates the IDs.&lt;br /&gt;
# Writes them back via &amp;lt;code&amp;gt;questionnaire.save(update_fields=[...])&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;organization_cache&amp;lt;/code&amp;gt; for instance orgs, &amp;lt;code&amp;gt;internal_organization_cache&amp;lt;/code&amp;gt; for facility orgs.&lt;br /&gt;
&lt;br /&gt;
Saving any organization link triggers a second write to the &amp;lt;code&amp;gt;Questionnaire&amp;lt;/code&amp;gt; row.&lt;br /&gt;
&lt;br /&gt;
== API integration notes ==&lt;br /&gt;
&lt;br /&gt;
* Questionnaires expose CRUD plus a submit endpoint (&amp;lt;code&amp;gt;/questionnaire/&amp;amp;lt;slug&amp;amp;gt;/submit/&amp;lt;/code&amp;gt;). Create uses &amp;lt;code&amp;gt;QuestionnaireSpec&amp;lt;/code&amp;gt; (requires ≥1 &amp;lt;code&amp;gt;organizations&amp;lt;/code&amp;gt;); update uses &amp;lt;code&amp;gt;QuestionnaireUpdateSpec&amp;lt;/code&amp;gt;; reads use &amp;lt;code&amp;gt;QuestionnaireReadSpec&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;questions&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;styling_metadata&amp;lt;/code&amp;gt; are open &amp;lt;code&amp;gt;JSONField&amp;lt;/code&amp;gt;s at the DB layer, but the API validates &amp;lt;code&amp;gt;questions&amp;lt;/code&amp;gt; against the recursive [[#question-nested-shape|&amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt;]] spec — unique &amp;lt;code&amp;gt;link_id&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt;, the choice/quantity/group constraints, and value-set existence. &amp;lt;code&amp;gt;styling_metadata&amp;lt;/code&amp;gt; is never validated.&lt;br /&gt;
* &amp;lt;code&amp;gt;organization_cache&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;internal_organization_cache&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;QuestionnaireResponseTemplate.available_keys&amp;lt;/code&amp;gt; are platform-maintained. Don&amp;#039;t set them from clients; write through the through-models or &amp;lt;code&amp;gt;template_data&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Submitting answers validates type/required/value-set server-side and, for clinical questions, materializes [[References/Observation|Observations]]. To void a response, set its status to &amp;lt;code&amp;gt;entered_in_error&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;QuestionnaireResponseUpdate&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;FormSubmissionWriteSpec&amp;lt;/code&amp;gt; resolves the questionnaire by slug and, when an encounter is supplied, forces the submission&amp;#039;s patient to the encounter&amp;#039;s patient.&lt;br /&gt;
&lt;br /&gt;
{{Related}}&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>