<?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%2FNotes</id>
	<title>References/Notes - 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%2FNotes"/>
	<link rel="alternate" type="text/html" href="https://ohcnwiki.tellmey.fyi/index.php?title=References/Notes&amp;action=history"/>
	<updated>2026-07-06T08:41:08Z</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/Notes&amp;diff=418&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/Notes&amp;diff=418&amp;oldid=prev"/>
		<updated>2026-07-06T04:04:37Z</updated>

		<summary type="html">&lt;p&gt;Automated edit (via update-page on MediaWiki MCP Server)&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 09:34, 6 July 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 178:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 178:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;lt;code&amp;gt;message_history&amp;lt;/code&amp;gt; is read-only. Each edit appends the previous body and authorship to &amp;lt;code&amp;gt;history&amp;lt;/code&amp;gt; server-side.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;lt;code&amp;gt;message_history&amp;lt;/code&amp;gt; is read-only. Each edit appends the previous body and authorship to &amp;lt;code&amp;gt;history&amp;lt;/code&amp;gt; server-side.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&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;created_date&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;modified_date&amp;lt;/code&amp;gt; are read-only audit fields from &amp;lt;code&amp;gt;EMRBaseModel&amp;lt;/code&amp;gt;; soft deletes use &amp;lt;code&amp;gt;deleted&amp;lt;/code&amp;gt;.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&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;created_date&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;modified_date&amp;lt;/code&amp;gt; are read-only audit fields from &amp;lt;code&amp;gt;EMRBaseModel&amp;lt;/code&amp;gt;; soft deletes use &amp;lt;code&amp;gt;deleted&amp;lt;/code&amp;gt;.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Navbox clinical}}&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Related}}&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Related}}&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Wiki: ohcnwiki.tellmey.fyi&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://ohcnwiki.tellmey.fyi/index.php?title=References/Notes&amp;diff=142&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/Notes&amp;diff=142&amp;oldid=prev"/>
		<updated>2026-07-04T22:44:23Z</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=clinical&lt;br /&gt;
