-
Notifications
You must be signed in to change notification settings - Fork 1
Add documentation for Patients with Billable Charge Item and Encounter/Appointment Details query #147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add documentation for Patients with Billable Charge Item and Encounter/Appointment Details query #147
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
|
|
||
| # Patients with Billable Charge Item and Encounter/Appointment Details - SSMM | ||
|
|
||
| > Patient-level list of encounters linked to appointments that have billable charge items | ||
|
|
||
| ## Purpose | ||
|
|
||
| Returns encounter records at SSMM where the linked appointment (`emr_tokenbooking`) has a charge item in `billable` status. The result includes patient details, SSMM identifier, encounter and appointment statuses, charge item status/value, and encounter date. | ||
|
|
||
| ## Parameters | ||
|
|
||
| | Parameter | Type | Description | Example | | ||
| |-----------|------|-------------|---------| | ||
| | `date_filter` | DATE / range | Metabase date filter (typically bound to `emr_encounter.created_date`) | `'2026-08-01'` | | ||
| | `encounter_class` | TEXT | Filter by encounter class (exact match on `emr_encounter.encounter_class`) | `'amb'` | | ||
| | `encounter_status` | TEXT | Filter by encounter status (exact match on `emr_encounter.status`) | `'in-progress'` | | ||
| | `ssmm_id` | TEXT | Filter by patient SSMM identifier value (exact match on `emr_patientidentifier.value`) | `'SSMM-100245'` | | ||
|
|
||
| --- | ||
|
|
||
| ## Query | ||
|
|
||
| ```sql | ||
| SELECT | ||
| emr_patient.name AS patient_name, | ||
| emr_patientidentifier.value AS ssmm_id, | ||
| emr_encounter.status AS encounter_status, | ||
| emr_encounter.encounter_class AS encounter_class, | ||
| emr_tokenbooking.status AS appointment_status, | ||
| emr_chargeitem.status AS charge_item_status, | ||
| emr_chargeitem.total_price AS total_price, | ||
| emr_encounter.created_date AS encounter_date | ||
| FROM emr_encounter | ||
| JOIN emr_patient | ||
| ON emr_patient.id = emr_encounter.patient_id | ||
| LEFT JOIN emr_patientidentifier | ||
| ON emr_patientidentifier.patient_id = emr_patient.id | ||
| AND emr_patientidentifier.config_id = 21 | ||
| JOIN emr_tokenbooking | ||
| ON emr_tokenbooking.associated_encounter_id = emr_encounter.id | ||
| JOIN emr_chargeitem | ||
| ON emr_chargeitem.id = emr_tokenbooking.charge_item_id | ||
| WHERE emr_chargeitem.status = 'billable' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Critical] No facility scoping — the Facility boundaries are normally enforced by the application, not by Postgres — a raw query has to add it explicitly (care-sql-code-review skill, inversion 2). This query has no Fix — scope through the encounter (or another table that carries WHERE emr_chargeitem.status = 'billable'
AND emr_chargeitem.total_price > 0
AND emr_encounter.facility_id = <ssmm_facility_id>
...If the intent is genuinely "all facilities, but named |
||
| AND emr_chargeitem.total_price > 0 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [High] No
Fix — add per table: FROM emr_encounter
JOIN emr_patient
ON emr_patient.id = emr_encounter.patient_id
AND emr_patient.deleted = FALSE
LEFT JOIN emr_patientidentifier
ON emr_patientidentifier.patient_id = emr_patient.id
AND emr_patientidentifier.config_id = 21
AND emr_patientidentifier.deleted = FALSE
JOIN emr_tokenbooking
ON emr_tokenbooking.associated_encounter_id = emr_encounter.id
AND emr_tokenbooking.status != 'entered_in_error'
AND emr_tokenbooking.deleted = FALSE
JOIN emr_chargeitem
ON emr_chargeitem.id = emr_tokenbooking.charge_item_id
AND emr_chargeitem.deleted = FALSE
WHERE emr_chargeitem.status = 'billable'
AND emr_chargeitem.total_price > 0
AND emr_encounter.status != 'entered_in_error'
AND emr_encounter.deleted = FALSE
...(Confirm the exact
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is already filter for encounter status in the query There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That filter is different from what this finding is about. Suggested fix, alongside the existing optional param: WHERE emr_chargeitem.status = 'billable'
AND emr_chargeitem.total_price > 0
AND emr_encounter.status != 'entered_in_error'
AND emr_tokenbooking.status != 'entered_in_error'
--[[AND {{date_filter}}]]
--[[AND {{encounter_class}}]]
--[[AND {{encounter_status}}]]
--[[AND emr_patientidentifier.value = {{ssmm_id}}]]Leaving this open — the optional param alone doesn't cover it (it's opt-in, single-table, and not an entered_in_error exclusion).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. commenting out the filters were intentional There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be clear — I'm not asking you to uncomment The finding is about a different, always-on exclusion that isn't in the query at all: a hardcoded If that's an acceptable tradeoff for this report (e.g.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes didnt add that check because the user wanted to filter using the encounter status filter, it was intentional There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Understood — thanks for confirming. If the intent is to let dashboard users scope out
|
||
| --[[AND {{date_filter}}]] | ||
| --[[AND {{encounter_class}}]] | ||
| --[[AND {{encounter_status}}]] | ||
| --[[AND emr_patientidentifier.value = {{ssmm_id}}]] | ||
| ORDER BY emr_encounter.created_date DESC, emr_patient.name; | ||
| ``` | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Medium] Missing The template calls for an |
||
|
|
||
| ## Notes | ||
|
|
||
| - **Core cohort:** Only rows where `emr_chargeitem.status = 'billable'` and `total_price > 0` are included. | ||
| - **Identifier mapping:** `config_id = 21` is hardcoded for SSMM patient identifier configuration; update if this mapping changes. | ||
|
|
||
| *Last updated: 2026-08-13* | ||
Uh oh!
There was an error while loading. Please reload this page.