AllergyIntolerance records a patient's allergy or intolerance to a substance, scoped to the encounter where it was captured. Care aligns it to FHIR AllergyIntolerance. You touch this resource when recording a known allergy during an encounter or reading a patient's allergy list.
The Django model is the storage layer. Several of its fields are opaque JSONFields whose real structure lives only in the Pydantic resource specs, which also define the enums, validation, the bound value set, and the read/write API schemas.
Source:
Models
| Model | Purpose |
|---|
AllergyIntolerance | Records a patient's allergy or intolerance to a substance, scoped to an encounter |
AllergyIntolerance extends EMRBaseModel, the shared Care EMR base that provides external_id, created_date/modified_date, soft-delete via deleted, created_by/updated_by, and history/meta JSON.
AllergyIntolerance fields
Clinical classification
| Field | Type (storage) | Spec type / values | Notes |
|---|
clinical_status | CharField(100), null | ClinicalStatusChoices | Active / inactive / resolved (FHIR clinical-status). Required on write. |
verification_status | CharField(100), null | VerificationStatusChoices | Confirmation level. Required on write. |
category | CharField(100), null | CategoryChoices | Allergy category. Required on create only; not accepted on update. |
criticality | CharField(100), null | CriticalityChoices | Potential clinical harm. Required on write. |
allergy_intolerance_type | CharField(20), default "allergy" | AllergyIntoleranceTypeOptions | Allergy vs intolerance. Defaults to allergy. |
Substance & coding
| Field | Type (storage) | Spec type / shape | Notes |
|---|
code | JSONField (default=dict, not null/blank) | Coding bound to value set system-allergy-code | The allergen/substance. Required. On write it is a ValueSetBoundCoding validated against the bound value set; on read it is a plain Coding. |
Coding shape: { system?: str, version?: str, code: str (required), display?: str } (extra="forbid").
Timing
| Field | Type (storage) | Spec type / shape | Notes |
|---|
onset | JSONField (default=dict) | AllergyIntoleranceOnSetSpec | Defaults to {}; accepted on create only. When supplied, note is required. Shape below. |
recorded_date | DateTimeField, null | datetime | None | When first asserted. Optional; accepted on create only. |
last_occurrence | DateTimeField, null | datetime | None | Most recent known reaction. Optional on both create and update. |
AllergyIntoleranceOnSetSpec shape:
| Sub-field | Type | Required | Default |
|---|
onset_datetime | datetime | No | None |
onset_age | int | No | None |
onset_string | str | No | None |
note | str | Yes | — |
Context & notes
| Field | Type (storage) | Spec type | Notes |
|---|
patient | FK → Patient (CASCADE) | excluded from specs | Subject of the allergy. Derived server-side from the encounter on create; clients never set it. |
encounter | FK → Encounter (CASCADE) | UUID4 | Encounter the allergy was recorded in. Sent as external_id, required on write, validated to exist. |
note | TextField, null | str | None | Free-text clinical note. Optional. |
copied_from | BigIntegerField, null (default=None) | not exposed | Source record ID when this entry is a maintained copy. Platform-maintained; never accepted from clients. |
Enum values
ClinicalStatusChoices
| Value |
|---|
active |
inactive |
resolved |
VerificationStatusChoices
| Value |
|---|
unconfirmed |
presumed |
confirmed |
refuted |
entered_in_error |
CategoryChoices
| Value |
|---|
food |
medication |
environment |
biologic |
CriticalityChoices
| Value |
|---|
low |
high |
unable_to_assess |
AllergyIntoleranceTypeOptions
| Value |
|---|
allergy (default) |
intolerance |
Bound value set
| Value set | Slug | System | Status |
|---|
CARE_ALLERGY_CODE_VALUESET ("Allergy") | system-allergy-code | SNOMED CT (http://snomed.info/sct) | active |
On write, code binds to this value set via ValueSetBoundCoding[...slug], which validates the submitted Coding against the value set (validate_valueset). The compose admits SNOMED CT concepts that are is-a descendants of: 105590001, 418038007, 267425008, 29736007, 340519003, 190753003, 413427002, 716186003. The value set is also registered as a system (register_as_system()).
Resource specs (API schema)
Every spec extends EMRResource (care/emr/resources/base.py), which provides serialize (DB object → pydantic, via model_construct) and de_serialize (pydantic → DB object), plus the perform_extra_serialization / perform_extra_deserialization hooks. BaseAllergyIntoleranceSpec sets __model__ = AllergyIntolerance and __exclude__ = ["patient", "encounter"]; those two fields skip auto-mapping and are wired by the hooks instead. The base also carries meta on every spec.
| Spec class | Role | Fields exposed |
|---|
BaseAllergyIntoleranceSpec | shared base | id: UUID4 |
AllergyIntoleranceWriteSpec | write · create | clinical_status, verification_status, category, criticality, last_occurrence?, recorded_date?, encounter (UUID4), code (bound Coding), onset (default {}), allergy_intolerance_type (default allergy), note? |
AllergyIntoleranceUpdateSpec | write · update | clinical_status, verification_status, criticality, last_occurrence?, note?, encounter (UUID4), allergy_intolerance_type (default allergy) |
AllergyIntoleranceReadSpec | read · list & detail | id, clinical_status, verification_status, category, criticality, code (Coding), encounter (UUID4), onset, last_occurrence?, recorded_date?, note?, allergy_intolerance_type, created_by?, updated_by?, created_date, modified_date |
AllergyIntoleranceOnSetSpec | nested (shape of onset JSON) | onset_datetime?, onset_age?, onset_string?, note (required) |
category, code, onset, and recorded_date are accepted only on create (AllergyIntoleranceWriteSpec) and absent from AllergyIntoleranceUpdateSpec — once set, the update path cannot change them.
AllergyIntoleranceReadSpec types the coded fields as plain str and code as Coding, and skips value-set re-validation, relying on model_construct for speed.
Validation
encounter (both write specs): validate_encounter_exists rejects with "Encounter not found" when no Encounter has that external_id.
code (create): validated against value set system-allergy-code — must be a permitted SNOMED CT allergy concept.
onset.note is required whenever an onset object is supplied.
datetime fields are stored as-is. The base enforces tz-aware handling for period-style values through PeriodSpec (start ≤ end, both tz-aware), but AllergyIntolerance uses scalar datetimes rather than a PeriodSpec.
Server-side side effects
- Create (
AllergyIntoleranceWriteSpec.perform_extra_deserialization): resolves encounter by external_id, sets obj.encounter, then sets obj.patient = obj.encounter.patient. The client never sends patient directly.
- Update (
AllergyIntoleranceUpdateSpec.perform_extra_deserialization): when encounter is present, re-resolves it and sets obj.encounter.
- Read (
AllergyIntoleranceReadSpec.perform_extra_serialization): sets mapping["id"] = obj.external_id, sets encounter to obj.encounter.external_id, and serializes audit users (created_by / updated_by) via serialize_audit_users.
Methods & save behaviour
serialize / de_serialize are inherited from EMRResource. de_serialize maps only DB fields that are neither in __exclude__ nor id/external_id, then calls perform_extra_deserialization for the encounter/patient wiring above.
patient is always derived from the encounter on create; no client payload can set it.
copied_from is platform-maintained for propagated/copied records and belongs to no spec.
patient and encounter both CASCADE-delete, so an allergy record never outlives its patient or encounter.
API integration notes
- API field names follow the spec classes above.
encounter is sent and returned as a UUID external_id, not a numeric FK.
- Submit
code as a Coding drawn from the bound value set system-allergy-code, not free text, so allergies can be matched against medications and other business logic.
- The coded status fields (
clinical_status, verification_status, category, criticality) accept only the enum values listed above; anything else is rejected on write.
- Never send
patient or copied_from — both are server-maintained.