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

References/Meta Artifact: Difference between revisions

From OHC Network Wiki
Content deleted Content added
OHC identity seed
 
Add Navbox platform (via update-page on MediaWiki MCP Server)
 
Line 209: Line 209:
* After creation, <code>associating_type</code>, <code>associating_id</code>, <code>object_type</code>, and <code>name</code> are fixed. Only <code>object_value</code> and <code>note</code> can change, via <code>MetaArtifactUpdateSpec</code>.
* After creation, <code>associating_type</code>, <code>associating_id</code>, <code>object_type</code>, and <code>name</code> are fixed. Only <code>object_value</code> and <code>note</code> can change, via <code>MetaArtifactUpdateSpec</code>.
* <code>EMRBaseModel</code> maintains the audit fields (<code>created_by</code>, <code>updated_by</code>, <code>created_date</code>, <code>modified_date</code>), the public <code>external_id</code> (exposed as <code>id</code>), and soft-delete (<code>deleted</code>). Don't set them from clients.
* <code>EMRBaseModel</code> maintains the audit fields (<code>created_by</code>, <code>updated_by</code>, <code>created_date</code>, <code>modified_date</code>), the public <code>external_id</code> (exposed as <code>id</code>), and soft-delete (<code>deleted</code>). Don't set them from clients.

{{Navbox platform}}


{{Related}}
{{Related}}

Latest revision as of 09:53, 6 July 2026

referenceplatformCARE 3.0+

A MetaArtifact attaches a freeform metadata payload to any Care object without a dedicated foreign key. You reach for it when a feature needs to hang structured data — a drawing on a patient, say — off an existing record without adding a column or a join table.

Storage and schema split across two layers. The Django model stays loose: object_value is an opaque JSONField, and associating_type / object_type are bare CharFields. The Pydantic resource specs constrain those values to known enums and define the request/response shapes the API accepts.

Source:

Models

Model Purpose
MetaArtifact Generic, polymorphic metadata record attached to any Care object by type + external ID

MetaArtifact extends EMRBaseModel, the shared Care EMR base that provides external_id, the audit fields created_by / updated_by and created_date / modified_date, and the soft-delete flag deleted.

MetaArtifact fields

Association

There is no Django ForeignKey to a parent. A MetaArtifact points at its target by storing the target's type and external_id instead.

Field Type Notes

{{Field|model=MetaArtifact|section=Association|name=associating_type|type=CharField(255)|notes=Non-null. The kind of object this artifact hangs off. API-constrained to [[#metaartifactassociatingtypechoices-values}} {{Field|model=MetaArtifact|section=Association|name=associating_external_id|type=UUIDField|notes=Non-null. The parent's external_id. Set server-side from the spec's associating_id (see [[#resource-specs-api-schema}}

A composite database index covers these two fields (see Methods & save behaviour), so looking up every artifact for a given parent stays cheap.

Content

Field Type Notes
name CharField(255) Spec rejects blank/whitespace-only on create

{{Field|model=MetaArtifact|section=Content|name=object_type|type=CharField(255)|notes=Names the shape held in object_value. API-constrained to [[#metaartifactobjecttypechoices-values}}

object_value JSONField The payload. Spec types it as dict
note TextField Nullable. Spec: str

Enum values

Two str enums constrain associating_type and object_type at the API layer. Both live in spec.py — this resource has no separate constants.py or valueset.py.

MetaArtifactAssociatingTypeChoices values

Binds associating_type.

Value
patient
encounter

MetaArtifactObjectTypeChoices values

Binds object_type.

Value
drawing

Resource specs (API schema)

All specs extend EMRResource ([https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/base.py care/emr/resources/base.py]), which provides serialize (model → pydantic) and de_serialize (pydantic → model) along with the perform_extra_serialization / perform_extra_deserialization hooks. __model__ = MetaArtifact.

Spec Role Fields exposed
MetaArtifactBaseSpec shared None), object_value (dict | list), note (str | None)
MetaArtifactCreateSpec write · create base + associating_type, associating_id (UUID4), object_type, name
MetaArtifactUpdateSpec write · update identical to MetaArtifactBaseSpec (only object_value / note are mutable; association and type are fixed after create)
MetaArtifactReadSpec read · detail/list None), updated_by (dict | None)

Field-level details and validation:

Field Spec type Required Default Validation / behaviour
id None optional None Read-only; populated from obj.external_id in perform_extra_serialization
object_value list yes Arbitrary JSON object or array
note None no None Free text
associating_type MetaArtifactAssociatingTypeChoices yes (create) patient or encounter
associating_id UUID4 yes (create) Parent's external_id; copied to model field associating_external_id in perform_extra_deserialization
object_type MetaArtifactObjectTypeChoices yes (create) drawing
name str yes (create) validate_name rejects blank/whitespace-only with "Name cannot be empty"
created_date datetime read From EMRBaseModel
modified_date datetime read From EMRBaseModel
created_by / updated_by None read None Serialized via serialize_audit_users (cached UserSpec)

Server-maintained behaviour:

  • Create (MetaArtifactCreateSpec.perform_extra_deserialization): sets obj.associating_external_id = self.associating_id. Clients send the parent's external_id as associating_id; the model stores it under associating_external_id.
  • Read (MetaArtifactReadSpec.perform_extra_serialization): sets mapping["id"] = obj.external_id and calls serialize_audit_users to attach created_by / updated_by.
  • Update: MetaArtifactUpdateSpec exposes only object_value and note (plus the inherited optional id). It never re-accepts associating_type, associating_id, object_type, or name, so association and classification are immutable once the record exists.

No field on this resource binds to a value set (there is no valueset.py); the only constrained vocabularies are the two str enums above.

Methods & save behaviour

MetaArtifact adds no custom methods and overrides neither save() nor delete(). Audit and soft-delete behaviour come entirely from EMRBaseModel.

Its Meta declares one composite index to back parent-object lookups:

Index(fields=["associating_type", "associating_external_id"])

API integration notes

  • Reference the target by its external_id (UUID), never its internal primary key, and pass it as associating_id on create. The associating_type + associating_external_id pair lets one table hold metadata for many Care object types without per-type foreign keys.
  • Add a new association or artifact kind by extending the str enums in spec.py — no schema migration, since the underlying CharFields are already open.
  • object_value accepts any dict | list, so payloads carry feature-specific structure without migrations; object_type records which shape to expect (e.g. drawing).
  • After creation, associating_type, associating_id, object_type, and name are fixed. Only object_value and note can change, via MetaArtifactUpdateSpec.
  • EMRBaseModel maintains the audit fields (created_by, updated_by, created_date, modified_date), the public external_id (exposed as id), and soft-delete (deleted). Don't set them from clients.