<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://ohcnwiki.tellmey.fyi/index.php?action=history&amp;feed=atom&amp;title=References%2FResource_Category</id>
	<title>References/Resource Category - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://ohcnwiki.tellmey.fyi/index.php?action=history&amp;feed=atom&amp;title=References%2FResource_Category"/>
	<link rel="alternate" type="text/html" href="https://ohcnwiki.tellmey.fyi/index.php?title=References/Resource_Category&amp;action=history"/>
	<updated>2026-07-06T07:11:32Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.4</generator>
	<entry>
		<id>https://ohcnwiki.tellmey.fyi/index.php?title=References/Resource_Category&amp;diff=473&amp;oldid=prev</id>
		<title>Admin: Add Navbox platform (via update-page on MediaWiki MCP Server)</title>
		<link rel="alternate" type="text/html" href="https://ohcnwiki.tellmey.fyi/index.php?title=References/Resource_Category&amp;diff=473&amp;oldid=prev"/>
		<updated>2026-07-06T04:24:45Z</updated>

		<summary type="html">&lt;p&gt;Add Navbox platform (via update-page on MediaWiki MCP Server)&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 09:54, 6 July 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 267:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 267:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Monetary-component propagation runs through Celery, so descendants&#039; &amp;lt;code&amp;gt;calculated_monetary_components&amp;lt;/code&amp;gt; is eventually consistent after a write.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Monetary-component propagation runs through Celery, so descendants&#039; &amp;lt;code&amp;gt;calculated_monetary_components&amp;lt;/code&amp;gt; is eventually consistent after a write.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Monetary-component fields serialize only for &amp;lt;code&amp;gt;resource_type == &amp;amp;quot;charge_item_definition&amp;amp;quot;&amp;lt;/code&amp;gt;; during merges, component identity rests on the nested &amp;lt;code&amp;gt;code.system&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;code.code&amp;lt;/code&amp;gt; pair.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Monetary-component fields serialize only for &amp;lt;code&amp;gt;resource_type == &amp;amp;quot;charge_item_definition&amp;amp;quot;&amp;lt;/code&amp;gt;; during merges, component identity rests on the nested &amp;lt;code&amp;gt;code.system&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;code.code&amp;lt;/code&amp;gt; pair.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Navbox platform}}&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Related}}&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Related}}&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://ohcnwiki.tellmey.fyi/index.php?title=References/Resource_Category&amp;diff=171&amp;oldid=prev</id>
		<title>Admin: OHC identity seed</title>
		<link rel="alternate" type="text/html" href="https://ohcnwiki.tellmey.fyi/index.php?title=References/Resource_Category&amp;diff=171&amp;oldid=prev"/>
		<updated>2026-07-04T22:45:34Z</updated>

		<summary type="html">&lt;p&gt;OHC identity seed&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Doc header&lt;br /&gt;
