> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Controlled Substance Inventory

> Track controlled substance receipts, dispensing, adjustments, counts, returns, and destructions per organization.

The Controlled Substance Inventory screen provides a transaction log for controlled substance activity at route `/cl/controlled-substances`.

## Overview

The page renders a list of inventory transactions from the `cl_controlled_substance_inventory` table, scoped to the current organization via `organization_id`. Transactions are ordered by `created_at` descending and soft-deleted records (`deleted_at IS NOT NULL`) are excluded. The `InventoryList` component accepts filter props (`siteId`, `ndcCode`, `schedule`, `transactionType`, `dateFrom`, `dateTo`) that are applied server-side in the query. Users with `cl.inventory.create` see a "Record Transaction" button that opens `InventoryTransactionFormDialog`. Users with `cl.inventory.admin` additionally see an `ArcosExportButton`. A running-balance reconciliation is available per NDC code and optional site via the `useInventoryReconciliation` hook (not surfaced on this list page itself).

## Who it's for

Requires permission `cl.inventory.view`.

## Before you start

You must hold the `cl.inventory.view` permission to access this page. Recording new transactions additionally requires `cl.inventory.create`. The ARCOS export action requires `cl.inventory.admin`.

## Steps

<Steps>
  <Step title="Open Controlled Substance Inventory">
    Navigate to `/cl/controlled-substances`. The page loads all non-deleted transactions for your organization, ordered by most recent first.
  </Step>

  <Step title="Filter transactions (optional)">
    Use the filter controls in `InventoryList` to narrow by site, NDC code, schedule, transaction type, or date range. Filters are applied server-side.
  </Step>

  <Step title="Record a transaction (if permitted)">
    Click "Record Transaction" (requires `cl.inventory.create`). The `InventoryTransactionFormDialog` opens. Fill in the required fields. If recording a Schedule II dispense, a witness must be provided — the system enforces this in the mutation and will return an error if `witness_id` is absent.
  </Step>

  <Step title="Export (if permitted)">
    Click the ARCOS export button (requires `cl.inventory.admin`) to initiate the export action.
  </Step>
</Steps>

## Key concepts

<AccordionGroup>
  <Accordion title="Transaction types">
    The `transaction_type` column accepts: `receive`, `dispense`, `adjust`, `count`, `return`, `destroy`. The reconciliation logic in code treats `receive`, `return`, and `adjust` as additive to the running balance, and `dispense` and `destroy` as subtractive. A `count` transaction records a physical count but does not change the computed running balance.
  </Accordion>

  <Accordion title="Schedule II witness enforcement">
    The `useCreateInventoryTransaction` mutation checks: if `schedule === 'II'` and `transaction_type === 'dispense'`, it throws if `witness_id` is absent. This check runs client-side in the mutation function before the database insert.
  </Accordion>

  <Accordion title="Soft delete">
    Transactions are never hard-deleted. The `useDeleteInventoryTransaction` mutation sets `deleted_at` to the current timestamp. Deleted records are excluded from all list and reconciliation queries.
  </Accordion>

  <Accordion title="Empty state">
    When the query returns no transactions (or loading is in progress), the `InventoryList` shows either skeleton placeholders or an empty state.
  </Accordion>
</AccordionGroup>

## Related

<Columns cols={2}>
  <Card title="Clinical" icon="stethoscope" href="/cl/overview">
    Overview of the Clinical core.
  </Card>

  <Card title="Governance & parity" icon="scale-balanced" href="/governance/index">
    Documentation coverage and governance.
  </Card>
</Columns>

<Note>
  This page documents shipped product behavior. It is not medical, legal, or
  billing advice. Verify against your organization's policies and applicable
  regulations before using it for clinical, compliance, or billing decisions.
  Protected health information (PHI) shown in the product is governed by your
  tenant's access controls and is never exposed in this documentation.
</Note>

<Accordion title="Documentation sources">
  * src/routes/cl.tsx
  * src/cores/cl/pages/ControlledSubstanceInventoryPage.tsx
  * src/cores/cl/hooks/useControlledSubstanceInventory.ts
</Accordion>
