Skip to main content
Version: 3.1

Supply Request

A SupplyRequest is a single line item: a quantity of one catalogue item (ProductKnowledge) that someone wants moved. Requests never stand alone — each belongs to a RequestOrder that groups them and describes the movement into a destination facility location, optionally from a supplier organization and/or an origin location. You create requests when an order needs stock; you read them back as part of the order they hang off.

The Django model is only storage. status, priority, intent, reason, category, and supplied_item_condition are plain CharFields with no DB-level constraint, so the database will hold any string. The allowed values, validation, and request/response shapes live in the Pydantic resource specs under care/emr/resources/inventory/supply_request/, covered below.

Source:

Models

ModelPurpose
SupplyRequestA request for a quantity of a catalogue item (product knowledge), grouped under an order
RequestOrderAn order that groups supply requests for movement of items into a destination facility location

Both extend EMRBaseModel, the shared Care EMR base providing external_id, audit fields (created_date/modified_date/created_by/updated_by), soft-delete via deleted, and history/meta JSON.

SupplyRequest fields

FieldTypeNotes
statusCharField(255)Lifecycle status, spec-bound to SupplyRequestStatusOptions (see below). Required on write.
quantityDecimalFieldmax_digits=20, decimal_places=6, nullable in DB. The write spec accepts a Decimal capped to decimal_places=0 (whole numbers); the read spec returns it as an int.
supplied_item_conditionCharField(255)Model-only — no current spec reads or writes it, so it's unreachable through the API.
itemFK → ProductKnowledgeCASCADE. The catalogue item being requested. Required on create, resolved server-side from an external_id. Cannot be changed afterwards.
orderFK → RequestOrderCASCADE, nullable in DB but required by the spec on both create and update. Resolved server-side from an external_id.

SupplyRequestStatusOptions values

Defined in spec.py and bound to SupplyRequest.status.

Value
draft
active
suspended
cancelled
processed
completed
entered_in_error

RequestOrder

The order is the unit you actually work with. It collects one or more SupplyRequest rows and carries the routing: a required destination facility location, plus an optional supplier organization and origin location.

supplier → FK Organization (nullable, CASCADE)
origin → FK FacilityLocation (nullable, CASCADE, related_name="origin_request_orders")
destination → FK FacilityLocation (CASCADE, related_name="destination_request_orders")
FieldTypeNotes
nameCharField(255)Required.
statusCharField(255)Spec-bound to SupplyRequestOrderStatusOptions.
noteTextFieldOptional (str | None).
tagsArrayField[int]Default list; tag IDs, not a relational join. Expanded to tag objects on read via SingleFacilityTagManager.
priorityCharField(255)Spec-bound to SupplyRequestPriorityOptions.
intentCharField(255)Spec-bound to SupplyRequestIntentOptions.
reasonCharField(255)Spec-bound to SupplyRequestReason.
categoryCharField(255)Spec-bound to SupplyRequestCategoryOptions.
supplierFK → OrganizationNullable CASCADE. On write, must be an organization with org_type == "product_supplier" — the server rejects anything else.
originFK → FacilityLocationNullable CASCADE, related_name="origin_request_orders". The sending location.
destinationFK → FacilityLocationCASCADE, related_name="destination_request_orders". The receiving location. Required.

origin and destination both point at FacilityLocation but carry distinct related_names, so one location can list the orders it sends (origin_request_orders) separately from the orders it receives (destination_request_orders).

RequestOrder enum values

From request_order.py. Each binds to the matching RequestOrder CharField.

SupplyRequestOrderStatusOptions (→ status)

Value
draft
pending
in_progress
completed
abandoned
entered_in_error

SUPPLY_REQUEST_ORDER_COMPLETED_STATUSES = [abandoned, entered_in_error, completed] marks the terminal/closed statuses.

SupplyRequestIntentOptions (→ intent)

Value
proposal
plan
directive
order
original_order
reflex_order
filler_order
instance_order