|title=Notes&lt;br /&gt;
|order=9&lt;br /&gt;
|introduced=3.0&lt;br /&gt;
|fhir=Notes&lt;br /&gt;
|model=Notes&lt;br /&gt;
|reference=References/Base models &amp;amp;amp; conventions&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Notes are threaded discussions attached to a patient. A &amp;lt;code&amp;gt;NoteThread&amp;lt;/code&amp;gt; groups messages; a &amp;lt;code&amp;gt;NoteMessage&amp;lt;/code&amp;gt; is one message in that thread, carrying a server-maintained edit history.&lt;br /&gt;
&lt;br /&gt;
The Django models (&amp;lt;code&amp;gt;care/emr/models/notes.py&amp;lt;/code&amp;gt;) store the data: &amp;lt;code&amp;gt;NoteThread&amp;lt;/code&amp;gt; holds the patient and optional encounter link, and &amp;lt;code&amp;gt;NoteMessage&amp;lt;/code&amp;gt; stores each body next to an opaque &amp;lt;code&amp;gt;message_history&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;JSONField&amp;lt;/code&amp;gt;. The Pydantic resource specs (&amp;lt;code&amp;gt;care/emr/resources/notes/&amp;lt;/code&amp;gt;) extend &amp;lt;code&amp;gt;EMRResource&amp;lt;/code&amp;gt; and define what the API exposes — the shape of &amp;lt;code&amp;gt;message_history&amp;lt;/code&amp;gt;, the read/write schema split, and the edit-history logic that runs on every update.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Source:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
* Model: [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/models/notes.py &amp;lt;code&amp;gt;care/emr/models/notes.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
* Specs: [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/notes/thread_spec.py &amp;lt;code&amp;gt;resources/notes/thread_spec.py&amp;lt;/code&amp;gt;], [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/notes/notes_spec.py &amp;lt;code&amp;gt;resources/notes/notes_spec.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
* Base: [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/base.py &amp;lt;code&amp;gt;resources/base.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== Models ==&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;NoteThread&amp;lt;/code&amp;gt;&lt;br /&gt;
| A discussion thread attached to a patient (optionally scoped to an encounter)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NoteMessage&amp;lt;/code&amp;gt;&lt;br /&gt;
| An individual message posted within a &amp;lt;code&amp;gt;NoteThread&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Both 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;, &amp;lt;code&amp;gt;created_date&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;modified_date&amp;lt;/code&amp;gt;, soft-delete via &amp;lt;code&amp;gt;deleted&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;, and the &amp;lt;code&amp;gt;history&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;meta&amp;lt;/code&amp;gt; JSON fields.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;code&amp;gt;NoteThread&amp;lt;/code&amp;gt; fields ==&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=Notes|section=NoteThread fields|name=title|type=CharField(255)|notes=Nullable and blank-allowed in the column, but the spec requires it on write (&amp;lt;code&amp;gt;title: str&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;max_length=255&amp;lt;/code&amp;gt;)}}&lt;br /&gt;
{{Field|model=Notes|section=NoteThread fields|name=patient|type=FK → Patient|notes=&amp;lt;code&amp;gt;on_delete=CASCADE&amp;lt;/code&amp;gt;; deleting the [[References/Patient}}&lt;br /&gt;
{{Field|model=Notes|section=NoteThread fields|name=encounter|type=FK → Encounter|notes=Nullable, blank-allowed, &amp;lt;code&amp;gt;on_delete=CASCADE&amp;lt;/code&amp;gt;. Scopes the thread to one [[References/Encounter}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A thread with no &amp;lt;code&amp;gt;encounter&amp;lt;/code&amp;gt; is patient-level; a thread with an &amp;lt;code&amp;gt;encounter&amp;lt;/code&amp;gt; is pinned to that visit. A &amp;lt;code&amp;gt;TODO&amp;lt;/code&amp;gt; in the source flags organization-based access restriction as planned but not yet implemented.&lt;br /&gt;
&lt;br /&gt;
== Related models ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;NoteMessage&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
One message inside a thread.&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=Notes|section=NoteMessage|name=thread|type=FK → NoteThread|notes=&amp;lt;code&amp;gt;on_delete=CASCADE&amp;lt;/code&amp;gt;; deleting the thread deletes its messages. Excluded from spec serialization (&amp;lt;code&amp;gt;__exclude__&amp;lt;/code&amp;gt;) and set from the URL/viewset context}}&lt;br /&gt;
{{Field|model=Notes|section=NoteMessage|name=message|type=TextField|notes=Free-text body. Required on write (&amp;lt;code&amp;gt;message: str&amp;lt;/code&amp;gt;)}}&lt;br /&gt;
{{Field|model=Notes|section=NoteMessage|name=message_history|type=JSONField|notes=Defaults to &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;. Opaque at the model layer; the spec gives it the shape below and rewrites it server-side on each edit. Read-only on the API}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;message_history&amp;lt;/code&amp;gt; shape ====&lt;br /&gt;
&lt;br /&gt;
The update spec writes a fixed structure, not a free-form blob. Each edit appends the &amp;#039;&amp;#039;previous&amp;#039;&amp;#039; message body to a &amp;lt;code&amp;gt;history&amp;lt;/code&amp;gt; list:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;jsonc&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;amp;quot;history&amp;amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;amp;quot;message&amp;amp;quot;: &amp;amp;quot;string&amp;amp;quot;,           // the prior message body (pre-edit)&lt;br /&gt;
      &amp;amp;quot;created_by&amp;amp;quot;: {&lt;br /&gt;
        &amp;amp;quot;username&amp;amp;quot;: &amp;amp;quot;string&amp;amp;quot;,&lt;br /&gt;
        &amp;amp;quot;external_id&amp;amp;quot;: &amp;amp;quot;uuid&amp;amp;quot;        // editor of the prior version&lt;br /&gt;
      },&lt;br /&gt;
      &amp;amp;quot;edited_at&amp;amp;quot;: &amp;amp;quot;datetime str&amp;amp;quot;,   // timezone.now() at the time of this edit&lt;br /&gt;
      &amp;amp;quot;created_at&amp;amp;quot;: &amp;amp;quot;datetime str&amp;amp;quot;   // the prior version&amp;#039;s modified_date&lt;br /&gt;
    }&lt;br /&gt;
    // ... one entry per edit, oldest first&lt;br /&gt;
  ]&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
Clients never write &amp;lt;code&amp;gt;message_history&amp;lt;/code&amp;gt;. It is read-only on the API and rebuilt server-side on each edit (see &amp;lt;code&amp;gt;NoteMessageUpdateSpec&amp;lt;/code&amp;gt; below).&lt;br /&gt;
&lt;br /&gt;
== Resource specs (API schema) ==&lt;br /&gt;
&lt;br /&gt;
Every spec extends &amp;lt;code&amp;gt;EMRResource&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;resources/base.py&amp;lt;/code&amp;gt;), which provides &amp;lt;code&amp;gt;serialize&amp;lt;/code&amp;gt; (DB object → pydantic, via &amp;lt;code&amp;gt;perform_extra_serialization&amp;lt;/code&amp;gt;) and &amp;lt;code&amp;gt;de_serialize&amp;lt;/code&amp;gt; (pydantic → DB object, via &amp;lt;code&amp;gt;perform_extra_deserialization&amp;lt;/code&amp;gt;). Fields named in &amp;lt;code&amp;gt;__exclude__&amp;lt;/code&amp;gt; are skipped in both directions and handled by hand.&lt;br /&gt;
&lt;br /&gt;
=== Thread specs ===&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;
! Fields exposed&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NoteThreadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| shared base&lt;br /&gt;
| &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; (UUID, read), &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt; (str, required, ≤255)&lt;br /&gt;
| &amp;lt;code&amp;gt;__model__ = NoteThread&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;__exclude__ = [&amp;amp;quot;patient&amp;amp;quot;, &amp;amp;quot;encounter&amp;amp;quot;]&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NoteThreadCreateSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · create&lt;br /&gt;
| base + &amp;lt;code&amp;gt;encounter&amp;lt;/code&amp;gt; (UUID, optional)&lt;br /&gt;
| Validates &amp;lt;code&amp;gt;encounter&amp;lt;/code&amp;gt; exists (raises &amp;lt;code&amp;gt;Encounter not found&amp;lt;/code&amp;gt;), then resolves the UUID to an &amp;lt;code&amp;gt;Encounter&amp;lt;/code&amp;gt; FK in &amp;lt;code&amp;gt;perform_extra_deserialization&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NoteThreadUpdateSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · update&lt;br /&gt;
| base (&amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt;)&lt;br /&gt;
| No extra behaviour; &amp;lt;code&amp;gt;encounter&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;patient&amp;lt;/code&amp;gt; cannot be reassigned through update&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NoteThreadReadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · detail/list&lt;br /&gt;
| base + &amp;lt;code&amp;gt;created_by&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;updated_by&amp;lt;/code&amp;gt; (dict, nullable), &amp;lt;code&amp;gt;created_date&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;modified_date&amp;lt;/code&amp;gt; (datetime)&lt;br /&gt;
| &amp;lt;code&amp;gt;perform_extra_serialization&amp;lt;/code&amp;gt; sets &amp;lt;code&amp;gt;id = external_id&amp;lt;/code&amp;gt; and serializes audit users via &amp;lt;code&amp;gt;serialize_audit_users&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Validation and server behaviour:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt; is required on write at the spec layer (&amp;lt;code&amp;gt;Field(..., max_length=255)&amp;lt;/code&amp;gt;), even though the column is nullable.&lt;br /&gt;
* &amp;lt;code&amp;gt;NoteThreadCreateSpec.encounter&amp;lt;/code&amp;gt; runs &amp;lt;code&amp;gt;validate_encounter_exists&amp;lt;/code&amp;gt;: a non-null value must match an existing &amp;lt;code&amp;gt;Encounter.external_id&amp;lt;/code&amp;gt;, or it raises &amp;lt;code&amp;gt;ValueError(&amp;amp;quot;Encounter not found&amp;amp;quot;)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* On create, &amp;lt;code&amp;gt;perform_extra_deserialization&amp;lt;/code&amp;gt; looks up the &amp;lt;code&amp;gt;Encounter&amp;lt;/code&amp;gt; by &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt; and assigns the FK. &amp;lt;code&amp;gt;patient&amp;lt;/code&amp;gt; belongs to no thread spec — it comes from the request context.&lt;br /&gt;
&lt;br /&gt;
=== Message specs ===&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;
! Fields exposed&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NoteMessageSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| shared base&lt;br /&gt;
| &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; (UUID, read), &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt; (str, required)&lt;br /&gt;
| &amp;lt;code&amp;gt;__model__ = NoteMessage&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;__exclude__ = [&amp;amp;quot;thread&amp;amp;quot;]&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NoteMessageCreateSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · create&lt;br /&gt;
| base (&amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt;)&lt;br /&gt;
| No extra behaviour&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NoteMessageUpdateSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · update&lt;br /&gt;
| base (&amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt;)&lt;br /&gt;
| &amp;lt;code&amp;gt;perform_extra_deserialization&amp;lt;/code&amp;gt; appends the pre-edit message to &amp;lt;code&amp;gt;message_history[&amp;amp;quot;history&amp;amp;quot;]&amp;lt;/code&amp;gt; (see below)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NoteMessageReadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · detail/list&lt;br /&gt;
| base + &amp;lt;code&amp;gt;message_history&amp;lt;/code&amp;gt; (dict), &amp;lt;code&amp;gt;created_by&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;updated_by&amp;lt;/code&amp;gt; (dict, nullable), &amp;lt;code&amp;gt;created_date&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;modified_date&amp;lt;/code&amp;gt; (datetime)&lt;br /&gt;
| &amp;lt;code&amp;gt;perform_extra_serialization&amp;lt;/code&amp;gt; sets &amp;lt;code&amp;gt;id = external_id&amp;lt;/code&amp;gt; and serializes audit users&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Validation and server behaviour:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt; is required on create and update.&lt;br /&gt;
* &amp;lt;code&amp;gt;thread&amp;lt;/code&amp;gt; is never in the request body (&amp;lt;code&amp;gt;__exclude__&amp;lt;/code&amp;gt;); it comes from the URL/viewset context.&lt;br /&gt;
* On update, &amp;lt;code&amp;gt;NoteMessageUpdateSpec.perform_extra_deserialization&amp;lt;/code&amp;gt; fetches the existing &amp;lt;code&amp;gt;NoteMessage&amp;lt;/code&amp;gt; by &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt;, initializes &amp;lt;code&amp;gt;message_history[&amp;amp;quot;history&amp;amp;quot;] = []&amp;lt;/code&amp;gt; if empty, then appends an entry: the prior &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt;, the prior author (&amp;lt;code&amp;gt;username&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;edited_at&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;timezone.now()&amp;lt;/code&amp;gt;), and &amp;lt;code&amp;gt;created_at&amp;lt;/code&amp;gt; (the prior &amp;lt;code&amp;gt;modified_date&amp;lt;/code&amp;gt;). Clients cannot write &amp;lt;code&amp;gt;message_history&amp;lt;/code&amp;gt; directly.&lt;br /&gt;
&lt;br /&gt;
== Methods &amp;amp;amp; save behaviour ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;NoteThread&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NoteMessage&amp;lt;/code&amp;gt; inherit save and audit behaviour from [[References/Base models &amp;amp;amp; conventions|&amp;lt;code&amp;gt;EMRBaseModel&amp;lt;/code&amp;gt;]]: &amp;lt;code&amp;gt;external_id&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;created_date&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;modified_date&amp;lt;/code&amp;gt;, and soft delete via &amp;lt;code&amp;gt;deleted&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Read specs populate audit users through &amp;lt;code&amp;gt;EMRResource.serialize_audit_users&amp;lt;/code&amp;gt;, which resolves &amp;lt;code&amp;gt;created_by&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;updated_by&amp;lt;/code&amp;gt; to cached &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt; dicts.&lt;br /&gt;
* &amp;lt;code&amp;gt;message_history&amp;lt;/code&amp;gt; changes only inside &amp;lt;code&amp;gt;NoteMessageUpdateSpec.perform_extra_deserialization&amp;lt;/code&amp;gt; — never from client input.&lt;br /&gt;
* Cascade deletes flow downward: deleting a patient removes its threads, and deleting a thread removes its messages.&lt;br /&gt;
&lt;br /&gt;
== API integration notes ==&lt;br /&gt;
&lt;br /&gt;
Payload field names follow the spec classes above, not the Django model names.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;patient&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;thread&amp;lt;/code&amp;gt; never appear in a request body; they come from the URL/viewset context.&lt;br /&gt;
* Send &amp;lt;code&amp;gt;encounter&amp;lt;/code&amp;gt; on create as the encounter&amp;#039;s &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt; (UUID); it is validated to exist. It cannot be reassigned on update.&lt;br /&gt;
* &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt; are required on write, even though the underlying columns are nullable.&lt;br /&gt;
* &amp;lt;code&amp;gt;message_history&amp;lt;/code&amp;gt; is read-only. Each edit appends the previous body and authorship to &amp;lt;code&amp;gt;history&amp;lt;/code&amp;gt; server-side.&lt;br /&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;created_date&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;modified_date&amp;lt;/code&amp;gt; are read-only audit fields from &amp;lt;code&amp;gt;EMRBaseModel&amp;lt;/code&amp;gt;; soft deletes use &amp;lt;code&amp;gt;deleted&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Related}}&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>