<?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%2FBooking</id>
	<title>References/Booking - 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%2FBooking"/>
	<link rel="alternate" type="text/html" href="https://ohcnwiki.tellmey.fyi/index.php?title=References/Booking&amp;action=history"/>
	<updated>2026-07-06T07:10:46Z</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/Booking&amp;diff=460&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/Booking&amp;diff=460&amp;oldid=prev"/>
		<updated>2026-07-06T04:19:43Z</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:49, 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 206:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 206:&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;tags&amp;lt;/code&amp;gt; is stored as an array of integer tag IDs but returned as rendered tag objects on read.&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;tags&amp;lt;/code&amp;gt; is stored as an array of integer tag IDs but returned as rendered tag objects on read.&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;* List requires a &amp;lt;code&amp;gt;resource_type&amp;lt;/code&amp;gt; query param and authorization scoped to organizations or resource IDs.&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;* List requires a &amp;lt;code&amp;gt;resource_type&amp;lt;/code&amp;gt; query param and authorization scoped to organizations or resource IDs.&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 scheduling}}&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;!-- diff cache key mediawiki:diff:1.41:old-174:rev-460:wikidiff2=table:1.14.2:bc2a06be --&gt;
&lt;/table&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://ohcnwiki.tellmey.fyi/index.php?title=References/Booking&amp;diff=174&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/Booking&amp;diff=174&amp;oldid=prev"/>
		<updated>2026-07-04T22:45:39Z</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=scheduling&lt;br /&gt;
|title=Booking&lt;br /&gt;
|order=2&lt;br /&gt;
|introduced=3.0&lt;br /&gt;
|model=Booking&lt;br /&gt;
|reference=References/Charge Item&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A booking puts a patient into a concrete time slot generated from a [[References/Schedule &amp;amp;amp; Availability|Schedule]]. &amp;lt;code&amp;gt;TokenSlot&amp;lt;/code&amp;gt; is a bookable unit of availability; &amp;lt;code&amp;gt;TokenBooking&amp;lt;/code&amp;gt; is a patient&amp;#039;s appointment against that slot, carrying its status through the lifecycle. You touch both whenever an integration creates, cancels, reschedules, or reads an appointment.&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/scheduling/booking.py &amp;lt;code&amp;gt;care/emr/models/scheduling/booking.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
* Resource spec: [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/scheduling/slot/spec.py &amp;lt;code&amp;gt;care/emr/resources/scheduling/slot/spec.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
* Viewset (side effects): [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/api/viewsets/scheduling/booking.py &amp;lt;code&amp;gt;care/emr/api/viewsets/scheduling/booking.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
These models live in two layers. The Django model is storage: &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt; is an unconstrained &amp;lt;code&amp;gt;CharField&amp;lt;/code&amp;gt; and several relations are opaque at the DB level. The Pydantic resource specs (&amp;lt;code&amp;gt;care/emr/resources/scheduling/slot/&amp;lt;/code&amp;gt;) are the API layer — they pin &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt; to a fixed enum, validate writes, and define the read schemas that embed slot, resource, facility, token, charge item, encounter, and patient sub-objects.&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;TokenSlot&amp;lt;/code&amp;gt;&lt;br /&gt;
| A concrete, bookable time window generated from a schedulable resource&amp;#039;s availability&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TokenBooking&amp;lt;/code&amp;gt;&lt;br /&gt;
| A patient&amp;#039;s appointment against a &amp;lt;code&amp;gt;TokenSlot&amp;lt;/code&amp;gt;, with status, notes, and optional links to an encounter, token, and charge item&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;]], the shared Care EMR base providing &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 &amp;lt;code&amp;gt;history&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;meta&amp;lt;/code&amp;gt; JSON.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;code&amp;gt;TokenBooking&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=Booking|section=TokenBooking fields|name=token_slot|type=FK → TokenSlot (PROTECT)|notes=The slot this appointment occupies; required. PROTECT prevents deleting a slot that has bookings}}&lt;br /&gt;
{{Field|model=Booking|section=TokenBooking fields|name=patient|type=FK → emr.Patient (CASCADE)|notes=The booked patient; required}}&lt;br /&gt;
{{Field|model=Booking|section=TokenBooking fields|name=booked_on|type=DateTimeField|notes=&amp;lt;code&amp;gt;auto_now_add&amp;lt;/code&amp;gt; — stamped once at creation, never accepted from clients}}&lt;br /&gt;
{{Field|model=Booking|section=TokenBooking fields|name=booked_by|type=FK → User (CASCADE)|notes=User who created the booking; nullable for self-service or system-created bookings}}&lt;br /&gt;
{{Field|model=Booking|section=TokenBooking fields|name=status|type=CharField (storage) → BookingStatusChoices (API)|notes=Appointment lifecycle status. Unbounded on the model; the write spec restricts it to the [[#bookingstatuschoices-values}}&lt;br /&gt;
{{Field|model=Booking|section=TokenBooking fields|name=note|type=TextField|notes=Free-text note; nullable in storage but required (&amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt;) on write}}&lt;br /&gt;
{{Field|model=Booking|section=TokenBooking fields|name=tags|type=ArrayField[int]|notes=Tag IDs, default empty list. Managed via &amp;lt;code&amp;gt;SingleFacilityTagManager&amp;lt;/code&amp;gt;; reads return rendered tag objects, not raw IDs}}&lt;br /&gt;
{{Field|model=Booking|section=TokenBooking fields|name=associated_encounter|type=FK → emr.Encounter (PROTECT)|notes=Encounter linked to the appointment; nullable, defaults to &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;. Surfaced only by &amp;lt;code&amp;gt;TokenBookingRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=Booking|section=TokenBooking fields|name=token|type=FK → emr.Token (PROTECT)|notes=Queue token issued for this booking; nullable, defaults to &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;related_name=&amp;amp;quot;token_booking&amp;amp;quot;&amp;lt;/code&amp;gt;. Created by the &amp;lt;code&amp;gt;generate_token&amp;lt;/code&amp;gt; action}}&lt;br /&gt;
{{Field|model=Booking|section=TokenBooking fields|name=charge_item|type=FK → emr.ChargeItem (CASCADE)|notes=Billing charge item for the appointment; nullable. Auto-created on booking when the schedule has a &amp;lt;code&amp;gt;charge_item_definition&amp;lt;/code&amp;gt;}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;BookingStatusChoices&amp;lt;/code&amp;gt; values ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;BookingStatusChoices&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;str, Enum&amp;lt;/code&amp;gt;) is the full set of &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt; values the write spec accepts:&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;proposed&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pending&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;booked&amp;lt;/code&amp;gt;&lt;br /&gt;
| Default applied server-side when a booking is created via &amp;lt;code&amp;gt;lock_create_appointment&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;arrived&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;fulfilled&amp;lt;/code&amp;gt;&lt;br /&gt;
| Terminal; in &amp;lt;code&amp;gt;COMPLETED_STATUS_CHOICES&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cancelled&amp;lt;/code&amp;gt;&lt;br /&gt;
| Set only via the &amp;lt;code&amp;gt;cancel&amp;lt;/code&amp;gt; endpoint; in &amp;lt;code&amp;gt;CANCELLED_STATUS_CHOICES&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;COMPLETED_STATUS_CHOICES&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;noshow&amp;lt;/code&amp;gt;&lt;br /&gt;
| Terminal; in &amp;lt;code&amp;gt;COMPLETED_STATUS_CHOICES&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;
| Set only via the &amp;lt;code&amp;gt;cancel&amp;lt;/code&amp;gt; endpoint; in &amp;lt;code&amp;gt;CANCELLED_STATUS_CHOICES&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;COMPLETED_STATUS_CHOICES&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;checked_in&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;waitlist&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;in_consultation&amp;lt;/code&amp;gt;&lt;br /&gt;
| Cannot be cancelled — the cancel handler rejects it&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;rescheduled&amp;lt;/code&amp;gt;&lt;br /&gt;
| Set only via the &amp;lt;code&amp;gt;reschedule&amp;lt;/code&amp;gt; endpoint; in &amp;lt;code&amp;gt;CANCELLED_STATUS_CHOICES&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;COMPLETED_STATUS_CHOICES&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Two derived sets (from &amp;lt;code&amp;gt;slot/spec.py&amp;lt;/code&amp;gt;) drive the lifecycle rules:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Set&lt;br /&gt;
! Values&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;CANCELLED_STATUS_CHOICES&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;entered_in_error&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;cancelled&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;rescheduled&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;COMPLETED_STATUS_CHOICES&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;fulfilled&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;noshow&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;entered_in_error&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;cancelled&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;rescheduled&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TokenBookingWriteSpec.perform_extra_deserialization&amp;lt;/code&amp;gt; rejects any write whose &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt; is in &amp;lt;code&amp;gt;CANCELLED_STATUS_CHOICES&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;amp;quot;Cannot cancel a booking. Use the cancel endpoint&amp;amp;quot;&amp;lt;/code&amp;gt;. Cancellation and rescheduling go through dedicated endpoints (see below), never a plain update.&lt;br /&gt;
&lt;br /&gt;
== Related models ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;TokenSlot&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
A bookable window derived from a resource&amp;#039;s availability. Bookings reference it via PROTECT, so a slot with active bookings cannot be deleted.&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=Booking|section=TokenSlot|name=resource|type=FK → SchedulableResource (CASCADE)|notes=The schedulable resource — practitioner, location, or healthcare service — the slot belongs to; required}}&lt;br /&gt;
{{Field|model=Booking|section=TokenSlot|name=availability|type=FK → Availability (CASCADE)|notes=The availability rule that generated this slot; nullable}}&lt;br /&gt;
{{Field|model=Booking|section=TokenSlot|name=start_datetime|type=DateTimeField|notes=Slot start; required, tz-aware}}&lt;br /&gt;
{{Field|model=Booking|section=TokenSlot|name=end_datetime|type=DateTimeField|notes=Slot end; required, tz-aware}}&lt;br /&gt;
{{Field|model=Booking|section=TokenSlot|name=allocated|type=IntegerField|notes=Count of bookings currently allocated to the slot, used to enforce capacity. Defaults to &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. Platform-maintained — never written by clients}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;SchedulableResource&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Availability&amp;lt;/code&amp;gt; live in the [[References/Schedule &amp;amp;amp; Availability|Schedule]] module. &amp;lt;code&amp;gt;SchedulableResource.resource_type&amp;lt;/code&amp;gt; is one of &amp;lt;code&amp;gt;SchedulableResourceTypeOptions&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;practitioner&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;healthcare_service&amp;lt;/code&amp;gt;.&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;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/base.py &amp;lt;code&amp;gt;base.py&amp;lt;/code&amp;gt;]): &amp;lt;code&amp;gt;serialize&amp;lt;/code&amp;gt; (DB → pydantic, read) and &amp;lt;code&amp;gt;de_serialize&amp;lt;/code&amp;gt; (pydantic → DB, write), with &amp;lt;code&amp;gt;perform_extra_serialization&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;perform_extra_deserialization&amp;lt;/code&amp;gt; hooks.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Spec class&lt;br /&gt;
! Role&lt;br /&gt;
! Exposes / behaviour&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TokenBookingBaseSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| shared&lt;br /&gt;
| &amp;lt;code&amp;gt;__model__ = TokenBooking&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;__exclude__ = [&amp;amp;quot;token_slot&amp;amp;quot;, &amp;amp;quot;patient&amp;amp;quot;]&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TokenBookingWriteSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · create + update&lt;br /&gt;
| Fields: &amp;lt;code&amp;gt;status: BookingStatusChoices&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;note: str&amp;lt;/code&amp;gt;. Rejects &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;CANCELLED_STATUS_CHOICES&amp;lt;/code&amp;gt; (use the cancel/reschedule endpoints). Serves as both &amp;lt;code&amp;gt;pydantic_model&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;pydantic_update_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TokenBookingMinimumReadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · embed&lt;br /&gt;
| Lightweight read for when a booking is embedded in another resource, such as a token. Fields: &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;token_slot&amp;lt;/code&amp;gt; (embedded &amp;lt;code&amp;gt;TokenSlotBaseSpec&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;booked_on&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;status: str&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;note&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;
| &amp;lt;code&amp;gt;TokenBookingBaseReadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · shared&lt;br /&gt;
| Adds &amp;lt;code&amp;gt;booked_by: UserSpec&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;resource_type&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;resource&amp;lt;/code&amp;gt; (serialized resource), &amp;lt;code&amp;gt;facility&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;token: TokenReadSpec&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;tags: list[dict]&amp;lt;/code&amp;gt; (rendered), &amp;lt;code&amp;gt;charge_item: dict&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TokenBookingReadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · list/default&lt;br /&gt;
| &amp;lt;code&amp;gt;TokenBookingBaseReadSpec&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;patient: PatientRetrieveSpec&amp;lt;/code&amp;gt;. The viewset&amp;#039;s &amp;lt;code&amp;gt;pydantic_read_model&amp;lt;/code&amp;gt; for list responses&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TokenBookingOTPReadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · OTP flow&lt;br /&gt;
| &amp;lt;code&amp;gt;TokenBookingBaseReadSpec&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;patient: PatientOTPReadSpec&amp;lt;/code&amp;gt; for the public/OTP booking flow&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TokenBookingRetrieveSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · detail&lt;br /&gt;
| &amp;lt;code&amp;gt;TokenBookingReadSpec&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;associated_encounter: dict&amp;lt;/code&amp;gt; (serialized &amp;lt;code&amp;gt;EncounterListSpec&amp;lt;/code&amp;gt;). The viewset&amp;#039;s &amp;lt;code&amp;gt;pydantic_retrieve_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TokenSlotBaseSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · embed&lt;br /&gt;
| &amp;lt;code&amp;gt;__model__ = TokenSlot&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;__exclude__ = [&amp;amp;quot;resource&amp;amp;quot;, &amp;amp;quot;availability&amp;amp;quot;]&amp;lt;/code&amp;gt;. Fields: &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;availability&amp;lt;/code&amp;gt; (embedded as &amp;lt;code&amp;gt;{name, tokens_per_slot, id, schedule:{name,id}}&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;start_datetime&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;end_datetime&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;allocated&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Read serialization details (&amp;lt;code&amp;gt;perform_extra_serialization&amp;lt;/code&amp;gt;) ===&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; always comes from &amp;lt;code&amp;gt;obj.external_id&amp;lt;/code&amp;gt; (UUID), not the integer PK.&lt;br /&gt;
* &amp;lt;code&amp;gt;token_slot&amp;lt;/code&amp;gt; is embedded via &amp;lt;code&amp;gt;TokenSlotBaseSpec.serialize(...)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;resource_type&amp;lt;/code&amp;gt; comes from &amp;lt;code&amp;gt;token_slot.resource.resource_type&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;resource&amp;lt;/code&amp;gt; is built by &amp;lt;code&amp;gt;serialize_resource()&amp;lt;/code&amp;gt; — a &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;practitioner&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;HealthcareServiceReadSpec&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;healthcare_service&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;FacilityLocationListSpec&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;facility&amp;lt;/code&amp;gt; is a cached &amp;lt;code&amp;gt;FacilityBareMinimumSpec&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;booked_by&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; are cached &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt;s.&lt;br /&gt;
* &amp;lt;code&amp;gt;tags&amp;lt;/code&amp;gt; are rendered through &amp;lt;code&amp;gt;SingleFacilityTagManager().render_tags(obj)&amp;lt;/code&amp;gt; as objects, not raw IDs.&lt;br /&gt;
* &amp;lt;code&amp;gt;token&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;TokenReadSpec&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;charge_item&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;ChargeItemReadSpec&amp;lt;/code&amp;gt;), and &amp;lt;code&amp;gt;associated_encounter&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;EncounterListSpec&amp;lt;/code&amp;gt;) appear only when present.&lt;br /&gt;
&lt;br /&gt;
== Methods &amp;amp;amp; save behaviour ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt; has no model-level &amp;lt;code&amp;gt;choices&amp;lt;/code&amp;gt;; the lifecycle lives entirely in the spec/viewset layer (&amp;lt;code&amp;gt;TokenBookingViewSet&amp;lt;/code&amp;gt;). The server-maintained behaviour:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Creation (&amp;lt;code&amp;gt;lock_create_appointment&amp;lt;/code&amp;gt;)&amp;#039;&amp;#039;&amp;#039; — runs under a per-resource lock and a transaction. Rejects past slots (&amp;lt;code&amp;gt;end_datetime &amp;amp;lt; now&amp;lt;/code&amp;gt;) and full slots (&amp;lt;code&amp;gt;allocated &amp;amp;gt;= availability.tokens_per_slot&amp;lt;/code&amp;gt;), rejects a duplicate active booking for the same patient/slot (any status not in &amp;lt;code&amp;gt;COMPLETED_STATUS_CHOICES&amp;lt;/code&amp;gt;), then increments &amp;lt;code&amp;gt;token_slot.allocated&amp;lt;/code&amp;gt;, creates the booking with &amp;lt;code&amp;gt;status=&amp;amp;quot;booked&amp;amp;quot;&amp;lt;/code&amp;gt;, and — if the schedule has a &amp;lt;code&amp;gt;charge_item_definition&amp;lt;/code&amp;gt; — auto-creates the linked &amp;lt;code&amp;gt;charge_item&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Cancel (&amp;lt;code&amp;gt;cancel&amp;lt;/code&amp;gt; action)&amp;#039;&amp;#039;&amp;#039; — accepts &amp;lt;code&amp;gt;CancelBookingSpec { reason: cancelled | entered_in_error | rescheduled, note?: str }&amp;lt;/code&amp;gt;. Rejects cancelling an &amp;lt;code&amp;gt;in_consultation&amp;lt;/code&amp;gt; booking. Decrements &amp;lt;code&amp;gt;token_slot.allocated&amp;lt;/code&amp;gt; (unless already cancelled), sets &amp;lt;code&amp;gt;status = reason&amp;lt;/code&amp;gt;, optionally overwrites &amp;lt;code&amp;gt;note&amp;lt;/code&amp;gt;, sets &amp;lt;code&amp;gt;updated_by&amp;lt;/code&amp;gt;, and aborts any linked &amp;lt;code&amp;gt;charge_item&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;handle_charge_item_cancel&amp;lt;/code&amp;gt; + status &amp;lt;code&amp;gt;aborted&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Reschedule (&amp;lt;code&amp;gt;reschedule&amp;lt;/code&amp;gt; action)&amp;#039;&amp;#039;&amp;#039; — accepts &amp;lt;code&amp;gt;RescheduleBookingSpec { new_slot: UUID, new_booking_note: str, previous_booking_note?: str, tags: list[UUID] }&amp;lt;/code&amp;gt; and requires &amp;lt;code&amp;gt;can_reschedule_booking&amp;lt;/code&amp;gt;. Cancels the existing booking with reason &amp;lt;code&amp;gt;rescheduled&amp;lt;/code&amp;gt;, then runs &amp;lt;code&amp;gt;lock_create_appointment&amp;lt;/code&amp;gt; to create a fresh booking on &amp;lt;code&amp;gt;new_slot&amp;lt;/code&amp;gt; for the same patient. Rejects rescheduling to the same slot.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Generate token (&amp;lt;code&amp;gt;generate_token&amp;lt;/code&amp;gt; action)&amp;#039;&amp;#039;&amp;#039; — accepts &amp;lt;code&amp;gt;TokenGenerationSpec { category: UUID, note?: str, queue?: UUID }&amp;lt;/code&amp;gt;. Rejects if a token already exists. Resolves or creates a &amp;lt;code&amp;gt;TokenQueue&amp;lt;/code&amp;gt; for the slot&amp;#039;s date and resource, allocates the next &amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt; under a queue lock, creates a &amp;lt;code&amp;gt;Token&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;status=&amp;amp;quot;CREATED&amp;amp;quot;&amp;lt;/code&amp;gt;), and links it to &amp;lt;code&amp;gt;booking.token&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;booked_on&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; is &amp;lt;code&amp;gt;auto_now_add&amp;lt;/code&amp;gt; — never set by clients.&lt;br /&gt;
&lt;br /&gt;
== API integration notes ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;TokenSlot&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;TokenBooking&amp;lt;/code&amp;gt; are exposed through Care&amp;#039;s scheduling REST API and align with the FHIR &amp;lt;code&amp;gt;Slot&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Appointment&amp;lt;/code&amp;gt; resources; payload field names may differ from Django model names.&lt;br /&gt;
* Writes use &amp;lt;code&amp;gt;TokenBookingWriteSpec&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt; constrained to &amp;lt;code&amp;gt;BookingStatusChoices&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;note&amp;lt;/code&amp;gt; required). &amp;lt;code&amp;gt;cancelled&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;entered_in_error&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;rescheduled&amp;lt;/code&amp;gt; cannot be set through a plain update — use the &amp;lt;code&amp;gt;cancel&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;reschedule&amp;lt;/code&amp;gt; actions.&lt;br /&gt;
* List responses use &amp;lt;code&amp;gt;TokenBookingReadSpec&amp;lt;/code&amp;gt;; detail responses use &amp;lt;code&amp;gt;TokenBookingRetrieveSpec&amp;lt;/code&amp;gt;, which adds &amp;lt;code&amp;gt;associated_encounter&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;allocated&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;TokenSlot&amp;lt;/code&amp;gt; is a capacity counter maintained by &amp;lt;code&amp;gt;lock_create_appointment&amp;lt;/code&amp;gt; and cancel; do not write it directly.&lt;br /&gt;
* &amp;lt;code&amp;gt;tags&amp;lt;/code&amp;gt; is stored as an array of integer tag IDs but returned as rendered tag objects on read.&lt;br /&gt;
* List requires a &amp;lt;code&amp;gt;resource_type&amp;lt;/code&amp;gt; query param and authorization scoped to organizations or resource IDs.&lt;br /&gt;
&lt;br /&gt;
{{Related}}&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>