← Knowledge library

Billing

Charge Item Definition

A charge item definition is a facility's pricing template for a billable resource: it answers "how much does resource X cost". It binds the resource to a set of price components — base rate, surcharges, discounts, and taxes — that get evaluated…

3.1 · versioned documentation · 7 min read

A charge item definition is a facility's pricing template for a billable resource: it answers "how much does resource X cost". It binds the resource to a set of price components — base rate, surcharges, discounts, and taxes — that get evaluated when a charge item is generated during data entry. You touch it when defining or revising the prices a facility charges.

The resource spans two layers. The Django model (care/emr/models/charge_item_definition.py) is storage: price_components and discount_configuration are opaque JSONFields with no structure of their own. The Pydantic specs (care/emr/resources/charge_item_definition/) are the API: they define the status enum, give those JSON fields a real shape via MonetaryComponent and DiscountConfiguration, enforce validation, and split the read and write schemas. See Resource specs (API schema).

Source:

Models

Model Purpose
ChargeItemDefinition Facility-scoped pricing template defining the price components applied to a billable resource

ChargeItemDefinition extends SlugBaseModel, the slug-aware MANSOQ EMR base, which itself extends EMRBaseModel. From that chain it inherits external_id, created_date/modified_date, soft-delete via deleted, created_by/updated_by, and the history/meta JSON fields, then adds facility-scoped slug helpers (see Methods & save behaviour).

ChargeItemDefinition fields

Identity & versioning

Field Type Required Notes
facility FK → facility.Facility yes PROTECT — the owning facility cannot be deleted while definitions reference it
version IntegerField — Default 1. Revision number; the spec surfaces it read-only
status CharField(255) yes Lifecycle status, constrained by ChargeItemDefinitionStatusOptions (draft, active, retired). See Status values
title CharField(255) yes Human-readable name
slug CharField(255) yes Stored slug. The client sends slug_value; the server prefixes it (see slug behaviour)
derived_from_uri TextField no Nullable, default None. URI of the upstream definition this was derived from

Descriptive

Field Type Required Notes
description TextField no Nullable, default None. Natural-language description
purpose TextField no Nullable, default None. Why the definition exists

Pricing & rules

Field Type Required Notes
price_components JSONField yes Default []. List of MonetaryComponent — see Price components shape
discount_configuration JSONField no Nullable, default None. Shaped as DiscountConfiguration — see Discount configuration shape
can_edit_charge_item BooleanField yes Default True. Whether a charge item generated from this definition stays editable after creation
category FK → emr.ResourceCategory no CASCADE, nullable. On write supplied as an ExtendedSlugType slug and resolved server-side
tags ArrayField[int] — Default []. Tag IDs on write; rendered to objects on read

Enum values

Status values

ChargeItemDefinitionStatusOptions (spec.py) constrains status. The model CharField is unconstrained at the DB level, so the spec is the source of truth.

Value Meaning
draft Not yet active; excluded from live billing
active In use; only these should drive new charge items
retired Withdrawn; excluded from live billing

Monetary component type values

MonetaryComponentType (common/monetary_component.py) sets the monetary_component_type of each price component.

Value Meaning
base The base rate. Exactly one allowed; must carry an amount; may not have conditions or a factor
surcharge An additive charge layered on the base
discount A reduction layered on the base
tax A tax component
informational Non-priced informational component

Discount applicability values

DiscountApplicability (common/monetary_component.py) sets discount_configuration.applicability_order.

Value Meaning
total_asc Apply discounts in ascending order of total
total_desc Apply discounts in descending order of total

JSON field shapes

Price components shape

price_components is a list[MonetaryComponent]. Each entry (common/monetary_component.py):

MonetaryComponent {
  monetary_component_type : MonetaryComponentType   # required; see enum above
  code                    : Coding | null           # billing code (system/version/code/display); code required if present
  factor                  : Decimal | null          # max_digits=20, decimal_places=6
  amount                  : Decimal | null          # max_digits=20, decimal_places=6
  tax_included_amount     : Decimal | null          # max_digits=20, decimal_places=6; base-only
  global_component        : bool                     # default false
  conditions              : list[EvaluatorConditionSpec]   # default []
}

Coding (common/coding.py, extra="forbid"): { system: str|null, version: str|null, code: str (required), display: str|null }.

EvaluatorConditionSpec (common/condition_evaluator.py): { metric: str, operation: str, value: dict|str }. metric is validated against EvaluatorMetricsRegistry, and that metric's evaluator validates operation and value.

Each MonetaryComponent is checked against these rules:

Rule Detail
tax_included_amount base-only Allowed only when monetary_component_type == base
base no conditions A base component must have no conditions
base requires amount A base component must have an amount
amount xor factor amount and factor cannot both be present
amount or factor required One of amount/factor must be present — except when global_component is true and a code is set

Discount configuration shape

discount_configuration is a DiscountConfiguration | null (common/monetary_component.py):

DiscountConfiguration {
  max_applicable      : int                     # required; >= 0
  applicability_order : DiscountApplicability   # required; total_asc | total_desc
}

Resource specs (API schema)

The API never serializes the Django model directly. It routes through Pydantic specs built on EMRResource (resources/base.py), which provide serialize (DB → API) and de_serialize (API → DB).

Spec class Role Exposes / behaviour
ChargeItemDefinitionSpec shared base id, status, title, derived_from_uri, description, purpose, price_components, can_edit_charge_item, discount_configuration. __exclude__ = []
ChargeItemDefinitionWriteSpec write · create + update Adds slug_value: SlugType and `category: ExtendedSlugType
ChargeItemDefinitionReadSpec read · list + detail Adds read-only version, category: dict, slug_config: dict, tags: list[dict], slug: str, created_by, updated_by, created_date, updated_date

These specs reuse several nested specs: MonetaryComponent (price component), DiscountConfiguration (discount rules), Coding (component code), and EvaluatorConditionSpec (component conditions).

Write-spec validation & side effects

Read-spec serialization

Slug type constraints

Type Constraints
SlugType (slug_value) min_length=5, max_length=50; pattern ^[a-zA-Z0-9][a-zA-Z0-9_-]*[a-zA-Z0-9]$ (URL-safe; alphanumeric start/end)
ExtendedSlugType (category) min_length=7, max_length=88; same pattern, and must start with f- or i-

Related models

ChargeItemDefinition references two other models by foreign key:

facility  → FK facility.Facility (PROTECT)
category  → FK emr.ResourceCategory (CASCADE, nullable)

Methods & save behaviour

ChargeItemDefinition overrides nothing of its own; slug behaviour comes from SlugBaseModel (FACILITY_SCOPED = True):

Method Behaviour
calculate_slug() Returns f-{facility.external_id}-{slug} when facility-scoped with a facility, otherwise i-{slug}
calculate_slug_from_facility(facility_external_id, slug) Classmethod — builds a facility-scoped slug string
calculate_slug_from_instance(slug) Classmethod — builds an instance-scoped slug string
parse_slug(slug) Splits a stored slug back into {facility, slug_value} (facility-scoped, f- prefix) or {slug_value} (instance-scoped, i- prefix); validates the embedded facility UUID; raises on length <= 2 or an unknown prefix

Because slugs are namespaced by the owning facility's external_id, the same slug_value (for example consultation-fee) can coexist across facilities without colliding.

API integration notes

Related

Source evidence

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