Skip to main content
Version: 3.1

Activity Definition

An ActivityDefinition is a FHIR-aligned, facility-scoped template for a clinical activity. It stores the defaults needed to spin up a downstream resource — currently a Service Request — and you "apply" it against an encounter, which merges those defaults with the encounter context to produce the live resource.

Source:

The Django model is just storage. Several fields are opaque JSONFields or integer ArrayFields whose real structure lives in the Pydantic resource specs — the API layer that defines the enums, JSON shapes, validation rules, and the split between read and write schemas. Neither layer is complete on its own; read them together.

Models​

ModelPurpose
ActivityDefinitionVersioned, facility-scoped template describing a clinical activity and the defaults used to create the resources it produces

ActivityDefinition extends SlugBaseModel, which adds a facility-scoped slug on top of EMRBaseModel. From EMRBaseModel it inherits external_id, created_date/modified_date, soft-delete via deleted, created_by/updated_by, and the history/meta JSON fields. See Base model.

ActivityDefinition fields​

Each field lists its storage type (Django model) and, where the spec constrains it, the API shape or values the Pydantic specs enforce.

Identity & versioning​

FieldStorage typeAPI shape / notes
facilityFK → facility.Facility (PROTECT)Owning facility. Spec-__exclude__d — set server-side and never accepted in the payload.
slugCharField(255)Facility-scoped identifier. On write you supply it as slug_value (SlugType); perform_extra_deserialization assigns it to obj.slug. On read it comes back as slug plus a parsed slug_config dict.
versionIntegerFieldDefault 1. Read-only in specs (version: int | None), serialized on list and retrieve. Drives the append-only version chain.
latestBooleanFieldDefault True. Marks the current version within a slug's chain. Server-maintained, not exposed in the specs.
derived_from_uriTextFieldNullable. URI this definition was derived from. Optional in specs (str | None = None).

Descriptive metadata​

FieldStorage typeAPI shape / notes
titleCharField(1024)Required (str). Human-friendly name.
statusCharField(255)Required enum — ActivityDefinitionStatusOptions (draft / active / retired / unknown).
classificationCharField(100)Required enum — ActivityDefinitionCategoryOptions (laboratory / imaging / counselling / surgical_procedure / education).
kindCharField(100)Required enum — ActivityDefinitionKindOptions (only service_request). Determines the resource produced on apply.
descriptionTextFieldOptional in specs; default "".
usageTextFieldOptional in specs; default "".

Coded clinical attributes (JSON)​

These are JSONFields. The spec binds each to a value set via ValueSetBoundCoding[<slug>], which validates the submitted code against that value set. Every coding is shaped { system?: str, version?: str, code: str (required), display?: str } with extra="forbid", so unknown keys are rejected.

FieldStorage typeAPI shape / notes
codeJSONField (nullable)Required Coding bound to value set activity-definition-procedure-code (SNOMED CT, concept is-a 71388002 "Procedure"). Nullable in the DB but rejected on write if absent.
body_siteJSONField (nullable)Optional Coding | None = None bound to value set system-body-site-observation (SNOMED CT body sites).
diagnostic_report_codesJSONField (nullable)list[Coding], default []. Each Coding bound to value set system-observation (LOINC).

Requirement & linkage arrays​

These store integer primary keys, not Django FK relations — ArrayField(IntegerField, default=list). The specs never expose those raw PKs: writes reference targets by external slug or UUID, and retrieves expand them back into serialized objects.

FieldStorage typeWrite shapeRead (retrieve) shape
specimen_requirementsArrayField[int]list[ExtendedSlugType]list[dict] — serialized Specimen Definitions (SpecimenDefinitionReadSpec)
observation_result_requirementsArrayField[int]list[ExtendedSlugType]list[dict] — serialized Observation Definitions (ObservationDefinitionReadSpec)
locationsArrayField[int]list[UUID4]list[dict] — serialized Locations (FacilityLocationListSpec)
charge_item_definitionsArrayField[int]list[ExtendedSlugType]list[dict] — serialized Charge Item Definitions (ChargeItemDefinitionReadSpec)
tagsArrayField[int]not written via speclist[dict] — rendered via SingleFacilityTagManager().render_tags(obj)

ExtendedSlugType: 7–88 chars, URL-safe, must start with f- or i-. SlugType (used for slug_value): 5–50 chars, URL-safe. The stored integer arrays carry no referential integrity — nothing stops you storing an ID whose target is later deleted, and retrieve serialization silently skips any ID that no longer resolves.

Service relationships​

