← Knowledge library

Billing

Charge Item

A ChargeItem is a single billable line for a service or product supplied to a patient — what was charged, the quantity, the unit and total price components, and any discounts or override reasons. You create one against a patient ; it always…

3.1 · versioned documentation · 10 min read

A ChargeItem is a single billable line for a service or product supplied to a patient — what was charged, the quantity, the unit and total price components, and any discounts or override reasons. You create one against a patient (and optionally an encounter); it always settles onto an Account.

Source:

The Django model is only the storage layer. Several fields are opaque JSONFields whose structure lives in the Pydantic resource specs under care/emr/resources/charge_item/, which also define the enums, validation, read/write API schemas, server-side cost calculation, and status side effects. The field tables below tell you what's stored; the spec and behaviour sections tell you what happens on write.

Models

Model Purpose
ChargeItem A single billable line item for a service or product rendered to a patient

ChargeItem extends EMRBaseModel (shared MANSOQ EMR base with external_id, audit fields — created_by/updated_by/created_date/modified_date — and soft-delete semantics — see Base model).

ChargeItem fields

Context & relationships

Field Type Notes
facility FK → facility.Facility (PROTECT) Set server-side from the URL; a body value is ignored
patient FK → emr.Patient (CASCADE) When you supply an encounter, the patient is taken from it rather than the request
encounter FK → emr.Encounter (CASCADE) Nullable; the encounter the charge relates to
charge_item_definition FK → emr.ChargeItemDefinition (CASCADE) Nullable; the template the charge was applied from. Not writable via create/update — set only by apply_charge_item_defs
account FK → emr.Account (CASCADE) The account this charge lands on. Falls back to the patient's default account when omitted

Description & status

Field Type Notes
title CharField(255) Required; display title for the charge
description TextField Nullable; longer description
status CharField(255) Required; lifecycle status, constrained to ChargeItemStatusOptions — see Status values
code JSONField Nullable; a Coding that identifies the charge (e.g. a billing code), shape Coding { system?, version?, code, display? } — see Coding shape. No bound value set
note TextField Nullable; free-text (markdown) comments

Pricing

Field Type Notes
quantity DecimalField(20, 6) Required on write; the quantity serviced. Multiplies the base/per-unit components during cost sync
unit_price_components JSONField Required on write; list of MonetaryComponent — see MonetaryComponent shape. At most one base component; duplicate component codes are rejected
total_price_components JSONField Nullable; server-computed list of MonetaryComponent (as dicts) — the resolved breakdown after base × quantity, surcharges, discounts, and taxes. Not client-writable
total_price DecimalField(20, 6) Nullable; server-computed total. Must be ≥ 0 unless the charge is a reversal
override_reason JSONField Nullable; ChargeItemOverrideReason { text: str, code?: Coding } explaining a list-price/factor override. No bound value set
discount_configuration JSONField Nullable (default None); DiscountConfiguration { max_applicable: int (≥0), applicability_order: total_asc | total_desc }. Populated from the definition/facility config when applied from a definition

Service source

These fields trace the charge back to the resource that produced it.

Field Type Notes
service_resource CharField(255) Nullable (default None); resource type, constrained to ChargeItemResourceOptions — see Service resource types
service_resource_id CharField(255) Nullable (default None); external id of the originating resource. Required once service_resource is set
performer_actor FK → users.User (CASCADE) Nullable (default None); the user who performed the service. Must belong to the facility's organization

Invoicing & tags

Field Type Notes
paid_invoice FK → emr.Invoice (CASCADE) Nullable (default None); denormalized link to the settling invoice. Platform-maintained; cleared on cancel
paid_on DateTimeField Nullable (default None); when the charge was paid. Platform-maintained; cleared on cancel
tags ArrayField[int] Tag IDs, default []. Managed through the tag mixin (SingleFacilityTagManager), serialized as objects on read

Enums

Status values

status is a plain CharField in storage, but every write passes through ChargeItemStatusOptions (care/emr/resources/charge_item/spec.py):

Value Meaning
billable Ready to be invoiced
not_billable Will not be billed
aborted Charge was cancelled before billing
billed Included on an invoice
paid Settled (links to paid_invoice / paid_on)
entered_in_error Recorded in error

(planned exists in the source as a commented-out option and is not currently selectable.)

not_billable, aborted, and entered_in_error form the cancelled set (CHARGE_ITEM_CANCELLED_STATUS). Moving into this set on update triggers the cancel side effect (see Methods & save behaviour). billed and paid cannot be set by hand — the viewset rejects manual transitions into them.

Service resource types

service_resource is constrained by ChargeItemResourceOptions:

Value
service_request
medication_dispense
appointment
bed_association

On create, the viewset validates the referenced resource: service_request must exist (and not be completed) for the patient/encounter, and bed_association must reference a FacilityLocationEncounter on a non-completed encounter in the facility.

