References/Location: Difference between revisions
More languages
More actions
OHC identity seed |
Automated edit (via update-page on MediaWiki MCP Server) |
||
| Line 395: | Line 395: | ||
* <code>parent</code>, <code>organizations</code>, and <code>mode</code> are settable only at creation (<code>FacilityLocationWriteSpec</code>). Updates go through <code>FacilityLocationUpdateSpec</code>, which omits all three. |
* <code>parent</code>, <code>organizations</code>, and <code>mode</code> are settable only at creation (<code>FacilityLocationWriteSpec</code>). Updates go through <code>FacilityLocationUpdateSpec</code>, which omits all three. |
||
* For fields you can't write, see [[#server-maintained-behaviour|Server-maintained behaviour]]. |
* For fields you can't write, see [[#server-maintained-behaviour|Server-maintained behaviour]]. |
||
{{Navbox facility}} |
|||
{{Related}} |
{{Related}} |
||
Wiki: ohcnwiki.tellmey.fyi |
|||
Latest revision as of 09:35, 6 July 2026
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:
- Model: [https://github.com/ohcnetwork/care/blob/develop/care/emr/models/location.py
care/emr/models/location.py] - Resource spec: [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/location/spec.py
care/emr/resources/location/spec.py] - Base resource: [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/base.py
care/emr/resources/base.py] - Coding type: [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/common/coding.py
care/emr/resources/common/coding.py]
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
}
Related models
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):
- If
parentis set,level_cache,root_location, andparent_cacheare derived from the parent, and the parent'shas_childrenis flipped toTrueif needed. - If
sort_indexis unset, it's assignedmax(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 linkedFacilityLocationOrganization, and the facility'sdefault_internal_organization_id, then writesfacility_organization_cache.get_parent_json()— returns the cached parent chain, refreshingcached_parent_json(viaFacilityLocationListSpec.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'scached_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, andsort_index(when left unset). - On read,
parentcomes back as the serialized parent chain (get_parent_json()), never the raw FK. - Access granted through
organizations/FacilityLocationOrganizationlands asynchronously; the org cache and descendant caches settle only after the cascade task runs. location_typetakes a freeCoding(no value-set slug) andmetadatais an open bag, so both add coded or extension data without a schema migration.
API integration notes
- The API is modelled on the FHIR
Locationresource, so payload field names may differ from these Django names. modeseparateskind(a location type) frominstance(a concrete location such as a bed). Beds areFacilityLocationinstances, not a separate model, andinstancelocations cannot have children.parent,organizations, andmodeare settable only at creation (FacilityLocationWriteSpec). Updates go throughFacilityLocationUpdateSpec, which omits all three.- For fields you can't write, see Server-maintained behaviour.
Related
Pages that link here:
- Reference: References/Base models & conventions
Wiki: ohcnwiki.tellmey.fyi