← Knowledge library

Inventory

Supply Delivery

A supply delivery records product moving into a destination location — either from another location or from an external supplier. Deliveries and dispensing together drive facility stock: supply delivered − supply dispensed = current stock. Each…

3.1 · versioned documentation · 7 min read

A supply delivery records product moving into a destination location — either from another location or from an external supplier. Deliveries and dispensing together drive facility stock: supply delivered − supply dispensed = current stock. Each delivery belongs to a DeliveryOrder, the shipment grouping usually created from a supply request.

Source:

The Django model is a thin store: status, delivery_type, and supplied_item_condition are plain CharFields, and extensions is an opaque JSONField. Enum values, validation, and the read/write schema split live in the Pydantic resource specs below.

Models

Model Purpose
SupplyDelivery A single line of delivered product (quantity, condition, source product/inventory)
DeliveryOrder Groups deliveries for a shipment between an origin and destination

Both extend EMRBaseModel, which supplies external_id, the created_by/updated_by and created_date/modified_date audit fields, soft-delete via deleted, and history/meta JSON.

SupplyDelivery fields

Delivered item & quantity

Field Type Notes
supplied_item FK → Product (CASCADE) Nullable. The product delivered. Required at the API layer only when the order has no origin (external delivery); scoped to order.destination.facility on write
supplied_inventory_item FK → InventoryItem (CASCADE) Nullable. Specific inventory item (batch/lot) drawn from. Required at the API layer when the order has an origin (intra-facility move); scoped to order.origin.facility
supplied_item_quantity DecimalField(max_digits=20, decimal_places=6) Nullable in DB. On write a Decimal with decimal_places=0 (whole units); on read serialized as int. Auto-derived as pack_quantity × pack_size when both are given
supplied_item_pack_quantity IntegerField Nullable; default None. Number of packs delivered
supplied_item_pack_size IntegerField Nullable; default None. Units per pack
supplied_item_condition CharField(255) Optional. Condition of the delivered item — enum SupplyDeliveryConditionOptions (see below)

Status & classification

Field Type Notes
status CharField(255) Required. Lifecycle state — enum SupplyDeliveryStatusOptions (see below)
delivery_type CharField(255) Enum SupplyDeliveryTypeOptions (product / device). Stored on the model but not exposed on the current Create/Update specs, so it can't be set through the API

Links & pricing

Field Type Notes
supply_request FK → SupplyRequest (CASCADE) Nullable. Request this delivery fulfils. Set by external_id on write
order FK → DeliveryOrder (CASCADE) Nullable in DB, but required on create (referenced by external_id). Optional on update
total_purchase_price DecimalField(max_digits=20, decimal_places=6) Nullable. Total purchase cost. Spec: Decimal max_digits=20, decimal_places=6
extensions JSONField Default {}. Validated per registered extension handler for ExtensionResource.supply_delivery (see Resource specs)

SupplyDelivery enum values

These are str enums in spec.py — the stored value equals the member value (snake_case), not a FHIR URI.

SupplyDeliveryStatusOptions (status)

Value
in_progress
completed
abandoned
entered_in_error

SupplyDeliveryConditionOptions (supplied_item_condition)

Value
normal
damaged

SupplyDeliveryTypeOptions (delivery_type)

Value
product
device

Related models

DeliveryOrder

A DeliveryOrder is one logical shipment. It groups its SupplyDelivery rows and moves stock between two facility locations, or from an external supplier into a facility.

supplier        → FK Organization (CASCADE, nullable)      -- external/source supplier
origin          → FK FacilityLocation (CASCADE, nullable)  -- related_name="origin_delivery_orders"
destination     → FK FacilityLocation (CASCADE)            -- related_name="destination_delivery_orders"
patient         → FK Patient (PROTECT, nullable)           -- patient the order is dispensed to
patient_invoice → FK Invoice (PROTECT, nullable)           -- linked billing invoice
Field Type Notes
name CharField(255) Required. Human-readable order name
status CharField(255) Required. Order lifecycle — enum SupplyDeliveryOrderStatusOptions (see below)
note TextField Nullable. Free-text note
tags ArrayField[int] Default []. Tag IDs; rendered via SingleFacilityTagManager on read
supplier FK → Organization (CASCADE) Nullable. On write must be an Organization with org_type = product_supplier
origin FK → FacilityLocation (CASCADE) Nullable. Source location; absence means stock is entering from an external supplier
destination FK → FacilityLocation (CASCADE) Required. Receiving location
patient FK → Patient (PROTECT) Nullable. Patient the order is dispensed to. Cannot be set together with origin
patient_invoice FK → Invoice (PROTECT) Nullable. Linked billing invoice; serialized as patient_invoice_id on read
extensions JSONField Default {}. Validated for ExtensionResource.supply_delivery_order

