Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

References/Location

From OHC Network Wiki
referencefacilityCARE 3.0+

FacilityLocation is a node in a facility's building/ward/room/bed tree — where resources sit and where care happens. You work with it when you place an encounter somewhere, scope organization access to part of a facility, or model a site's physical layout.

Source:

Nodes nest without limit: every node may have a parent and children, so one tree can run from a campus down to a single bed. Encounters and organizations attach to nodes, and access granted at a node cascades to its descendants asynchronously rather than resolving on each request. The model maps to the [https://build.fhir.org/location.html FHIR Location] resource.

The Django model is only the storage layer. location_type, metadata, and cached_parent_json are opaque JSONFields; their real shape lives in the Pydantic resource specs (care/emr/resources/location/spec.py), which also define every enum and the read/write schema split. See Resource specs (API schema).

Models

Model Purpose
FacilityLocation A node in a facility's location tree (building, ward, room, bed, …)
FacilityLocationOrganization Grants a FacilityOrganization access to a location
FacilityLocationEncounter Records how/when an encounter occupied a location (e.g. a bed)

All three extend EMRBaseModel, which supplies external_id, audit fields, and soft-delete semantics.

FacilityLocation fields

Descriptive

Field Type Spec values / shape Notes
name CharField(255) str, required
description CharField(255) str, required
status CharField(255) StatusChoices enum
operational_status CharField(255) FacilityLocationOperationalStatusChoices enum
system_availability_status CharField(255) str (read-only)
mode CharField(255) FacilityLocationModeChoices enum
location_type JSONField (default=dict, nullable) Coding
form CharField(255) FacilityLocationFormChoices enum

Hierarchy & tree caches

These fields denormalize the tree so descendants are queryable without recursive joins. save() and the cascade task own them; never set them from a client.

Field Type Notes
parent FK → FacilityLocation SET_NULL, nullable. Immediate parent. Accepted on write as a UUID (parent); on read it's dropped in favour of the serialized parent JSON
root_location FK → self CASCADE, related_name="root", nullable. Top of this node's tree. Excluded from specs
has_children BooleanField default=False. Set True on the parent when a child is created. Read-only in list/retrieve specs
level_cache IntegerField default=0. Depth in the tree (parent.level_cache + 1)
parent_cache ArrayField[int] Ordered ancestor IDs (parent.parent_cache + [parent.id])
cached_parent_json JSONField (default=dict) Serialized parent chain (FacilityLocationListSpec) plus a cache_expiry ISO timestamp. Rebuilt lazily by get_parent_json(), invalidated by the cascade task. cache_expiry_days = 15
sort_index IntegerField default=0. In specs int

Access & encounter

Field Type Notes
facility FK → facility.Facility PROTECT. Owning facility. Excluded from specs — resolved from route/context
facility_organization_cache ArrayField[int] default=list. Org IDs that can reach this location; rebuilt by sync_organization_cache()
current_encounter FK → Encounter SET_NULL, nullable, default=None. Populated from FacilityLocationEncounter. Excluded from the base spec; surfaced as serialized JSON in list/retrieve specs
metadata JSONField default=dict. Open extension bag for deployment-specific data

Enum values

Every enum is a str Enum in care/emr/resources/location/spec.py. Values below are character-for-character from source.

StatusChoices values

Value Meaning
active Location is active
inactive Location is inactive
unknown Status unknown

FacilityLocationOperationalStatusChoices values

FHIR HL7 v2 bed/location operational status codes.

Code Meaning
C Closed
H Housekeeping
O Occupied
U Unoccupied
K Contaminated
I Isolated

FacilityLocationModeChoices values

Value Meaning
instance A single, concrete location (e.g. Bed 1). Instances cannot have children
kind A class/type of location (e.g. a ward or building)

FacilityLocationFormChoices values

FHIR location-physical-type codes.

Code Meaning
si Site
bu Building
wi Wing
wa Ward
lvl Level
co Corridor
ro Room
bd Bed
ve Vehicle
ho House
ca Cabinet
rd Road
area Area
jdn Jurisdiction
vi Virtual

LocationEncounterAvailabilityStatusChoices values

Used by FacilityLocationEncounter.status — how an encounter occupies a location.

Value Meaning
planned Occupancy planned
active Currently occupied
reserved Reserved
completed Occupancy ended

LocationAvailabilityStatusChoices values

The server-derived values that system_availability_status resolves to.

Value Meaning
available Not actively tied to an encounter
reserved Tied to an encounter

Coding shape

location_type is a single Coding object (extra="forbid"):

Coding {
  system:  str | None = None
  version: str | None = None
  code:    str            # required
  display: str | None = None
}

FacilityLocationOrganization

Links an organization to a location. Users under that organization inherit access to the location and its encounters through whatever role they hold on the organization.

location     → FK FacilityLocation (CASCADE)
organization → FK FacilityOrganization (CASCADE)

Saving one of these rows calls location.save() (rebuilding facility_organization_cache), then location.cascade_changes() to propagate the grant down to descendants asynchronously. On write, the organization set comes from FacilityLocationWriteSpec.organizations, a list of UUIDs.

FacilityLocationEncounter

A bed assignment, in effect: it records how an encounter occupied a location over a time window.

Field Type Spec Notes
status CharField(25) LocationEncounterAvailabilityStatusChoices
location FK → FacilityLocation excluded / nested
encounter FK → Encounter UUID on write, JSON on read
start_datetime DateTimeField datetime (required)
end_datetime DateTimeField (nullable) datetime

FacilityLocation.current_encounter is populated from these rows.

Methods & save behaviour

save() side effects

On insert (no id yet):

  1. If parent is set, level_cache, root_location, and parent_cache are derived from the parent, and the parent's has_children is flipped to True if needed.
  2. If sort_index is unset, it's assigned max(sibling sort_index) + 1.

On update, cached_parent_json is cleared so it rebuilds lazily. After every super().save(), sync_organization_cache() runs and persists facility_organization_cache through a second save(update_fields=[...]), so each write touches the row twice.

Caches & cascade

  • sync_organization_cache() — unions the parent's org cache, the org chains of every linked FacilityLocationOrganization, and the facility's default_internal_organization_id, then writes facility_organization_cache.
  • get_parent_json() — returns the cached parent chain, refreshing cached_parent_json (via FacilityLocationListSpec.serialize(parent)) once it expires (cache_expiry_days = 15).
  • cascade_changes() / handle_cascade(base_location) — a Celery task that walks every descendant and re-saves it to invalidate each node's cached_parent_json. It fires when a location's organizations change, so propagation is eventually consistent, not immediate.

validate_uniqueness()

Classmethod that enforces name uniqueness among siblings at the same level_cache within the same root_location — or among root-level locations when there's no root. For a new instance with a parent, level_cache and root_location are computed from that parent before the check runs.

Resource specs (API schema)

The Pydantic specs in care/emr/resources/location/spec.py define the request/response shapes. All extend EMRResource, which provides serialize/de_serialize plus the perform_extra_serialization/perform_extra_deserialization hooks (see base model and [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/base.py base.py]).

Location specs

Spec class Role Exposes / notes
FacilityLocationBaseSpec shared base None. __exclude__ = [parent, facility, organizations, root_location, current_encounter]
FacilityLocationSpec shared fields None), form, sort_index (0..10000, default 0)
FacilityLocationWriteSpec write · create None, organizations: list[UUID4] (required), mode: FacilityLocationModeChoices. Validator: a set parent must exist and must not be mode = instance ("Instances cannot have children"). perform_extra_deserialization resolves the parent UUID to an FK
FacilityLocationUpdateSpec write · update Same fields as FacilityLocationSpec. Drops parent/organizations/mode — hierarchy and mode are fixed after creation
FacilityLocationMinimalListSpec read · minimal Adds parent: dict, mode: str, has_children: bool, system_availability_status: str. perform_extra_serialization sets id = external_id and parent = obj.get_parent_json()
FacilityLocationListSpec read · list None, serialized via EncounterListSpec when present
FacilityLocationRetrieveSpec read · detail Extends list; adds created_by/updated_by (via serialize_audit_users)