SupplyRequestCategoryOptions (→ category)

Value
central
nonstock

SupplyRequestPriorityOptions (→ priority)

Value
routine
urgent
asap
stat

SupplyRequestReason (→ reason)

Value
patient_care
ward_stock

Resource specs (API schema)

Every spec extends EMRResource (serialize / de_serialize, with perform_extra_serialization / perform_extra_deserialization hooks). Write specs resolve foreign keys from external_id values in perform_extra_deserialization; read specs expand related objects in perform_extra_serialization.

Supply request specs (spec.py)

Spec classRoleFieldsNotes
BaseSupplyRequestSpecsharedid, status, quantity__model__ = SupplyRequest, __exclude__ = ["item"]. quantity: Decimal(max_digits=20, decimal_places=0). status: SupplyRequestStatusOptions.
SupplyRequestWriteSpecwrite · createbase + item: UUID4, order: UUID4Resolves itemProductKnowledge and orderRequestOrder by external_id; 404 if either is missing.
SupplyRequestUpdateSpecwrite · updatebase + order: UUID4Resolves orderRequestOrder by external_id. Omits item — the catalogue item is fixed once created.
SupplyRequestReadSpecread · detail/listbase + quantity: int, item: dict, order: dictid = external_id. item expanded via ProductKnowledgeReadSpec; order via SupplyRequestOrderReadSpec.

Request order specs (request_order.py)

Spec classRoleFieldsNotes
BaseSupplyRequestOrderSpecsharedid, status, name, note, intent, category, priority, reason__model__ = RequestOrder. Coded fields bound to their enums; note optional.
SupplyRequestOrderWriteSpecwrite · create/updatebase + supplier: UUID4 | None, origin: UUID4 | None, destination: UUID4Resolves supplier/origin/destination by external_id. Raises ValidationError unless supplier.org_type == "product_supplier".
SupplyRequestOrderReadSpecread · detail/listbase + supplier, origin: dict | None, destination: dict, tags: list[dict], created_date, modified_date, created_by, updated_byid = external_id. supplier expanded via OrganizationReadSpec; origin/destination via FacilityLocationListSpec; tags via SingleFacilityTagManager; audit users via serialize_audit_users.

Validation and server-maintained behaviour

  • FK resolution. Every foreign key on write comes in as an external_id UUID and is resolved server-side with get_object_or_404: item, order, supplier, origin, destination.
  • Supplier type guard. SupplyRequestOrderWriteSpec rejects any supplier whose org_type is not product_supplier.
  • id handling. Read specs set id to external_id; de_serialize never writes id or external_id back to the row.
  • quantity. Write accepts a Decimal pinned to decimal_places=0 (whole numbers) even though the DB column allows decimal_places=6; read returns an int.
  • item immutability. Create takes item; SupplyRequestUpdateSpec drops it, so the requested catalogue item can't change after creation.

Methods and save behaviour

  • Neither model overrides save(); standard EMRBaseModel audit and soft-delete behaviour applies.
  • Status is free-text at the DB layer — the lifecycle is enforced only by the spec enums at the API boundary. Neither model tracks status_history.
  • Deleting a RequestOrder cascades to its SupplyRequest rows (the order FK is CASCADE); deleting a referenced ProductKnowledge cascades to the request.

API integration notes

  • Payload field names match the spec fields above. Foreign keys go out as external_id UUIDs on write and come back as expanded objects on read.
  • Send status, priority, intent, reason, and category as the exact strings listed above — they're validated against the spec enums.
  • supplied_item_condition lives on the model but no current spec surfaces it.
  • quantity travels as a whole number through the specs; the DB column keeps six decimal places regardless.
  • tags on RequestOrder is an integer array of tag IDs, rendered to tag objects on read by the facility tag manager.
  • external_id (from EMRBaseModel) is the stable public identifier in API URLs — never the internal primary key.