Skip to main content
Version: 3.1

Supplier

Technical reference for the supplier organization in Care EMR. A supplier is not a separate Django model. Care stores it as an Organization row with org_type = "product_supplier". See the concept Supplier.

Source: care/emr/models/organization.py · resources/organization/spec.py · api/viewsets/organization.py · resources/inventory/supply_request/request_order.py · resources/inventory/supply_delivery/delivery_order.py

The storage layer is the Organization table. The product_supplier value of org_type is what makes a row a supplier, and the resource specs of the supply chain enforce that value. Read Organization for the full field list, the tree caches, and the save behaviour.

Models

ModelPurpose
OrganizationInstance-wide organization. A row with org_type = "product_supplier" is a supplier
OrganizationUserMembership row linking a User to an Organization with a RoleModel

Organization extends OrganizationCommonBase, which extends EMRBaseModel.

Discriminating field

FieldTypeRequiredValueNotes
org_typeCharField(255)yesproduct_supplierFree text in the database. Writes bind to OrganizationTypeChoices in resources/organization/spec.py

OrganizationTypeChoices values

ValueMeaning
teamWorking grouping of people
govtGovernance or governmental unit
roleUser group, flat and managed by superadmins
product_supplierSupplier of products for the supply chain

The frontend enum OrgType in src/types/organization/organization.ts adds an other member that the backend enum does not define.

Fields used for a supplier

A supplier uses the common organization columns. The columns below are the ones the supplier screens write.

FieldTypeRequiredDefaultNotes
nameCharField(255)yesFeeds validate_uniqueness. Names must be unique among siblings under the same root
descriptionTextFieldnonullThe specs default it to ""
org_typeCharField(255)yesproduct_supplier
parentFK → selfnonullThe supplier screens create suppliers without a parent, so a supplier is a root organization
activeBooleanFieldnoTrue
metadataJSONFieldno{}Open key-value bag. The supplier form does not write it

Resource specs (API schema)

SpecRole
OrganizationWriteSpecwrite · create. Adds parent: UUID4 | None and validates that the parent exists
OrganizationUpdateSpecwrite · update. Same base fields, no parent
OrganizationReadSpecread · list. Adds level_cache, system_generated, has_children, and the nested parent JSON
OrganizationRetrieveSpecread · detail

All four extend OrganizationBaseSpec, which carries id, active, org_type, name, description, and metadata.

Authorization

OrganizationViewSet in care/emr/api/viewsets/organization.py gates every write.

ActionCheckPermission slug
createauthorize_createcan_create_organization_objcan_create_organization
updateauthorize_updatecan_manage_organization_objcan_manage_organization
destroyauthorize_destroycan_manage_organization_objcan_manage_organization
list, retrieveget_accessible_organizationscan_view_organization

Two behaviours are specific to the product_supplier type:

  • authorize_create and authorize_update block the govt and role types for a non-superuser, but not product_supplier. A user with organization create permission on the parent can therefore create a supplier. A root supplier still needs a superuser, because authorize_create rejects a create with no parent for every other user.
  • get_accessible_organizations in care/security/authorization/organization.py adds org_type__in=[govt, product_supplier] to the accessible queryset. Every authenticated user can therefore list every supplier, without a membership.

Permission definitions and their role lists are in care/security/permissions/organization.py.

Supply chain integration

Two order models hold a nullable foreign key to Organization.

RequestOrder.supplier → Organization (null=True, blank=True, CASCADE)
DeliveryOrder.supplier → Organization (null=True, blank=True, CASCADE)

The write specs enforce the type, in two different ways:

SpecFileEnforcement
SupplyRequestOrderWriteSpecresources/inventory/supply_request/request_order.pyFetches the organization by external_id, then raises ValidationError when org_type != "product_supplier"
SupplyDeliveryOrderWriteSpecresources/inventory/supply_delivery/delivery_order.pyFilters on external_id and org_type="product_supplier", so a wrong type returns 404

Both read specs serialize the supplier with OrganizationReadSpec.

API integration notes

  • Suppliers use the organization endpoints. Filter with org_type=product_supplier on GET /api/v1/organization/, and add name for a case-insensitive substring search.
  • The frontend lists suppliers with parent="" and limit=100, so it shows root suppliers only.
  • level_cache, parent_cache, root_org, has_children, and cached_parent_json are platform-maintained. Do not write them.
  • OTP-authenticated patient sessions cannot read suppliers. get_queryset limits that mode to the govt type.