References/Encounter
More languages
More actions
An Encounter records a single interaction between a patient and a facility — a visit, admission, or consultation — and maps to the FHIR Encounter resource. You create one when a patient presents, drive it through its status lifecycle, and read it back to render the clinical timeline.
The Django model is only the storage layer: several fields are opaque JSONFields whose real shape lives in the Pydantic resource specs, so the model alone won't tell you what a write must look like. The spec tables below carry that detail.
Source:
- Model: [https://github.com/ohcnetwork/care/blob/develop/care/emr/models/encounter.py
care/emr/models/encounter.py] - Specs: [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/encounter/spec.py
care/emr/resources/encounter/spec.py] · [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/encounter/constants.pyconstants.py] · [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/encounter/valueset.pyvalueset.py] · [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/encounter/enum_display_names.pyenum_display_names.py]
Models
| Model | Purpose |
|---|---|
Encounter
|
A single interaction between a patient and a facility (visit, admission, consultation) |
EncounterOrganization
|
Links an Encounter to a FacilityOrganization for access control
|
Both extend EMRBaseModel, the shared Care EMR base that provides external_id, audit fields, and soft-delete semantics.
Encounter fields
Classification & status
| Field | Type | Notes |
|---|---|---|
status |
CharField(100) |
Nullable in DB; required in API. One of StatusChoices (see below)
|
status_history |
JSONField |
Default {}. Server-maintained. Shape: { "history": [{ "status": str, "moved_at": str (ISO datetime) }] }
|
encounter_class |
CharField(100) |
Nullable in DB; required in API. One of ClassChoices (see below)
|
encounter_class_history |
JSONField |
Default {}. Server-maintained. Shape: { "history": [{ "status": str, "moved_at": str (ISO datetime) }] }
|
priority |
CharField(100) |
Nullable in DB; required in API. One of EncounterPriorityChoices (see below)
|
external_identifier |
CharField(100) |
Nullable. Identifier from an external/source system |
Subject & facility
| Field | Type | Notes |
|---|---|---|
patient |
FK → Patient |
CASCADE. The patient this encounter is for. Set on create only
|
facility |
FK → Facility |
PROTECT. The facility where the encounter takes place. Set on create only
{{Field|model=Encounter|section=Subject & facility|name=appointment|type=FK → TokenBooking|notes= |
Timing & disposition
| Field | Type | Notes |
|---|---|---|
period |
JSONField |
Default {}. PeriodSpec { start: datetime (tz-aware, optional), end: datetime (tz-aware, optional) }. If both set, start ≤ end
|
hospitalization |
JSONField |
Default {}. HospitalizationSpec (see shape below). Nullable
|
discharge_summary_advice |
TextField |
Nullable. Free-text discharge advice. Explicitly cleared to None on update when omitted
|
Care team
| Field | Type | Notes |
|---|---|---|
care_team |
JSONField |
Default {}. Stored as a list of { "user_id": int, "role": Coding } entries. Not writable on create/update (excluded); managed via the dedicated care-team write spec
|
care_team_users |
ArrayField[int] |
Platform-maintained denormalized cache of user IDs derived from care_team via sync_care_team_users_cache() on every save
|
Organization cache, tags & extensions
| Field | Type | Notes
{{Field|model=Encounter|section=Organization cache, tags & extensions|name=facility_organization_cache|type=ArrayField[int]|notes=Platform-maintained cache of facility-[[References/Organization}} |
|---|---|---|
tags |
ArrayField[int] |
Tag IDs applied to the encounter. Serialized via SingleFacilityTagManager().render_tags()
|
extensions |
JSONField |
Default {}. Open extension bag for deployment-specific metadata. Validated by ExtensionValidator against ExtensionResource.encounter
|
Nested JSON shapes
PeriodSpec (period)
Defined in [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/base.py resources/base.py].
| Field | Type | Notes |
|---|---|---|
start |
datetime |
Must be timezone-aware if provided |
end |
datetime |
Must be timezone-aware if provided |
validate_period rejects naive datetimes, and when both start and end are set it requires start not to exceed end.
HospitalizationSpec (hospitalization)
Defined in spec.py. All fields optional/nullable.
| Field | Type | Values |
|---|---|---|
re_admission
|
None | — |
admit_source
|
None | see [[#admit-source-values-admitsourceschoices |
discharge_disposition
|
None | see [[#discharge-disposition-values-dischargedispositionchoices |
diet_preference
|
None | see [[#diet-preference-values-dietpreferencechoices |
Enum values
Status values (StatusChoices)
| Value | |
|---|---|
planned
|
|
in_progress
|
|
on_hold
|
|
discharged
|
|
completed
|
terminal (in COMPLETED_CHOICES)
|
cancelled
|
terminal (in COMPLETED_CHOICES)
|
discontinued
|
terminal (in COMPLETED_CHOICES)
|
entered_in_error
|
terminal (in COMPLETED_CHOICES and ERROR_CHOICES)
|
unknown
|
COMPLETED_CHOICES = [completed, cancelled, entered_in_error, discontinued]; ERROR_CHOICES = [entered_in_error].
Class values (ClassChoices)
| Value | Meaning |
|---|---|
imp
|
inpatient |
amb
|
ambulatory |
obsenc
|
observation |
emer
|
emergency |
vr
|
virtual |
hh
|
home health |
Priority values (EncounterPriorityChoices)
| Value |
|---|
ASAP
|
callback_results
|
callback_for_scheduling
|
elective
|
emergency
|
preop
|
as_needed
|
routine
|
rush_reporting
|
stat
|
timing_critical
|
use_as_directed
|
urgent
|
Admit source values (AdmitSourcesChoices)
| Value | Display (get_admit_source_display)
|
|---|---|
hosp_trans
|
Transferred from other hospital |
emd
|
From accident/emergency department |
outp
|
From outpatient department |
born
|
Born in hospital |
gp
|
General Practitioner referral |
mp
|
Medical Practitioner/physician referral |
nursing
|
From nursing home |
psych
|
From psychiatric hospital |
rehab
|
From rehabilitation facility |
other
|
Other |
Discharge disposition values (DischargeDispositionChoices)
| Value | Display (get_discharge_disposition_display)
|
|---|---|
home
|
Home |
alt_home
|
Alternate Home |
other_hcf
|
Other Health Care Facility |
hosp
|
Hospital |
long
|
Long-term Care Facility |
aadvice
|
Against Medical Advice |
exp
|
Expired |
psy
|
Psychiatric Hospital |
rehab
|
Rehabilitation Facility |
snf
|
Skilled Nursing Facility |
oth
|
Other |
Diet preference values (DietPreferenceChoices)
| Value |
|---|
vegetarian
|
dairy_free
|
nut_free
|
gluten_free
|
vegan
|
halal
|
kosher
|
none
|
Resource specs (API schema)
All specs build on EMRResource, which provides serialize / de_serialize plus the perform_extra_serialization / perform_extra_deserialization hooks. EncounterSpecBase sets __exclude__ = [patient, organizations, facility, appointment, current_location, care_team]; those fields move through hooks or dedicated endpoints rather than direct assignment, which is why the create and read schemas diverge from the raw model.
| Spec | Role | Notes |
|---|---|---|
EncounterSpecBase
|
shared | None, default {}), priority, external_identifier, discharge_summary_advice. __model__ = Encounter
|
EncounterCreateSpec
|
write · create | None. Resolves FKs by external_id; validates appointment belongs to the patient and facility
|
EncounterUpdateSpec
|
write · update | Extends base + ExtensionValidator. Does not accept patient/facility/organizations/appointment — only mutable fields. Appends to status/class history on change
|
EncounterListSpec
|
read · list | Adds serialized patient ([[References/Patient
|
EncounterRetrieveSpec
|
read · detail | Extends list + EncounterPermissionsMixin. Adds appointment (TokenBookingReadSpec), created_by/updated_by ([[References/User & Skills
|
HospitalizationSpec
|
nested | Plain BaseModel; see shape above
|
EncounterCareTeamMemberSpec
|
nested (write) | { user_id: UUID4, role: Coding }, role bound to the system-practitioner-role-code value set
|
EncounterCareTeamMemberWriteSpec
|
write · care team | { members: list[EncounterCareTeamMemberSpec] }. Dedicated payload for replacing the care team
|
Server-maintained behaviour
- Status history: on create,
status_historystarts as{ "history": [{ status, moved_at }] }carrying the initial status; on update, a new entry is appended only whenstatuschanges.encounter_class_history/encounter_classfollow the same rule. - FK resolution (create):
patient,facility, andappointmentresolve fromexternal_id(404 if not found). The appointment must belong to the same patient and to a slot whose resource sits in the same facility. - Organizations (create):
organizations, deduplicated to a list of UUIDs, is stashed onobj._organizations, and the resultingEncounterOrganizationrows drivefacility_organization_cache. - Discharge advice (update): omitting
discharge_summary_adviceon update clears it toNonerather than leaving the prior value. - Care team:
rolebinds to thePRACTITIONER_ROLE_VALUESET(slugsystem-practitioner-role-code), a SNOMED CT value set of descendants of223366009(healthcare professional) and224930009(healthcare-related occupation).
Related models
EncounterOrganization
Associates an encounter with a facility-scoped organization to drive organization-based access control on encounters.
encounter → FK Encounter (CASCADE)
organization → FK FacilityOrganization (CASCADE)
Saving an EncounterOrganization calls encounter.sync_organization_cache(), which rebuilds the encounter's facility_organization_cache.
Methods & save behaviour
sync_care_team_users_cache()
When care_team is a list, fills care_team_users with int(entry["user_id"]) for each entry, falling back to -1 when a user_id is missing. The flat integer array lets queries skip JSON traversal.
sync_organization_cache()
Recomputes facility_organization_cache as the union of:
- every linked
EncounterOrganizationorganization plus itsparent_cachechain, and - the facility's
default_internal_organization_id.
Persists the result with super().save(update_fields=["facility_organization_cache"]).
save() side effects
On every save:
sync_care_team_users_cache()runs, refreshingcare_team_users.- A record with no
pkis flagged as newlycreated. - Inside a single
transaction.atomic()block, the basesave()runs. For newly created encounters,evaluate_patient_facility_default_values(patient, facility)then generates facility-scoped patient identifier defaults. - After the transaction,
sync_organization_cache()runs, performing a second write (update_fields=["facility_organization_cache"]).
Expect two write passes per create or update through the ORM, plus identifier-default generation on creation.
API integration notes
- Reads use
EncounterListSpec/EncounterRetrieveSpec; writes useEncounterCreateSpec/EncounterUpdateSpec. status,encounter_class, andpriorityare required on write and validated against their enums, even though the DB columns are nullable.- Never set
status_history,encounter_class_history,care_team_users, orfacility_organization_cachefrom a client; the server appends history on create and update and derives the caches fromcare_teamandEncounterOrganization. - Create and update don't touch the care team. Replace it through the dedicated care-team endpoint with
EncounterCareTeamMemberWriteSpec, where each member'srolemust resolve within thesystem-practitioner-role-codevalue set. periodandhospitalizationcarry structured JSON matching the nested-spec shapes above;period.startandperiod.endmust be timezone-aware.current_locationis a cached convenience field. The authoritative record islocation_history, fromFacilityLocationEncounter.extensionsholds custom key-value data without a schema migration, validated byExtensionValidator.
Related
Pages that link here:
- Concepts/Encounter
- References/Device
- References/Meta Artifact
- References/Questionnaire Response
- References/Token
- Concept: Concepts/Patient
- Reference: References/User & Skills