patient and patient_invoice use PROTECT: a referenced patient or invoice can't be deleted while a delivery order points to it.

SupplyDeliveryOrderStatusOptions (status)

Value Notes
draft Allowed on create
pending Allowed on create
in_progress
completed Terminal (in SUPPLY_DELIVERY_ORDER_COMPLETED_STATUSES)
abandoned Terminal (in SUPPLY_DELIVERY_ORDER_COMPLETED_STATUSES)
entered_in_error Terminal (in SUPPLY_DELIVERY_ORDER_COMPLETED_STATUSES)

Resource specs (API schema)

Every spec extends EMRResource (base.py): serialize builds the read payload from the DB object (perform_extra_serialization hook), de_serialize builds the DB object from the request (perform_extra_deserialization hook), and to_json() dumps the model excluding meta.

SupplyDelivery specs

Spec Role Exposes / behaviour
BaseSupplyDeliverySpec shared id, status (required), supplied_item_condition?, total_purchase_price?. __exclude__ = ["supplied_item", "supply_request", "supplied_inventory_item"] (these are resolved by hooks, not direct field copy)
SupplyDeliveryWriteSpec write · create Adds supplied_item_pack_quantity?, supplied_item_pack_size?, supplied_item_quantity (Decimal, decimal_places=0), supplied_item?, supplied_inventory_item?, supply_request?, order (required), extensions. Mixes in ExtensionValidator
SupplyDeliveryUpdateSpec write · update order? only (plus shared base fields + extensions). Mixes in ExtensionValidator
SupplyDeliveryReadSpec read · list supplied_item_quantity: int, created_date, modified_date, supplied_item_pack_quantity?, supplied_item_pack_size?, extensions, and nested objects supplied_item, supplied_inventory_item, supply_request, order (serialized as dict). Mixes in ExtensionListRenderer
SupplyDeliveryRetrieveSpec read · detail Extends SupplyDeliveryReadSpec; adds created_by/updated_by (UserSpec). Mixes in ExtensionRetrieveRenderer

Write validation (SupplyDeliveryWriteSpec):

Update (SupplyDeliveryUpdateSpec): perform_extra_deserialization re-resolves order from external_id only when order is provided.

Read serialization: perform_extra_serialization sets id = external_id and inlines related objects via their read specs — supplied_item → ProductReadSpec, supplied_inventory_item → InventoryItemReadSpec, supply_request → SupplyRequestReadSpec, order → SupplyDeliveryOrderReadSpec.

DeliveryOrder specs

Spec Role Exposes / behaviour
BaseSupplyDeliveryOrderSpec shared id, status (required), name (required), note?. Mixes in ExtensionValidator
SupplyDeliveryOrderWriteSpec write · create/update Adds supplier?, origin?, destination (required), patient? (all by external_id)
SupplyDeliveryOrderReadSpec read · list Nested origin?, destination, supplier?, patient? (dict), tags, patient_invoice_id?, created_date, modified_date, created_by?, updated_by?. Mixes in ExtensionListRenderer
SupplyDeliveryOrderRetrieveSpec read · detail Extends SupplyDeliveryOrderReadSpec (no extra fields). Mixes in ExtensionRetrieveRenderer

Write validation (SupplyDeliveryOrderWriteSpec.perform_extra_deserialization):

Read serialization: id = external_id; inlines origin/destination via FacilityLocationListSpec, supplier via OrganizationReadSpec, patient via PatientListSpec; renders tags via SingleFacilityTagManager; exposes the linked invoice as patient_invoice_id (string); attaches audit users.

Extensions

extensions is not free-form JSON. On write, ExtensionValidator runs each registered handler for the resource type (supply_delivery / supply_delivery_order): unknown keys are dropped, and known keys are validated and re-serialized. On read, ExtensionListRenderer / ExtensionRetrieveRenderer render every registered extension for the resource (list vs retrieve variants).

API integration notes

Related

Source evidence

References are pinned to the private MANSOQ source repository. Repository access is required to open these links.