Alert Facility Fields | Canvas Medical

kevincareycanvas/alert-facility-fields

You can also View the extension on GitHub

alert_facility_fields

A Canvas SDK plugin that adds an Alert facility Yes/No field to the Medication Statement, Stop Medication, Prescribe, Adjust Prescription, and Refill commands and blocks committing those commands until the field is set.

Why

Healthcare teams routinely need to flag whether a medication change should trigger a notification to the patient's facility (skilled nursing facility, group home, school, etc.). Capturing this signal at the point of charting — and refusing to commit a medication command (Medication Statement, Stop Medication, Prescribe, Adjust Prescription, or Refill) without it — keeps the data consistent and makes downstream automation (alerting, reporting, integrations) trivial: the answer is on the command itself, not buried in free text.

What it does

When a clinician opens or prints a note containing a Medication Statement, Stop Medication, Prescribe, Adjust Prescription, or Refill command, the plugin contributes one extra form field:

Property Value
Label Alert facility
Type Single-select dropdown
Options Yes / No
Required Yes — the command cannot be committed until a value is chosen

The selected value is persisted as command metadata under the key alert_facility (value "Yes" or "No"). Any downstream consumer — a CPA-style workflow plugin, a FHIR exporter, a reporting job — can read the value via the SDK's command-metadata data layer:

from canvas_sdk.v1.data.command import CommandMetadata

entry = CommandMetadata.objects.filter(
    command__id=command_uuid,
    key="alert_facility",
).first()

The field renders both in the in-command charting UI and on the printed note. The Canvas SDK omits the field from the printout when no value is stored.

How it works

Two BaseHandler subclasses, both registered in CANVAS_MANIFEST.json:

AlertFacilityFormHandler

Subscribes to EventType.COMMAND__FORM__GET_ADDITIONAL_FIELDS. On each event, it inspects event.context["schema_key"]; for medicationStatement, stopMedication, prescribe, adjustPrescription, or refill it returns a CommandMetadataCreateFormEffect declaring the Alert facility field. The same effect is returned regardless of event.context["purpose"] ("form" for chart UI, "print" for the printout), so the field surfaces in both contexts.

AlertFacilityRequiredValidator

Subscribes to MEDICATION_STATEMENT_COMMAND__POST_VALIDATION, STOP_MEDICATION_COMMAND__POST_VALIDATION, PRESCRIBE_COMMAND__POST_VALIDATION, ADJUST_PRESCRIPTION_COMMAND__POST_VALIDATION, and REFILL_COMMAND__POST_VALIDATION. On commit it reads the stored alert_facility metadata via CommandMetadata.objects.filter(...). If the value is missing or blank it returns a CommandValidationErrorEffect with the message "Alert Facility is a required field." — the platform surfaces the error inline and refuses the commit until the user makes a choice.

Demo

Loom walkthrough — shows the Alert facility dropdown rendering on a Medication Statement command, the validation error appearing when commit is attempted without a value, and the command committing cleanly once a value is selected.

Project layout

alert-facility-fields/                          # repo root
├── pyproject.toml
├── mypy.ini
├── tests/
│   └── test_alert_facility_form.py
└── alert_facility_fields/                      # plugin package
    ├── CANVAS_MANIFEST.json
    ├── README.md
    ├── __init__.py
    └── protocols/
        ├── __init__.py
        └── alert_facility_form.py              # both handlers live here

Installation

Install the plugin onto a Canvas instance using the Canvas CLI:

uv run canvas install --host <your-instance> alert_facility_fields

<your-instance> is the section header from your ~/.canvas/credentials.ini. The CLI reuploads on subsequent runs and the platform hot-reloads the plugin.

Configuration

None. The plugin declares no secrets, no environment variables, and no scope — it consumes only the platform-supplied event context and writes to command metadata.

Development

# install dev dependencies
uv sync

# run tests with coverage
uv run pytest --cov=alert_facility_fields --cov-report=term-missing --cov-branch

# type-check
uv run mypy --config-file=mypy.ini alert_facility_fields tests

Behavior notes

References