FieldStorage typeAPI shape / notes
healthcare_serviceFK → emr.HealthcareService (PROTECT)Nullable; default None. Write: UUID4 | None, resolved by external_id in perform_extra_deserialization. Retrieve: serialized via HealthcareServiceReadSpec. See Healthcare Service.
categoryFK → emr.ResourceCategory (CASCADE)Nullable. Write: ExtendedSlugType | None, resolved by slug. Read: serialized via ResourceCategoryReadSpec. Deleting the Resource Category cascades to the definition.

Enum values​

ActivityDefinitionStatusOptions (status)​

Value
draft
active
retired
unknown

ActivityDefinitionKindOptions (kind)​

ValueNotes
service_requestOnly supported kind; applying the definition produces a Service Request

ActivityDefinitionCategoryOptions (classification)​

Value
laboratory
imaging
counselling
surgical_procedure
education

Bound value sets​

FieldValue set slugSource system / filter
codeactivity-definition-procedure-codeSNOMED CT, concept is-a 71388002 (Procedure)
body_sitesystem-body-site-observationSNOMED CT body-site concepts
diagnostic_report_codes[]system-observationLOINC (http://loinc.org)

Resource specs (API schema)​

All specs extend EMRResource (see Base model), which provides serialize (DB → Pydantic) and de_serialize (Pydantic → DB) plus the perform_extra_serialization / perform_extra_deserialization hooks. Here __model__ = ActivityDefinition and __exclude__ = ["facility"].

Spec classRoleNotes
BaseActivityDefinitionSpecshared baseid, title, derived_from_uri, status, description, usage, classification, kind, code, body_site, diagnostic_report_codes.
ActivityDefinitionWriteSpecwrite · create + updateAdds locations (list[UUID4]), specimen_requirements / observation_result_requirements / charge_item_definitions (list[ExtendedSlugType]), healthcare_service (UUID4 | None), category (ExtendedSlugType | None), slug_value (SlugType).
ActivityDefinitionReadSpecread · listBase fields plus version, tags, category (serialized dict), slug, slug_config.
ActivityDefinitionRetrieveSpecread · detailExtends ReadSpec; expands specimen_requirements, observation_result_requirements, locations, healthcare_service, charge_item_definitions from ID arrays into fully serialized nested objects.

Server-side behaviour​

  • ActivityDefinitionWriteSpec.perform_extra_deserialization (write path):
    • Resolves healthcare_service by external_id, or clears it to None when absent.
    • Resolves category by slug, only when provided.
    • Assigns obj.slug = self.slug_value.
  • ActivityDefinitionReadSpec.perform_extra_serialization (read path): sets id = external_id, renders tags, serializes category (when present) via ResourceCategoryReadSpec, and parses slug_config = obj.parse_slug(obj.slug).
  • ActivityDefinitionRetrieveSpec.perform_extra_serialization: calls the parent, then resolves each ID array (specimen_requirements, observation_result_requirements, locations, charge_item_definitions) against its model — dropping IDs that no longer exist — and serializes healthcare_service.
  • The base de_serialize writes only model-mapped fields with exclude_defaults=True, so any unset optional field falls back to its model default.

Methods & save behaviour​

  • Apply → Service Request (service_request.py): convert_ad_to_sr(activity_definition, encounter) builds a draft ServiceRequest. It carries over title, category, code, body_site, locations, and healthcare_service, and binds patient/encounter from the encounter. The new request starts at status=draft, intent=proposal, priority=routine, do_not_perform=False.
  • Charge items on apply: apply_ad_charge_definitions(activity_definition, encounter, service_request) loads every linked Charge Item Definition and, for each, instantiates a Charge Item (via apply_charge_item_definition), tags it to the service request (service_resource = service_request, service_resource_id = external_id), copies the creator, and sets performer_actor to the request's requester when one is set.
  • version and latest form an append-only chain per slug: query latest=True for the current definition; superseded versions stay readable so existing references don't break.

API integration notes​

  • Payload field names follow the Pydantic specs, not the Django model. Send slug as slug_value. Reference specimen_requirements, observation_result_requirements, charge_item_definitions, and category by external slug (ExtendedSlugType, f-/i- prefixed); reference locations and healthcare_service by UUID.
  • code is required and must validate against the activity-definition-procedure-code value set. body_site and each entry of diagnostic_report_codes validate against their bound value sets.
  • Apply instantiates the target kind (only service_request today) by merging stored defaults with the encounter, and instantiates any linked charge_item_definitions in the same pass.
  • The requirement and linkage fields are plain integer ID arrays. Retrieve serialization resolves them to nested objects and skips any ID that no longer resolves, so a response can omit a requirement you stored.