|type=reference&lt;br /&gt;
|domain=platform&lt;br /&gt;
|title=Resource Category&lt;br /&gt;
|order=5&lt;br /&gt;
|introduced=3.0&lt;br /&gt;
|model=ResourceCategory&lt;br /&gt;
|reference=References/Base models &amp;amp;amp; conventions&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ResourceCategory&amp;lt;/code&amp;gt; is a facility-scoped, self-nesting category tree that classifies resources — &amp;lt;code&amp;gt;product_knowledge&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;activity_definition&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;charge_item_definition&amp;lt;/code&amp;gt; — and carries charge-item monetary components that inherit down the tree.&lt;br /&gt;
&lt;br /&gt;
The Django model is just storage. The behaviour you code against lives in the Pydantic resource specs in &amp;lt;code&amp;gt;care/emr/resources/resource_category/&amp;lt;/code&amp;gt;: the &amp;lt;code&amp;gt;resource_type&amp;lt;/code&amp;gt; enum, the &amp;lt;code&amp;gt;MonetaryComponent&amp;lt;/code&amp;gt; shape behind the &amp;lt;code&amp;gt;*_monetary_components&amp;lt;/code&amp;gt; JSON fields, slug validation, and the split between read and write schemas. Several model fields are opaque &amp;lt;code&amp;gt;JSONField&amp;lt;/code&amp;gt;s whose real structure exists only in the specs — see [[#resource-specs-api-schema|Resource specs (API schema)]].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Source:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
* Model: [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/models/resource_category.py &amp;lt;code&amp;gt;care/emr/models/resource_category.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
* Spec: [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/resource_category/spec.py &amp;lt;code&amp;gt;care/emr/resources/resource_category/spec.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
* Shared: [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/base.py &amp;lt;code&amp;gt;base.py&amp;lt;/code&amp;gt;] · [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/common/monetary_component.py &amp;lt;code&amp;gt;common/monetary_component.py&amp;lt;/code&amp;gt;] · [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/common/coding.py &amp;lt;code&amp;gt;common/coding.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== Models ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Model&lt;br /&gt;
! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ResourceCategory&amp;lt;/code&amp;gt;&lt;br /&gt;
| A facility-scoped, self-nesting category tree node that classifies resources (&amp;lt;code&amp;gt;product_knowledge&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;activity_definition&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;charge_item_definition&amp;lt;/code&amp;gt;) and carries inheritable charge-item monetary components&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ResourceCategory&amp;lt;/code&amp;gt; extends [[References/Base models &amp;amp;amp; conventions|&amp;lt;code&amp;gt;SlugBaseModel&amp;lt;/code&amp;gt;]] with &amp;lt;code&amp;gt;FACILITY_SCOPED = True&amp;lt;/code&amp;gt;, the facility-scoped slug variant of the base. It inherits the EMR base fields — &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt;, audit fields, soft-delete, &amp;lt;code&amp;gt;history&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;meta&amp;lt;/code&amp;gt; JSON — and adds &amp;lt;code&amp;gt;slug&amp;lt;/code&amp;gt; handling on top.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;code&amp;gt;ResourceCategory&amp;lt;/code&amp;gt; fields ==&lt;br /&gt;
&lt;br /&gt;
=== Core ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Notes&lt;br /&gt;
{{Field|model=ResourceCategory|section=Core|name=facility|type=FK → facility.Facility (PROTECT)|notes=yes}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=Core|name=resource_type|type=CharField(255)|notes=yes}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=Core|name=resource_sub_type|type=CharField(255)|notes=yes}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=Core|name=title|type=CharField(255)|notes=yes}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=Core|name=slug|type=CharField(255)|notes=yes}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=Core|name=description|type=TextField|notes=no}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Meta&amp;lt;/code&amp;gt; declares a composite index on &amp;lt;code&amp;gt;(slug, facility)&amp;lt;/code&amp;gt; for slug lookups within a facility.&lt;br /&gt;
&lt;br /&gt;
=== Tree structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Notes&lt;br /&gt;
{{Field|model=ResourceCategory|section=Tree structure|name=parent|type=FK → emr.ResourceCategory (CASCADE)|notes=Self-reference to the parent node; nullable. &amp;lt;code&amp;gt;related_name=&amp;amp;quot;children&amp;amp;quot;&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;__exclude__&amp;lt;/code&amp;gt;d from spec serialization — written via slug lookup, read via &amp;lt;code&amp;gt;get_parent_json()&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=Tree structure|name=is_child|type=BooleanField|notes=Default &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;. Exposed on write (&amp;lt;code&amp;gt;ResourceCategoryWriteSpec&amp;lt;/code&amp;gt;) and read}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=Tree structure|name=has_children|type=BooleanField|notes=Default &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;. Flips to &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; on the parent when a child is created (see [[#methods--save-behaviour}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=Tree structure|name=root_org|type=FK → emr.ResourceCategory (CASCADE)|notes=Self-reference to the root of this node&amp;#039;s tree; nullable. &amp;lt;code&amp;gt;related_name=&amp;amp;quot;root&amp;amp;quot;&amp;lt;/code&amp;gt;. Not exposed in specs}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Tree caches ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set_organization_cache()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;get_parent_json()&amp;lt;/code&amp;gt; denormalize the ancestor chain into these fields, so reads resolve it without recursive joins. They are platform-maintained; clients never write them.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Rebuilt by&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;parent_cache&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;ArrayField[int]&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;set_organization_cache()&amp;lt;/code&amp;gt; — the parent&amp;#039;s &amp;lt;code&amp;gt;parent_cache&amp;lt;/code&amp;gt; plus the parent&amp;#039;s id&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;level_cache&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;IntegerField&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;set_organization_cache()&amp;lt;/code&amp;gt; — parent&amp;#039;s &amp;lt;code&amp;gt;level_cache + 1&amp;lt;/code&amp;gt; (default &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; for roots). Exposed read-only (&amp;lt;code&amp;gt;level_cache: int = 0&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cached_parent_json&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;JSONField&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;get_parent_json()&amp;lt;/code&amp;gt; — nested snapshot (shape below) with a &amp;lt;code&amp;gt;cache_expiry&amp;lt;/code&amp;gt; timestamp; refreshed after &amp;lt;code&amp;gt;cache_expiry_days&amp;lt;/code&amp;gt; (15)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;get_parent_json()&amp;lt;/code&amp;gt; builds &amp;lt;code&amp;gt;cached_parent_json&amp;lt;/code&amp;gt; in this shape, which is also the shape of the &amp;lt;code&amp;gt;parent&amp;lt;/code&amp;gt; field in &amp;lt;code&amp;gt;ResourceCategoryReadSpec&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;id&amp;quot;: str,            # parent.external_id (UUID)&lt;br /&gt;
  &amp;quot;slug&amp;quot;: str,          # parent.slug (encoded)&lt;br /&gt;
  &amp;quot;title&amp;quot;: str,&lt;br /&gt;
  &amp;quot;description&amp;quot;: str | null,&lt;br /&gt;
  &amp;quot;parent&amp;quot;: { ... },    # recursively the grandparent&amp;#039;s cached_parent_json ({} at root)&lt;br /&gt;
  &amp;quot;cache_expiry&amp;quot;: str   # ISO datetime; now + 15 days&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Root nodes (no &amp;lt;code&amp;gt;parent_id&amp;lt;/code&amp;gt;) serialize &amp;lt;code&amp;gt;parent&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Charge item monetary components ===&lt;br /&gt;
&lt;br /&gt;
Both are &amp;lt;code&amp;gt;JSONField(default=list)&amp;lt;/code&amp;gt; in the model; the spec types each element as a &amp;lt;code&amp;gt;MonetaryComponent&amp;lt;/code&amp;gt; (see [[#monetarycomponent-nested-shape|shape]]). They serialize only when &amp;lt;code&amp;gt;resource_type == charge_item_definition&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Notes&lt;br /&gt;
{{Field|model=ResourceCategory|section=Charge item monetary components|name=configured_monetary_components|type=JSONField → list[MonetaryComponent] | None|notes=Components configured directly on this category}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=Charge item monetary components|name=calculated_monetary_components|type=JSONField → list[MonetaryComponent] | None|notes=Effective components after merging the parent&amp;#039;s calculated components with this node&amp;#039;s configured components (see [[#methods--save-behaviour}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Enums ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;ResourceCategoryResourceTypeOptions&amp;lt;/code&amp;gt; values ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;care/emr/resources/resource_category/spec.py&amp;lt;/code&amp;gt; — bound to &amp;lt;code&amp;gt;resource_type&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;product_knowledge&amp;lt;/code&amp;gt;&lt;br /&gt;
| Category classifies [[References/Product Knowledge]] entries&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;activity_definition&amp;lt;/code&amp;gt;&lt;br /&gt;
| Category classifies [[References/Activity Definition&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;charge_item_definition&amp;lt;/code&amp;gt;&lt;br /&gt;
| Category classifies [[References/Charge Item Definition&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;MonetaryComponentType&amp;lt;/code&amp;gt; values ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;care/emr/resources/common/monetary_component.py&amp;lt;/code&amp;gt; — bound to &amp;lt;code&amp;gt;MonetaryComponent.monetary_component_type&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;base&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;surcharge&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;discount&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tax&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;informational&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Resource specs (API schema) ==&lt;br /&gt;
&lt;br /&gt;
All specs extend &amp;lt;code&amp;gt;EMRResource&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;serialize&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;de_serialize&amp;lt;/code&amp;gt;; reads run &amp;lt;code&amp;gt;perform_extra_serialization&amp;lt;/code&amp;gt;, writes run &amp;lt;code&amp;gt;perform_extra_deserialization&amp;lt;/code&amp;gt;). With &amp;lt;code&amp;gt;__model__ = ResourceCategory&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;__exclude__ = [&amp;amp;quot;parent&amp;amp;quot;]&amp;lt;/code&amp;gt;, the &amp;lt;code&amp;gt;parent&amp;lt;/code&amp;gt; FK is never auto-mapped — every spec resolves it explicitly.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Spec class&lt;br /&gt;
! Role&lt;br /&gt;
! Exposes / behaviour&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ResourceCategoryBaseSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| shared base&lt;br /&gt;
| &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; (UUID, read), &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;resource_type&amp;lt;/code&amp;gt; (enum), &amp;lt;code&amp;gt;resource_sub_type&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ResourceCategoryWriteSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · create&lt;br /&gt;
| Base + &amp;lt;code&amp;gt;parent: str | None&amp;lt;/code&amp;gt; (parent &amp;#039;&amp;#039;&amp;#039;slug&amp;#039;&amp;#039;&amp;#039;), &amp;lt;code&amp;gt;is_child: bool = False&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;slug_value: SlugType&amp;lt;/code&amp;gt;. When &amp;lt;code&amp;gt;parent&amp;lt;/code&amp;gt; is set, &amp;lt;code&amp;gt;perform_extra_deserialization&amp;lt;/code&amp;gt; resolves &amp;lt;code&amp;gt;obj.parent = ResourceCategory.objects.get(slug=self.parent)&amp;lt;/code&amp;gt;, and sets &amp;lt;code&amp;gt;obj.slug = self.slug_value&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ResourceCategoryUpdateSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · update&lt;br /&gt;
| Base + &amp;lt;code&amp;gt;slug_value: SlugType&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;perform_extra_deserialization&amp;lt;/code&amp;gt; sets &amp;lt;code&amp;gt;obj.slug = self.slug_value&amp;lt;/code&amp;gt;; update never reassigns &amp;lt;code&amp;gt;parent&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ResourceCategoryReadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · list &amp;amp;amp; detail&lt;br /&gt;
| Base + &amp;lt;code&amp;gt;parent: dict&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;has_children: bool&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;level_cache: int = 0&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;is_child: bool&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;slug: str&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;slug_config: dict&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;calculated_monetary_components&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;configured_monetary_components&amp;lt;/code&amp;gt;. See serialization below&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Docstrings label these &amp;amp;quot;ChargeItemDefinition Category&amp;amp;quot;, but the model is &amp;lt;code&amp;gt;ResourceCategory&amp;lt;/code&amp;gt;. There is no separate &amp;lt;code&amp;gt;*ListSpec&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;*RetrieveSpec&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;ResourceCategoryReadSpec&amp;lt;/code&amp;gt; serves both list and detail.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
=== &amp;lt;code&amp;gt;ResourceCategoryReadSpec&amp;lt;/code&amp;gt; serialization (&amp;lt;code&amp;gt;perform_extra_serialization&amp;lt;/code&amp;gt;) ===&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;id = obj.external_id&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;parent = obj.get_parent_json()&amp;lt;/code&amp;gt; — the nested ancestor snapshot (shape above)&lt;br /&gt;
* &amp;lt;code&amp;gt;slug_config = obj.parse_slug(obj.slug)&amp;lt;/code&amp;gt; — a facility-scoped slug returns &amp;lt;code&amp;gt;{&amp;amp;quot;facility&amp;amp;quot;: &amp;amp;lt;uuid str&amp;amp;gt;, &amp;amp;quot;slug_value&amp;amp;quot;: &amp;amp;lt;str&amp;amp;gt;}&amp;lt;/code&amp;gt;; an instance slug returns &amp;lt;code&amp;gt;{&amp;amp;quot;slug_value&amp;amp;quot;: &amp;amp;lt;str&amp;amp;gt;}&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;calculated_monetary_components&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;configured_monetary_components&amp;lt;/code&amp;gt; — set only when &amp;lt;code&amp;gt;resource_type == &amp;amp;quot;charge_item_definition&amp;amp;quot;&amp;lt;/code&amp;gt;; otherwise these default-&amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; fields are omitted&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;SlugType&amp;lt;/code&amp;gt; validation ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;slug_value&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;Annotated[str, Field(min_length=5, max_length=50), AfterValidator(slug_validator)]&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* length 5–50&lt;br /&gt;
* regex &amp;lt;code&amp;gt;^[a-zA-Z0-9][a-zA-Z0-9_-]*[a-zA-Z0-9]$&amp;lt;/code&amp;gt; — URL-safe (letters, digits, &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;_&amp;lt;/code&amp;gt;), starting and ending alphanumeric&lt;br /&gt;
&lt;br /&gt;
The stored &amp;lt;code&amp;gt;slug&amp;lt;/code&amp;gt; is the encoded form &amp;lt;code&amp;gt;f-&amp;amp;lt;facility_external_id&amp;amp;gt;-&amp;amp;lt;slug_value&amp;amp;gt;&amp;lt;/code&amp;gt; (via &amp;lt;code&amp;gt;SlugBaseModel.calculate_slug()&amp;lt;/code&amp;gt;); &amp;lt;code&amp;gt;slug_config&amp;lt;/code&amp;gt; round-trips it back to &amp;lt;code&amp;gt;{facility, slug_value}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;MonetaryComponent&amp;lt;/code&amp;gt; (nested shape) ===&lt;br /&gt;
&lt;br /&gt;
Element type of &amp;lt;code&amp;gt;configured_monetary_components&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;calculated_monetary_components&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;common/monetary_component.py&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Default&lt;br /&gt;
! Notes&lt;br /&gt;
{{Field|model=ResourceCategory|section=MonetaryComponent (nested shape)|name=monetary_component_type|type=MonetaryComponentType enum|notes=—}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=MonetaryComponent (nested shape)|name=code|type=Coding | None|notes=&amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=MonetaryComponent (nested shape)|name=factor|type=Decimal | None|notes=&amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=MonetaryComponent (nested shape)|name=amount|type=Decimal | None|notes=&amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=MonetaryComponent (nested shape)|name=tax_included_amount|type=Decimal | None|notes=&amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=MonetaryComponent (nested shape)|name=global_component|type=bool|notes=&amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=ResourceCategory|section=MonetaryComponent (nested shape)|name=conditions|type=list[EvaluatorConditionSpec]|notes=&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MonetaryComponent&amp;lt;/code&amp;gt; model validators:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;tax_included_amount&amp;lt;/code&amp;gt; only allowed when type is &amp;lt;code&amp;gt;base&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;base&amp;lt;/code&amp;gt; must have no &amp;lt;code&amp;gt;conditions&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;base&amp;lt;/code&amp;gt; must have an &amp;lt;code&amp;gt;amount&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;amount&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;factor&amp;lt;/code&amp;gt; are mutually exclusive (not both)&lt;br /&gt;
* either &amp;lt;code&amp;gt;amount&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;factor&amp;lt;/code&amp;gt; must be present (unless &amp;lt;code&amp;gt;global_component and code&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;The category stores and validates these per element as &amp;lt;code&amp;gt;MonetaryComponent&amp;lt;/code&amp;gt;. The stricter collection validators — &amp;lt;code&amp;gt;MonetaryComponents&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;MonetaryComponentsWithoutBase&amp;lt;/code&amp;gt; (single base, no duplicate codes, tax-sum balance) — live with the charge-item resources, not the category list.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
== Methods &amp;amp;amp; save behaviour ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ResourceCategory&amp;lt;/code&amp;gt; overrides &amp;lt;code&amp;gt;save()&amp;lt;/code&amp;gt; to populate the tree caches on create. A handful of helper methods plus a Celery task maintain those caches and the inherited monetary components.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;save()&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
* On &amp;#039;&amp;#039;&amp;#039;create&amp;#039;&amp;#039;&amp;#039; (&amp;lt;code&amp;gt;self.id&amp;lt;/code&amp;gt; not yet set): runs &amp;lt;code&amp;gt;super().save()&amp;lt;/code&amp;gt;, then &amp;lt;code&amp;gt;set_organization_cache()&amp;lt;/code&amp;gt;, then enqueues monetary-component summarisation via &amp;lt;code&amp;gt;summarise_monetary_components(self)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* On &amp;#039;&amp;#039;&amp;#039;update&amp;#039;&amp;#039;&amp;#039;: a plain &amp;lt;code&amp;gt;super().save(*args, **kwargs)&amp;lt;/code&amp;gt;, no cache rebuild.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;set_organization_cache()&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Runs once on creation when a &amp;lt;code&amp;gt;parent&amp;lt;/code&amp;gt; is present:&lt;br /&gt;
&lt;br /&gt;
* Sets &amp;lt;code&amp;gt;parent_cache = [*parent.parent_cache, parent.id]&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;level_cache = parent.level_cache + 1&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Sets &amp;lt;code&amp;gt;root_org&amp;lt;/code&amp;gt; to the parent&amp;#039;s &amp;lt;code&amp;gt;root_org&amp;lt;/code&amp;gt;, or to the parent itself if the parent is a root.&lt;br /&gt;
* If the parent&amp;#039;s &amp;lt;code&amp;gt;has_children&amp;lt;/code&amp;gt; was &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;, flips it to &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; and persists it with &amp;lt;code&amp;gt;save(update_fields=[&amp;amp;quot;has_children&amp;amp;quot;])&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Persists the node via &amp;lt;code&amp;gt;super().save()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;get_parent_json()&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Returns &amp;lt;code&amp;gt;cached_parent_json&amp;lt;/code&amp;gt;, rebuilding it lazily. A snapshot still within its &amp;lt;code&amp;gt;cache_expiry&amp;lt;/code&amp;gt; is returned as-is. Past expiry, the method walks the parent chain, builds a fresh nested snapshot with a new expiry (&amp;lt;code&amp;gt;now + cache_expiry_days&amp;lt;/code&amp;gt;), persists it via &amp;lt;code&amp;gt;save(update_fields=[&amp;amp;quot;cached_parent_json&amp;amp;quot;])&amp;lt;/code&amp;gt;, and returns it. Root nodes (no &amp;lt;code&amp;gt;parent_id&amp;lt;/code&amp;gt;) return &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;summarise_monetary_components(category)&amp;lt;/code&amp;gt; — Celery task ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;@shared_task&amp;lt;/code&amp;gt; that recomputes &amp;lt;code&amp;gt;calculated_monetary_components&amp;lt;/code&amp;gt; down the subtree:&lt;br /&gt;
&lt;br /&gt;
* For a root (no &amp;lt;code&amp;gt;parent&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;calculated_monetary_components = configured_monetary_components&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Otherwise it merges the parent&amp;#039;s &amp;lt;code&amp;gt;calculated_monetary_components&amp;lt;/code&amp;gt; with this node&amp;#039;s &amp;lt;code&amp;gt;configured_monetary_components&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;merge_monetary_components()&amp;lt;/code&amp;gt;, then persists with &amp;lt;code&amp;gt;save(update_fields=[&amp;amp;quot;calculated_monetary_components&amp;amp;quot;])&amp;lt;/code&amp;gt;.&lt;br /&gt;
* It re-dispatches itself (&amp;lt;code&amp;gt;.delay(component.id)&amp;lt;/code&amp;gt;) for every child, propagating changes through the tree.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;merge_monetary_components(parent, child)&amp;lt;/code&amp;gt; keys components by &amp;lt;code&amp;gt;code.system + code.code&amp;lt;/code&amp;gt;; child components override parent components sharing a key, and components without a &amp;lt;code&amp;gt;code&amp;lt;/code&amp;gt; are appended unmerged.&lt;br /&gt;
&lt;br /&gt;
== API integration notes ==&lt;br /&gt;
&lt;br /&gt;
* Categories are facility-scoped. The &amp;lt;code&amp;gt;(slug, facility)&amp;lt;/code&amp;gt; index and &amp;lt;code&amp;gt;SlugBaseModel&amp;lt;/code&amp;gt; encoding (&amp;lt;code&amp;gt;f-&amp;amp;lt;facility&amp;amp;gt;-&amp;amp;lt;slug&amp;amp;gt;&amp;lt;/code&amp;gt;) keep slugs unique per facility. Clients send &amp;lt;code&amp;gt;slug_value&amp;lt;/code&amp;gt; (5–50, URL-safe); the server encodes it and &amp;lt;code&amp;gt;slug_config&amp;lt;/code&amp;gt; decodes it.&lt;br /&gt;
* Write &amp;lt;code&amp;gt;parent&amp;lt;/code&amp;gt; by &amp;#039;&amp;#039;&amp;#039;slug&amp;#039;&amp;#039;&amp;#039; (&amp;lt;code&amp;gt;ResourceCategoryWriteSpec.parent&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;ResourceCategory.objects.get(slug=...)&amp;lt;/code&amp;gt;), not by id. On read it comes back as the nested &amp;lt;code&amp;gt;get_parent_json()&amp;lt;/code&amp;gt; snapshot.&lt;br /&gt;
* &amp;lt;code&amp;gt;parent_cache&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;level_cache&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;root_org&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;has_children&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;cached_parent_json&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;calculated_monetary_components&amp;lt;/code&amp;gt; are platform-maintained — don&amp;#039;t set them. Write &amp;lt;code&amp;gt;parent&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;configured_monetary_components&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;save()&amp;lt;/code&amp;gt; and the Celery task derive the rest.&lt;br /&gt;
* Cache rebuilds (&amp;lt;code&amp;gt;set_organization_cache&amp;lt;/code&amp;gt;, monetary-component summarisation) run only on &amp;#039;&amp;#039;&amp;#039;create&amp;#039;&amp;#039;&amp;#039;. Changing an existing node&amp;#039;s &amp;lt;code&amp;gt;parent&amp;lt;/code&amp;gt; or configured components does not rebuild the caches.&lt;br /&gt;
* Monetary-component propagation runs through Celery, so descendants&amp;#039; &amp;lt;code&amp;gt;calculated_monetary_components&amp;lt;/code&amp;gt; is eventually consistent after a write.&lt;br /&gt;
* Monetary-component fields serialize only for &amp;lt;code&amp;gt;resource_type == &amp;amp;quot;charge_item_definition&amp;amp;quot;&amp;lt;/code&amp;gt;; during merges, component identity rests on the nested &amp;lt;code&amp;gt;code.system&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;code.code&amp;lt;/code&amp;gt; pair.&lt;br /&gt;
&lt;br /&gt;
{{Related}}&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>