Encounter-association specs

Spec class Role Exposes / notes
FacilityLocationEncounterBaseSpec shared base None. __exclude__ = [encounter, location]
FacilityLocationEncounterCreateSpec write · create None. Validator: encounter must exist. perform_extra_deserialization resolves the encounter UUID to an FK
FacilityLocationEncounterUpdateSpec write · update status, start_datetime, end_datetime. Encounter is not re-assignable
FacilityLocationEncounterListSpec read · list encounter: UUID4, start_datetime, end_datetime, status: str; id = external_id
FacilityLocationEncounterListSpecWithLocation read · list Extends list; adds location: dict (serialized via FacilityLocationListSpec)
FacilityLocationEncounterReadSpec read · detail encounter: dict (serialized via EncounterRetrieveSpec), start_datetime, end_datetime, status, created_by/updated_by

Server-maintained behaviour

  • These are platform-maintained — don't write them from a client: system_availability_status, has_children, level_cache, parent_cache, cached_parent_json, facility_organization_cache, current_encounter, and sort_index (when left unset).
  • On read, parent comes back as the serialized parent chain (get_parent_json()), never the raw FK.
  • Access granted through organizations / FacilityLocationOrganization lands asynchronously; the org cache and descendant caches settle only after the cascade task runs.
  • location_type takes a free Coding (no value-set slug) and metadata is an open bag, so both add coded or extension data without a schema migration.

API integration notes

  • The API is modelled on the FHIR Location resource, so payload field names may differ from these Django names.
  • mode separates kind (a location type) from instance (a concrete location such as a bed). Beds are FacilityLocation instances, not a separate model, and instance locations cannot have children.
  • parent, organizations, and mode are settable only at creation (FacilityLocationWriteSpec). Updates go through FacilityLocationUpdateSpec, which omits all three.
  • For fields you can't write, see Server-maintained behaviour.

Pages that link here: