← Knowledge library

Appointments & queues

Token

A Token is a numbered ticket a patient holds in a walk-in queue — use it when scheduling runs on first-come flow rather than fixed appointment slots. The patient gets a number against a schedulable resource , optionally routed to a sub-queue or…

3.1 · versioned documentation · 8 min read

A Token is a numbered ticket a patient holds in a walk-in queue — use it when scheduling runs on first-come flow rather than fixed appointment slots. The patient gets a number against a schedulable resource (practitioner, location, or healthcare service), optionally routed to a sub-queue or room.

The Django models store the data; the rules that make a token correct — status enums, the resource binding, queue progression — live in the Pydantic resource specs and the API viewsets. Both layers are covered here.

Source:

Models

Four models make up the subsystem.

Model Purpose
TokenQueue A queue of tokens for one schedulable resource on one date
TokenSubQueue A sub-queue splitting a resource's tokens (e.g. multiple rooms)
TokenCategory Reusable token categories per facility / resource type
Token A numbered token issued to a patient within a queue

All four extend EMRBaseModel, the shared MANSOQ EMR base that supplies external_id, audit fields created_by/updated_by/created_date/modified_date, and soft-delete via deleted.

TokenQueue and TokenSubQueue both carry a resource FK to emr.SchedulableResource, a polymorphic binding to a practitioner (user), location, or healthcare_service, distinguished by resource_type. See Schedule.

Token fields

Field Type Required Notes
facility FK → facility.Facility (CASCADE) yes (server) Copied from the queue's facility on create
patient FK → emr.Patient (CASCADE) optional Nullable. The patient the token belongs to. See Patient
queue FK → TokenQueue (CASCADE) yes (server) Taken from the URL queue, not the body
category FK → TokenCategory (CASCADE) yes Resolved from the category UUID on create. Must be in the same facility as the queue
sub_queue FK → TokenSubQueue (CASCADE) optional Nullable. Must match the queue's facility and resource
number IntegerField yes (server) Auto-assigned: count(tokens in queue with same category) + 1
status CharField(255) yes (server) TokenStatusOptions enum (below). Starts at CREATED
is_next BooleanField (default False) server Queue-progression flag; clients never write it
note TextField optional Nullable free-text note
booking FK → emr.TokenBooking (CASCADE) optional Nullable. Links the token to a booking. related_name="booking_token"

number is unique per category within a queue, not across the whole queue — so one patient can hold several tokens in the same queue, and two categories can both have a token 1.

TokenStatusOptions values

Defined in token/spec.py; bound on Token.status through the read and update specs.

Value Meaning
UNFULFILLED Token issued but not served
CREATED Default state on creation
IN_PROGRESS Currently being served (set when made the sub-queue's current token)
FULFILLED Service completed
CANCELLED Cancelled
ENTERED_IN_ERROR Set automatically on delete (soft-delete)

Related models

TokenQueue

One resource, one date, one queue of tokens.

facility         → FK Facility (CASCADE)
resource         → FK SchedulableResource (CASCADE)
name             → CharField(255)
is_primary       → BooleanField (default True)
date             → DateField
system_generated → BooleanField (default False)

TokenSubQueue

A sub-queue routes one queue's tokens to several physical points — multiple vaccination rooms, say, each pulling from its own sub-queue.

facility      → FK Facility (CASCADE)
resource      → FK SchedulableResource (CASCADE)
name          → CharField(255)
status        → CharField(255)          # TokenSubQueueStatusOptions
current_token → FK Token (CASCADE, nullable)

The spec binds status to TokenSubQueueStatusOptions:

Value
active
inactive

current_token is whichever token is being served at that point. The progression actions (set_next, set_next_token_to_subqueue) keep it current server-side.

TokenCategory

A reusable category scoped to a facility and resource type — "General", "Priority", and so on.

facility      → FK Facility (CASCADE)
resource_type → CharField(255)          # SchedulableResourceTypeOptions
name          → CharField(255)
shorthand     → CharField(255)          # spec limits to max_length 5
metadata      → JSONField (default dict)
default       → BooleanField (default False)

SchedulableResourceTypeOptions values

Defined in scheduling/schedule/spec.py; used by TokenCategory.resource_type and every *WithQueue / create spec that binds to a resource.

Value
practitioner
location
healthcare_service

Resource specs (API schema)

Every spec extends EMRResource (care/emr/resources/base.py): serialize builds the read payload from the model (plus perform_extra_serialization), and de_serialize writes a model from the payload (plus perform_extra_deserialization). id is always the model's external_id (UUID).

Token

Spec Role Exposed fields
TokenBaseSpec shared id
TokenGenerateSpec write · create (nested under a queue) patient? (UUID), category (UUID, required), note?, sub_queue? (UUID)
TokenGenerateWithQueueSpec write · create (queue resolved/created) adds resource_type (SchedulableResourceTypeOptions), resource_id (UUID), date
TokenUpdateSpec write · update status? (TokenStatusOptions), note?, sub_queue (UUID, nullable)
TokenMinimalSpec read · embedded note, number, status, category (serialized via TokenCategoryReadSpec)
TokenReadSpec read · list category, sub_queue, note, patient, number, status, queue (TokenQueueReadSpec)
TokenRetrieveSpec read · detail extends TokenReadSpec + created_by/updated_by (UserSpec), booking, resource_type, resource, encounter?

What happens on write, from perform_extra_deserialization and the viewset:

TokenQueue

Spec Role Exposed fields
TokenQueueBaseSpec shared id, name
TokenQueueCreateSpec write · create adds resource_type (SchedulableResourceTypeOptions), resource_id (UUID), date
TokenQueueUpdateSpec write · update id, name only
TokenQueueReadSpec read · list adds date, is_primary, system_generated
TokenQueueRetrieveSpec read · detail adds created_by, updated_by

TokenQueueCreateSpec.perform_extra_deserialization stashes resource_type and resource_id onto the instance. The viewset's perform_create then resolves or creates the SchedulableResource, sets facility, and computes is_primary.

TokenSubQueue

Spec Role Exposed fields
TokenSubQueueBaseSpec shared / write · update id, name, status (TokenSubQueueStatusOptions)
TokenSubQueueCreateSpec write · create adds resource_type (SchedulableResourceTypeOptions), resource_id (UUID)
TokenSubQueueReadSpec read adds current_token (TokenMinimalSpec, nullable)

TokenSubQueueCreateSpec.perform_extra_deserialization stashes resource_type and resource_id. On create the viewset resolves or creates the resource and validates it. current_token is serialized only when set.

TokenCategory

Spec Role Exposed fields
TokenCategoryBaseSpec shared id, name, resource_type (SchedulableResourceTypeOptions), shorthand (max 5), metadata? (dict)
TokenCategoryCreateSpec write · create same as base
TokenCategoryReadSpec read · list adds default
TokenCategoryRetrieveSpec read · detail adds created_by, updated_by

facility is set from the URL on create. default is read-only here and toggled through the set_default action.

Methods & save behaviour

API integration notes

Related

Source evidence

References are pinned to the private MANSOQ source repository. Repository access is required to open these links.