MonetaryComponentType values

Used by every entry in unit_price_components / total_price_components (care/emr/resources/common/monetary_component.py):

Value Role in cost sync
base Per-unit base price. Exactly one allowed; must carry amount (not factor); no conditions. base.amount × quantity seeds the running total
surcharge Added on top of base; amount or factor (% of base)
discount Subtracted from the net price; amount or factor (% of net). Filtered/limited by discount_configuration
tax Added on the post-discount taxable price; amount or factor (% of taxable)
informational Carried through without affecting the computed total

DiscountApplicability values

discount_configuration.applicability_order (care/emr/resources/common/monetary_component.py):

Value Effect
total_asc Sort candidate discounts by amount ascending before applying max_applicable
total_desc Sort by amount descending before applying max_applicable

max_applicable = 0 drops all discounts.

JSON field shapes

Coding shape

code, plus the code field inside components and override_reason (care/emr/resources/common/coding.py, extra="forbid"):

Coding {
  system?:  str
  version?: str
  code:     str        # required
  display?: str
}

MonetaryComponent shape

Each entry of unit_price_components and total_price_components (care/emr/resources/common/monetary_component.py):

MonetaryComponent {
  monetary_component_type: base | surcharge | discount | tax | informational   # required
  code?:                Coding
  factor?:              Decimal(20,6)      # percentage; mutually exclusive with amount
  amount?:              Decimal(20,6)      # absolute; mutually exclusive with factor
  tax_included_amount?: Decimal(20,6)      # base component only
  global_component:     bool = False       # resolved against facility monetary config
  conditions:           [EvaluatorConditionSpec] = []   # not allowed on base
}

Validation: exactly one of amount/factor (unless global_component with a code); base must have amount, no factor, no conditions; tax_included_amount only on base; duplicate component codes are rejected.

EvaluatorConditionSpec { metric: str, operation: str, value: dict | str } — conditions are evaluated against patient/facility/encounter context when a definition is applied; a component whose conditions fail is dropped.

ChargeItemOverrideReason shape

override_reason (care/emr/resources/charge_item/spec.py):

ChargeItemOverrideReason {
  text: str            # required
  code?: Coding        # no bound value set
}

DiscountConfiguration shape

discount_configuration (care/emr/resources/common/monetary_component.py):

DiscountConfiguration {
  max_applicable:      int (>= 0)               # 0 drops all discounts
  applicability_order: total_asc | total_desc
}

Resource specs (API schema)

Charge items are exposed through ChargeItemViewSet (create / retrieve / update / upsert / list / tag actions, plus the apply_charge_item_defs and change_account custom actions). The Pydantic specs in care/emr/resources/charge_item/spec.py build on EMRResource (serialize / de_serialize, with perform_extra_serialization / perform_extra_deserialization hooks).

Spec Role Notes
ChargeItemSpec shared base __model__ = ChargeItem, __exclude__ = ["encounter", "account"]. Fields: id, title, description, status, code, quantity, unit_price_components, note, override_reason. Validators: no duplicate component codes, ≤1 base component
ChargeItemWriteSpec write · create Extends base with encounter, patient, account, service_resource, service_resource_id, performer_actor (all UUID4/enum, optional). Requires encounter or patient; requires service_resource_id when service_resource set
ChargeItemUpdateSpec write · update Base fields + performer_actor. Does not re-bind patient/encounter/account
ChargeItemReadSpec read · list & detail Base fields + server-side: total_price_components, total_price, charge_item_definition (nested), paid_invoice (nested), tags (objects), service_resource(_id), created_date, modified_date, paid_on, performer_actor, created_by, updated_by, discount_configuration

Notable validation and binding:

Nested / related specs

Spec Used by Shape
Coding code, component & override codes see Coding shape
MonetaryComponent unit_price_components, total_price_components see MonetaryComponent shape
ChargeItemOverrideReason override_reason { text, code? }
DiscountConfiguration discount_configuration { max_applicable, applicability_order }
ChargeItemDefinitionReadSpec charge_item_definition (read) full nested definition — see Charge Item Definition
InvoiceReadSpec paid_invoice (read) full nested invoice — see Invoice
UserSpec performer_actor, audit users (read) see User

Related models

ChargeItem is a leaf model — it holds foreign keys rather than owning child rows:

facility               → FK facility.Facility (PROTECT)
patient                → FK emr.Patient (CASCADE)
encounter              → FK emr.Encounter (CASCADE, nullable)
charge_item_definition → FK emr.ChargeItemDefinition (CASCADE, nullable)
account                → FK emr.Account (CASCADE)
paid_invoice           → FK emr.Invoice (CASCADE, nullable)
performer_actor        → FK users.User (CASCADE, nullable)

Methods & save behaviour

Cost resolution and status side effects live in the spec helpers and the viewset, not in the model's save().

API integration notes

Related

Source evidence

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