diff --git a/.gitignore b/.gitignore index 60c0277e..caeb9d42 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ CLAUDE.md # Python __pycache__ +tamanu_source_dbt.egg-info/ # Dependencies dbt_packages/ diff --git a/.maui b/.maui index 24608df7..9f724f3b 160000 --- a/.maui +++ b/.maui @@ -1 +1 @@ -Subproject commit 24608df7af9078c3d0e555637dcae6a9a0ad9ae9 +Subproject commit 9f724f3b101501bd838e5e736a98a7668008cbc9 diff --git a/README.md b/README.md index 1c7dc123..3087a662 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,16 @@ The generated assets are saved in the `compiled/` folder. The documentation is v - Import script: `compiled/reports/importReports.js` - Versioned documentation: `compiled/v{VERSION}/reporting-docs-v{VERSION}-{DEPLOYMENT}.html` +## Sensitive Facility Reporting + +Set `has_sensitive_facility: true` in the `vars` block of `dbt_project.yml` to include models +tagged `restricted` (sensitive-facility dataset views) when generating reports and the reporting +schema script. When `false` (the default), those models are silently excluded from both +`generate_project_reports()` and `generate_reporting_schema_script()`. + +The flag is read at script run-time from `dbt_project.yml` via `get_dbt_project_vars()`, not +from the dbt runtime context, so it must be set in the file before running the build scripts. + ## Generate survey models To automatically generate dbt models and documentation for surveys from database, execute the following command: ``` diff --git a/compiled/v2.50.11/analytics-metadata-v2.50.11-standard.yml b/compiled/v2.50.11/analytics-metadata-v2.50.11-standard.yml new file mode 100644 index 00000000..bfbd448d --- /dev/null +++ b/compiled/v2.50.11/analytics-metadata-v2.50.11-standard.yml @@ -0,0 +1,5191 @@ +- columns: + condition_id: + data_type: character varying + description: Reference to the condition ([Reference Data](#!/source/source.tamanu.tamanu.reference_data), + `type = diagnosis`). + name: condition_id + id: + data_type: character varying + description: Tamanu internal identifier (generally a UUID) in contributing_death_causes. + name: id + patient_death_data_id: + data_type: character varying + description: The [`patient_death_data`](#!/source/source.tamanu.tamanu.patient_death_data) + record. + name: patient_death_data_id + time_after_onset: + data_type: integer + description: Time between onset of recorded cause and death in minutes. + name: time_after_onset + config: + tags: + - base + - clinical + description: Contributing causes recorded with the patient's death data. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: contributing_death_causes + tags: + - base + - clinical +- columns: + code: + data_type: character varying + description: Code for department. + name: code + facility_id: + data_type: character varying + description: Reference to the [facility](#!/source/source.tamanu.tamanu.facilities) + this department is in. + name: facility_id + id: + data_type: character varying + description: Tamanu internal identifier (generally a UUID) in departments. + name: id + name: + data_type: character varying + description: Full readable name for department. + name: name + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in departments." + name: visibility_status + config: + tags: + - base + - reference + description: Basic department info with a reference to parent facility. + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: departments + tags: + - base + - reference +- columns: + discharged_by_id: + data_type: character varying + description: The [discharging clinician](#!/source/source.tamanu.tamanu.users). + name: discharged_by_id + disposition_id: + data_type: character varying + description: The discharge disposition or classification of the discharge ([Reference + Data](#!/source/source.tamanu.tamanu.reference_data)). + name: disposition_id + encounter_id: + data_type: character varying + description: Reference to the [encounter](#!/source/source.tamanu.tamanu.encounters) + this discharge is for. + name: encounter_id + id: + data_type: character varying + description: Tamanu internal identifier (generally a UUID) in discharges. + name: id + note: + data_type: text + description: "Free-form notes about the discharge.\r\n\r\nMay include treatment\ + \ plan and follow-ups, written by the discharging clinician.\r\n\r\nSince\ + \ v2.0, also see the [`notes`](#!/source/source.tamanu.tamanu.notes) table\ + \ for encounter and discharge notes." + name: note + config: + tags: + - base + - clinical + description: "Information about a discharge.\r\n\r\nA discharge is the end of the\ + \ lifecycle for an encounter." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: discharges + tags: + - base + - clinical +- columns: + created_datetime: + data_type: timestamp + description: Timestamp of when record was created in document_metadata. + name: created_datetime + encounter_id: + data_type: character varying(255) + description: Reference to the [encounter](#!/source/source.tamanu.tamanu.encounters) + the document was uploaded to. + name: encounter_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in document_metadata. + name: id + name: + data_type: character varying(255) + description: "Free-form name of the document.\r\n\r\nOften this is the filename." + name: name + patient_id: + data_type: character varying(255) + description: Reference to the [patient](#!/source/source.tamanu.tamanu.patients) + the document was uploaded to. + name: patient_id + type: + data_type: character varying(255) + description: The [media type](https://en.wikipedia.org/wiki/Media_type) of the + file. + name: type + config: + tags: + - base + - clinical + description: "Information about an uploaded document or file, typically attached\ + \ to an encounter or directly to a patient.\r\n\r\nThe actual file data is stored\ + \ in [`attachments`](#!/source/source.tamanu.tamanu.attachments)." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: document_metadata + tags: + - base + - clinical +- columns: + certainty: + data_type: character varying + description: "The level of certainty of the recorded diagnosis.\r\n\r\nOne of:\r\ + \n- `confirmed`\r\n- `disproven`\r\n- `emergency`\r\n- `error`\r\n- `suspected`\r\ + \n\r\n`disproven` and `error` are excluded for reporting" + name: certainty + datetime: + data_type: timestamp + description: Local date for the record in encounter_diagnoses. + name: datetime + diagnosed_by_id: + data_type: character varying + description: Reference to the [clinician](#!/source/source.tamanu.tamanu.users) + recording that diagnosis. + name: diagnosed_by_id + diagnosis_id: + data_type: character varying + description: The diagnosis ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: diagnosis_id + encounter_id: + data_type: character varying + description: Reference to the [encounter](#!/source/source.tamanu.tamanu.encounters) + this diagnosis is for. + name: encounter_id + id: + data_type: character varying + description: Tamanu internal identifier (generally a UUID) in encounter_diagnoses. + name: id + is_primary: + data_type: boolean + description: A boolean indicating if this is a primary diagnosis + name: is_primary + config: + tags: + - base + - clinical + description: Records diagnoses made during an encounter + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: encounter_diagnoses + tags: + - base + - clinical +- columns: + created_datetime: + data_type: timestamp + description: Timestamp of when record was created in the encounter_diagnoses + table. + name: created_datetime + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in encounter_diagnoses. + name: id + updated_datetime: + data_type: timestamp + description: Timestamp of when record was last updated in the encounter_diagnoses + table. + name: updated_datetime + config: + tags: + - base + - clinical + - log + description: Metadata information extracted from the change logs for encounter_diagnoses. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: encounter_diagnoses_metadata + tags: + - base + - clinical + - log +- columns: + diet_id: + data_type: character varying(255) + description: The diet ([Reference Data](#!/source/source.tamanu.tamanu.reference_data), + `type = diet`). + name: diet_id + encounter_id: + data_type: character varying(255) + description: Reference to the [encounter](#!/source/source.tamanu.tamanu.encounters) + this diet is for. + name: encounter_id + id: + data_type: uuid + description: Tamanu internal identifier (generally a UUID) in encounter_diets. + name: id + config: + tags: + - base + - administration + description: "A diet associated with an encounter.\r\n\r\nA patient can be placed\ + \ on a diet for various medical purposes.\r\nDiets are specified in reference\ + \ data." + meta: + classification: confidential + domain: admin + owner: bes-maui + pii: false + tier: silver + name: encounter_diets + tags: + - base + - administration +- columns: + change_type: + data_type: character varying(255) + description: "The field which was changed.\r\n\r\nOne of:\r\n- `encounter_type`\r\ + \n- `location`\r\n- `department`\r\n- `examiner`" + name: change_type + clinician_id: + data_type: character varying(255) + description: Reference to the [examiner](#!/source/source.tamanu.tamanu.users) + for the encounter. + name: clinician_id + date: + data_type: character(19) + description: Local date for the record in encounter_history. + name: date + department_id: + data_type: character varying(255) + description: Reference to the [department](#!/source/source.tamanu.tamanu.departments) + the encounter was in. + name: department_id + encounter_id: + data_type: character varying(255) + description: Reference to the original [encounter](#!/source/source.tamanu.tamanu.encounters) + this history is for. + name: encounter_id + encounter_type: + data_type: character varying(255) + description: "The type of the encounter.\r\n\r\nOne of:\r\n- `admission`\r\n\ + - `clinic`\r\n- `imaging`\r\n- `emergency`\r\n- `observation`\r\n- `triage`\r\ + \n- `surveyResponse`\r\n- `vaccination`" + name: encounter_type + id: + data_type: uuid + description: Tamanu internal identifier (generally a UUID) in encounter_history. + name: id + location_id: + data_type: character varying(255) + description: Reference to the [location](#!/source/source.tamanu.tamanu.locations) + the encounter was in. + name: location_id + updated_by_id: + data_type: character varying(255) + description: '[Who](#!/source/source.tamanu.tamanu.users) made the change.' + name: updated_by_id + config: + tags: + - base + - clinical + description: Records changes to an encounter's basic details. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: encounter_history + tags: + - base + - clinical +- columns: + encounter_id: + data_type: character varying(255) + description: The [encounter](#!/source/source.tamanu.tamanu.encounters) + name: encounter_id + id: + data_type: uuid + description: Tamanu internal identifier (generally a UUID) in encounter_prescriptions. + name: id + is_selected_for_discharge: + data_type: boolean + description: Whether the prescription is for when the patient is discharged. + name: is_selected_for_discharge + prescription_id: + data_type: character varying(255) + description: The [prescription](#!/source/source.tamanu.tamanu.prescriptions) + name: prescription_id + config: + tags: + - base + - clinical + description: Association of encounter to prescription + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: true + tier: silver + name: encounter_prescriptions + tags: + - base + - clinical +- columns: + clinician_id: + data_type: character varying(255) + description: Reference to the [examiner](#!/source/source.tamanu.tamanu.users). + name: clinician_id + department_id: + data_type: character varying(255) + description: Reference to the [department](#!/source/source.tamanu.tamanu.departments) + this encounter is in. + name: department_id + device_id: + data_type: text + description: "Unique identifier for the device that created the encounter.\r\ + \n\r\nDevice IDs are proper to each device and not globally recorded in e.g.\ + \ a `devices` table." + name: device_id + discharge_draft: + data_type: jsonb + description: Draft data of the encounter + name: discharge_draft + encounter_type: + data_type: character varying(31) + description: "The type of the encounter.\r\n\r\nOne of:\r\n- `admission`\r\n\ + - `clinic`\r\n- `imaging`\r\n- `emergency`\r\n- `observation`\r\n- `triage`\r\ + \n- `surveyResponse`\r\n- `vaccination`" + name: encounter_type + end_datetime: + data_type: timestamp + description: The date encounter was discharged/ended + name: end_datetime + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in encounters. + name: id + location_id: + data_type: character varying(255) + description: Reference to the current [location](#!/source/source.tamanu.tamanu.locations) + this encounter is in. + name: location_id + patient_billing_type_id: + data_type: character varying(255) + description: The billing type ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)) + of the patient. + name: patient_billing_type_id + patient_id: + data_type: character varying(255) + description: Reference to the [patient](#!/source/source.tamanu.tamanu.patients). + name: patient_id + planned_location_id: + data_type: character varying(255) + description: "The [location](#!/source/source.tamanu.tamanu.locations) that\ + \ the encounter will transfer to at the\r\n`planned_location_start_time`." + name: planned_location_id + planned_location_start_datetime: + data_type: timestamp + description: The time that the encounter will transfer to the planned location. + name: planned_location_start_datetime + reason_for_encounter: + data_type: text + description: "Free-form information about the encounter.\r\n\r\nCan include\ + \ info like type of survey submitted, emergency diagnosis, etc." + name: reason_for_encounter + referral_source_id: + data_type: character varying(255) + description: The referral source ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)) + of the patient. + name: referral_source_id + start_datetime: + data_type: timestamp + description: The beginning of the encounter + name: start_datetime + config: + tags: + - base + - clinical + description: Tracks the basic information of the patient encounters within Tamanu + from start to finish + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: encounters + tags: + - base + - clinical +- columns: + created_datetime: + data_type: timestamp + description: Timestamp of when record was created in the encounters table. + name: created_datetime + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in encounters. + name: id + updated_datetime: + data_type: timestamp + description: Timestamp of when record was last updated in the encounters table. + name: updated_datetime + config: + tags: + - base + - clinical + - log + description: Metadata information extracted from the change logs for encounters. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: encounters_metadata + tags: + - base + - clinical + - log +- columns: + catchment_id: + data_type: text + description: Catchment area ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: catchment_id + city_town: + data_type: character varying + description: City or town of the facility. + name: city_town + code: + data_type: character varying + description: Code (identifier) for the facility. + name: code + contact_number: + data_type: character varying + description: Administrative contact number of the facility. + name: contact_number + division: + data_type: character varying + description: Administrative division this facility lives in. + name: division + email: + data_type: character varying + description: Administrative email address of the facility. + name: email + id: + data_type: character varying + description: Tamanu internal identifier (generally a UUID) in facilities. + name: id + is_sensitive: + data_type: boolean + description: If set to `true`, encounters created on this facility will only + be viewable when logged into this facility + name: is_sensitive + name: + data_type: character varying + description: Full readable name. + name: name + street_address: + data_type: character varying + description: Street address of the facility. + name: street_address + type: + data_type: character varying + description: Type of the facility. + name: type + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in facilities." + name: visibility_status + config: + tags: + - base + - reference + description: "Table of facilities.\r\n\r\nFacilities may be either or both of:\r\ + \n\r\n- Any healthcare facility, like hospitals, clinics, mobile vaccination vans,\ + \ laboratories, etc\r\n- A Tamanu Facility deployment.\r\n\r\nWhen syncing, patient\ + \ and related records are scoped to a facility, according to the\r\n[`patient_facilities`](#!/source/source.tamanu.tamanu.patient_facilities)\ + \ table." + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: facilities + tags: + - base + - reference +- columns: + area_id: + data_type: character varying(255) + description: Reference to the imaging area ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: area_id + code: + data_type: text + description: External code. + name: code + description: + data_type: text + description: Human-friendly description for the area/code. + name: description + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in imaging_area_external_codes. + name: id + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in imaging_area_external_codes." + name: visibility_status + config: + tags: + - base + - reference + description: "External codes for imaging areas (such as for [PACS](https://en.wikipedia.org/wiki/Picture_archiving_and_communication_system)).\r\ + \n\r\nImaging areas are stored in [Reference Data](#!/source/source.tamanu.tamanu.reference_data),\ + \ this\r\ntable adds additional (external) codes." + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: imaging_area_external_codes + tags: + - base + - reference +- columns: + area_id: + data_type: character varying(255) + description: The imaging area ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: area_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in imaging_request_areas. + name: id + imaging_request_id: + data_type: character varying + description: The [imaging request](#!/source/source.tamanu.tamanu.imaging_requests). + name: imaging_request_id + config: + tags: + - base + - clinical + description: Areas to be imaged as part of an [imaging request](#!/source/source.tamanu.tamanu.imaging_requests). + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: imaging_request_areas + tags: + - base + - clinical +- columns: + completed_by_id: + data_type: character varying(255) + description: Reference to the [user](#!/source/source.tamanu.tamanu.users) who + completed this imaging. + name: completed_by_id + datetime: + data_type: timestamp + description: When the imaging was requested. + name: datetime + display_id: + data_type: character varying(255) + description: Short unique identifier used on the frontend. + name: display_id + encounter_id: + data_type: character varying(255) + description: Reference to the [encounter](#!/source/source.tamanu.tamanu.encounters) + this imaging request is a part of. + name: encounter_id + id: + data_type: character varying + description: Tamanu internal identifier (generally a UUID) in imaging_requests. + name: id + imaging_type: + data_type: character varying(31) + description: "Type of imaging.\r\n\r\nOne of:\r\n- `angiogram`\r\n- `colonoscopy`\r\ + \n- `ctScan`\r\n- `ecg`\r\n- `echocardiogram`\r\n- `endoscopy`\r\n- `fluroscopy`\r\ + \n- `holterMonitor`\r\n- `mammogram`\r\n- `orthopantomography`\r\n- `mri`\r\ + \n- `stressTest`\r\n- `ultrasound`\r\n- `vascularStudy`\r\n- `xRay`" + name: imaging_type + location_group_id: + data_type: character varying(255) + description: Reference to the [location group](#!/source/source.tamanu.tamanu.location_groups) + for this imaging request. + name: location_group_id + location_id: + data_type: character varying(255) + description: Reference to the [location](#!/source/source.tamanu.tamanu.locations) + for this imaging request. + name: location_id + priority: + data_type: character varying(255) + description: "Priority of the request.\r\n\r\nThis is a customisable list; by\ + \ default the values are `routine`, `urgent`, `asap`, `stat`." + name: priority + reason_for_cancellation: + data_type: character varying(1024) + description: "If the request is cancelled, why that is.\r\n\r\nThis is a customisable\ + \ list; by default the values are `duplicate` and `entered-in-error`.\r\n\r\ + \nThe 31-character limit was [arbitrary to avoid extremely long values set\ + \ in error](https://github.com/beyondessential/tamanu/pull/3512/files#r1102169113)." + name: reason_for_cancellation + requested_by_id: + data_type: character varying(255) + description: Reference to the [user](#!/source/source.tamanu.tamanu.users) who + requested this imaging. + name: requested_by_id + status: + data_type: character varying(255) + description: "The status of the request.\r\n\r\nOne of:\r\n- `pending`\r\n-\ + \ `in_progress`\r\n- `completed`\r\n- `cancelled`\r\n- `deleted`\r\n- `entered_in_error`" + name: status + config: + tags: + - base + - clinical + description: "Imaging requests are the entrypoint of imaging workflows in Tamanu.\r\ + \n\r\nEach row is a request for radiology to perform one or more imagings on a\ + \ patient.\r\n\r\nImagings can have one or more [request areas](#!/source/source.tamanu.tamanu.imaging_request_areas)\r\ + \nattached, and when completed will have [results](#!/source/source.tamanu.tamanu.imaging_results)." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: imaging_requests + tags: + - base + - clinical +- columns: + completed_by_id: + data_type: character varying(255) + description: Reference to the [user](#!/source/source.tamanu.tamanu.users) who + completed this imaging. + name: completed_by_id + datetime: + data_type: timestamp + description: When this result was completed. + name: datetime + description: + data_type: text + description: Free-form description / notes about this imaging. + name: description + external_code: + data_type: text + description: External code for this result, used with PACS integration (generally + via FHIR). + name: external_code + id: + data_type: uuid + description: Tamanu internal identifier (generally a UUID) in imaging_results. + name: id + imaging_request_id: + data_type: character varying + description: Reference to the [imaging request](#!/source/source.tamanu.tamanu.imaging_requests). + name: imaging_request_id + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in imaging_results." + name: visibility_status + config: + tags: + - base + - clinical + description: "Result of an [imaging request](#!/source/source.tamanu.tamanu.imaging_requests).\r\ + \n\r\nIn practice, there is usually one or two results per request:\r\n- one containing\ + \ a reference to a PACS image, when imaging integrations are enabled;\r\n- one\ + \ containing notes from a doctor who analysed the image.\r\n\r\nHowever there\ + \ is no limit; for example there may be multiple notes from multiple doctors." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: imaging_results + tags: + - base + - clinical +- columns: + coverage_value: + data_type: numeric + description: The amount of coverage (in percentage) of the insurance contract + item. + name: coverage_value + id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in invoice_insurance_plan_items. + name: id + invoice_insurance_plan_id: + data_type: text + description: Reference to the [insurance contract](#!/source/source.tamanu.tamanu.invoice_insurance_plans). + name: invoice_insurance_plan_id + invoice_product_id: + data_type: text + description: Reference to the [invoice product](#!/source/source.tamanu.tamanu.invoice_products). + name: invoice_product_id + config: + tags: + - base + - reference + description: Table for insurance contract items used for invoicing. + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: invoice_insurance_plan_items + tags: + - base + - reference +- columns: + code: + data_type: character varying(255) + description: Unique identifier code for the insurance contract. + name: code + default_coverage: + data_type: numeric + description: The default coverage (in percentage) of the insurance contract. + name: default_coverage + id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in invoice_insurance_plans. + name: id + name: + data_type: character varying(255) + description: Human-readable name of the insurance contract. + name: name + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in invoice_insurance_plans." + name: visibility_status + config: + tags: + - base + - reference + description: Table for insurance contracts used for invoicing. + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: invoice_insurance_plans + tags: + - base + - reference +- columns: + approved: + data_type: boolean + description: A boolean field that enables clinicians to track the approval status + of individual invoice line items + name: approved + date: + data_type: date + description: When the item was ordered. + name: date + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in invoice_items. + name: id + invoice_id: + data_type: character varying(255) + description: The [invoice](#!/source/source.tamanu.tamanu.invoices). + name: invoice_id + manual_entry_price: + data_type: numeric + description: Manually entered price override for this item, if specified. When + set, this takes precedence over the product's standard price. + name: manual_entry_price + ordered_by_user_id: + data_type: character varying(255) + description: '[Who](#!/source/source.tamanu.tamanu.users) ordered the item.' + name: ordered_by_user_id + price_final: + data_type: numeric + description: The final price per unit for this item on the invoice. This is + determined by the manual_entry_price if provided, otherwise from the product's + price when the invoice is finalised. + name: price_final + product_code_final: + data_type: character varying(255) + description: The final product code used on the invoice. Saved from the product + code field when the invoice is finalised. + name: product_code_final + product_id: + data_type: character varying(255) + description: The [product](#!/source/source.tamanu.tamanu.invoice_products). + name: product_id + product_name_final: + data_type: character varying(255) + description: The final product name used on the invoice. Saved from the product + name field when the invoice is finalised. + name: product_name_final + quantity: + data_type: integer + description: Quantity ordered. + name: quantity + source_record_id: + data_type: character varying(255) + description: Foreign key relation for record type. + name: source_record_id + source_record_type: + data_type: character varying(255) + description: The underlying model that the source record belongs to. + name: source_record_type + config: + tags: + - base + - administration + description: Items (products) on invoices. + name: invoice_items + tags: + - base + - administration +- columns: + id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in invoice_price_list_items. + name: id + invoice_price_list_id: + data_type: text + description: Foreign key reference to the invoice_price_lists table. Links this + pricing item to its parent price list. + name: invoice_price_list_id + invoice_product_id: + data_type: text + description: Foreign key reference to the invoice products/services that can + be priced. Identifies which product or service this pricing item applies to. + name: invoice_product_id + is_hidden: + data_type: boolean + description: Determines whether the related invoice product should be hidden + from searches on the frontend and also whether it should be automatically + added to the invoice. + name: is_hidden + price: + data_type: numeric + description: The price amount for this product in the context of this price + list. Stored as a numeric value representing the cost in the system's base + currency. + name: price + config: + tags: + - base + - reference + description: Contains individual pricing entries for specific products within a + price list. Each record defines the price or pricing configuration for a particular + product in the context of a specific price list. + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: invoice_price_list_items + tags: + - base + - reference +- columns: + code: + data_type: character varying(255) + description: Unique identifier code for the price list. Used for referencing + the price list in business logic and integrations. + name: code + id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in invoice_price_lists. + name: id + name: + data_type: character varying(255) + description: Human-readable name of the price list, displayed in user interfaces + and reports. + name: name + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in invoice_price_lists." + name: visibility_status + config: + tags: + - base + - reference + description: Contains price list definitions used for invoice line item pricing. + Each price list represents a set of pricing rules that can be applied to different + types of invoices, patients, or services. + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: invoice_price_lists + tags: + - base + - reference +- columns: + category: + data_type: character varying(255) + description: The category of the product. + name: category + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in invoice_products. + name: id + insurable: + data_type: boolean + description: Whether or not discounts can be applied to a product + name: insurable + name: + data_type: text + description: Name of the product. + name: name + source_record_id: + data_type: character varying(255) + description: The id of the source record for the product. + name: source_record_id + visibility_status: + data_type: character varying(255) + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in invoice_products." + name: visibility_status + config: + tags: + - base + - reference + description: Products which can be invoiced. + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: invoice_products + tags: + - base + - reference +- columns: + datetime: + data_type: timestamp + description: Local date for the record in invoices. + name: datetime + display_id: + data_type: character varying(255) + description: Short unique identifier used on the frontend. + name: display_id + encounter_id: + data_type: character varying(255) + description: Reference to the [encounter](#!/source/source.tamanu.tamanu.encounters) + this invoice is a part of. + name: encounter_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in invoices. + name: id + insurer_payment_status: + data_type: character varying(255) + description: "Payment status (insurer portion, if applicable).\r\n\r\nOne of:\r\ + \n- `unpaid`\r\n- `paid`\r\n- `partial`\r\n- `rejected`" + name: insurer_payment_status + patient_payment_status: + data_type: character varying(255) + description: "Payment status (patient portion, if applicable).\r\n\r\nOne of:\r\ + \n- `unpaid`\r\n- `paid`\r\n- `partial`" + name: patient_payment_status + status: + data_type: character varying(255) + description: "Status of the invoice.\r\n\r\nOne of:\r\n- `cancelled`\r\n- `in_progress`\r\ + \n- `finalised`" + name: status + config: + tags: + - base + - administration + description: Invoices related to encounters. + name: invoices + tags: + - base + - administration +- columns: + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in lab_request_logs. + name: id + lab_request_id: + data_type: character varying(255) + description: Reference to the [lab request](#!/source/source.tamanu.tamanu.lab_requests). + name: lab_request_id + status: + data_type: character varying(255) + description: The status the lab request was updated to. + name: status + updated_by_id: + data_type: character varying(255) + description: Reference to the [user](#!/source/source.tamanu.tamanu.users) who + updated this lab request. + name: updated_by_id + config: + tags: + - base + - clinical + - log + description: This is a log of who changed the status of a lab request when. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: lab_request_logs + tags: + - base + - clinical + - log +- columns: + created_datetime: + data_type: timestamp + description: Timestamp of when record was created in the lab_request_logs table. + name: created_datetime + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in lab_request_logs. + name: id + updated_datetime: + data_type: timestamp + description: Timestamp of when record was last updated in the lab_request_logs + table. + name: updated_datetime + config: + tags: + - base + - clinical + - log + description: Metadata information extracted from the change logs for lab_request_logs. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: lab_request_logs_metadata + tags: + - base + - clinical + - log +- columns: + collected_by_id: + data_type: character varying(255) + description: Reference to the [Clinician](#!/source/source.tamanu.tamanu.users) + who collected the sample. + name: collected_by_id + collected_datetime: + data_type: timestamp + description: When the sample was collected. + name: collected_datetime + department_id: + data_type: character varying(255) + description: Reference to the [Department](#!/source/source.tamanu.tamanu.departments) + the request comes from. + name: department_id + display_id: + data_type: character varying(255) + description: Short unique identifier used on the frontend. + name: display_id + encounter_id: + data_type: character varying(255) + description: Reference to the [Encounter](#!/source/source.tamanu.tamanu.encounters) + the request is a part of. + name: encounter_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in lab_requests. + name: id + is_specimen_collected: + data_type: boolean + description: "Whether a specimen is attached.\r\n\r\nThis implies `specimen_type_id`." + name: is_specimen_collected + is_urgent: + data_type: boolean + description: Deprecated. + name: is_urgent + lab_sample_site_id: + data_type: character varying(255) + description: "Reference to the [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\ + \ representing where\r\non the patient the sample was taken." + name: lab_sample_site_id + lab_test_category_id: + data_type: character varying(255) + description: "Reference to the [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\ + \ representing the\r\ncategory of this request's test." + name: lab_test_category_id + lab_test_laboratory_id: + data_type: character varying(255) + description: "Reference to the [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\ + \ representing the\r\nlaboratory fulfilling this request." + name: lab_test_laboratory_id + lab_test_panel_request_id: + data_type: uuid + description: "Reference to the [Test Panel Request](#!/source/source.tamanu.tamanu.lab_test_panel_requests)\r\ + \nassociated with this request, if any." + name: lab_test_panel_request_id + lab_test_priority_id: + data_type: character varying(255) + description: "Reference to the [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\ + \ representing the\r\npriority of this request." + name: lab_test_priority_id + published_date: + data_type: character(19) + description: When this lab request's results were published. + name: published_date + reason_for_cancellation: + data_type: character varying(31) + description: "Why this request was cancelled.\r\n\r\nOne of:\r\n- `clinical`\r\ + \n- `duplicate`\r\n- `entered-in-error`\r\n- `other`\r\n- `patient-discharged`\r\ + \n- `patient-refused`" + name: reason_for_cancellation + requested_by_id: + data_type: character varying(255) + description: Reference to the [Clinician](#!/source/source.tamanu.tamanu.users) + who submitted the request. + name: requested_by_id + requested_datetime: + data_type: timestamp + description: When the request was submitted. + name: requested_datetime + specimen_type_id: + data_type: character varying(255) + description: "Reference to the [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\ + \ representing the\r\ntype of the specimen for the request, if specified." + name: specimen_type_id + status: + data_type: character varying(255) + description: "The status of the request.\r\n\r\nOne of:\r\n- `reception_pending`\r\ + \n- `results_pending`\r\n- `interim_results`\r\n- `to_be_verified`\r\n- `verified`\r\ + \n- `published`\r\n- `cancelled`\r\n- `invalidated`\r\n- `deleted`\r\n- `sample-not-collected`\r\ + \n- `entered-in-error`" + name: status + config: + tags: + - base + - clinical + description: "Lab requests are the entrypoint of laboratory workflows in Tamanu.\r\ + \n\r\nEach row is a request for a laboratory to perform a group of tests on a\ + \ sample taken from a patient.\r\n\r\nIt will be updated over the course of the\ + \ workflow to various statuses, starting with\r\n`reception_pending` (lab has\ + \ not received the request yet), up to `published` (lab has completed the\r\n\ + tests and has attached verified results).\r\n\r\nSee also: `lab_request_attachments`,\ + \ `lab_request_logs`, `lab_results`, `lab_tests`,\r\n`lab_test_panels`, and related\ + \ tables to those." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: lab_requests + tags: + - base + - clinical +- columns: + created_datetime: + data_type: timestamp + description: Timestamp of when record was created in the lab_requests table. + name: created_datetime + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in lab_requests. + name: id + updated_datetime: + data_type: timestamp + description: Timestamp of when record was last updated in the lab_requests table. + name: updated_datetime + config: + tags: + - base + - clinical + - log + description: Metadata information extracted from the change logs for lab_requests. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: lab_requests_metadata + tags: + - base + - clinical + - log +- columns: + id: + description: Tamanu internal identifier (generally a UUID) in lab_test_panel_lab_test_types. + name: id + lab_test_panel_id: + description: The [test panel](#!/source/source.tamanu.tamanu.lab_test_panels). + name: lab_test_panel_id + lab_test_type_id: + description: The [test type](#!/source/source.tamanu.tamanu.lab_test_types). + name: lab_test_type_id + config: + tags: + - base + - reference + description: "The lab tests contained in a lab test panel.\r\n\r\nSee [`lab_test_panels`](#!/source/source.tamanu.tamanu.lab_test_panels)\ + \ for more about lab test\r\npanels, and [`lab_test_types`](#!/source/source.tamanu.tamanu.lab_test_types)\ + \ for the test types." + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: lab_test_panel_lab_test_types + tags: + - base + - reference +- columns: + encounter_id: + data_type: character varying(255) + description: Reference to the [encounter](#!/source/source.tamanu.tamanu.encounters) + this lab test panel request is a part of. + name: encounter_id + id: + data_type: uuid + description: Tamanu internal identifier (generally a UUID) in lab_test_panel_requests. + name: id + lab_test_panel_id: + data_type: character varying(255) + description: The [test panel](#!/source/source.tamanu.tamanu.lab_test_panels). + name: lab_test_panel_id + config: + tags: + - base + - clinical + description: "A request for a lab test panel.\r\n\r\nSee [`lab_test_panels`](#!/source/source.tamanu.tamanu.lab_test_panels)\ + \ for more about those." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: lab_test_panel_requests + tags: + - base + - clinical +- columns: + category_id: + data_type: character varying(255) + description: Reference to the category ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)) + of this test panel. + name: category_id + code: + data_type: character varying(255) + description: Internal Tamanu code of the panel. + name: code + external_code: + data_type: text + description: External code, such as for interfacing with LIMS. + name: external_code + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in lab_test_panels. + name: id + name: + data_type: character varying(255) + description: Name of the test panel. + name: name + visibility_status: + data_type: character varying(255) + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in lab_test_panels." + name: visibility_status + config: + tags: + - base + - reference + description: "A panel is a collection of lab test types, usually standardised.\r\ + \n\r\nFor example the BMP (basic metabolic panel) is a panel of 8 blood tests.\ + \ Instead of ordering all 8\r\ntests individually, a clinician can order the panel\ + \ all at once. This may also used to more\r\nefficiently use samples.\r\n\r\n\ + This table defines the available test panels, and\r\n[`lab_test_panel_lab_test_types`](#!/source/source.tamanu.tamanu.lab_test_panel_lab_test_types)\r\ + \ncontains the actual test types that are part of each panel. See\r\n[`lab_test_panel_requests`](#!/source/source.tamanu.tamanu.lab_test_panel_requests)\ + \ for requesting\r\npanels specifically, and [`lab_test_requests`](#!/source/source.tamanu.tamanu.lab_test_requests)\ + \ for\r\nrequesting lab tests in general." + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: lab_test_panels + tags: + - base + - reference +- columns: + code: + data_type: character varying(255) + description: Internal Tamanu code of the test. + name: code + external_code: + data_type: text + description: External code for the test (such as for LIMS). + name: external_code + female_max: + data_type: double precision + description: Maximum typical range for females. + name: female_max + female_min: + data_type: double precision + description: Minimum typical range for females. + name: female_min + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in lab_test_types. + name: id + is_sensitive: + data_type: boolean + description: Used to indicate if the lab test type is sensitive and should be + hidden accordingly. + name: is_sensitive + lab_test_category_id: + data_type: character varying(255) + description: Reference to the category ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)) + of this test. + name: lab_test_category_id + male_max: + data_type: double precision + description: Maximum typical range for males. + name: male_max + male_min: + data_type: double precision + description: Minimum typical range for males. + name: male_min + name: + data_type: character varying(255) + description: Human-friendly name of the test. + name: name + options: + data_type: text + description: Comma-separated list of options. Unused. + name: options + range_text: + data_type: character varying(255) + description: Unused. + name: range_text + result_type: + data_type: character varying(255) + description: "Input type of result.\r\n\r\nOne of:\r\n- `FreeText`\r\n- `Number`\r\ + \n- `Select`" + name: result_type + unit: + data_type: character varying(255) + description: Unit the test result is measured in. + name: unit + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in lab_test_types." + name: visibility_status + config: + tags: + - base + - reference + description: "A kind of test that's possible to request.\r\n\r\nThis includes information\ + \ about the test itself, and also parameters around result formatting, like\r\n\ + data type, expected ranges, etc." + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: lab_test_types + tags: + - base + - reference +- columns: + completed_datetime: + data_type: timestamp + description: Datetime at which the test was completed. + name: completed_datetime + date: + data_type: date + description: Local date for the record in lab_tests. + name: date + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in lab_tests. + name: id + lab_request_id: + data_type: character varying(255) + description: The [lab request](#!/source/source.tamanu.tamanu.lab_requests) + this test is part of. + name: lab_request_id + lab_test_method_id: + data_type: character varying(255) + description: Reference to the method ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)) + of this test. + name: lab_test_method_id + lab_test_type_id: + data_type: character varying(255) + description: The [type](#!/source/source.tamanu.tamanu.lab_test_types) of the + test. + name: lab_test_type_id + laboratory_officer: + data_type: character varying(255) + description: Name of the lab officer performing the test. + name: laboratory_officer + result: + data_type: character varying(255) + description: The result of the test. + name: result + verification: + data_type: character varying(255) + description: "Free-form field for a verification indication.\r\n\r\nMay be a\ + \ verifying or supervising officer's name, a department, lab notes..." + name: verification + config: + tags: + - base + - clinical + description: A single test as part of a [lab request](#!/source/source.tamanu.tamanu.lab_requests). + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: lab_tests + tags: + - base + - clinical +- columns: + booking_type_id: + data_type: character varying(255) + description: "Reference to a [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\r\ + \n(`type=bookingType`)." + name: booking_type_id + clinician_id: + data_type: character varying(255) + description: Reference to the [clinician](#!/source/source.tamanu.tamanu.users) + recording that appointment. + name: clinician_id + encounter_id: + data_type: character varying(255) + description: Reference to the [encounter](#!/source/source.tamanu.tamanu.encounters) + linked to this appointment + name: encounter_id + end_datetime: + data_type: timestamp + description: When the appointment ends. + name: end_datetime + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in appointments. + name: id + is_high_priority: + data_type: boolean + description: Boolean specify if the appointment is high priority. + name: is_high_priority + location_id: + data_type: character varying(255) + description: The [location](#!/source/source.tamanu.tamanu.locations) where + the appointment will take place. + name: location_id + patient_id: + data_type: character varying(255) + description: Reference to the [patient](#!/source/source.tamanu.tamanu.patients). + name: patient_id + start_datetime: + data_type: timestamp + description: When the appointment starts. + name: start_datetime + status: + data_type: character varying(255) + description: "The current status of the appointment record.\r\n\r\nOne of:\r\ + \n- `Confirmed`\r\n- `Arrived`\r\n- `No-show`\r\n- `Cancelled`" + name: status + config: + tags: + - base + - clinical + description: Table of appointments. (location bookings) + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: location_bookings + tags: + - base + - clinical +- columns: + code: + data_type: character varying(255) + description: Code for location group + name: code + facility_id: + data_type: character varying(255) + description: Reference to the [facility](#!/source/source.tamanu.tamanu.facilities) + this location group is in. + name: facility_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in location_groups. + name: id + name: + data_type: character varying(255) + description: Full readable name for location group + name: name + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in location_groups." + name: visibility_status + config: + tags: + - base + - reference + description: A group of locations managed as a single unit (e.g. a ward in hospital) + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: location_groups + tags: + - base + - reference +- columns: + code: + data_type: character varying(255) + description: Code for location + name: code + facility_id: + data_type: character varying(255) + description: Reference to the [facility](#!/source/source.tamanu.tamanu.facilities) + this location is in. + name: facility_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in locations. + name: id + location_group_id: + data_type: character varying(255) + description: Reference to the [group](#!/source/source.tamanu.tamanu.location_groups) + this location is in. + name: location_group_id + max_occupancy: + data_type: integer + description: The maximum number of patients that can be in this location + name: max_occupancy + name: + data_type: character varying(255) + description: Full readable name for location + name: name + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in locations." + name: visibility_status + config: + tags: + - base + - reference + description: Information on the hospital locations. + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: locations + tags: + - base + - reference +- columns: + dispensed_at: + data_type: timestamp + description: The timestamp indicating when the medication was physically dispensed + to the patient. + name: dispensed_at + dispensed_by_user_id: + data_type: character varying(255) + description: Reference to the [user](#!/model/model.public.users) (typically + a pharmacist or pharmacy staff member) who dispensed the medication. + name: dispensed_by_user_id + id: + data_type: uuid + description: Tamanu internal identifier (generally a UUID) in medication_dispenses. + name: id + pharmacy_order_prescription_id: + data_type: uuid + description: Reference to the [pharmacy_order_prescription](#!/source/source.tamanu.tamanu.pharmacy_order_prescriptions) + that this dispense record fulfills. Links this dispensing event to the specific + medication order being filled. + name: pharmacy_order_prescription_id + quantity: + data_type: integer + description: The quantity of medication units dispensed to the patient in each + dispensing. + name: quantity + config: + tags: + - base + - clinical + - reference + description: Records of medication dispensing events, tracking when medications + from pharmacy orders are physically dispensed to patients. Each record represents + a single dispensing event for a specific prescription within a pharmacy order. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: medication_dispenses + tags: + - base + - clinical + - reference +- columns: + authored_by_id: + data_type: character varying(255) + description: Reference to the [user](#!/source/source.tamanu.tamanu.users) who + published this note. + name: authored_by_id + content: + data_type: text + description: The content of the note recorded. + name: content + datetime: + data_type: timestamp + description: Local date for the record in notes. + name: datetime + id: + data_type: uuid + description: Tamanu internal identifier (generally a UUID) in notes. + name: id + note_type_id: + data_type: character varying(255) + description: Reference to the note type ([Reference Data](#!/source/source.tamanu.tamanu.reference_data), + `type = noteType`). + name: note_type_id + on_behalf_of_id: + data_type: character varying(255) + description: Reference to the [user](#!/source/source.tamanu.tamanu.users) who + wrote this note, if it wasn't the user who published it. + name: on_behalf_of_id + record_id: + data_type: character varying(255) + description: Polymorphic relationship to the record to which the note is attached + (id). + name: record_id + record_type: + data_type: character varying(255) + description: Polymorphic relationship to the record to which the note is attached + (type). + name: record_type + updated_note_id: + data_type: uuid + description: Reference to the [note](#!/source/source.tamanu.tamanu.notes) that + is being revised. + name: updated_note_id + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in notes." + name: visibility_status + config: + tags: + - base + - clinical + description: "Notes recorded by clinicians or system generated.\r\n\r\nAlso see\ + \ the deprecated [`note_items`](#!/source/source.tamanu.tamanu.note_items),\r\n\ + [`note_pages`](#!/source/source.tamanu.tamanu.note_pages), and the even older\r\ + \n[`notes_legacy`](#!/source/source.tamanu.tamanu.notes_legacy).\r\n\r\nThis is\ + \ the current version (3) of the notes system." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: notes + tags: + - base + - clinical +- columns: + appointment_type_id: + data_type: character varying(255) + description: "Reference to a [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\r\ + \n(`type=appointmentType`)." + name: appointment_type_id + cancelled_at_date: + data_type: character(10) + description: The date from which appointments in a schedule have been cancelled, + this is set when cancelling 'this and all future appointments'. + name: cancelled_at_date + clinician_id: + data_type: character varying(255) + description: Reference to the [clinician](#!/source/source.tamanu.tamanu.users) + recording that appointment. + name: clinician_id + days_of_week: + data_type: array + description: "Stores an array of ISO weekday abbreviations. \r\nGiven `WEEKLY`\ + \ frequency `days_of_week` determines the weekday that the repeated appointment\ + \ occurs on. \r\nGiven `MONTHLY` frequency `days_of_week` is combined with\ + \ `nth_weekday` to determine the date in each month that the repeated appointment\ + \ occurs on.\r\n\r\nOne of: \r\n- `MO`\r\n- `TU`\r\n- `WE`\r\n- `TH`\r\n-\ + \ `FR`\r\n- `SA`\r\n- `SU`" + name: days_of_week + encounter_id: + data_type: character varying(255) + description: Reference to the [encounter](#!/source/source.tamanu.tamanu.encounters) + linked to this appointment + name: encounter_id + end_datetime: + data_type: timestamp + description: When the appointment ends. + name: end_datetime + frequency: + data_type: character varying(255) + description: "How often the the recurrence occurs.\r\n\r\nOne of:\r\n- `WEEKLY`\r\ + \n- `MONTHLY`" + name: frequency + generated_until_date: + data_type: character(10) + description: The date of the most recent appointment in a schedule, this is + set after generation of the repeated appointment and then updated if it is + necessary to generate further appointments. + name: generated_until_date + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in appointments. + name: id + interval: + data_type: integer + description: "The recurrence interval. For example:\r\n- For a `frequency` of\ + \ `WEEKLY`, an `interval` of 1 means \"Once a week.\"\r\n- For a `frequency`\ + \ of `MONTHLY`, an `interval` of 3 means \"Every 3 months.\"" + name: interval + is_fully_generated: + data_type: boolean + description: Whether or not all repeating appointments have been created for + a schedule + name: is_fully_generated + is_high_priority: + data_type: boolean + description: Boolean specify if the appointment is high priority. + name: is_high_priority + location_group_id: + data_type: character varying(255) + description: The [location group](#!/source/source.tamanu.tamanu.location_groups) + where the appointment will take place. + name: location_group_id + nth_weekday: + data_type: integer + description: "Ordinal weekday for monthly recurrence interpreted with `days_of_week`\ + \ for example:\r\n- `1` with `days_of_week = ['MO']` = First Monday of the\ + \ month\r\n- `2` with `days_of_week = ['TU']` = Second Tuesday of the month\r\ + \n- `-1` with `days_of_week = ['FR']` = Last Friday of the month" + name: nth_weekday + occurrence_count: + data_type: integer + description: "When this value is set, the recurrence ends after generating the\ + \ specified number of occurrences\r\nAt least one of `occurrence_count` or\ + \ `until_date` must be set." + name: occurrence_count + patient_id: + data_type: character varying(255) + description: Reference to the [patient](#!/source/source.tamanu.tamanu.patients). + name: patient_id + schedule_id: + data_type: uuid + description: Reference to the [appointment schedule](#!/source/source.tamanu.tamanu.appointment_schedules) + in the case of repeating appointments. + name: schedule_id + start_datetime: + data_type: timestamp + description: When the appointment starts. + name: start_datetime + status: + data_type: character varying(255) + description: "The current status of the appointment record.\r\n\r\nOne of:\r\ + \n- `Confirmed`\r\n- `Arrived`\r\n- `No-show`\r\n- `Cancelled`" + name: status + until_date: + data_type: date + description: "The end date for the recurrence. No occurrences will be generated\ + \ beyond this date. \r\nBoth `until_date` and `occurrence_count` cannot be\ + \ null at the same time to ensure the recurrence has an end condition." + name: until_date + config: + tags: + - base + - clinical + description: Table of appointments. (outpatient appointment) + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: outpatient_appointments + tags: + - base + - clinical +- columns: + appointment_id: + description: Reference to the [appointment](#!/model/model.tamanu_source_dbt.outpatient_appointments) + that was modified. + name: appointment_id + appointment_type_id: + description: Current [appointment type](#!/model/model.tamanu_source_dbt.reference_data) + ID (after the change). + name: appointment_type_id + change_id: + description: Unique identifier for the change log entry (UUID from logs.changes). + name: change_id + change_sequence: + description: "Sequential number of this change for the appointment.\r\n- 1 =\ + \ initial creation event\r\n- 2+ = subsequent modifications\r\n\r\nUses ROW_NUMBER()\ + \ partitioned by appointment_id and ordered by logged_at." + name: change_sequence + clinician_id: + description: Current [clinician](#!/model/model.tamanu_source_dbt.users) ID + (after the change). + name: clinician_id + created_by_user_id: + description: Reference to the [user](#!/model/model.tamanu_source_dbt.users) + who originally created the appointment. + name: created_by_user_id + end_datetime: + description: Current appointment end date and time (after the change). + name: end_datetime + is_high_priority: + description: Current priority status (after the change). Boolean indicating + if the appointment is high priority. + name: is_high_priority + location_group_id: + description: Current [location group](#!/model/model.tamanu_source_dbt.location_groups)/area + ID (after the change). + name: location_group_id + modified_by_user_id: + description: Reference to the [user](#!/model/model.tamanu_source_dbt.users) + who made the modification. + name: modified_by_user_id + modified_datetime: + description: Timestamp when the change was logged (from logs.changes.logged_at). + name: modified_datetime + patient_id: + description: Reference to the [patient](#!/model/model.tamanu_source_dbt.patients) + associated with the appointment. + name: patient_id + prev_appointment_type_id: + description: Previous appointment type ID (before the change). Null for creation + events (change_sequence = 1). + name: prev_appointment_type_id + prev_clinician_id: + description: Previous clinician ID (before the change). Null for creation events + (change_sequence = 1). + name: prev_clinician_id + prev_end_datetime: + description: Previous appointment end date and time (before the change). Null + for creation events (change_sequence = 1). + name: prev_end_datetime + prev_is_high_priority: + description: Previous priority status (before the change). Null for creation + events (change_sequence = 1). + name: prev_is_high_priority + prev_location_group_id: + description: Previous location group/area ID (before the change). Null for creation + events (change_sequence = 1). + name: prev_location_group_id + prev_start_datetime: + description: Previous appointment start date and time (before the change). Null + for creation events (change_sequence = 1). + name: prev_start_datetime + prev_status: + description: Previous appointment status (before the change). Null for creation + events (change_sequence = 1). + name: prev_status + schedule_id: + description: Current recurring schedule ID (after the change). References appointment_schedules + table. + name: schedule_id + start_datetime: + description: Current appointment start date and time (after the change). + name: start_datetime + status: + description: "Current appointment status (after the change).\r\n\r\nOne of:\r\ + \n- `Confirmed`\r\n- `Arrived`\r\n- `No-show`\r\n- `Cancelled`" + name: status + config: + tags: + - base + - base + - clinical + - audit + description: 'Base model for appointment change logs. Contains all changes to appointments + extracted from the logs.changes table, including the initial creation. Each row + represents a change event with both current and previous values. + + ' + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: outpatient_appointments_change_logs + tags: + - base + - clinical + - audit +- columns: + blood_type: + data_type: character varying(255) + description: "Blood type.\r\n\r\nOne of:\r\n- `A+`\r\n- `A-`\r\n- `AB-`\r\n\ + - `AB+`\r\n- `B+`\r\n- `B-`\r\n- `O+`\r\n- `O-`" + name: blood_type + tags: + - quasi_identifier + country_id: + data_type: character varying(255) + description: Reference to patient country of residence ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: country_id + tags: + - quasi_identifier + country_of_birth_id: + data_type: character varying(255) + description: Reference to patient country of birth ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: country_of_birth_id + tags: + - quasi_identifier + division_id: + data_type: character varying(255) + description: Reference to patient administrative division of residence ([Reference + Data](#!/source/source.tamanu.tamanu.reference_data)). + name: division_id + tags: + - quasi_identifier + educational_level: + data_type: character varying(255) + description: Highest educational attainment. + name: educational_level + tags: + - quasi_identifier + ethnicity_id: + data_type: character varying(255) + description: Reference to patient ethnicity ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: ethnicity_id + tags: + - quasi_identifier + father_id: + data_type: character varying(255) + description: Reference to [patient](#!/source/source.tamanu.tamanu.patients) + ID of father / parent. + name: father_id + tags: + - quasi_identifier + health_center_id: + data_type: text + description: Reference to patient primary health center ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: health_center_id + tags: + - quasi_identifier + insurer_id: + data_type: character varying(255) + description: Reference to patient insurer ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: insurer_id + tags: + - quasi_identifier + marital_status: + data_type: character varying(255) + description: "Marital status.\r\n\r\nOne of:\r\n- `Defacto`\r\n- `Married`\r\ + \n- `Single`\r\n- `Widow`\r\n- `Divorced`\r\n- `Separated`\r\n- `Unknown`" + name: marital_status + tags: + - quasi_identifier + medical_area_id: + data_type: character varying(255) + description: Reference to patient administrative medical area of residence ([Reference + Data](#!/source/source.tamanu.tamanu.reference_data)). + name: medical_area_id + tags: + - quasi_identifier + mother_id: + data_type: character varying(255) + description: Reference to [patient](#!/source/source.tamanu.tamanu.patients) + ID of mother / parent. + name: mother_id + tags: + - quasi_identifier + nationality_id: + data_type: character varying(255) + description: Reference to patient nationality ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: nationality_id + tags: + - quasi_identifier + nursing_zone_id: + data_type: character varying(255) + description: Reference to patient administrative nursing zone of residence ([Reference + Data](#!/source/source.tamanu.tamanu.reference_data)). + name: nursing_zone_id + tags: + - quasi_identifier + occupation_id: + data_type: character varying(255) + description: Reference to patient occupation ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: occupation_id + tags: + - quasi_identifier + patient_billing_type_id: + data_type: character varying(255) + description: Reference to patient billing type. + name: patient_billing_type_id + tags: + - quasi_identifier + patient_id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in patient_additional_data. + name: patient_id + place_of_birth: + data_type: character varying(255) + description: Free-form place of birth (typically a place name or country). + name: place_of_birth + tags: + - quasi_identifier + registered_by_id: + data_type: character varying(255) + description: Reference to the [user](#!/source/source.tamanu.tamanu.users) who + registered the patient in Tamanu. + name: registered_by_id + registration_date: + data_type: date + description: Timestamp of when record was created in patient_additional_data + which is used as a best estimate of registration date. + name: registration_date + religion_id: + data_type: character varying(255) + description: Reference to patient religion ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: religion_id + tags: + - quasi_identifier + secondary_village_id: + data_type: text + description: "Reference to patient administrative village of residence ([Reference\ + \ Data](#!/source/source.tamanu.tamanu.reference_data), secondary).\r\n\r\n\ + See also [`patients.village_id`](#!/source/source.tamanu.tamanu.patients)." + name: secondary_village_id + tags: + - quasi_identifier + subdivision_id: + data_type: character varying(255) + description: Reference to patient administrative subdivision of residence ([Reference + Data](#!/source/source.tamanu.tamanu.reference_data)). + name: subdivision_id + tags: + - quasi_identifier + title: + data_type: character varying(255) + description: 'Patient name: title.' + name: title + updated_by_field: + data_type: json + description: "JSON object recording the updated datetime for individual columns.\r\ + \n\r\nAs PADs contain a lot of disparate data, it's not uncommon that fields\ + \ are edited separately in\r\ndifferent facilities. The default sync strategy\ + \ is for the last edit to a whole row to \"win out\" in\r\ncase of a conflict,\ + \ but this can lead to discarding important data in the case of PADs. This\ + \ field\r\nis used to implement per-field \"last edit wins\" instead." + name: updated_by_field + config: + tags: + - base + - patient + description: "Core or adjunct patient data that doesn't fit elsewhere, but is only\ + \ downloaded to a facility once a\r\npatient is marked for sync.\r\n\r\nThis is\ + \ often referred to as \"PAD\".\r\n\r\nSee also `patient_field_definition_categories`,\ + \ `patient_field_definitions`, and `patient_field_values`,\r\nwhich define and\ + \ specify custom/non-standard data to be stored against patients." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: true + tier: silver + name: patient_additional_data + tags: + - base + - patient +- columns: + blood_type: + data_type: text + description: "Blood type.\r\n\r\nOne of:\r\n- `A+`\r\n- `A-`\r\n- `AB-`\r\n\ + - `AB+`\r\n- `B+`\r\n- `B-`\r\n- `O+`\r\n- `O-` from history." + name: blood_type + tags: + - quasi_identifier + changelog_id: + data_type: uuid + description: The ID of the change log row. UUID + name: changelog_id + country_id: + data_type: text + description: Reference to patient country of residence ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + from history. + name: country_id + tags: + - quasi_identifier + country_of_birth_id: + data_type: text + description: Reference to patient country of birth ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + from history. + name: country_of_birth_id + tags: + - quasi_identifier + division_id: + data_type: text + description: Reference to patient administrative division of residence ([Reference + Data](#!/source/source.tamanu.tamanu.reference_data)). from history. + name: division_id + tags: + - quasi_identifier + educational_level: + data_type: text + description: Highest educational attainment. from history. + name: educational_level + tags: + - quasi_identifier + ethnicity_id: + data_type: text + description: Reference to patient ethnicity ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + from history. + name: ethnicity_id + tags: + - quasi_identifier + father_id: + data_type: text + description: Reference to [patient](#!/source/source.tamanu.tamanu.patients) + ID of father / parent. from history. + name: father_id + tags: + - quasi_identifier + health_center_id: + data_type: text + description: Reference to patient primary health center ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + from history. + name: health_center_id + tags: + - quasi_identifier + insurer_id: + data_type: text + description: Reference to patient insurer ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + from history. + name: insurer_id + tags: + - quasi_identifier + logged_at: + data_type: timestamp + description: The timestamp this change was logged. in patient additional data + history. + name: logged_at + marital_status: + data_type: text + description: "Marital status.\r\n\r\nOne of:\r\n- `Defacto`\r\n- `Married`\r\ + \n- `Single`\r\n- `Widow`\r\n- `Divorced`\r\n- `Separated`\r\n- `Unknown`\ + \ from history." + name: marital_status + tags: + - quasi_identifier + medical_area_id: + data_type: text + description: Reference to patient administrative medical area of residence ([Reference + Data](#!/source/source.tamanu.tamanu.reference_data)). from history. + name: medical_area_id + tags: + - quasi_identifier + mother_id: + data_type: text + description: Reference to [patient](#!/source/source.tamanu.tamanu.patients) + ID of mother / parent. from history. + name: mother_id + tags: + - quasi_identifier + nationality_id: + data_type: text + description: Reference to patient nationality ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + from history. + name: nationality_id + tags: + - quasi_identifier + nursing_zone_id: + data_type: text + description: Reference to patient administrative nursing zone of residence ([Reference + Data](#!/source/source.tamanu.tamanu.reference_data)). from history. + name: nursing_zone_id + tags: + - quasi_identifier + occupation_id: + data_type: text + description: Reference to patient occupation ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + from history. + name: occupation_id + tags: + - quasi_identifier + patient_billing_type_id: + data_type: text + description: Reference to patient billing type. from history. + name: patient_billing_type_id + tags: + - quasi_identifier + patient_id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in patient_additional_data + from history. + name: patient_id + place_of_birth: + data_type: text + description: Free-form place of birth (typically a place name or country). from + history. + name: place_of_birth + tags: + - quasi_identifier + registered_by_id: + data_type: text + description: Reference to the [user](#!/source/source.tamanu.tamanu.users) who + registered the patient in Tamanu. from history. + name: registered_by_id + registration_date: + data_type: date + description: Timestamp of when record was created in patient additional data + history which is used as a best estimate of registration date. + name: registration_date + religion_id: + data_type: text + description: Reference to patient religion ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + from history. + name: religion_id + tags: + - quasi_identifier + secondary_village_id: + data_type: text + description: "Reference to patient administrative village of residence ([Reference\ + \ Data](#!/source/source.tamanu.tamanu.reference_data), secondary).\r\n\r\n\ + See also [`patients.village_id`](#!/source/source.tamanu.tamanu.patients).\ + \ from history." + name: secondary_village_id + tags: + - quasi_identifier + subdivision_id: + data_type: text + description: Reference to patient administrative subdivision of residence ([Reference + Data](#!/source/source.tamanu.tamanu.reference_data)). from history. + name: subdivision_id + tags: + - quasi_identifier + title: + data_type: text + description: 'Patient name: title. from history.' + name: title + updated_by_field: + data_type: jsonb + description: "JSON object recording the updated datetime for individual columns.\r\ + \n\r\nAs PADs contain a lot of disparate data, it's not uncommon that fields\ + \ are edited separately in\r\ndifferent facilities. The default sync strategy\ + \ is for the last edit to a whole row to \"win out\" in\r\ncase of a conflict,\ + \ but this can lead to discarding important data in the case of PADs. This\ + \ field\r\nis used to implement per-field \"last edit wins\" instead. from\ + \ history." + name: updated_by_field + updated_by_user_id: + data_type: text + description: "The value of the `updated_by_user_id` field of the change data.\r\ + \n\r\nThis is extracted from the data to make it easier to query on. in patient\ + \ additional data history." + name: updated_by_user_id + config: + tags: + - base + - patient + - log + description: "Change logs of Core or adjunct patient data that doesn't fit elsewhere,\ + \ but is only downloaded to a facility once a\r\npatient is marked for sync.\r\ + \n\r\nThis is often referred to as \"PAD\".\r\n\r\nSee also `patient_field_definition_categories`,\ + \ `patient_field_definitions`, and `patient_field_values`,\r\nwhich define and\ + \ specify custom/non-standard data to be stored against patients." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: true + tier: silver + name: patient_additional_data_change_logs + tags: + - base + - patient + - log +- columns: + allergy_id: + data_type: character varying(255) + description: Reference to an allergy ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: allergy_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in patient_allergies. + name: id + patient_id: + data_type: character varying(255) + description: Reference to the [patient](#!/source/source.tamanu.tamanu.patients). + name: patient_id + recorded_by: + data_type: character varying(255) + description: Reference to the [practitioner](#!/source/source.tamanu.tamanu.users) + recording this allergy. + name: recorded_by + recorded_date: + data_type: date + description: Datetime at which this allergy was recorded. + name: recorded_date + config: + tags: + - base + - clinical + description: "List of allergies known of the patient.\r\n\r\nIn Tamanu this is displayed\ + \ and entered in the patient view sidebar, under \"Allergies\".\r\n\r\nSee also:\ + \ `public.patient_care_plans`, `public.patient_conditions`,\r\n`public.patient_family_histories`,\ + \ `public.patient_issues`." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_allergies + tags: + - base + - clinical +- columns: + apgar_score_five_minutes: + data_type: integer + description: '[Apgar score](https://en.wikipedia.org/wiki/Apgar_score) five + minutes after birth.' + name: apgar_score_five_minutes + apgar_score_one_minute: + data_type: integer + description: '[Apgar score](https://en.wikipedia.org/wiki/Apgar_score) one minute + after birth.' + name: apgar_score_one_minute + apgar_score_ten_minutes: + data_type: integer + description: '[Apgar score](https://en.wikipedia.org/wiki/Apgar_score) ten minutes + after birth.' + name: apgar_score_ten_minutes + attendant_at_birth: + data_type: character varying(255) + description: "The type of the attendant at birth.\r\n\r\nOne of:\r\n- `doctor`\r\ + \n- `midwife`\r\n- `nurse`\r\n- `traditional_birth_attentdant`\r\n- `other`" + name: attendant_at_birth + birth_delivery_type: + data_type: character varying(255) + description: "Type of delivery.\r\n\r\nOne of:\r\n- `normal_vaginal_delivery`\r\ + \n- `breech`\r\n- `emergency_c_section`\r\n- `elective_c_section`\r\n- `vacuum_extraction`\r\ + \n- `forceps`\r\n- `other`" + name: birth_delivery_type + birth_facility_id: + data_type: character varying(255) + description: "Reference to the [facility](#!/source/source.tamanu.tamanu.facilities)\ + \ the birth was recorded at.\r\n\r\nThis is only required when `registered_birth_place`\ + \ is `health_facility`." + name: birth_facility_id + birth_length: + data_type: numeric + description: Length in cm at birth. + name: birth_length + birth_time: + data_type: time + description: Datetime of birth. + name: birth_time + birth_type: + data_type: character varying(255) + description: '`single` or `plural` birth.' + name: birth_type + birth_weight: + data_type: numeric + description: Weight in kg at birth. + name: birth_weight + gestational_age_estimate: + data_type: double precision + description: Gestational age estimate (weeks). + name: gestational_age_estimate + name_of_attendant_at_birth: + data_type: character varying(255) + description: Name of attendant at birth. + name: name_of_attendant_at_birth + patient_id: + data_type: character varying(255) + description: "Reference to the [patient](#!/source/source.tamanu.tamanu.patients).\r\ + \n\r\nThere is at most one `patient_birth_data` row per patient.\r\n\r\nNote\ + \ that the `id` column is generated from this column to enforce this." + name: patient_id + registered_birth_place: + data_type: character varying(255) + description: "Type of the actual birth place.\r\n\r\nOne of:\r\n- `health_facility`\r\ + \n- `home`\r\n- `other`" + name: registered_birth_place + registration_date: + data_type: date + description: Timestamp of when record was created in patient_birth_data. + name: registration_date + config: + tags: + - base + - clinical + description: "Information about the birth of the patient, if their birth was recorded\ + \ into Tamanu.\r\n\r\nThis is specifically data about the newborn, and only the\ + \ birth-relevant data.\r\nOther patient data is found in the normal tables i.e.\ + \ `patients`, `patient_additional_data`, etc." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_birth_data + tags: + - base + - clinical +- columns: + care_plan_datetime: + data_type: timestamp + description: Local date for the record in patient_care_plans. + name: care_plan_datetime + care_plan_id: + data_type: character varying(255) + description: Reference to the care plan ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: care_plan_id + clinician_id: + data_type: character varying(255) + description: Reference to the [practitioner](#!/source/source.tamanu.tamanu.users) + who prescribed this care plan. + name: clinician_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in patient_care_plans. + name: id + patient_id: + data_type: character varying(255) + description: Reference to the [patient](#!/source/source.tamanu.tamanu.patients). + name: patient_id + config: + tags: + - base + - clinical + description: "List of current care plans the patient is on.\r\n\r\nIn Tamanu this\ + \ is displayed and entered in the patient view sidebar, under \"Care plans\".\r\ + \n\r\nSee also: `public.patient_allergies`, `public.patient_conditions`, `public.patient_family_histories`,\r\ + \n`public.patient_issues`." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_care_plans + tags: + - base + - clinical +- columns: + condition_id: + data_type: character varying(255) + description: Reference to a diagnosis describing this issue ([Reference Data](#!/source/source.tamanu.tamanu.reference_data)). + name: condition_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in patient_conditions. + name: id + is_resolved: + data_type: boolean + description: Whether the condition has resolved. + name: is_resolved + note: + data_type: character varying(255) + description: Free-form description of this condition. + name: note + patient_id: + data_type: character varying(255) + description: Reference to the [patient](#!/source/source.tamanu.tamanu.patients). + name: patient_id + recorded_by_id: + data_type: character varying(255) + description: "Reference to the [practitioner](#!/source/source.tamanu.tamanu.users)\ + \ diagnosing/recording this\r\ncondition." + name: recorded_by_id + recorded_datetime: + data_type: timestamp + description: Datetime at which this issue was recorded. + name: recorded_datetime + resolution_note: + data_type: text + description: Free-form description or notes about the resolution of this condition. + name: resolution_note + resolved_by_id: + data_type: character varying(255) + description: "Reference to the [practitioner](#!/source/source.tamanu.tamanu.users)\ + \ diagnosing/recording the\r\nresolution of this condition." + name: resolved_by_id + resolved_datetime: + data_type: character(19) + description: Datetime at which this issue was resolved. + name: resolved_datetime + config: + tags: + - base + - clinical + description: "List of ongoing conditions known about a patient.\r\n\r\nIn Tamanu\ + \ this is displayed and entered in the patient view sidebar, under \"Ongoing conditions\"\ + .\r\n\r\nSee also: `public.patient_allergies`, `public.patient_care_plans`,\r\n\ + `public.patient_family_histories`, `public.patient_issues`." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_conditions + tags: + - base + - clinical +- columns: + condition_id: + data_type: character varying(255) + description: Reference to the condition ([Reference Data](#!/source/source.tamanu.tamanu.reference_data), + `type = diagnosis`). + name: condition_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in contributing_death_causes. + name: id + min_after_onset: + data_type: integer + description: Time between onset of recorded cause and death in minutes. + name: min_after_onset + patient_death_data_id: + data_type: character varying(255) + description: The [`patient_death_data`](#!/source/source.tamanu.tamanu.patient_death_data) + record. + name: patient_death_data_id + config: + tags: + - base + - clinical + description: Contributing causes recorded with the patient's death data. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_death_contributing_causes + tags: + - base + - clinical +- columns: + antecedent_cause1_condition_id: + data_type: character varying(255) + description: "Reference to an antecedent (1) cause of death\r\n([Reference Data](#!/source/source.tamanu.tamanu.reference_data)),\ + \ if applicable." + name: antecedent_cause1_condition_id + antecedent_cause1_mins_after_onset: + data_type: integer + description: The time in minutes after onset of an antecedent (1) cause of death, + if applicable. + name: antecedent_cause1_mins_after_onset + antecedent_cause2_condition_id: + data_type: character varying(255) + description: "Reference to an antecedent (2) cause of death\r\n([Reference Data](#!/source/source.tamanu.tamanu.reference_data)),\ + \ if applicable." + name: antecedent_cause2_condition_id + antecedent_cause2_mins_after_onset: + data_type: integer + description: The time in minutes after onset of an antecedent (2) cause of death, + if applicable. + name: antecedent_cause2_mins_after_onset + antecedent_cause3_condition_id: + data_type: character varying(255) + description: "Reference to an antecedent (3) cause of death\r\n([Reference Data](#!/source/source.tamanu.tamanu.reference_data)),\ + \ if applicable." + name: antecedent_cause3_condition_id + antecedent_cause3_mins_after_onset: + data_type: integer + description: The time in minutes after onset of an antecedent (3) cause of death, + if applicable. + name: antecedent_cause3_mins_after_onset + autopsy_findings_used: + data_type: character varying(255) + description: If an autopsy was requested, whether the findings were used in + the death certification. + name: autopsy_findings_used + autopsy_requested: + data_type: character varying(255) + description: Whether an autopsy was requested. + name: autopsy_requested + birth_weight: + data_type: integer + description: If the deceased was a foetus, stillborn, or infant, their birth + weight. + name: birth_weight + carrier_age: + data_type: integer + description: If the deceased was a foetus, stillborn, or infant, the age of + the carrier. + name: carrier_age + carrier_pregnancy_weeks: + data_type: integer + description: If the deceased was a foetus, stillborn, or infant, how many weeks + pregnant their carrier was. + name: carrier_pregnancy_weeks + external_cause_date: + data_type: date + description: Datetime of external cause of death, if applicable. + name: external_cause_date + external_cause_location: + data_type: character varying(255) + description: Physical location of external cause of death, if applicable. + name: external_cause_location + external_cause_notes: + data_type: text + description: Free-form description of the location of external cause of death, + if applicable. + name: external_cause_notes + facility_id: + data_type: character varying(255) + description: Reference to the [facility](#!/source/source.tamanu.tamanu.facilities) + where this death is being recorded. + name: facility_id + had_recent_surgery: + data_type: character varying(255) + description: Whether the deceased patient had a recent surgery, if any. + name: had_recent_surgery + hours_survived_since_birth: + data_type: integer + description: If the deceased was an infant, how many days since the birth passed + before their death. + name: hours_survived_since_birth + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in patient_death_data. + name: id + is_final: + data_type: boolean + description: "Whether this date record is final.\r\n\r\nIn Tamanu, this is set\ + \ by a supervisor after review, and cannot be reversed; it causes all fields\ + \ to\r\nbecome read-only. The only way to undo this record is through a `death_revert_logs`." + name: is_final + last_surgery_date: + data_type: date + description: Datetime of the most recent surgery the patient received, if any. + name: last_surgery_date + last_surgery_reason_id: + data_type: character varying(255) + description: "Reference to a `diagnosis` ([Reference Data](#!/source/source.tamanu.tamanu.reference_data))\ + \ for the\r\nreason of the most recent surgery the patient received, if any." + name: last_surgery_reason_id + manner: + data_type: character varying(255) + description: A descriptive text specifying the manner of death. + name: manner + manner_of_death_description: + data_type: text + description: If an external cause occurred, a text description on how and if + applicable, notes of poisoning agent. + name: manner_of_death_description + mother_condition_description: + data_type: text + description: A text description stating the conditions of mother that affected + the fetus/newborn, if the death was perinatal. + name: mother_condition_description + multiple_pregnancy: + data_type: character varying(255) + description: Whether the deceased infant happened in a multiple pregnancy. + name: multiple_pregnancy + patient_id: + data_type: character varying(255) + description: The [patient](#!/source/source.tamanu.tamanu.patients) who died. + name: patient_id + pregnancy_contributed: + data_type: character varying(255) + description: Whether the pregnancy contributed to the death. + name: pregnancy_contributed + pregnancy_moment: + data_type: character varying(255) + description: The status of the pregnancy of the deceased, if applicable. + name: pregnancy_moment + primary_cause_condition_id: + data_type: character varying(255) + description: "Reference to the primary cause of death\r\n([Reference Data](#!/source/source.tamanu.tamanu.reference_data)),\ + \ if known." + name: primary_cause_condition_id + primary_cause_mins_after_onset: + data_type: integer + description: The time in minutes after onset of the primary cause of death, + if known. + name: primary_cause_mins_after_onset + recorded_by_id: + data_type: character varying(255) + description: Reference to the [clinician](#!/source/source.tamanu.tamanu.users) + who is recording this death. + name: recorded_by_id + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in patient_death_data." + name: visibility_status + was_fetal_or_infant: + data_type: boolean + description: Whether the deceased was themselves a foetus or infant. + name: was_fetal_or_infant + was_outside_health_facility: + data_type: boolean + description: Whether the death occurred outside of the facility. + name: was_outside_health_facility + was_pregnant: + data_type: character varying(255) + description: Whether the deceased was pregnant. + name: was_pregnant + was_stillborn: + data_type: character varying(255) + description: Whether the deceased was themselves stillborn. + name: was_stillborn + was_within_day_of_birth: + data_type: boolean + description: If the deceased was a foetus, stillborn, or infant, whether their + passing was on the day of their birth. + name: was_within_day_of_birth + config: + tags: + - base + - clinical + description: Information about a patient's death. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_death_data + tags: + - base + - clinical +- columns: + created_at: + data_type: timestamp with time zone + description: Timestamp of when record was created in patient_facilities. + name: created_at + facility_id: + data_type: character varying(255) + description: Reference to the [facility](#!/source/source.tamanu.tamanu.facilities). + name: facility_id + id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in patient_facilities. + name: id + patient_id: + data_type: character varying(255) + description: Reference to the [patient](#!/source/source.tamanu.tamanu.patients). + name: patient_id + config: + tags: + - base + - clinical + description: "Tracks which patients are of interest to which facilities.\r\n\r\n\ + This is used to refine sync data: only patient data related to these patients\ + \ is synced to a\r\nfacility (plus general data, and some exceptions apply like\ + \ vaccine data under some conditions).\r\n\r\nIn Tamanu, this can be set manually\ + \ on the facility server (via the \"mark for sync\" button), or\r\ncentrally (via\ + \ some labs / vaccine programs, or via bulk-imports).\r\n\r\n_(\"Joe Patient attends\ + \ X Clinic\" is clinical info; even though an entry in patient facilities\r\n\ + doesn't necessarily imply this, it often does.)_" + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_facilities + tags: + - base + - clinical +- columns: + clinician_id: + data_type: character varying(255) + description: Reference to the [practitioner](#!/source/source.tamanu.tamanu.users) + recording this history. + name: clinician_id + diagnosis_id: + data_type: character varying(255) + description: "Reference to a diagnosis ([Reference Data](#!/source/source.tamanu.tamanu.reference_data))\r\ + \ndescribing this issue." + name: diagnosis_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in patient_family_histories. + name: id + note: + data_type: character varying(255) + description: Free-form description of this issue. + name: note + patient_id: + data_type: character varying(255) + description: Reference to the [patient](#!/source/source.tamanu.tamanu.patients). + name: patient_id + recorded_datetime: + data_type: timestamp + description: Datetime at which this issue was recorded. + name: recorded_datetime + relationship: + data_type: character varying(255) + description: Free-form description of the family relationship. + name: relationship + config: + tags: + - base + - clinical + description: "List of family history conditions known about a patient.\r\n\r\nIn\ + \ Tamanu this is displayed and entered in the patient view sidebar, under \"Family\ + \ history\".\r\n\r\nSee also: `public.patient_allergies`, `public.patient_care_plans`,\ + \ `public.patient_conditions`,\r\n`public.patient_issues`." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_family_histories + tags: + - base + - clinical +- columns: + definition_id: + data_type: character varying(255) + description: The [field definition](#!/source/source.tamanu.tamanu.patient_field_definitions). + name: definition_id + patient_id: + data_type: character varying(255) + description: Reference to the [patient](#!/source/source.tamanu.tamanu.patients). + name: patient_id + value: + data_type: text + description: Value. + name: value + config: + tags: + - base + - patient + description: "Values recorded in custom patient fields.\r\n\r\nThe `id` column is\ + \ generated to enforce one value row per field definition per patient." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: true + tier: silver + name: patient_field_values + tags: + - base + - patient +- columns: + datetime: + data_type: timestamp + description: Local date for the record in patient_program_registration_conditions. + name: datetime + deleted_by_id: + data_type: character varying(255) + description: Reference to the [Clinician](#!/source/source.tamanu.tamanu.users) + that removed the condition. + name: deleted_by_id + deleted_datetime: + data_type: timestamp + description: Date field which is a timestamp of record being deleted in patient_program_registration_conditions. + name: deleted_datetime + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in patient_program_registration_conditions. + name: id + patient_program_registration_id: + data_type: uuid + description: "Reference to the [Patient Program Registry](#!/source/source.tamanu.tamanu.patient_program_registrations)\r\ + \nof the condition." + name: patient_program_registration_id + program_registry_condition_category_id: + data_type: character varying(255) + description: "Reference to the [Program Registry Condition Category](#!/source/source.tamanu.tamanu.program_registry_condition_categories)\r\ + \nof the condition." + name: program_registry_condition_category_id + program_registry_condition_id: + data_type: character varying(255) + description: Reference to the [Program Registry Condition](#!/source/source.tamanu.tamanu.program_registry_conditions). + name: program_registry_condition_id + reason_for_change: + data_type: character varying(255) + description: Optional field for recording the reason for changing the condition. + name: reason_for_change + recorded_by_id: + data_type: character varying(255) + description: Reference to the [Clinician](#!/source/source.tamanu.tamanu.users) + recording that condition. + name: recorded_by_id + config: + tags: + - base + - clinical + description: Table of conditions related to patients in a program registration. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_program_registration_conditions + tags: + - base + - clinical +- columns: + changelog_id: + data_type: uuid + description: The ID of the change log row. UUID + name: changelog_id + datetime: + data_type: timestamp + description: Local date for the record in patient_program_registration_conditions + history. + name: datetime + deleted_by_id: + data_type: text + description: Reference to the [Clinician](#!/source/source.tamanu.tamanu.users) + that removed the condition. from history. + name: deleted_by_id + deleted_datetime: + data_type: timestamp + description: Date field which is a timestamp of record being deleted in patient_program_registration_conditions + history. + name: deleted_datetime + id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in patient_program_registration_conditions. + name: id + logged_at: + data_type: timestamp + description: The timestamp this change was logged. in patient program registration + condition record. + name: logged_at + patient_program_registration_id: + data_type: text + description: "Reference to the [Patient Program Registry](#!/source/source.tamanu.tamanu.patient_program_registrations)\r\ + \nof the condition. from history." + name: patient_program_registration_id + program_registry_condition_category_id: + data_type: text + description: "Reference to the [Program Registry Condition Category](#!/source/source.tamanu.tamanu.program_registry_condition_categories)\r\ + \nof the condition. from history." + name: program_registry_condition_category_id + program_registry_condition_id: + data_type: text + description: Reference to the [Program Registry Condition](#!/source/source.tamanu.tamanu.program_registry_conditions). + from history. + name: program_registry_condition_id + reason_for_change: + data_type: text + description: Optional field for recording the reason for changing the condition. + from history. + name: reason_for_change + recorded_by_id: + data_type: text + description: Reference to the [Clinician](#!/source/source.tamanu.tamanu.users) + recording that condition. from history. + name: recorded_by_id + updated_by_user_id: + data_type: text + description: "The value of the `updated_by_user_id` field of the change data.\r\ + \n\r\nThis is extracted from the data to make it easier to query on. in patient\ + \ program registration condition record." + name: updated_by_user_id + config: + tags: + - base + - clinical + - log + description: Change logs of Table of conditions related to patients in a program + registration. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_program_registration_conditions_change_logs + tags: + - base + - clinical + - log +- columns: + clinical_status_id: + data_type: character varying(255) + description: "Reference to the [Program Registry Clinical Status](#!/source/source.tamanu.tamanu.program_registry_clinical_statuses)\r\ + \nof the registration." + name: clinical_status_id + datetime: + data_type: timestamp + description: Local date for the record in patient_program_registrations. + name: datetime + deactivated_by_id: + data_type: character varying(255) + description: The clinician that removed the patient from the program registry. + name: deactivated_by_id + deactivated_datetime: + data_type: timestamp + description: The date that the patient from the program registry. + name: deactivated_datetime + facility_id: + data_type: character varying(255) + description: "Reference to the [Facility](#!/source/source.tamanu.tamanu.facilities)\ + \ this program\r\nregistration is from." + name: facility_id + id: + data_type: uuid + description: Tamanu internal identifier (generally a UUID) in patient_program_registrations. + name: id + patient_id: + data_type: character varying(255) + description: Reference to the [Patient](#!/source/source.tamanu.tamanu.patients). + name: patient_id + program_registry_id: + data_type: character varying(255) + description: "Reference to the [Program Registry](#!/source/source.tamanu.tamanu.program_registries)\r\ + \nof the registration." + name: program_registry_id + registered_by_id: + data_type: character varying(255) + description: "Reference to the [Clinician](#!/source/source.tamanu.tamanu.users)\ + \ recording that\r\nregistration." + name: registered_by_id + registering_facility_id: + data_type: character varying(255) + description: "Reference to the [Facility](#!/source/source.tamanu.tamanu.facilities)\ + \ where the\r\nregistration was registered in." + name: registering_facility_id + registration_status: + data_type: text + description: "The current status of the registration.\r\n\r\nOne of:\r\n- `active`\r\ + \n- `inactive`\r\n- `recordedInError`" + name: registration_status + village_id: + data_type: character varying(255) + description: "Reference to the [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\r\ + \n(`type=village`) this program registration is from." + name: village_id + config: + tags: + - base + - clinical + description: "Table with information about the program registrations of a patient.\ + \ This is helpful\r\nto enroll a specific patient within a program that will be\ + \ followed for an extended\r\nperiod of time.\r\n\r\n**This table is append-only.**\r\ + \nA new record is created every time there is a change to the status of a registration.\ + \ \r\n\r\nAt the moment, this implies that when merging two patients, both with\ + \ a registration to the same\r\nregistry, the merged patient ends up with two\ + \ registrations." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_program_registrations + tags: + - base + - clinical +- columns: + changelog_id: + data_type: uuid + description: The ID of the change log row. UUID + name: changelog_id + clinical_status_id: + data_type: text + description: "Reference to the [Program Registry Clinical Status](#!/source/source.tamanu.tamanu.program_registry_clinical_statuses)\r\ + \nof the registration. from history." + name: clinical_status_id + datetime: + data_type: timestamp + description: Local date for the record in patient_program_registrations history. + name: datetime + deactivated_by_id: + data_type: text + description: The clinician that removed the patient from the program registry. + from history. + name: deactivated_by_id + deactivated_datetime: + data_type: timestamp + description: The date that the patient from the program registry. from history. + name: deactivated_datetime + facility_id: + data_type: text + description: "Reference to the [Facility](#!/source/source.tamanu.tamanu.facilities)\ + \ this program\r\nregistration is from. from history." + name: facility_id + id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in patient_program_registrations. + name: id + logged_at: + data_type: timestamp + description: The timestamp this change was logged. in patient_program registrations + history. + name: logged_at + patient_id: + data_type: text + description: Reference to the [Patient](#!/source/source.tamanu.tamanu.patients). + from history. + name: patient_id + program_registry_id: + data_type: text + description: "Reference to the [Program Registry](#!/source/source.tamanu.tamanu.program_registries)\r\ + \nof the registration. from history." + name: program_registry_id + registered_by_id: + data_type: text + description: "Reference to the [Clinician](#!/source/source.tamanu.tamanu.users)\ + \ recording that\r\nregistration. from history." + name: registered_by_id + registering_facility_id: + data_type: text + description: "Reference to the [Facility](#!/source/source.tamanu.tamanu.facilities)\ + \ where the\r\nregistration was registered in. from history." + name: registering_facility_id + registration_status: + data_type: text + description: "The current status of the registration.\r\n\r\nOne of:\r\n- `active`\r\ + \n- `inactive`\r\n- `recordedInError` from history." + name: registration_status + updated_by_user_id: + data_type: text + description: "The value of the `updated_by_user_id` field of the change data.\r\ + \n\r\nThis is extracted from the data to make it easier to query on. in patient_program\ + \ registrations history." + name: updated_by_user_id + village_id: + data_type: text + description: "Reference to the [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\r\ + \n(`type=village`) this program registration is from. from history." + name: village_id + config: + tags: + - base + - clinical + - log + description: "Change logs of Table with information about the program registrations\ + \ of a patient. This is helpful\r\nto enroll a specific patient within a program\ + \ that will be followed for an extended\r\nperiod of time.\r\n\r\n**This table\ + \ is append-only.**\r\nA new record is created every time there is a change to\ + \ the status of a registration. \r\n\r\nAt the moment, this implies that when\ + \ merging two patients, both with a registration to the same\r\nregistry, the\ + \ merged patient ends up with two registrations." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_program_registrations_change_logs + tags: + - base + - clinical + - log +- columns: + days_till_due: + data_type: integer + description: "Number of days until the scheduled vaccine is due. Negative numbers\ + \ indicates the number of days in the past the vaccine\r\nwas due." + name: days_till_due + due_date: + data_type: date + description: Due date of the scheduled vaccine. + name: due_date + patient_id: + data_type: character varying + description: The [patient](#!/source/source.tamanu.tamanu.patients). + name: patient_id + status: + data_type: text + description: Status of the upcoming vaccination listed ['DUE', 'OVERDUE', 'MISSED', + 'SCHEDULED', 'UPCOMING'] + name: status + vaccine_category: + data_type: character varying + description: Vaccine category [Routine, Catch-up, Campaign, Other] + name: vaccine_category + vaccine_id: + data_type: character varying + description: Reference to the vaccine ([Reference Data](#!/source/source.tamanu.tamanu.reference_data), + `type = drug`). + name: vaccine_id + vaccine_schedules_id: + data_type: character varying + description: Reference to the [scheduled vaccine](#!/source/source.tamanu.tamanu.scheduled_vaccines). + name: vaccine_schedules_id + config: + tags: + - base + - clinical + description: "A **view** which lists patients and next vaccine due for a given vaccine\ + \ type.\r\n\r\nThe first dose of a vaccine type is based on weeks from birth due\ + \ whilst subsequent doses are based on weeks from last \r\nvaccination due.\r\n\ + \r\nAge limits in years and thresholds in days for scheduled status are configurable\ + \ with the following defaults:\r\n\r\n- Age = 15\r\n- Status: Scheduled = 28\r\ + \n- Status: Upcoming = 7\r\n- Status: Due = -7\r\n- Status: Overdue = -55\r\n\ + - Status: Missed = -Infinity" + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: patient_vaccinations_upcoming + tags: + - base + - clinical +- columns: + date_of_birth: + data_type: date + description: Date of birth of patient + name: date_of_birth + tags: + - quasi_identifier + date_of_death: + data_type: timestamp + description: Date and time of death of patient + name: date_of_death + tags: + - quasi_identifier + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in patients. + name: id + sex: + data_type: character varying(255) + description: "Sex of patient.\r\n\r\nOne of:\r\n- `male`\r\n- `female`\r\n-\ + \ `other`" + name: sex + tags: + - quasi_identifier + village_id: + data_type: character varying(255) + description: Tamanu village identifier defined in the reference data + name: village_id + tags: + - quasi_identifier + config: + tags: + - base + - patient + description: "The central record for a patient.\r\n\r\n⚠️ The full contents of this\ + \ table are synced to all devices, and in larger deployments this may be\r\nhundreds\ + \ of thousands of records (or even millions), so it is critical to keep the row\ + \ size small.\r\n\r\nOnly contains basic patient data (name, dob, etc.): the bare\ + \ minimum to be able to find that patient\r\nin the system from the search page.\r\ + \n\r\nThe remainder of the patient data is stored in the `patient_additional_data`\ + \ table, which is only\r\nsynced to a device once it has marked that patient for\ + \ sync (in the `patient_facility` table)." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: true + tier: silver + name: patients + tags: + - base + - patient +- columns: + back_end_context: + data_type: jsonb + description: A JSON object containing back end information about the record + access + name: back_end_context + device_id: + data_type: text + description: The id for the device that the user was accessing the record on + name: device_id + facility_id: + data_type: text + description: The facility that the record was accessed on + name: facility_id + front_end_context: + data_type: jsonb + description: A JSON object containing front end information about the record + access + name: front_end_context + id: + data_type: uuid + description: Tamanu internal identifier (generally a UUID) in patients_access_logs. + name: id + is_mobile: + data_type: boolean + description: Whether or not the user accessed the record from mobile + name: is_mobile + logged_at: + data_type: timestamp with time zone + description: The time string of when the record was accessed + name: logged_at + patient_id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in patients. + name: patient_id + session_id: + data_type: text + description: The user session that the record was accessed on + name: session_id + user_id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in users. + name: user_id + version: + data_type: text + description: The version of tamanu the record was created on + name: version + config: + tags: + - base + - administration + - log + description: Access logs of patient data + meta: + classification: confidential + domain: admin + owner: bes-maui + pii: false + tier: silver + name: patients_access_logs + tags: + - base + - administration + - log +- columns: + changelog_id: + data_type: uuid + description: The ID of the change log row. UUID + name: changelog_id + date_of_birth: + data_type: date + description: Date of birth of patient from history. + name: date_of_birth + tags: + - quasi_identifier + date_of_death: + data_type: timestamp + description: Date and time of death of patient from history. + name: date_of_death + tags: + - quasi_identifier + id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in patients. + name: id + logged_at: + data_type: timestamp + description: The timestamp this change was logged. in patients history. + name: logged_at + registration_date: + data_type: date + description: Timestamp of when record was created in patients history which + is used as a best estimate of registration date. + name: registration_date + sex: + data_type: text + description: "Sex of patient.\r\n\r\nOne of:\r\n- `male`\r\n- `female`\r\n-\ + \ `other` from history." + name: sex + tags: + - quasi_identifier + updated_by_user_id: + data_type: text + description: "The value of the `updated_by_user_id` field of the change data.\r\ + \n\r\nThis is extracted from the data to make it easier to query on. in patients\ + \ history." + name: updated_by_user_id + village_id: + data_type: text + description: Tamanu village identifier defined in the reference data from history. + name: village_id + tags: + - quasi_identifier + config: + tags: + - base + - patient + - log + description: "Change logs for The central record for a patient.\r\n\r\n⚠️ The full\ + \ contents of this table are synced to all devices, and in larger deployments\ + \ this may be\r\nhundreds of thousands of records (or even millions), so it is\ + \ critical to keep the row size small.\r\n\r\nOnly contains basic patient data\ + \ (name, dob, etc.): the bare minimum to be able to find that patient\r\nin the\ + \ system from the search page.\r\n\r\nThe remainder of the patient data is stored\ + \ in the `patient_additional_data` table, which is only\r\nsynced to a device\ + \ once it has marked that patient for sync (in the `patient_facility` table)." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: true + tier: silver + name: patients_change_logs + tags: + - base + - patient + - log +- columns: + date_of_birth: + data_type: date + description: Date of birth of patient + name: date_of_birth + tags: + - quasi_identifier + date_of_death: + data_type: timestamp + description: Date and time of death of patient + name: date_of_death + tags: + - quasi_identifier + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in patients. + name: id + registration_date: + data_type: date + description: Timestamp of when record was created in patients which is used + as a best estimate of registration date. + name: registration_date + sex: + data_type: character varying(255) + description: "Sex of patient.\r\n\r\nOne of:\r\n- `male`\r\n- `female`\r\n-\ + \ `other`" + name: sex + tags: + - quasi_identifier + village_id: + data_type: character varying(255) + description: Tamanu village identifier defined in the reference data + name: village_id + tags: + - quasi_identifier + config: + tags: + - base + - patient + description: "Only includes patients that have been merged. The central record for\ + \ a patient.\r\n\r\n⚠️ The full contents of this table are synced to all devices,\ + \ and in larger deployments this may be\r\nhundreds of thousands of records (or\ + \ even millions), so it is critical to keep the row size small.\r\n\r\nOnly contains\ + \ basic patient data (name, dob, etc.): the bare minimum to be able to find that\ + \ patient\r\nin the system from the search page.\r\n\r\nThe remainder of the patient\ + \ data is stored in the `patient_additional_data` table, which is only\r\nsynced\ + \ to a device once it has marked that patient for sync (in the `patient_facility`\ + \ table)." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: true + tier: silver + name: patients_merged + tags: + - base + - patient +- columns: + created_datetime: + data_type: timestamp + description: Timestamp of when record was created in the patients table. + name: created_datetime + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in patients. + name: id + updated_datetime: + data_type: timestamp + description: Timestamp of when record was last updated in the patients table. + name: updated_datetime + config: + tags: + - base + - patient + - log + description: Metadata information extracted from the change logs for patients. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: true + tier: silver + name: patients_metadata + tags: + - base + - patient + - log +- columns: + display_id: + data_type: character varying(255) + description: Human-readable request number for this prescription order. A new + request number is generated each time a prescription is sent to pharmacy. + name: display_id + id: + data_type: uuid + description: Tamanu internal identifier (generally a UUID) in pharmacy_order_prescriptions. + name: id + is_completed: + data_type: boolean + description: Indicates whether this prescription has been fully completed. Set + to `true` when all repeats have been dispensed for a discharge prescription + (outpatient medication). Used to filter completed prescriptions from active + medication request lists. + name: is_completed + ongoing_prescription_id: + data_type: text + description: When this pharmacy order prescription was created from an ongoing + prescription (send to pharmacy flow), references the ongoing [prescription](#!/source/source.tamanu.tamanu.prescriptions). + Null for encounter-based pharmacy orders. + name: ongoing_prescription_id + pharmacy_order_id: + data_type: uuid + description: Reference to the [pharmacy_order](#!/source/source.tamanu.tamanu.pharmacy_orders). + name: pharmacy_order_id + prescription_id: + data_type: text + description: Reference to the [prescription](#!/source/source.tamanu.tamanu.prescriptions). + name: prescription_id + quantity: + data_type: integer + description: Quantity of medication ordered. + name: quantity + repeats: + data_type: integer + description: Number of repeats for the prescription. + name: repeats + config: + tags: + - base + - clinical + - reference + description: Individual prescriptions that are included in a [pharmacy_order](#!/source/source.tamanu.tamanu.pharmacy_orders). + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: pharmacy_order_prescriptions + tags: + - base + - clinical + - reference +- columns: + datetime: + data_type: timestamp + description: Local date and time for the record in pharmacy_orders. + name: datetime + encounter_id: + data_type: text + description: Reference to the [encounter](#!/source/source.tamanu.tamanu.encounters) + for the order. + name: encounter_id + facility_id: + data_type: character varying(255) + description: Reference to the [facility](#!/source/source.tamanu.tamanu.facilities) + where the pharmacy order was placed. + name: facility_id + id: + data_type: uuid + description: Tamanu internal identifier (generally a UUID) in pharmacy_orders. + name: id + is_discharge_prescription: + data_type: boolean + description: If the patient is being discharged with this prescription. + name: is_discharge_prescription + ordering_clinician_id: + data_type: text + description: Reference to the [clinician](#!/source/source.tamanu.tamanu.users) + who placed the order. + name: ordering_clinician_id + config: + tags: + - base + - clinical + - reference + description: An order for prescriptions placed by Tamanu to a Pharmacy + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: pharmacy_orders + tags: + - base + - clinical + - reference +- columns: + datetime: + data_type: timestamp + description: Local date and time for the record in prescriptions. + name: datetime + discontinued_by_id: + data_type: character varying(255) + description: If the prescription was discontinued, who did it. + name: discontinued_by_id + discontinued_datetime: + data_type: timestamp + description: If the prescription was discontinued, when that happened. + name: discontinued_datetime + discontinuing_reason: + data_type: character varying(255) + description: If the prescription was discontinued, why that happened. + name: discontinuing_reason + dose_amount: + data_type: numeric + description: Numeric field to record dose amount + name: dose_amount + duration_unit: + data_type: character varying(255) + description: The duration unit of the prescription + name: duration_unit + duration_value: + data_type: numeric + description: The duration value of the prescription + name: duration_value + end_datetime: + data_type: timestamp + description: When the prescription ends. + name: end_datetime + frequency: + data_type: character varying(255) + description: The frequency of the prescription + name: frequency + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in prescriptions. + name: id + ideal_times: + data_type: array + description: Ideal times which are specified by prescriber + name: ideal_times + indication: + data_type: character varying(255) + description: The [indication of use](https://en.wikipedia.org/wiki/Indication_(medicine)) + for the medicine. + name: indication + is_discontinued: + data_type: boolean + description: Whether the prescription was discontinued. + name: is_discontinued + is_ongoing: + data_type: boolean + description: A flag to determine whether or not the current prescription is + ongoing + name: is_ongoing + is_phone_order: + data_type: boolean + description: A flag to determine whether or not the current prescription is + phone order + name: is_phone_order + is_prn: + data_type: boolean + description: A flag to determine whether or not the current prescription is + prn + name: is_prn + is_variable_dose: + data_type: boolean + description: A flag to determine whether or not the current prescription is + variable does + name: is_variable_dose + medication_id: + data_type: character varying(255) + description: The medication ([Reference Data](#!/source/source.tamanu.tamanu.reference_data), + `type = drug`). + name: medication_id + prescriber_id: + data_type: character varying(255) + description: '[Who](#!/source/source.tamanu.tamanu.users) prescribed the medication.' + name: prescriber_id + quantity: + data_type: integer + description: Quantity of medicine to dispense. + name: quantity + repeats: + data_type: integer + description: How many times this prescription can be repeatedly dispensed without + a new prescription. + name: repeats + route: + data_type: character varying(255) + description: Administration route for the medication. + name: route + start_datetime: + data_type: timestamp + description: The start date of the prescription + name: start_datetime + units: + data_type: character varying(255) + description: The units of the prescription + name: units + config: + tags: + - base + - clinical + description: Records prescriptions for medications. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: true + tier: silver + name: prescriptions + tags: + - base + - clinical +- columns: + anaesthetic_id: + data_type: character varying(255) + description: Reference to the anaesthetic ([Reference Data](#!/source/source.tamanu.tamanu.reference_data), + `type = drug`). + name: anaesthetic_id + anaesthetist_id: + data_type: character varying(255) + description: Reference to the [anaesthetist](#!/source/source.tamanu.tamanu.users). + name: anaesthetist_id + assistant_anaesthetist_id: + data_type: character varying(255) + description: Reference to the assistant [anaesthetist](#!/source/source.tamanu.tamanu.users). + name: assistant_anaesthetist_id + clinician_id: + data_type: character varying(255) + description: Reference to the [physician](#!/source/source.tamanu.tamanu.users). + name: clinician_id + completed_note: + data_type: text + description: Free-form notes at completion of the procedure. + name: completed_note + date: + data_type: date + description: Local date for the record in procedures. + name: date + encounter_id: + data_type: character varying(255) + description: The [encounter](#!/source/source.tamanu.tamanu.encounters) this + procedure is a part of. + name: encounter_id + end_time: + data_type: time + description: When the procedure ended, if it's completed. + name: end_time + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in procedures. + name: id + is_completed: + data_type: boolean + description: Whether the procedure has completed. + name: is_completed + location_id: + data_type: character varying(255) + description: Reference to the [location](#!/source/source.tamanu.tamanu.locations) + the procedure happens in. + name: location_id + note: + data_type: text + description: Free-form description of the procedure. + name: note + procedure_type_id: + data_type: character varying(255) + description: Reference to the procedure type ([Reference Data](#!/source/source.tamanu.tamanu.reference_data), + `type = procedureType`). + name: procedure_type_id + start_time: + data_type: time + description: When the procedure started. + name: start_time + time_in: + data_type: time + description: The time when the patient entered the procedure room or when the + procedure setup began. + name: time_in + time_out: + data_type: time + description: The time when the patient left the procedure room or when the procedure + cleanup was completed. + name: time_out + config: + tags: + - base + - clinical + description: Record of each procedure in progress or completed. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: procedures + tags: + - base + - clinical +- columns: + created_datetime: + data_type: timestamp + description: Timestamp of when record was created in the procedures table. + name: created_datetime + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in procedures. + name: id + updated_datetime: + data_type: timestamp + description: Timestamp of when record was last updated in the procedures table. + name: updated_datetime + config: + tags: + - base + - clinical + - log + description: Metadata information extracted from the change logs for procedures. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: procedures_metadata + tags: + - base + - clinical + - log +- columns: + code: + data_type: character varying(255) + description: "Machine-friendly short name for the question.\r\n\r\nThis is also\ + \ used to refer to questions within criteria and such." + name: code + default_options: + data_type: text + description: Default options if this is a dropdown. + name: default_options + default_text: + data_type: character varying(255) + description: Default value. + name: default_text + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in program_data_elements. + name: id + indicator: + data_type: character varying(255) + description: "Another name for the data element.\r\n\r\nIt's named `indicator`\ + \ from mimicry of Tupaia." + name: indicator + name: + data_type: character varying(255) + description: Human-friendly name + name: name + type: + data_type: character varying(31) + description: "Type of the field.\r\n\r\nTypes are here: " + name: type + visualisation_config: + data_type: text + description: JSON visualisation configuration. + name: visualisation_config + config: + tags: + - base + - reference + description: "Describes how a survey question gets stored.\r\n\r\nSee [survey screen\ + \ components](#!/source/source.tamanu.tamanu.survey_screen_components), which\r\ + \ndescribes how the question is displayed." + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: program_data_elements + tags: + - base + - reference +- columns: + code: + data_type: text + description: Machine-friendly identifier. + name: code + currently_at_type: + data_type: text + description: "Defines what kind of location the registry can be filtered with.\r\ + \n\r\nOne of:\r\n- `village`\r\n- `facility`" + name: currently_at_type + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in program_registries. + name: id + name: + data_type: text + description: Human-friendly name. + name: name + program_id: + data_type: character varying(255) + description: Reference to a [program](#!/source/source.tamanu.tamanu.programs). + name: program_id + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in program_registries." + name: visibility_status + config: + tags: + - base + - reference + description: "Table of program registries.\r\n\r\nThis provides functionality to\ + \ track a patient population defined by a particular disease or\r\ncondition,\ + \ and follow this population over time.\r\n\r\nThis table defines the different\ + \ registries available to track users with." + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: program_registries + tags: + - base + - reference +- columns: + code: + data_type: text + description: Code (identifier) for the clinical status. + name: code + color: + data_type: text + description: "A color for the clinical status.\r\n\r\nOne of:\r\n- `purple`\r\ + \n- `pink`\r\n- `orange`\r\n- `yellow`\r\n- `blue`\r\n- `green`\r\n- `grey`\r\ + \n- `red`\r\n- `brown`\r\n- `teal`" + name: color + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in program_registry_clinical_statuses. + name: id + name: + data_type: text + description: The name of the clinical status. + name: name + program_registry_id: + data_type: character varying(255) + description: "Reference to the [Program Registry](#!/source/source.tamanu.tamanu.program_registries)\r\ + \nthe status is a part of." + name: program_registry_id + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in program_registry_clinical_statuses." + name: visibility_status + config: + tags: + - base + - reference + description: Table of clinical statuses used in program registries. + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: program_registry_clinical_statuses + tags: + - base + - reference +- columns: + code: + data_type: text + description: The code for the category. + name: code + id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in program_registry_condition_categories. + name: id + name: + data_type: text + description: The name for the category. + name: name + program_registry_id: + data_type: character varying(255) + description: The id of the program registry. + name: program_registry_id + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in program_registry_condition_categories." + name: visibility_status + config: + tags: + - base + - reference + description: Categories to be set against patient program registry conditions. The + categories are configured through the program importer for each program registry. + There is a hard-loaded list that is seeded by default in the database for each + program registry. + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: program_registry_condition_categories + tags: + - base + - reference +- columns: + code: + data_type: text + description: Code (identifier) for the condition. + name: code + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in program_registry_conditions. + name: id + name: + data_type: text + description: The name of the condition. + name: name + program_registry_id: + data_type: character varying(255) + description: "Reference to the [Program Registry](#!/source/source.tamanu.tamanu.program_registries)\r\ + \nthe condition is a part of." + name: program_registry_id + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in program_registry_conditions." + name: visibility_status + config: + tags: + - base + - reference + description: Table of program registry conditions. + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: program_registry_conditions + tags: + - base + - reference +- columns: + code: + data_type: character varying(255) + description: Machine-friendly code. + name: code + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in programs. + name: id + name: + data_type: character varying(255) + description: Human-friendly name. + name: name + config: + tags: + - base + - reference + description: Groups of [surveys](#!/source/source.tamanu.tamanu.surveys) or [program + registries](#!/source/source.tamanu.tamanu.program_registries). + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: programs + tags: + - base + - reference +- columns: + code: + data_type: character varying(255) + description: Code of the data item (short value, alphanumerics and hyphens). + name: code + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in reference_data. + name: id + name: + data_type: text + description: Actual data + name: name + type: + data_type: character varying(255) + description: "Class of the data (referred to in code).\r\n\r\nWhenever this\ + \ table is referred to in a relationship, it's to a specific `type` here.\ + \ For example a\r\ntable might have a `diagnosis_id`, which is a reference\ + \ to this table, for specifically only the\r\nrows with `type = diagnosis`." + name: type + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in reference_data." + name: visibility_status + config: + tags: + - base + - reference + description: "User imported reference data for the environment grouped by type.\r\ + \n\r\n- Catch-all for simple reference data types - there are a LOT of kinds of\ + \ reference data that exist as just an ID, a \r\nstring label, and occasionally\ + \ a code; these are all grouped into this table to avoid overcomplicating the\ + \ schema.\r\n- Occasionally a type of simple reference data will gain some complexity,\ + \ at which point it will be refactored/migrated \r\nout to use its own table.\r\ + \n- Simple reference data types include a code, type, name and visibility status.\r\ + \n- Example types include `diagnosis`, `procedures`" + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: reference_data + tags: + - base + - reference +- columns: + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in referrals. + name: id + initiating_encounter_id: + data_type: character varying(255) + description: Reference to the [initiating encounter](#!/source/source.tamanu.tamanu.encounters). + name: initiating_encounter_id + referred_facility: + data_type: character varying(255) + description: Unused. + name: referred_facility + status: + data_type: character varying(255) + description: "Status of the referral.\r\n\r\nOne of:\r\n- `pending`\r\n- `cancelled`\r\ + \n- `completed`" + name: status + survey_response_id: + data_type: character varying(255) + description: Reference to the [survey response](#!/source/source.tamanu.tamanu.survey_responses) + with more data. + name: survey_response_id + config: + tags: + - base + - clinical + description: "[Referrals](https://en.wikipedia.org/wiki/Referral_(medicine)).\r\n\ + \r\nReferrals use a confusing mix of data in the `referrals` table and\r\n[`survey_response_answers`](#!/source/source.tamanu.tamanu.survey_response_answers)\ + \ identified by\r\nthe text of the question they are for. \r\n\r\nSome additional\ + \ data is captured in\r\n[survey response answers](#!/source/source.tamanu.tamanu.survey_response_answers),\ + \ but this is\r\nvariable and not enforced through any validation:\r\n- Where\ + \ the person is being referred to can be captured by a range of questions, sometimes\ + \ with a\r\n list of hard coded facility name options, or location groups, or\ + \ departments.\r\n- Who the referral is \"completed by\" can be captured by a\ + \ question either the name\r\n 'Referring doctor' or 'Referral completed by'.\r\ + \n- Some referrals are the product of a previous screening survey. In some cases\ + \ (e.g. Samoa) there is\r\n a SurveyLink question that captures which survey\ + \ led to this referral, in others (e.g. Nauru)\r\n there is no such question\ + \ so the two survey responses cannot be reliably linked." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: referrals + tags: + - base + - clinical +- columns: + created_at: + description: Timestamp of when record was created + name: created_at + device_id: + description: Unique device ID from the client. + name: device_id + expires_at: + description: When the refresh token expires. + name: expires_at + id: + description: Tamanu internal identifier (generally a UUID) + name: id + updated_at: + description: Timestamp of when record was last updated + name: updated_at + user_id: + description: The [user](#!/source/source.tamanu.tamanu.users) being authenticated + as. + name: user_id + config: + tags: + - base + - administration + description: Refresh tokens are used by API clients to refresh their authentication + quickly, within a timeout. + meta: + classification: confidential + domain: admin + owner: bes-maui + pii: false + tier: silver + name: refresh_tokens + tags: + - base + - administration +- columns: + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in roles. + name: id + name: + data_type: character varying(255) + description: Readable name for the role. + name: name + config: + tags: + - base + - administration + description: "These are sets of permissions that are given to users to determine\ + \ what they can do in Tamanu.\r\n\r\nThe actual permissions are associated to\ + \ the role in the\r\n[`permissions`](#!/source/source.tamanu.tamanu.permissions)\ + \ table." + meta: + classification: confidential + domain: admin + owner: bes-maui + pii: false + tier: silver + name: roles + tags: + - base + - administration +- columns: + body: + data_type: text + description: Value of the answer. + name: body + data_element_id: + data_type: character varying(255) + description: Reference to the [question](#!/source/source.tamanu.tamanu.program_data_elements). + name: data_element_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in survey_response_answers. + name: id + name: + data_type: character varying(255) + description: Name of the question. + name: name + response_id: + data_type: character varying(255) + description: The [survey response](#!/source/source.tamanu.tamanu.survey_responses). + name: response_id + config: + tags: + - base + - clinical + description: A single answer as part of a [survey response](#!/source/source.tamanu.tamanu.survey_responses). + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: survey_response_answers + tags: + - base + - clinical +- columns: + encounter_id: + data_type: character varying(255) + description: Reference to the [encounter](#!/source/source.tamanu.tamanu.encounters) + this survey response is a part of. + name: encounter_id + end_datetime: + data_type: timestamp + description: When the survey was completed. + name: end_datetime + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in survey_responses. + name: id + is_notified: + data_type: boolean + description: "If the [survey](#!/source/source.tamanu.tamanu.surveys) is `notifiable`,\ + \ whether this response's\r\nnotification has been sent." + name: is_notified + result_text: + data_type: text + description: The textual value that is the summary of the survey response. + name: result_text + start_datetime: + data_type: timestamp + description: When the survey was started. + name: start_datetime + submitted_by_id: + data_type: character varying(255) + description: Reference to the [user](#!/source/source.tamanu.tamanu.users) recording + this survey response. + name: submitted_by_id + survey_id: + data_type: character varying(255) + description: The [survey](#!/source/source.tamanu.tamanu.surveys) being responded + to. + name: survey_id + config: + tags: + - base + - clinical + description: "A response to a survey (as recorded by a practitioner).\r\n\r\nTypically\ + \ surveys are filled on behalf of patients as part of an encounter.\r\n\r\nBecause\ + \ there are multiple distinct kinds of dates at play here:\r\n- `created_at`,\ + \ `updated_at`, `deleted_at` are system data for syncing and cannot be relied\ + \ on for realtime\r\n- `start_time`, `end_time` are real datetimes automatically\ + \ recorded when starting and submitting a survey response\r\n- in survey response\ + \ answers, there could be a data element for targeting the date of when exactly\ + \ the data is recorded in real time." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: survey_responses + tags: + - base + - clinical +- columns: + calculation: + data_type: character varying(255) + description: "Math expression to do calculations on the entered value before\ + \ it's saved.\r\n\r\nFor example `questionCode + 3`." + name: calculation + component_index: + data_type: integer + description: The absolute index (order) of the component in the survey. + name: component_index + config: + data_type: character varying(255) + description: JSON additional config of the component. + name: config + data_element_id: + data_type: character varying(255) + description: "Reference to the [data element](#!/source/source.tamanu.tamanu.program_data_elements)\ + \ configuring\r\nhow the data from the question is stored." + name: data_element_id + detail: + data_type: character varying(255) + description: Longer description or explanatory text of this component. + name: detail + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in survey_screen_components. + name: id + options: + data_type: character varying(255) + description: JSON array of strings of options to be selected. + name: options + screen_index: + data_type: integer + description: "Screen this component should appear on.\r\n\r\nSurveys can have\ + \ multiple \"screens\" or pages, this index sets where this particular question\ + \ sits." + name: screen_index + survey_id: + data_type: character varying(255) + description: The [survey](#!/source/source.tamanu.tamanu.surveys). + name: survey_id + text: + data_type: character varying(255) + description: Description or question of this component. + name: text + validation_criteria: + data_type: text + description: JSON criteria that determines whether the value entered in this + component is accepted. + name: validation_criteria + visibility_criteria: + data_type: character varying(255) + description: "JSON criteria that determines when this component is visible.\r\ + \n\r\nA criteria is a list of other components' codes and the value that will\ + \ make this question show up:\r\n\r\n```json\r\n{\r\n \"otherQuestion\":\ + \ \"Yes\"\r\n}\r\n```\r\n\r\nThere can also be the special criterium `{\"\ + hidden\": true}` which always hides the question, and the\r\nspecial key `\"\ + _conjunction\": \"or\"` which makes it so _any one_ item in the list is sufficient\ + \ to\r\nshow the question, instead of the default where _all_ items must match." + name: visibility_criteria + visibility_status: + data_type: character varying(255) + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in survey_screen_components." + name: visibility_status + config: + tags: + - base + - reference + description: "Describes how a survey question gets displayed.\r\n\r\nSee [program\ + \ data element](#!/source/source.tamanu.tamanu.program_data_elements), which describes\r\ + \nhow the data from the question is stored." + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: survey_screen_components + tags: + - base + - reference +- columns: + code: + data_type: character varying(255) + description: Machine-friendly code. + name: code + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in surveys. + name: id + is_notifiable: + data_type: boolean + description: "Whether filling this survey sends a notification email.\r\n\r\n\ + These are sent by the `SurveyCompletionNotifierProcessor` scheduled task." + name: is_notifiable + is_sensitive: + data_type: boolean + description: Whether the data recorded in the survey is sensitive. + name: is_sensitive + name: + data_type: character varying(255) + description: Human-friendly name. + name: name + notify_email_addresses: + data_type: array + description: If `notifiable` is true, where to send the notification. + name: notify_email_addresses + program_id: + data_type: character varying(255) + description: The [program](#!/source/source.tamanu.tamanu.programs) grouping + this survey. + name: program_id + survey_type: + data_type: character varying(255) + description: "Type of survey.\r\n\r\nOne of:\r\n- `programs`\r\n- `referral`\r\ + \n- `obsolete`\r\n- `vitals`" + name: survey_type + visibility_status: + data_type: character varying(255) + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in surveys." + name: visibility_status + config: + tags: + - base + - reference + description: "Surveys, aka custom forms that can be filled by practitioners.\r\n\ + \r\nThese are composed of [screen components](#!/source/source.tamanu.tamanu.survey_screen_components)." + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: surveys + tags: + - base + - reference +- columns: + language: + data_type: text + description: The language code. + name: language + string_id: + data_type: text + description: The internal reference of the item being translated. + name: string_id + text: + data_type: text + description: The actual translated text. + name: text + config: + tags: + - base + - reference + description: "Localisation and translation strings.\r\n\r\nThese are used for two\ + \ distinct purposes:\r\n- to translate Tamanu in languages other than English\r\ + \n- to adjust the wording of specific items in the UI" + meta: + classification: internal + domain: admin + owner: bes-maui + pii: false + tier: silver + name: translated_strings + tags: + - base + - reference +- columns: + arrival_datetime: + data_type: timestamp + description: When the patient arrived. + name: arrival_datetime + arrival_mode_id: + data_type: character varying(255) + description: Reference to how the patient arrived ([Reference Data](#!/source/source.tamanu.tamanu.reference_data), + `type = arrivalMode`). + name: arrival_mode_id + chief_complaint_id: + data_type: character varying(255) + description: Reference to the primary complaint ([Reference Data](#!/source/source.tamanu.tamanu.reference_data), + `type = triageReason`). + name: chief_complaint_id + clinician_id: + data_type: character varying(255) + description: Reference to the [practitioner](#!/source/source.tamanu.tamanu.users) + assigned to this patient. + name: clinician_id + closed_datetime: + data_type: timestamp + description: When the patient was processed. + name: closed_datetime + encounter_id: + data_type: character varying(255) + description: Reference to the [encounter](#!/source/source.tamanu.tamanu.encounters) + this triage is for. + name: encounter_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in triages. + name: id + score: + data_type: text + description: Classification done by the triage practitioner. + name: score + secondary_complaint_id: + data_type: character varying(255) + description: Reference to the secondary complaint ([Reference Data](#!/source/source.tamanu.tamanu.reference_data), + `type = triageReason`). + name: secondary_complaint_id + triage_datetime: + data_type: timestamp + description: When the patient was triaged. + name: triage_datetime + config: + tags: + - base + - clinical + description: Triage data of patients waiting in an emergency department. + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: triages + tags: + - base + - clinical +- columns: + display_id: + data_type: character varying(255) + description: "Display identifier for the user.\r\n\r\nThis may be the employee\ + \ code or badge number." + name: display_id + display_name: + data_type: character varying(255) + description: The human readable display name for the user. + name: display_name + email: + data_type: character varying(255) + description: Email address for user. This is used to login and receive emails. + name: email + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in users. + name: id + phone_number: + data_type: character varying(255) + description: "Phone number for the user.\r\n\r\nThis is not currently available\ + \ anywhere visible." + name: phone_number + role: + data_type: character varying(255) + description: "The role of the user, which sets their permission level.\r\n\r\ + \nThe special values `admin` and `system` indicate a superadmin and a system\ + \ user respectively." + name: role + visibility_status: + data_type: character varying(255) + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in users." + name: visibility_status + config: + tags: + - base + - administration + description: "Records of each user that can login to Tamanu.\r\n\r\nThis includes\ + \ machine users.\r\n\r\nThere is one special user account with an all-zero `id`,\ + \ which is the global \"system\" user. This is\r\nused as a pseudo identity where\ + \ the Tamanu system itself takes an action that normally is performed\r\nby a\ + \ human or API user." + meta: + classification: restricted + domain: admin + owner: bes-maui + pii: true + tier: silver + name: users + tags: + - base + - administration +- columns: + created_datetime: + data_type: timestamp + description: Timestamp of when record was created in the users table. + name: created_datetime + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in users. + name: id + updated_datetime: + data_type: timestamp + description: Timestamp of when record was last updated in the users table. + name: updated_datetime + config: + tags: + - base + - administration + - log + description: Metadata information extracted from the change logs for users. + meta: + classification: confidential + domain: admin + owner: bes-maui + pii: false + tier: silver + name: users_metadata + tags: + - base + - administration + - log +- columns: + batch: + data_type: character varying(255) + description: Batch identifier of vaccine administrations recorded + name: batch + circumstance_ids: + data_type: array + description: "Array of references to [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\r\ + \n(`type=vaccineCircumstance`)." + name: circumstance_ids + consent_given_by: + data_type: text + description: "Free text field recording who gave consent for the vaccination.\r\ + \nThis is usually the patient themselves, but may differ for children or dependent\r\ + \npersons or other cases." + name: consent_given_by + datetime: + data_type: timestamp + description: Local date for the record in vaccine_administrations. + name: datetime + department_id: + data_type: character varying(255) + description: "Reference to the [Department](#!/source/source.tamanu.tamanu.departments)\ + \ at which the vaccine was\r\ngiven." + name: department_id + disease: + data_type: text + description: Disease the vaccine addresses of the vaccine administration recorded + name: disease + encounter_id: + data_type: character varying(255) + description: Reference to the [Encounter](#!/source/source.tamanu.tamanu.encounters) + this vaccine was given in. + name: encounter_id + given_by_id: + data_type: text + description: "Free text field for the name of the health practitioner who administered\ + \ the\r\nvaccine. This is defaulted to the `display_name` of the logged-in\ + \ User, but can\r\nbe changed. It is not a requirement that the administerer\ + \ is a Tamanu User." + name: given_by_id + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in vaccine_administrations. + name: id + injection_site: + data_type: character varying(255) + description: Injection site of the vaccine administrations recorded + name: injection_site + is_consented: + data_type: boolean + description: Consent of the vaccine administrations recorded + name: is_consented + is_given_elsewhere: + data_type: boolean + description: Checks if the vaccine was given elsewhere + name: is_given_elsewhere + location_id: + data_type: character varying(255) + description: "Reference to the [Location](#!/source/source.tamanu.tamanu.locations)\ + \ at which the vaccine was\r\ngiven." + name: location_id + not_given_reason_id: + data_type: character varying(255) + description: "Reference to a [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\r\ + \n(`type=vaccineNotGivenReason`).\r\n\r\nThese are presented as a dropdown\ + \ for ease of recording and reporting, alongside the free-text field." + name: not_given_reason_id + reason: + data_type: character varying(255) + description: Reason for vaccine administrations `NOT_GIVEN` status. This is + a free text field + name: reason + recorded_by_id: + data_type: character varying(255) + description: "Reference to the [User](#!/source/source.tamanu.tamanu.users)\ + \ who recorded this vaccination.\r\nThis may differ from the User or person\ + \ who administered the vaccine." + name: recorded_by_id + scheduled_vaccine_id: + data_type: character varying(255) + description: "Reference to the [Scheduled Vaccine](#!/source/source.tamanu.tamanu.scheduled_vaccines)\ + \ that was\r\nadministered." + name: scheduled_vaccine_id + status: + data_type: character varying(255) + description: "Status of vaccine administrations recorded. \r\n\r\nThe `RECORDED_IN_ERROR`\ + \ status is assigned to vaccines initially recorded\r\nas `GIVEN` that are\ + \ then deleted.\r\n\r\nThe `HISTORICAL` status is assigned to vaccines initially\ + \ recorded as \r\n`NOT_GIVEN` that are then recorded as `GIVEN`. This `HISTORICAL`\ + \ status \r\nkeeps a record that the vaccine was marked as `NOT_GIVEN` but\ + \ hides this\r\nrecord from the frontend to avoid confusion or conflict with\ + \ the `GIVEN`\r\nrecord." + name: status + vaccine_brand: + data_type: text + description: Vaccine brand of the vaccine administration recorded + name: vaccine_brand + vaccine_name: + data_type: text + description: Vaccine name of the vaccine administration recorded + name: vaccine_name + config: + tags: + - base + - clinical + description: "Table of vaccines administered to patients.\r\n\r\nVaccinations are\ + \ recorded via the Vaccinations modal; they are selected\r\nfrom a list of Scheduled\ + \ Vaccines and linked to a Patient via an Encounter." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: vaccine_administrations + tags: + - base + - clinical +- columns: + batch: + data_type: text + description: Batch identifier of vaccine administrations recorded from history. + name: batch + changelog_id: + data_type: uuid + description: The ID of the change log row. UUID + name: changelog_id + circumstance_ids: + data_type: text + description: "Array of references to [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\r\ + \n(`type=vaccineCircumstance`). from history." + name: circumstance_ids + consent_given_by: + data_type: text + description: "Free text field recording who gave consent for the vaccination.\r\ + \nThis is usually the patient themselves, but may differ for children or dependent\r\ + \npersons or other cases. from history." + name: consent_given_by + created_at: + data_type: timestamp + description: Timestamp of when record was created in vaccine_administrations + from history. + name: created_at + datetime: + data_type: timestamp + description: Local date for the record in vaccine_administrations from history. + name: datetime + department_id: + data_type: text + description: "Reference to the [Department](#!/source/source.tamanu.tamanu.departments)\ + \ at which the vaccine was\r\ngiven. from history." + name: department_id + disease: + data_type: text + description: Disease the vaccine addresses of the vaccine administration recorded + from history. + name: disease + encounter_id: + data_type: text + description: Reference to the [Encounter](#!/source/source.tamanu.tamanu.encounters) + this vaccine was given in. from history. + name: encounter_id + given_by: + data_type: text + description: "Free text field for the name of the health practitioner who administered\ + \ the\r\nvaccine. This is defaulted to the `display_name` of the logged-in\ + \ User, but can\r\nbe changed. It is not a requirement that the administerer\ + \ is a Tamanu User. from history." + name: given_by + id: + data_type: text + description: Tamanu internal identifier (generally a UUID) in vaccine_administrations + from history. + name: id + injection_site: + data_type: text + description: Injection site of the vaccine administrations recorded from history. + name: injection_site + is_consented: + data_type: boolean + description: Consent of the vaccine administrations recorded from history. + name: is_consented + is_given_elsewhere: + data_type: boolean + description: Checks if the vaccine was given elsewhere from history. + name: is_given_elsewhere + location_id: + data_type: text + description: "Reference to the [Location](#!/source/source.tamanu.tamanu.locations)\ + \ at which the vaccine was\r\ngiven. from history." + name: location_id + logged_at: + data_type: timestamp + description: The timestamp this change was logged. in vaccine administrations + history. + name: logged_at + not_given_reason_id: + data_type: text + description: "Reference to a [Reference Data](#!/source/source.tamanu.tamanu.reference_data)\r\ + \n(`type=vaccineNotGivenReason`).\r\n\r\nThese are presented as a dropdown\ + \ for ease of recording and reporting, alongside the free-text field. from\ + \ history." + name: not_given_reason_id + reason: + data_type: text + description: Reason for vaccine administrations `NOT_GIVEN` status. This is + a free text field from history. + name: reason + recorded_by_id: + data_type: text + description: "Reference to the [User](#!/source/source.tamanu.tamanu.users)\ + \ who recorded this vaccination.\r\nThis may differ from the User or person\ + \ who administered the vaccine. from history." + name: recorded_by_id + scheduled_vaccine_id: + data_type: text + description: "Reference to the [Scheduled Vaccine](#!/source/source.tamanu.tamanu.scheduled_vaccines)\ + \ that was\r\nadministered. from history." + name: scheduled_vaccine_id + status: + data_type: text + description: "Status of vaccine administrations recorded. \r\n\r\nThe `RECORDED_IN_ERROR`\ + \ status is assigned to vaccines initially recorded\r\nas `GIVEN` that are\ + \ then deleted.\r\n\r\nThe `HISTORICAL` status is assigned to vaccines initially\ + \ recorded as \r\n`NOT_GIVEN` that are then recorded as `GIVEN`. This `HISTORICAL`\ + \ status \r\nkeeps a record that the vaccine was marked as `NOT_GIVEN` but\ + \ hides this\r\nrecord from the frontend to avoid confusion or conflict with\ + \ the `GIVEN`\r\nrecord. from history." + name: status + updated_at: + data_type: timestamp + description: Timestamp of when record was last updated in vaccine_administrations + from history. + name: updated_at + updated_by_user_id: + data_type: text + description: "The value of the `updated_by_user_id` field of the change data.\r\ + \n\r\nThis is extracted from the data to make it easier to query on. in vaccine\ + \ administrations history." + name: updated_by_user_id + vaccine_brand: + data_type: text + description: Vaccine brand of the vaccine administration recorded from history. + name: vaccine_brand + vaccine_name: + data_type: text + description: Vaccine name of the vaccine administration recorded from history. + name: vaccine_name + config: + tags: + - base + - clinical + - log + description: "Change logs of Table of vaccines administered to patients.\r\n\r\n\ + Vaccinations are recorded via the Vaccinations modal; they are selected\r\nfrom\ + \ a list of Scheduled Vaccines and linked to a Patient via an Encounter." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: vaccine_administrations_change_logs + tags: + - base + - clinical + - log +- columns: + category: + data_type: character varying(255) + description: Vaccine category [Routine, Catch-up, Campaign, Other] + name: category + dose_label: + data_type: character varying(255) + description: "Dose label indicates what will appear on the front end of Tamanu\ + \ re when the dose is due. It can be a time in a child's \r\nlife (e.g. 'Birth',\ + \ '6 weeks') or a dose of vaccine (e.g. 'Dose 1', 'Dose 2')" + name: dose_label + id: + data_type: character varying(255) + description: Tamanu internal identifier (generally a UUID) in vaccine_schedules. + name: id + index: + data_type: integer + description: "This column is used to show when a second dose is due in relation\ + \ to the first dose. For example, if dose 1 is due at 6 \r\nweeks and dose\ + \ 2 is due at 10 weeks, this column would read '4' against the 10 week dose\ + \ as dose 2 is due 4 weeks after \r\ndose 1 is given." + name: index + label: + data_type: character varying(255) + description: "Contents of the label column is what will be displayed on the\ + \ front end of Tamanu \r\nunder fields labelled 'Vaccine'. This is where the\ + \ vaccine name is listed. E.g. 'BCG'." + name: label + sort_index: + data_type: integer + description: Sort index defaults to 0 + name: sort_index + vaccine_id: + data_type: character varying(255) + description: "Use the vaccineId column to link the id column of the Reference\ + \ Data sheet Drug to the vaccine schedule. Copy the exact \r\nid from the\ + \ id column in the reference data sheet Drug and paste it in the vaccineId\ + \ column in the Scheduled Vaccine \r\nsheet." + name: vaccine_id + visibility_status: + data_type: text + description: "The visibility status of the record.\r\n\r\n- `current` indicates\ + \ the record is currently in use and should be visible and accessible to users\r\ + \n on the User Interface.\r\n- `historical` indicates that the record is\ + \ no longer in use and should not be visible nor\r\n accessible to users.\ + \ However, the record may still be present in Reporting.\r\n- `merged` indicates\ + \ that the record has been merged, is no longer in use and should not be visible\r\ + \n nor accessible to users.\r\n\r\nThe default value is `current`. in vaccine_schedules." + name: visibility_status + weeks_from_birth_due: + data_type: integer + description: "This column is used to tell Tamanu how many weeks from the child's\ + \ date of birth a vaccine is due. This will populate \r\nthe front end within\ + \ the Vaccine schedule section in the column 'Due date'. For a vaccine to\ + \ appear in the Vaccine \r\nschedule a dose must have a `weeksFromBirthDue`\ + \ entered into the reference data. \r\n\r\nThis field should be used only\ + \ for the first dose of the vaccine. Subsequent doses should use \r\n`weeks_from_last_vaccination_due`" + name: weeks_from_birth_due + weeks_from_last_vaccination_due: + data_type: integer + description: "This column is used to show when a second dose is due in relation\ + \ to the first dose. For example, if dose 1 is due at 6 \r\nweeks and dose\ + \ 2 is due at 10 weeks, this column would read '4' against the 10 week dose\ + \ as dose 2 is due 4 weeks after \r\ndose 1 is given. The order of a vaccine\ + \ dose is defined at the `index` field. \r\n\r\nThis field should not be used\ + \ for the first dose but for subsequent doses. First dose should use `weeks_from_birth_due`" + name: weeks_from_last_vaccination_due + config: + tags: + - base + - clinical + description: "A vaccine schedule listing all vaccines expected to be given to a\ + \ child as part of a country wide Expanded Program of \r\nImmunisation can be\ + \ incorporated into Tamanu to show each dose and due date on the front end of\ + \ the system. \r\n\r\nFirst dose of a vaccine should use `weeks_from_birth_due`\ + \ whilst subsequent doses should use \r\n`weeks_from_last_vaccination_due`." + meta: + classification: restricted + domain: clinical + owner: bes-maui + pii: false + tier: silver + name: vaccine_schedules + tags: + - base + - clinical diff --git a/compiled/v2.50.11/reporting-docs-v2.50.11-standard.html b/compiled/v2.50.11/reporting-docs-v2.50.11-standard.html new file mode 100644 index 00000000..1de3af98 --- /dev/null +++ b/compiled/v2.50.11/reporting-docs-v2.50.11-standard.html @@ -0,0 +1,250 @@ + + + + + + + dbt Docs + + + + + + + + + + + + + + + +
+ icons + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + \ No newline at end of file diff --git a/compiled/v2.50.11/reporting-schema-v2.50.11-standard.sql b/compiled/v2.50.11/reporting-schema-v2.50.11-standard.sql new file mode 100644 index 00000000..f51f2e86 --- /dev/null +++ b/compiled/v2.50.11/reporting-schema-v2.50.11-standard.sql @@ -0,0 +1,4979 @@ +drop schema if exists reporting cascade; +create schema reporting; +grant usage on schema reporting to reporting; +alter default privileges in schema reporting grant select on tables to reporting; +create or replace view "reporting"."contributing_death_causes" as ( +select + cdc.id, + cdc.time_after_onset, + cdc.patient_death_data_id, + cdc.condition_id +from "public"."contributing_death_causes" cdc +join "public"."patient_death_data" pdd on pdd.id = cdc.patient_death_data_id +where cdc.deleted_at is null + and pdd.deleted_at is null + and pdd.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."departments" as ( +select + id, + code, + name, + facility_id, + visibility_status +from "public"."departments" +where deleted_at is null +); +create or replace view "reporting"."discharges" as ( +select distinct on (d.encounter_id) + d.id, + d.note, + d.encounter_id, + d.discharger_id as discharged_by_id, + d.disposition_id +from "public"."discharges" d +join "public"."encounters" e on e.id = d.encounter_id +where d.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +order by d.encounter_id asc, d.created_at asc +); +create or replace view "reporting"."document_metadata" as ( +select + id, + name, + type, + created_at::timestamp as created_datetime, + patient_id, + encounter_id +from "public"."document_metadata" +where deleted_at is null +); +create or replace view "reporting"."encounters" as ( +select + id, + start_date::timestamp as start_datetime, + case + when end_date < start_date then start_date::timestamp + else end_date::timestamp + end as end_datetime, + encounter_type, + reason_for_encounter, + device_id, + patient_id, + department_id, + location_id, + examiner_id as clinician_id, + patient_billing_type_id, + referral_source_id, + planned_location_id, + planned_location_start_time::timestamp as planned_location_start_datetime, + discharge_draft +from "public"."encounters" +where deleted_at is null + and patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."encounters_metadata" as ( +with change_logs as ( + select + record_id, + logged_at, + least(record_created_at, logged_at) as created_datetime + from "logs"."changes" + where table_name = 'encounters' +) +select + record_id as id, + min(created_datetime) as created_datetime, + max(logged_at) as updated_datetime +from change_logs +group by record_id +); +create or replace view "reporting"."encounter_diagnoses" as ( +select + ed.id, + ed.date::timestamp as datetime, + ed.is_primary, + ed.certainty, + ed.encounter_id, + ed.diagnosis_id, + ed.clinician_id as diagnosed_by_id +from "public"."encounter_diagnoses" ed +join "public"."encounters" e on e.id = ed.encounter_id +where ed.deleted_at is null + and ed.certainty not in ('disproven', 'error') + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."encounter_diagnoses_metadata" as ( +with change_logs as ( + select + record_id, + logged_at, + least(record_created_at, logged_at) as created_datetime + from "logs"."changes" + where table_name = 'encounter_diagnoses' +) +select + record_id as id, + min(created_datetime) as created_datetime, + max(logged_at) as updated_datetime +from change_logs +group by record_id +); +create or replace view "reporting"."encounter_diets" as ( +select + ed.id, + ed.encounter_id, + ed.diet_id +from "public"."encounter_diets" ed +join "public"."encounters" e on e.id = ed.encounter_id +where ed.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."encounter_history" as ( +select + eh.id, + eh.date::timestamp as datetime, + eh.encounter_id, + eh.department_id, + eh.location_id, + eh.encounter_type, + eh.examiner_id as clinician_id, + eh.actor_id as updated_by_id, + eh.change_type::text[] +from "public"."encounter_history" eh +join "public"."encounters" e on e.id = eh.encounter_id +where eh.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."encounter_prescriptions" as ( +select + ep.id, + ep.encounter_id, + ep.prescription_id, + ep.is_selected_for_discharge +from "public"."encounter_prescriptions" ep +join "public"."encounters" e on e.id = ep.encounter_id +where ep.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."facilities" as ( +select + id, + code, + name, + division, + type, + email, + contact_number, + city_town, + street_address, + catchment_id, + visibility_status, + is_sensitive +from "public"."facilities" +where deleted_at is null +); +create or replace view "reporting"."imaging_area_external_codes" as ( +select + id, + area_id, + code, + description, + visibility_status +from "public"."imaging_area_external_codes" +where deleted_at is null +); +create or replace view "reporting"."imaging_requests" as ( +select + ir.id, + ir.display_id, + ir.requested_date::timestamp as datetime, + ir.status, + ir.priority, + ir.imaging_type, + ir.encounter_id, + ir.requested_by_id, + ir.completed_by_id, + ir.location_id, + ir.location_group_id, + ir.reason_for_cancellation +from "public"."imaging_requests" ir +join "public"."encounters" e on e.id = ir.encounter_id +where ir.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."imaging_request_areas" as ( +select + ira.id, + ira.imaging_request_id, + ira.area_id +from "public"."imaging_request_areas" ira +join "public"."imaging_requests" ir on ir.id = ira.imaging_request_id +join "public"."encounters" e on e.id = ir.encounter_id +where ira.deleted_at is null + and ir.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."imaging_results" as ( +select + ires.id, + ires.completed_at::timestamp as datetime, + ires.description, + ires.imaging_request_id, + ires.external_code, + ires.completed_by_id, + ires.visibility_status +from "public"."imaging_results" ires +join "public"."imaging_requests" ireq on ireq.id = ires.imaging_request_id +join "public"."encounters" e on e.id = ireq.encounter_id +where ires.deleted_at is null + and ireq.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."invoices" as ( +select + i.id, + i.display_id, + i.date::timestamp as datetime, + i.status, + i.patient_payment_status, + i.insurer_payment_status, + i.encounter_id +from "public"."invoices" i +join "public"."encounters" e on e.id = i.encounter_id +where + i.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."invoice_insurance_plans" as ( +select + id, + name, + code, + default_coverage, + visibility_status +from "public"."invoice_insurance_plans" +where deleted_at is null +); +create or replace view "reporting"."invoice_insurance_plan_items" as ( +select + id, + invoice_insurance_plan_id, + invoice_product_id, + coverage_value +from "public"."invoice_insurance_plan_items" +where deleted_at is null +); +create or replace view "reporting"."invoice_items" as ( +select + ii.id, + ii.invoice_id, + ii.order_date::date as date, + ii.product_id, + ii.product_code_final, + ii.product_name_final, + ii.price_final, + ii.manual_entry_price, + ii.quantity, + ii.ordered_by_user_id, + ii.approved, + ii.source_record_type, + ii.source_record_id +from "public"."invoice_items" ii +join "public"."invoices" i on i.id = ii.invoice_id +join "public"."encounters" e on e.id = i.encounter_id +where + ii.deleted_at is null + and i.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."invoice_price_lists" as ( +select + id, + name, + code, + visibility_status +from "public"."invoice_price_lists" +where deleted_at is null +); +create or replace view "reporting"."invoice_price_list_items" as ( +select + id, + invoice_price_list_id, + invoice_product_id, + price, + is_hidden +from "public"."invoice_price_list_items" +where deleted_at is null +); +create or replace view "reporting"."invoice_products" as ( +select + id, + name, + insurable, + category, + source_record_id, + visibility_status +from "public"."invoice_products" +where deleted_at is null +); +create or replace view "reporting"."lab_requests" as ( +select + lr.id, + lr.created_at as created_datetime, + lr.updated_at as updated_datetime, + lr.display_id, + lr.urgent as is_urgent, + lr.status, + lr.requested_date::timestamp as requested_datetime, + lr.lab_test_priority_id, + lr.lab_test_category_id, + lr.lab_test_panel_request_id, + lr.lab_test_laboratory_id, + lr.requested_by_id, + lr.specimen_attached as is_specimen_collected, + lr.specimen_type_id, + lr.lab_sample_site_id, + lr.sample_time::timestamp as collected_datetime, + lr.collected_by_id, + lr.reason_for_cancellation, + lr.published_date::timestamp as published_datetime, + lr.encounter_id, + lr.department_id +from "public"."lab_requests" lr +join "public"."encounters" e on e.id = lr.encounter_id +where lr.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."lab_requests_metadata" as ( +with change_logs as ( + select + record_id, + logged_at, + least(record_created_at, logged_at) as created_datetime + from "logs"."changes" + where table_name = 'lab_requests' +) +select + record_id as id, + min(created_datetime) as created_datetime, + max(logged_at) as updated_datetime +from change_logs +group by record_id +); +create or replace view "reporting"."lab_request_logs" as ( +select + lrl.id, + lrl.created_at as created_datetime, + lrl.updated_at as updated_datetime, + lrl.lab_request_id, + lrl.status, + lrl.updated_by_id +from "public"."lab_request_logs" lrl +join "public"."lab_requests" lr on lr.id = lrl.lab_request_id +join "public"."encounters" e on e.id = lr.encounter_id +where lrl.deleted_at is null + and lr.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."lab_request_logs_metadata" as ( +with change_logs as ( + select + record_id, + logged_at, + least(record_created_at, logged_at) as created_datetime + from "logs"."changes" + where table_name = 'lab_request_logs' +) +select + record_id as id, + min(created_datetime) as created_datetime, + max(logged_at) as updated_datetime +from change_logs +group by record_id +); +create or replace view "reporting"."lab_tests" as ( +select + lt.id, + lt.date::date as date, + lt.result, + lt.lab_request_id, + lt.lab_test_type_id, + lt.lab_test_method_id, + lt.laboratory_officer, + lt.completed_date::timestamp as completed_datetime, + lt.verification +from "public"."lab_tests" lt +join "public"."lab_requests" lr on lr.id = lt.lab_request_id +join "public"."encounters" e on e.id = lr.encounter_id +where lt.deleted_at is null + and lr.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."lab_test_panels" as ( +select + id, + code, + external_code, + name, + category_id, + visibility_status +from "public"."lab_test_panels" +where deleted_at is null +); +create or replace view "reporting"."lab_test_panel_lab_test_types" as ( +select + id, + lab_test_panel_id, + lab_test_type_id +from "public"."lab_test_panel_lab_test_types" +where deleted_at is null +); +create or replace view "reporting"."lab_test_panel_requests" as ( +select + ltpr.id, + ltpr.lab_test_panel_id, + ltpr.encounter_id +from "public"."lab_test_panel_requests" ltpr +join "public"."encounters" e on e.id = ltpr.encounter_id +where ltpr.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."lab_test_types" as ( +select + id, + code, + external_code, + name, + unit, + male_min, + male_max, + female_min, + female_max, + range_text + as result_type, + options, + lab_test_category_id, + visibility_status, + is_sensitive +from "public"."lab_test_types" +where deleted_at is null +); +create or replace view "reporting"."locations" as ( +select + id, + code, + name, + max_occupancy, + location_group_id, + facility_id, + visibility_status +from "public"."locations" +where deleted_at is null +); +create or replace view "reporting"."location_bookings" as ( +select + id, + start_time::timestamp as start_datetime, + end_time::timestamp as end_datetime, + patient_id, + clinician_id, + encounter_id, + location_id, + booking_type_id, + is_high_priority, + status +from "public"."appointments" +where booking_type_id notnull + and deleted_at is null + and patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."location_groups" as ( +select + id, + code, + name, + facility_id, + visibility_status +from "public"."location_groups" +where deleted_at is null +); +create or replace view "reporting"."medication_dispenses" as ( +select + md.id, + md.pharmacy_order_prescription_id, + md.quantity, + md.dispensed_at::timestamp as dispensed_at, + md.dispensed_by_user_id +from "public"."medication_dispenses" md +join "public"."pharmacy_order_prescriptions" pop + on pop.id = md.pharmacy_order_prescription_id +join "public"."pharmacy_orders" po on po.id = pop.pharmacy_order_id +join "public"."encounters" e on e.id = po.encounter_id +where md.deleted_at is null + and pop.deleted_at is null + and po.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."notes" as ( +-- May include notes for the test patient. +select + n.id, + n.date::timestamp as datetime, + n.content, + n.note_type_id, + rd.name as note_type, + n.record_type, + n.record_id, + n.author_id as authored_by_id, + n.on_behalf_of_id, + n.revised_by_id as updated_note_id, + n.visibility_status +from "public"."notes" n +join "public"."reference_data" rd + on rd.id = n.note_type_id +where n.deleted_at is null +); +create or replace view "reporting"."outpatient_appointments" as ( +select + a.id, + a.start_time::timestamp as start_datetime, + a.end_time::timestamp as end_datetime, + a.patient_id, + a.clinician_id, + a.encounter_id, + a.schedule_id, + a.location_group_id, + a.appointment_type_id, + case + when a.is_high_priority then 'Yes' else 'No' + end as priority, + a.status, + s.until_date::date as until_date, + s.interval, + s.days_of_week, + s.frequency, + s.nth_weekday, + s.occurrence_count, + s.is_fully_generated, + s.generated_until_date, + s.cancelled_at_date +from "public"."appointments" a +left join "public"."appointment_schedules" s on s.id = a.schedule_id +where a.deleted_at is null + and a.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' + and a.appointment_type_id notnull +); +create or replace view "reporting"."outpatient_appointments_change_logs" as ( +-- Base model for outpatient appointment change logs +-- Extracts appointment modifications from logs.changes table +-- Each row represents a change event to an appointment + +with appointment_changes as ( + select + c.id as change_id, + c.record_id as appointment_id, + c.logged_at as modified_datetime, + c.updated_by_user_id as modified_by_user_id, + -- Extract current values from the change log record_data + (c.record_data ->> 'start_time')::timestamp as start_datetime, + (c.record_data ->> 'end_time')::timestamp as end_datetime, + c.record_data ->> 'patient_id' as patient_id, + c.record_data ->> 'clinician_id' as clinician_id, + c.record_data ->> 'location_group_id' as location_group_id, + c.record_data ->> 'appointment_type_id' as appointment_type_id, + (c.record_data ->> 'is_high_priority')::boolean as is_high_priority, + c.record_data ->> 'status' as status, + (c.record_data ->> 'schedule_id')::uuid as schedule_id, + -- Get creator from the first change_sequence (initial creation) + first_value(c.updated_by_user_id) over ( + partition by c.record_id + order by c.logged_at + ) as created_by_user_id, + -- Use LAG to get the previous record state + lag(c.record_data) over ( + partition by c.record_id + order by c.logged_at + ) as previous_record_data, + -- Track change sequence + row_number() over ( + partition by c.record_id + order by c.logged_at + ) as change_sequence + from "logs"."changes" c + where c.table_name = 'appointments' + and c.record_deleted_at is null + and (c.record_data ->> 'appointment_type_id') is not null +) + +select + change_id, + appointment_id, + modified_datetime, + modified_by_user_id, + created_by_user_id, + patient_id, + -- Current appointment details + start_datetime, + end_datetime, + clinician_id, + location_group_id, + appointment_type_id, + is_high_priority, + status, + schedule_id, + -- Previous appointment details + (previous_record_data ->> 'start_time')::timestamp as prev_start_datetime, + (previous_record_data ->> 'end_time')::timestamp as prev_end_datetime, + (previous_record_data ->> 'clinician_id') as prev_clinician_id, + (previous_record_data ->> 'location_group_id') as prev_location_group_id, + (previous_record_data ->> 'appointment_type_id') as prev_appointment_type_id, + (previous_record_data ->> 'is_high_priority')::boolean as prev_is_high_priority, + (previous_record_data ->> 'status') as prev_status, + change_sequence +from appointment_changes +); +create or replace view "reporting"."patients" as ( +select + id, + created_at as created_datetime, + updated_at as updated_datetime, + display_id as display_id, + first_name as first_name, + middle_name as middle_name, + last_name as last_name, + cultural_name as cultural_name, + email as email, + initcap(sex::text) as sex, + date_of_birth::date as date_of_birth, + date_of_death::timestamp as date_of_death, + village_id as village_id +from "public"."patients" +where deleted_at is null + and id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' + and visibility_status != 'merged' +); +create or replace view "reporting"."patients_access_logs" as ( +select + id, + user_id, + record_id as patient_id, + facility_id, + logged_at at time zone 'Australia/Sydney' as logged_at, + session_id, + device_id, + is_mobile, + version, + front_end_context, + back_end_context +from "logs"."accesses" +where deleted_at is null + and record_type = 'Patient' +); +create or replace view "reporting"."patients_change_logs" as ( +with filtered_changes as ( + select + id as changelog_id, + logged_at, + updated_by_user_id, + record_created_at, + record_updated_at, + record_id, + record_data + from "logs"."changes" + where table_name = 'patients' + and record_id not in ( + select id::text + from "public"."patients" t + where t.deleted_at notnull + ) + and record_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +) + +select + fc.changelog_id, + fc.logged_at at time zone 'Australia/Sydney' as logged_at, + fc.updated_by_user_id, + fc.record_id as id, + fc.record_data ->> 'display_id' as display_id, + fc.record_data ->> 'first_name' as first_name, + fc.record_data ->> 'middle_name' as middle_name, + fc.record_data ->> 'last_name' as last_name, + fc.record_data ->> 'cultural_name' as cultural_name, + fc.record_data ->> 'email' as email, + initcap(fc.record_data ->> 'sex') as sex, + (fc.record_data ->> 'date_of_birth')::date as date_of_birth, + (fc.record_data ->> 'date_of_death')::timestamp as date_of_death, + fc.record_data ->> 'village_id' as village_id, + (fc.record_data ->> 'created_at')::date as registration_date +from filtered_changes fc +); +create or replace view "reporting"."patients_merged" as ( +select + id, + display_id as display_id, + first_name as first_name, + middle_name as middle_name, + last_name as last_name, + cultural_name as cultural_name, + email as email, + initcap(sex::text) as sex, + date_of_birth::date as date_of_birth, + date_of_death::timestamp as date_of_death, + village_id as village_id, + created_at::date as registration_date +from "public"."patients" +where deleted_at is null + and id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' + and visibility_status = 'merged' +); +create or replace view "reporting"."patients_metadata" as ( +with change_logs as ( + select + record_id, + logged_at, + least(record_created_at, logged_at) as created_datetime + from "logs"."changes" + where table_name = 'patients' +) +select + record_id as id, + min(created_datetime) as created_datetime, + max(logged_at) as updated_datetime +from change_logs +group by record_id +); +create or replace view "reporting"."patient_additional_data" as ( +select + patient_id, + title as title, + marital_status as marital_status, + primary_contact_number as primary_contact_number, + secondary_contact_number as secondary_contact_number, + emergency_contact_name as emergency_contact_name, + emergency_contact_number as emergency_contact_number, + social_media as social_media, + ethnicity_id as ethnicity_id, + religion_id as religion_id, + nationality_id as nationality_id, + secondary_village_id as secondary_village_id, + country_id as country_id, + division_id as division_id, + subdivision_id as subdivision_id, + medical_area_id as medical_area_id, + nursing_zone_id as nursing_zone_id, + settlement_id as settlement_id, + city_town as city_town, + street_village as street_village, + country_of_birth_id as country_of_birth_id, + place_of_birth as place_of_birth, + birth_certificate as birth_certificate, + driving_license as driving_license, + passport as passport, + educational_level as educational_level, + occupation_id as occupation_id, + blood_type as blood_type, + patient_billing_type_id as patient_billing_type_id, + health_center_id as health_center_id, + insurer_id as insurer_id, + insurer_policy_number as insurer_policy_number, + mother_id as mother_id, + father_id as father_id, + registered_by_id as registered_by_id, + updated_at_by_field as updated_by_field, + created_at::date as registration_date +from "public"."patient_additional_data" +where deleted_at is null + and id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."patient_additional_data_change_logs" as ( +with filtered_changes as ( + select + id as changelog_id, + logged_at, + updated_by_user_id, + record_created_at, + record_updated_at, + record_id, + record_data + from "logs"."changes" + where table_name = 'patient_additional_data' + and record_id not in ( + select id::text + from "public"."patient_additional_data" t + where t.deleted_at notnull + ) + and record_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' -- noqa: ST10 +) + +select + fc.changelog_id, + fc.logged_at at time zone 'Australia/Sydney' as logged_at, + fc.updated_by_user_id, + fc.record_id as patient_id, + fc.record_data ->> 'title' as title, + fc.record_data ->> 'marital_status' as marital_status, + fc.record_data ->> 'primary_contact_number' as primary_contact_number, + fc.record_data ->> 'secondary_contact_number' as secondary_contact_number, + fc.record_data ->> 'emergency_contact_name' as emergency_contact_name, + fc.record_data ->> 'emergency_contact_number' as emergency_contact_number, + fc.record_data ->> 'social_media' as social_media, + fc.record_data ->> 'ethnicity_id' as ethnicity_id, + fc.record_data ->> 'religion_id' as religion_id, + fc.record_data ->> 'nationality_id' as nationality_id, + fc.record_data ->> 'secondary_village_id' as secondary_village_id, + fc.record_data ->> 'country_id' as country_id, + fc.record_data ->> 'division_id' as division_id, + fc.record_data ->> 'subdivision_id' as subdivision_id, + fc.record_data ->> 'medical_area_id' as medical_area_id, + fc.record_data ->> 'nursing_zone_id' as nursing_zone_id, + fc.record_data ->> 'settlement_id' as settlement_id, + fc.record_data ->> 'city_town' as city_town, + fc.record_data ->> 'street_village' as street_village, + fc.record_data ->> 'country_of_birth_id' as country_of_birth_id, + fc.record_data ->> 'place_of_birth' as place_of_birth, + fc.record_data ->> 'birth_certificate' as birth_certificate, + fc.record_data ->> 'driving_license' as driving_license, + fc.record_data ->> 'passport' as passport, + fc.record_data ->> 'educational_level' as educational_level, + fc.record_data ->> 'occupation_id' as occupation_id, + fc.record_data ->> 'blood_type' as blood_type, + fc.record_data ->> 'patient_billing_type_id' as patient_billing_type_id, + fc.record_data ->> 'health_center_id' as health_center_id, + fc.record_data ->> 'insurer_id' as insurer_id, + fc.record_data ->> 'insurer_policy_number' as insurer_policy_number, + fc.record_data ->> 'mother_id' as mother_id, + fc.record_data ->> 'father_id' as father_id, + fc.record_data ->> 'registered_by_id' as registered_by_id, + fc.record_data -> 'updated_at_by_field' as updated_by_field, + (fc.record_data ->> 'created_at')::date as registration_date +from filtered_changes fc +); +create or replace view "reporting"."patient_allergies" as ( +select + id, + patient_id, + allergy_id, + recorded_date::date as recorded_date, + practitioner_id as recorded_by +from "public"."patient_allergies" +where deleted_at is null +); +create or replace view "reporting"."patient_birth_data" as ( +select + patient_id, + time_of_birth::time as birth_time, + gestational_age_estimate, + attendant_at_birth, + name_of_attendant_at_birth, + birth_type, + birth_delivery_type, + birth_weight, + birth_length, + apgar_score_one_minute, + apgar_score_five_minutes, + apgar_score_ten_minutes, + registered_birth_place, + birth_facility_id, + created_at::date as registration_date +from "public"."patient_birth_data" +where deleted_at is null + and id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."patient_care_plans" as ( +select + id, + date::timestamp as care_plan_datetime, + patient_id, + examiner_id as clinician_id, + care_plan_id +from "public"."patient_care_plans" +where deleted_at is null + and patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."patient_conditions" as ( +select + id, + recorded_date::timestamp as recorded_datetime, + note, + condition_id, + patient_id, + examiner_id as recorded_by_id, + resolved as is_resolved, + resolution_date::timestamp as resolved_datetime, + resolution_practitioner_id as resolved_by_id, + resolution_note +from "public"."patient_conditions" +where deleted_at is null + and patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."patient_death_contributing_causes" as ( +select + cdc.id, + cdc.time_after_onset as mins_after_onset, + cdc.patient_death_data_id, + cdc.condition_id +from "public"."contributing_death_causes" cdc +join "public"."patient_death_data" pdd on pdd.id = cdc.patient_death_data_id +where cdc.deleted_at is null + and pdd.deleted_at is null + and pdd.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."patient_death_data" as ( +select + id, + manner, + recent_surgery as had_recent_surgery, + last_surgery_date::date as last_surgery_date, + last_surgery_reason_id, + external_cause_date::date as external_cause_date, + external_cause_location, + external_cause_notes, + was_pregnant, + pregnancy_contributed, + fetal_or_infant as was_fetal_or_infant, + stillborn as was_stillborn, + birth_weight, + within_day_of_birth as was_within_day_of_birth, + hours_survived_since_birth, + carrier_age, + carrier_pregnancy_weeks, + outside_health_facility as was_outside_health_facility, + primary_cause_time_after_onset as primary_cause_mins_after_onset, + primary_cause_condition_id, + antecedent_cause1_time_after_onset as antecedent_cause1_mins_after_onset, + antecedent_cause1_condition_id, + antecedent_cause2_time_after_onset as antecedent_cause2_mins_after_onset, + antecedent_cause2_condition_id, + antecedent_cause3_time_after_onset as antecedent_cause3_mins_after_onset, + antecedent_cause3_condition_id, + patient_id, + clinician_id as recorded_by_id, + facility_id, + is_final, + visibility_status, + autopsy_requested, + autopsy_findings_used, + manner_of_death_description, + pregnancy_moment, + multiple_pregnancy, + mother_condition_description +from "public"."patient_death_data" +where deleted_at is null + and patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."patient_facilities" as ( +select + id, + created_at, + patient_id, + facility_id +from "public"."patient_facilities" +where deleted_at is null + and patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."patient_family_histories" as ( +select + id, + recorded_date::timestamp as recorded_datetime, + patient_id, + practitioner_id as clinician_id, + diagnosis_id, + relationship, + note +from "public"."patient_family_histories" +where deleted_at is null + and patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."patient_field_values" as ( +select + patient_id, + definition_id, + value +from "public"."patient_field_values" +where deleted_at is null + and patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."patient_program_registrations" as ( +select + id, + date::timestamp as datetime, + registration_status, + patient_id, + program_registry_id, + clinical_status_id, + clinician_id as registered_by_id, + registering_facility_id, + facility_id, + village_id, + deactivated_clinician_id as deactivated_by_id, + deactivated_date::timestamp as deactivated_datetime +from "public"."patient_program_registrations" +where deleted_at is null + and patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."patient_program_registrations_change_logs" as ( +with filtered_changes as ( + select + id as changelog_id, + logged_at, + updated_by_user_id, + record_created_at, + record_updated_at, + record_id, + record_data + from "logs"."changes" + where table_name = 'patient_program_registrations' + and record_id not in ( + select id::text + from "public"."patient_program_registrations" t + where t.deleted_at notnull + ) + and ( + version = 'unknown' + or string_to_array(version, '.')::int [] >= string_to_array('2.33.0', '.')::int [] + ) + and record_data ->> 'patient_id' != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +) + +select + fc.changelog_id, + fc.logged_at, + fc.updated_by_user_id, + fc.record_id as id, + (fc.record_data ->> 'date')::timestamp as datetime, + fc.record_data ->> 'registration_status' as registration_status, + fc.record_data ->> 'patient_id' as patient_id, + fc.record_data ->> 'program_registry_id' as program_registry_id, + fc.record_data ->> 'clinical_status_id' as clinical_status_id, + fc.record_data ->> 'clinician_id' as registered_by_id, + fc.record_data ->> 'registering_facility_id' as registering_facility_id, + fc.record_data ->> 'facility_id' as facility_id, + fc.record_data ->> 'village_id' as village_id, + fc.record_data ->> 'deactivated_clinician_id' as deactivated_by_id, + (fc.record_data ->> 'deactivated_date')::timestamp as deactivated_datetime +from filtered_changes fc +); +create or replace view "reporting"."patient_program_registration_conditions" as ( +select + pprc.id, + pprc.date::timestamp as datetime, + pprc.program_registry_condition_id, + pprc.patient_program_registration_id, + pprc.program_registry_condition_category_id, + pprc.reason_for_change, + pprc.clinician_id as recorded_by_id, + pprc.deletion_date::timestamp as deleted_datetime, + pprc.deletion_clinician_id as deleted_by_id +from "public"."patient_program_registration_conditions" pprc +join "public"."patient_program_registrations" ppr + on ppr.id = pprc.patient_program_registration_id +where pprc.deleted_at is null + and ppr.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."patient_program_registration_conditions_change_logs" as ( +with filtered_changes as ( + select + id as changelog_id, + logged_at, + updated_by_user_id, + record_created_at, + record_updated_at, + record_id, + record_data + from "logs"."changes" + where table_name = 'patient_program_registration_conditions' + and record_id not in ( + select id::text + from "public"."patient_program_registration_conditions" t + where t.deleted_at notnull + ) + and ( + version = 'unknown' + or string_to_array(version, '.')::int [] >= string_to_array('2.33.0', '.')::int [] + ) +) + +select + fc.changelog_id, + fc.logged_at, + fc.updated_by_user_id, + fc.record_id as id, + (fc.record_data ->> 'date')::timestamp as datetime, + fc.record_data ->> 'program_registry_condition_id' as program_registry_condition_id, + fc.record_data ->> 'patient_program_registration_id' as patient_program_registration_id, + fc.record_data ->> 'program_registry_condition_category_id' as program_registry_condition_category_id, + fc.record_data ->> 'reason_for_change' as reason_for_change, + fc.record_data ->> 'clinician_id' as recorded_by_id, + (fc.record_data ->> 'deletion_date')::timestamp as deleted_datetime, + fc.record_data ->> 'deletion_clinician_id' as deleted_by_id +from filtered_changes fc +); +create or replace view "reporting"."patient_vaccinations_upcoming" as ( +select + patient_id, + scheduled_vaccine_id as vaccine_schedules_id, + vaccine_category, + vaccine_id, + due_date::date, + days_till_due, + status +from "public"."upcoming_vaccinations" +where patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."pharmacy_orders" as ( +select + po.id, + po.encounter_id, + po.ordering_clinician_id, + po.facility_id, + po.is_discharge_prescription, + po.date::timestamp as datetime +from "public"."pharmacy_orders" po +join "public"."encounters" e on e.id = po.encounter_id +where po.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."pharmacy_order_prescriptions" as ( +select + pop.id, + pop.pharmacy_order_id, + pop.prescription_id, + pop.ongoing_prescription_id, + pop.display_id, + pop.quantity, + pop.repeats, + pop.is_completed +from "public"."pharmacy_order_prescriptions" pop +join "public"."pharmacy_orders" po on po.id = pop.pharmacy_order_id +join "public"."encounters" e on e.id = po.encounter_id +where pop.deleted_at is null + and po.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."prescriptions" as ( +select + p.id, + p.date::timestamp as datetime, + p.start_date::timestamp as start_datetime, + p.end_date::timestamp as end_datetime, + p.medication_id, + p.prescriber_id, + p.indication, + p.route, + p.quantity, + p.repeats, + p.is_ongoing, + p.is_prn, + p.is_variable_dose, + p.dose_amount, + p.units, + p.frequency, + p.duration_value, + p.duration_unit, + p.is_phone_order, + p.ideal_times, + p.discontinued as is_discontinued, + p.discontinuing_clinician_id as discontinued_by_id, + p.discontinuing_reason, + p.discontinued_date::timestamp as discontinued_datetime +from "public"."prescriptions" p +where p.deleted_at is null + and exists ( + select 1 + from "public"."encounter_prescriptions" ep + join "public"."encounters" e on e.id = ep.encounter_id + where ep.prescription_id = p.id + and ep.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' + ) +); +create or replace view "reporting"."procedures" as ( +select + p.id, + p.date::date as date, + p.start_time::timestamp::time as start_time, + p.end_time::timestamp::time as end_time, + p.completed as is_completed, + p.note, + p.completed_note, + p.encounter_id, + p.location_id, + p.procedure_type_id, + p.anaesthetic_id, + p.physician_id as clinician_id, + p.anaesthetist_id, + p.assistant_anaesthetist_id, + p.time_in::time as time_in, + p.time_out::time as time_out +from "public"."procedures" p +join "public"."encounters" e on e.id = p.encounter_id +where p.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."procedures_metadata" as ( +with change_logs as ( + select + record_id, + logged_at, + least(record_created_at, logged_at) as created_datetime + from "logs"."changes" + where table_name = 'procedures' +) +select + record_id as id, + min(created_datetime) as created_datetime, + max(logged_at) as updated_datetime +from change_logs +group by record_id +); +create or replace view "reporting"."programs" as ( +select + id, + code, + name +from "public"."programs" +where deleted_at is null +); +create or replace view "reporting"."program_data_elements" as ( +select + id, + code, + name, + type, + indicator, + default_text, + default_options, + visualisation_config +from "public"."program_data_elements" +where deleted_at is null +); +create or replace view "reporting"."program_registries" as ( +select + id, + code, + name, + currently_at_type, + visibility_status, + program_id +from "public"."program_registries" +where deleted_at is null +); +create or replace view "reporting"."program_registry_clinical_statuses" as ( +select + id, + code, + name, + color, + visibility_status, + program_registry_id +from "public"."program_registry_clinical_statuses" +where deleted_at is null +); +create or replace view "reporting"."program_registry_conditions" as ( +select + id, + code, + name, + visibility_status, + program_registry_id +from "public"."program_registry_conditions" +where deleted_at is null +); +create or replace view "reporting"."program_registry_condition_categories" as ( +select + id, + code, + name, + visibility_status, + program_registry_id +from "public"."program_registry_condition_categories" +where deleted_at is null +); +create or replace view "reporting"."reference_data" as ( +select + id, + code, + name, + type, + visibility_status +from "public"."reference_data" +where deleted_at is null +); +create or replace view "reporting"."referrals" as ( +select + id, + status, + referred_facility, + initiating_encounter_id, + survey_response_id +from "public"."referrals" +where deleted_at is null +); +create or replace view "reporting"."refresh_tokens" as ( +select + id, + device_id, + user_id, + expires_at, + created_at, + updated_at +from + "public"."refresh_tokens" +where deleted_at is null +); +create or replace view "reporting"."roles" as ( +select + id, + name +from "public"."roles" +where deleted_at is null +); +create or replace view "reporting"."surveys" as ( +select + id, + code, + name, + survey_type, + is_sensitive, + notifiable as is_notifiable, + notify_email_addresses, + program_id, + visibility_status +from "public"."surveys" +where deleted_at is null +); +create or replace view "reporting"."survey_responses" as ( +select + id, + start_time::timestamp as start_datetime, + end_time::timestamp as end_datetime, + result_text, + notified as is_notified, + survey_id, + encounter_id, + user_id as submitted_by_id +from "public"."survey_responses" +where deleted_at is null +); +create or replace view "reporting"."survey_response_answers" as ( +select + id, + name, + body, + response_id, + data_element_id +from "public"."survey_response_answers" +where deleted_at is null +); +create or replace view "reporting"."survey_screen_components" as ( +select + id, + screen_index, + component_index, + text, + visibility_criteria, + validation_criteria, + detail, + config, + options, + calculation, + survey_id, + data_element_id, + visibility_status +from "public"."survey_screen_components" +where deleted_at is null +); +create or replace view "reporting"."translated_strings" as ( +select + string_id, + language, + text +from "public"."translated_strings" +where deleted_at is null +); +create or replace view "reporting"."triages" as ( +select + t.id, + t.arrival_time::timestamp as arrival_datetime, + t.triage_time::timestamp as triage_datetime, + t.closed_time::timestamp as closed_datetime, + t.arrival_mode_id, + t.score, + t.encounter_id, + t.practitioner_id as clinician_id, + t.chief_complaint_id, + t.secondary_complaint_id +from "public"."triages" t +join "public"."encounters" e on e.id = t.encounter_id +where t.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."users" as ( +select + id, + display_id, + display_name, + email, + phone_number, + role, + visibility_status +from "public"."users" +where deleted_at is null +); +create or replace view "reporting"."users_metadata" as ( +with change_logs as ( + select + record_id, + logged_at, + least(record_created_at, logged_at) as created_datetime + from "logs"."changes" + where table_name = 'users' +) +select + record_id as id, + min(created_datetime) as created_datetime, + max(logged_at) as updated_datetime +from change_logs +group by record_id +); +create or replace view "reporting"."vaccine_administrations" as ( +select + av.id, + av.date::timestamp as datetime, + av.encounter_id, + av.location_id, + av.department_id, + av.scheduled_vaccine_id, + av.status, + av.reason, + av.not_given_reason_id, + av.batch, + av.vaccine_name, + av.vaccine_brand, + av.disease, + av.consent as is_consented, + av.consent_given_by, + av.injection_site, + av.given_by, + av.given_elsewhere as is_given_elsewhere, + av.circumstance_ids, + av.recorder_id as recorded_by_id +from "public"."administered_vaccines" av +join "public"."encounters" e on e.id = av.encounter_id +where av.deleted_at is null + and e.deleted_at is null + and e.patient_id != 'h1627394-3778-4c31-a510-9fcb88efdbf3' +); +create or replace view "reporting"."vaccine_schedules" as ( +select + id, + category, + vaccine_id, + label, + dose_label, + index, + weeks_from_birth_due, + weeks_from_last_vaccination_due, + sort_index, + visibility_status +from "public"."scheduled_vaccines" +where deleted_at is null +); +create or replace view "reporting"."vaccine_administrations_change_logs" as ( +with filtered_changes as ( + select + av.changelog_id, + av.logged_at, + av.updated_by_user_id, + av.record_created_at, + av.record_updated_at, + av.record_id, + av.record_data + from (select + id as changelog_id, + logged_at, + updated_by_user_id, + record_created_at, + record_updated_at, + record_id, + record_data + from "logs"."changes" + where table_name = 'administered_vaccines' + and record_id not in ( + select id::text + from "public"."administered_vaccines" t + where t.deleted_at notnull + )) av + join "reporting"."encounters" e on e.id = av.record_data ->> 'encounter_id' +) + +select + fc.changelog_id, + fc.logged_at at time zone 'Australia/Sydney' as logged_at, + fc.record_created_at at time zone 'Australia/Sydney' as created_at, + fc.record_updated_at at time zone 'Australia/Sydney' as updated_at, + fc.updated_by_user_id, + fc.record_id as id, + (fc.record_data ->> 'date')::timestamp as datetime, + fc.record_data ->> 'batch' as batch, + (fc.record_data ->> 'consent')::boolean as is_consented, + fc.record_data ->> 'disease' as disease, + fc.record_data ->> 'given_by' as given_by, + (fc.record_data ->> 'given_elsewhere')::boolean as is_given_elsewhere, + fc.record_data ->> 'circumstance_ids' as circumstance_ids, + fc.record_data ->> 'recorder_id' as recorded_by_id, + fc.record_data ->> 'encounter_id' as encounter_id, + fc.record_data ->> 'location_id' as location_id, + fc.record_data ->> 'department_id' as department_id, + fc.record_data ->> 'vaccine_name' as vaccine_name, + fc.record_data ->> 'vaccine_brand' as vaccine_brand, + fc.record_data ->> 'injection_site' as injection_site, + fc.record_data ->> 'consent_given_by' as consent_given_by, + fc.record_data ->> 'scheduled_vaccine_id' as scheduled_vaccine_id, + fc.record_data ->> 'status' as status, + fc.record_data ->> 'reason' as reason, + fc.record_data ->> 'not_given_reason_id' as not_given_reason_id +from filtered_changes fc +); +create or replace view "reporting"."ds__sensitive_admissions" as ( + + +with admission_encounters as ( + select + e.id, + e.patient_id, + e.start_datetime, + e.end_datetime, + e.location_id, + e.patient_billing_type_id, + f.id as facility_id, + f.name as facility_name + from "reporting"."encounters" e + join "reporting"."locations" l on l.id = e.location_id + join "reporting"."facilities" f on f.id = l.facility_id + where e.encounter_type = 'admission' + and f.is_sensitive = True +), + +encounter_history_consolidated as ( + select + eh.encounter_id, + eh.datetime, + eh.change_type, + eh.clinician_id, + eh.department_id, + eh.location_id, + u.display_name as clinician_name, + d.name as department_name, + l.name as location_name, + lg.id as location_group_id, + lg.name as location_group_name, + -- Window functions for ordering and lag operations + row_number() over ( + partition by eh.encounter_id, ('encounter_type' = any(eh.change_type)) + order by eh.datetime + ) as encounter_type_change_sequence, + lag(lg.id) over ( + partition by eh.encounter_id + order by eh.datetime + ) as prev_location_group_id + from admission_encounters ae + left join "reporting"."encounter_history" eh + on eh.encounter_id = ae.id + and eh.encounter_type = 'admission' + and (eh.change_type is null or eh.change_type && array['encounter_type', 'examiner', 'department', 'location']) + left join "reporting"."users" u + on u.id = eh.clinician_id + left join "reporting"."departments" d + on d.id = eh.department_id + left join "reporting"."locations" l + on l.id = eh.location_id + left join "reporting"."location_groups" lg + on lg.id = l.location_group_id +), + +-- Clinician changes and admitting clinician logic +clinician_data as ( + select + encounter_id, + bool_or('encounter_type' = any(change_type) and encounter_type_change_sequence = 1) as is_transfer, + min(datetime) filter (where change_type is null or change_type && array['encounter_type', 'examiner']) as admission_datetime, + array_agg( + datetime + order by datetime + ) filter (where change_type is null or change_type && array['encounter_type', 'examiner'] + ) as clinician_datetimes, + array_agg( + clinician_id + order by datetime + ) filter (where change_type is null or change_type && array['encounter_type', 'examiner'] + ) as clinician_ids, + array_agg( + clinician_name + order by datetime + ) filter (where change_type is null or change_type && array['encounter_type', 'examiner'] + ) as clinician_names + from encounter_history_consolidated + group by encounter_id +), + +-- Admitting clinician determination +admitting_clinicians as ( + select + encounter_id, + admission_datetime, + case + when is_transfer and array_length(clinician_ids, 1) > 1 + then clinician_ids[2] + else clinician_ids[1] + end as admitting_clinician_id, + case + when is_transfer and array_length(clinician_names, 1) > 1 + then clinician_names[2] + else clinician_names[1] + end as admitting_clinician_name + from clinician_data +), + +-- Department changes aggregation +department_changes as ( + select + encounter_id, + string_agg( + to_char(datetime, 'YYYY-MM-DD HH24:MI'), + '; ' + order by datetime + ) as department_datetimes, + array_agg( + department_id + order by datetime + ) as department_ids, + string_agg( + department_name, ', ' + order by datetime + ) as departments + from encounter_history_consolidated + where change_type is null or change_type && array['encounter_type', 'department'] + group by encounter_id +), + +-- Location changes aggregation +location_changes as ( + select + encounter_id, + string_agg( + to_char(datetime, 'YYYY-MM-DD HH24:MI'), + '; ' + order by datetime + ) as location_datetimes, + array_agg( + location_id + order by datetime + ) as location_ids, + string_agg( + location_name, ', ' + order by datetime + ) as locations + from encounter_history_consolidated + where change_type is null or change_type && array['encounter_type', 'location'] + group by encounter_id +), + +-- Location group changes (deduplicated in single pass) +location_group_changes as ( + select + encounter_id, + string_agg( + to_char(datetime, 'YYYY-MM-DD HH24:MI'), + '; ' + order by datetime + ) as location_group_datetimes, + array_agg( + location_group_id + order by datetime + ) as location_group_ids, + string_agg( + location_group_name, ', ' + order by datetime + ) as location_groups + from encounter_history_consolidated + where (change_type is null or change_type && array['encounter_type', 'location']) + and (location_group_id != prev_location_group_id or prev_location_group_id is null) + group by encounter_id +), + +-- Diagnoses aggregation +encounter_diagnoses as ( + select + ed.encounter_id, + string_agg( + case when ed.is_primary + then rd.name || ' (' || rd.code || ')' + end, + '; ' + order by ed.datetime + ) as primary_diagnoses, + string_agg( + case when not ed.is_primary + then rd.name || ' (' || rd.code || ')' + end, + '; ' + order by ed.datetime + ) as secondary_diagnoses + from admission_encounters ae + inner join "reporting"."encounter_diagnoses" ed + on ed.encounter_id = ae.id + inner join "reporting"."reference_data" rd + on rd.id = ed.diagnosis_id + where ed.certainty not in ('disproven', 'error') + group by ed.encounter_id +), + +-- Patient and reference data +patient_data as ( + select + ae.id as encounter_id, + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + p.sex, + p.village_id, + village.name as village_name, + ae.patient_billing_type_id, + bt.name as billing_type_name, + ae.start_datetime, + ae.end_datetime, + ae.location_id, + ae.facility_id, + ae.facility_name + from admission_encounters ae + left join "reporting"."patients" p + on p.id = ae.patient_id + left join "reporting"."reference_data" village + on village.id = p.village_id + left join "reporting"."reference_data" bt + on bt.id = ae.patient_billing_type_id +) + +select + pd.patient_id, + pd.display_id, + pd.first_name, + pd.last_name, + pd.date_of_birth, + date_part('year', age(ac.admission_datetime, pd.date_of_birth)) as age, + initcap(pd.sex::text) as sex, + pd.village_id, + pd.village_name as village, + pd.patient_billing_type_id as billing_type_id, + pd.billing_type_name as billing_type, + ac.admitting_clinician_id, + ac.admitting_clinician_name as admitting_clinician, + ac.admission_datetime, + case + when pd.end_datetime is null then 'active' + else 'discharged' + end as admission_status, + pd.end_datetime as discharge_datetime, + pd.facility_id, + pd.facility_name as facility, + dc.department_ids, + dc.departments, + dc.department_datetimes, + lgc.location_group_ids, + lgc.location_groups, + lgc.location_group_datetimes, + lc.location_ids, + lc.locations, + lc.location_datetimes, + ed.primary_diagnoses, + ed.secondary_diagnoses +from patient_data pd +left join admitting_clinicians ac + on ac.encounter_id = pd.encounter_id +left join department_changes dc + on dc.encounter_id = pd.encounter_id +left join location_changes lc + on lc.encounter_id = pd.encounter_id +left join location_group_changes lgc + on lgc.encounter_id = pd.encounter_id +left join encounter_diagnoses ed + on ed.encounter_id = pd.encounter_id + + +); +create or replace view "reporting"."ds__sensitive_diagnoses" as ( + + +select + e.id as encounter_id, + p.id as patient_id, + diagnosis.id as diagnosis_id, + diagnosis.name as diagnosis, + ed.datetime as diagnosis_datetime, + p.first_name, + p.last_name, + p.display_id, + date_part('year', age(ed.datetime::date, p.date_of_birth)) as age, + p.sex, + coalesce(pad.primary_contact_number, pad.secondary_contact_number) as contact_number, + village.id as village_id, + village.name as village, + clinician.id as clinician_id, + clinician.display_name as clinician, + d.id as department_id, + d.name as department, + l.id as location_id, + l.name as location, + f.id as facility_id, + f.name as facility, + initcap(ed.certainty) as certainty, + case when ed.is_primary = true then 'Yes' else 'No' end as is_primary +from "reporting"."encounter_diagnoses" ed +join "reporting"."reference_data" diagnosis on diagnosis.id = ed.diagnosis_id +join "reporting"."encounters" e on e.id = ed.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +left join "reporting"."patient_additional_data" pad on pad.patient_id = p.id +left join "reporting"."reference_data" village on village.id = p.village_id +left join "reporting"."users" clinician on clinician.id = e.clinician_id +left join "reporting"."departments" d on d.id = e.department_id +join "reporting"."locations" l on l.id = e.location_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = True + + +); +create or replace view "reporting"."ds__sensitive_encounters_emergency" as ( + + +select + t.id as triage_id, + t.arrival_datetime, + t.triage_datetime, + t.closed_datetime, + t.score, + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + p.sex, + p.village_id, + village.name as village, + e.id as encounter_id, + e.encounter_type, + arrival_mode.name as arrival_mode, + chief_complaint.name as chief_complaint, + secondary_complaint.name as secondary_complaint, + clinician.display_name as clinician, + t.clinician_id, + f.id as facility_id, + f.name as facility +from "reporting"."triages" t +join "reporting"."encounters" e on e.id = t.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +left join "reporting"."locations" l on l.id = e.location_id +join "reporting"."facilities" f on f.id = l.facility_id and f.is_sensitive = True +left join "reporting"."reference_data" village on village.id = p.village_id +left join "reporting"."reference_data" arrival_mode on arrival_mode.id = t.arrival_mode_id +left join "reporting"."reference_data" chief_complaint on chief_complaint.id = t.chief_complaint_id +left join "reporting"."reference_data" secondary_complaint on secondary_complaint.id = t.secondary_complaint_id +left join "reporting"."users" clinician on clinician.id = t.clinician_id + + +); +create or replace view "reporting"."ds__sensitive_encounter_diets" as ( + + +with diets as ( + select + ed.encounter_id, + string_agg( + rd.name, ', ' + order by rd.name + ) as diets + from "reporting"."encounter_diets" ed + join "reporting"."reference_data" rd + on rd.id = ed.diet_id + group by ed.encounter_id +), + +allergies as ( + select + pa.patient_id, + string_agg( + rd.name, ', ' + order by rd.name + ) as allergies + from "reporting"."patient_allergies" pa + join "reporting"."reference_data" rd + on rd.id = pa.allergy_id + group by pa.patient_id +) + +select + e.id as encounter_id, + p.id as patient_id, + p.display_id, + concat(p.first_name, ' ', p.last_name) as patient_name, + e.start_datetime, + case + when age(current_date, p.date_of_birth) < interval '8 days' + then concat(extract(day from age(current_date, p.date_of_birth)), ' days') + when age(current_date, p.date_of_birth) >= interval '8 days' + and age(current_date, p.date_of_birth) < interval '1 month' + then concat(extract(week from age(current_date, p.date_of_birth)), ' weeks') + when age(current_date, p.date_of_birth) >= interval '1 month' + and age(current_date, p.date_of_birth) < interval '2 years' + then concat(extract(month from age(current_date, p.date_of_birth)), ' months') + when age(current_date, p.date_of_birth) >= interval '2 years' + then concat(extract(year from age(current_date, p.date_of_birth)), ' years') + end as age, + l.id as location_id, + l.name as location, + lg.id as location_group_id, + lg.name as location_group, + d.diets, + a.allergies +from "reporting"."encounters" e +join "reporting"."patients" p + on p.id = e.patient_id +join "reporting"."locations" l + on l.id = e.location_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = True +left join "reporting"."location_groups" lg + on lg.id = l.location_group_id +left join diets d + on d.encounter_id = e.id +left join allergies a + on a.patient_id = p.id +where e.end_datetime is null + + +); +create or replace view "reporting"."ds__sensitive_encounter_prescriptions" as ( + + +select + ep.encounter_id, + ep.prescription_id, + pr.datetime, + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(pr.datetime, p.date_of_birth)) as age, + p.sex, + coalesce(pd.primary_contact_number, pd.secondary_contact_number) as contact_number, + vil.id as village_id, + vil.name as village, + l.facility_id, + f.name as facility, + ep.is_selected_for_discharge, + pr.medication_id, + m.code as medication_code, + m.name as medication, + pr.route, + pr.quantity, + pr.repeats, + pr.is_ongoing, + pr.is_prn, + pr.is_variable_dose, + pr.dose_amount, + pr.units, + pr.frequency, + pr.is_discontinued, + pr.discontinued_by_id, + pr.discontinuing_reason, + pr.discontinued_datetime +from "reporting"."encounter_prescriptions" ep +join "reporting"."encounters" e on e.id = ep.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +join "reporting"."prescriptions" pr on pr.id = ep.prescription_id +join "reporting"."locations" l on l.id = e.location_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = True +left join "reporting"."patient_additional_data" pd on pd.patient_id = p.id +left join "reporting"."reference_data" vil on vil.id = p.village_id +join "reporting"."reference_data" m on m.id = pr.medication_id + + +); +create or replace view "reporting"."ds__sensitive_imaging_requests" as ( + + +with results as ( + select + imaging_request_id, + min(datetime) as completed_datetime + from "reporting"."imaging_results" + group by imaging_request_id +), + +imaging_area_notes as ( + select + record_id as imaging_request_id, + string_agg(content, ', ' order by datetime) as imaging_area + from "reporting"."notes" + where record_type = 'ImagingRequest' + and note_type_id = 'notetype-areaToBeImaged' + group by record_id +), + +imaging_areas as ( + select + ir.id as imaging_request_id, + coalesce( + string_agg(ia.name, ', ' order by ia.name), + n.imaging_area + ) as imaging_area + from "reporting"."imaging_requests" ir + left join "reporting"."imaging_request_areas" ira on ira.imaging_request_id = ir.id + left join "reporting"."reference_data" ia on ia.id = ira.area_id + left join imaging_area_notes n on n.imaging_request_id = ir.id + group by ir.id, n.imaging_area +) + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(ir.datetime::date, p.date_of_birth)) as age, + p.sex, + v.id as village_id, + v.name as village, + f.id as facility_id, + f.name as facility, + d.id as department_id, + d.name as department, + lg.id as location_group_id, + lg.name as location_group, + ir.display_id as request_id, + ir.datetime as requested_datetime, + su.id as supervising_clinician_id, + su.display_name as supervising_clinician, + ru.id as requesting_clinician_id, + ru.display_name as requesting_clinician, + case + when ir.priority = 'routine' then 'Routine' + when ir.priority = 'urgent' then 'Urgent' + when ir.priority = 'asap' then 'ASAP' + when ir.priority = 'stat' then 'STAT' + when ir.priority = 'today' then 'Today' + else ir.priority + end as priority, + ir.imaging_type, + areas.imaging_area, + ir.status as status_id, + case + when ir.status = 'pending' then 'Pending' + when ir.status = 'in_progress' then 'In progress' + when ir.status = 'completed' then 'Completed' + when ir.status = 'cancelled' then 'Cancelled' + when ir.status = 'deleted' then 'Deleted' + when ir.status = 'entered_in_error' then 'Entered in error' + else 'Unknown' + end as status, + case + when ir.status = 'completed' then irs.completed_datetime + end as completed_datetime, + case + when ir.reason_for_cancellation = 'clinical' then 'Clinical reason' + when ir.reason_for_cancellation = 'duplicate' then 'Duplicate' + when ir.reason_for_cancellation = 'entered-in-error' then 'Entered in error' + when ir.reason_for_cancellation = 'patient-discharged' then 'Patient discharged' + when ir.reason_for_cancellation = 'patient-refused' then 'Patient refused' + when ir.reason_for_cancellation = 'other' then 'Other' + end as reason_for_cancellation +from "reporting"."imaging_requests" ir +join "reporting"."encounters" e on e.id = ir.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +join "reporting"."locations" l on l.id = e.location_id +left join "reporting"."location_groups" lg on lg.id = l.location_group_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = True +left join "reporting"."departments" d on d.id = e.department_id +left join "reporting"."users" su on su.id = e.clinician_id +left join "reporting"."users" ru on ru.id = ir.requested_by_id +left join imaging_areas areas on areas.imaging_request_id = ir.id +left join "reporting"."reference_data" v on v.id = p.village_id +left join results irs on irs.imaging_request_id = ir.id + + +); +create or replace view "reporting"."ds__sensitive_lab_requests" as ( + + +with lab_test_data as ( + select + lr.id as lab_request_id, + string_agg(ltt.name, ', ' + order by ltt.name + ) as tests, + max(lt.completed_datetime) as completed_datetime + from "reporting"."lab_requests" lr + join "reporting"."lab_tests" lt on lt.lab_request_id = lr.id + join "reporting"."lab_test_types" ltt on ltt.id = lt.lab_test_type_id + where ltt.is_sensitive = True + group by lr.id +) + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(lr.requested_datetime, p.date_of_birth)) as age, + p.sex, + village.id as village_id, + village.name as village, + f.id as facility_id, + f.name as facility, + d.name as department, + d.id as department_id, + l.id as location_id, + l.name as location, + lg.id as location_group_id, + lg.name as location_group, + laboratory.id as laboratory_id, + laboratory.name as laboratory, + lr.display_id as request_id, + case lr.status + when 'reception_pending' then 'Reception pending' + when 'results_pending' then 'Results pending' + when 'to_be_verified' then 'To be verified' + when 'verified' then 'Verified' + when 'published' then 'Published' + when 'cancelled' then 'Cancelled' + when 'deleted' then 'Deleted' + when 'sample-not-collected' then 'Sample not collected' + when 'entered-in-error' then 'Entered in error' + else lr.status + end as status, + lr.status as status_id, + lr.requested_datetime, + req_clinician.id as requested_by_id, + req_clinician.display_name as requested_by, + lr.department_id as requesting_department_id, + req_department.name as requesting_department, + lr.lab_test_priority_id as priority_id, + priority.name as priority, + category.id as lab_test_category_id, + category.name as lab_test_category, + ltp.name as lab_test_panel, + lta.tests, + lr.collected_datetime, + lr.collected_by_id, + collector.display_name as collected_by, + lr.specimen_type_id, + specimen.name as specimen_type, + site.name as site, + lta.completed_datetime, + case lr.reason_for_cancellation + when 'clinical' then 'Clinical reason' + when 'duplicate' then 'Duplicate' + when 'entered-in-error' then 'Entered in error' + when 'patient-discharged' then 'Patient discharged' + when 'patient-refused' then 'Patient refused' + when 'other' then 'Other' + else lr.reason_for_cancellation + end as reason_for_cancellation +from "reporting"."lab_requests" lr +join lab_test_data lta on lta.lab_request_id = lr.id +join "reporting"."encounters" e on e.id = lr.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +left join "reporting"."reference_data" village on village.id = p.village_id +left join "reporting"."locations" l on l.id = e.location_id +left join "reporting"."location_groups" lg on lg.id = l.location_group_id +left join "reporting"."departments" d on d.id = e.department_id +left join "reporting"."facilities" f on f.id = l.facility_id +left join "reporting"."reference_data" laboratory on laboratory.id = lr.lab_test_laboratory_id +left join "reporting"."users" req_clinician on req_clinician.id = lr.requested_by_id +left join "reporting"."departments" req_department on req_department.id = lr.department_id +left join "reporting"."reference_data" priority on priority.id = lr.lab_test_priority_id +left join "reporting"."reference_data" category on category.id = lr.lab_test_category_id +left join "reporting"."users" collector on collector.id = lr.collected_by_id +left join "reporting"."reference_data" specimen on specimen.id = lr.specimen_type_id +left join "reporting"."reference_data" site on site.id = lr.lab_sample_site_id +left join "reporting"."lab_test_panel_requests" ltpr + on ltpr.id = lr.lab_test_panel_request_id +left join "reporting"."lab_test_panels" ltp on ltp.id = ltpr.lab_test_panel_id + + +); +create or replace view "reporting"."ds__sensitive_lab_tests" as ( + + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(lr.requested_datetime, p.date_of_birth::date)) as age, + p.sex, + village.id as village_id, + village.name as village, + f.id as facility_id, + f.name as facility, + d.id as department_id, + d.name as department, + req_dept.id as requesting_department_id, + req_dept.name as requesting_department, + lg.id as location_group_id, + lg.name as location_group, + l.id as location_id, + l.name as location, + lr.display_id as lab_request_id, + lr.status as status_id, + case lr.status + when 'reception_pending' then 'Reception pending' + when 'results_pending' then 'Results pending' + when 'to_be_verified' then 'To be verified' + when 'verified' then 'Verified' + when 'published' then 'Published' + when 'cancelled' then 'Cancelled' + when 'deleted' then 'Deleted' + when 'sample-not-collected' then 'Sample not collected' + when 'entered-in-error' then 'Entered in error' + else lr.status + end as status, + ltp.id as lab_test_panel_id, + ltp.name as lab_test_panel, + category.id as lab_test_category_id, + category.name as lab_test_category, + lr.requested_datetime, + requester.id as requested_by_id, + requester.display_name as requested_by, + lr.published_datetime as lab_request_published_datetime, + lt.date as lab_test_date, + lt.result, + lt.verification, + ltt.id as lab_test_type_id, + ltt.name as lab_test_type, + lt.completed_datetime as lab_test_completed_datetime +from "reporting"."lab_requests" lr +join "reporting"."encounters" e on e.id = lr.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +left join "reporting"."reference_data" village on village.id = p.village_id +left join "reporting"."locations" l on l.id = e.location_id +left join "reporting"."location_groups" lg on lg.id = l.location_group_id +left join "reporting"."departments" d on d.id = e.department_id +left join "reporting"."departments" req_dept on req_dept.id = lr.department_id +left join "reporting"."facilities" f on f.id = l.facility_id +left join "reporting"."users" requester on requester.id = lr.requested_by_id +left join "reporting"."lab_test_panel_requests" ltpr on ltpr.id = lr.lab_test_panel_request_id +left join "reporting"."lab_test_panels" ltp on ltp.id = ltpr.lab_test_panel_id +left join "reporting"."reference_data" category on category.id = lr.lab_test_category_id +join "reporting"."lab_tests" lt on lt.lab_request_id = lr.id +join "reporting"."lab_test_types" ltt on ltt.id = lt.lab_test_type_id +where ltt.is_sensitive = True + + +); +create or replace view "reporting"."ds__sensitive_location_bookings" as ( + + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(a.start_datetime::date, p.date_of_birth)) as age, + p.sex, + vil.id as village_id, + vil.name as village, + billing.id as billing_type_id, + billing.name as billing_type, + a.start_datetime as booking_start_datetime, + a.end_datetime as booking_end_datetime, + a.status as booking_status, + u.id as clinician_id, + u.display_name as clinician, + lg.id as location_group_id, + lg.name as location_group, + l.id as location_id, + l.name as location, + a.booking_type_id, + bt.name as booking_type +from "reporting"."location_bookings" a +join "reporting"."patients" p on p.id = a.patient_id +left join "reporting"."users" u on u.id = a.clinician_id +join "reporting"."locations" l on l.id = a.location_id +left join "reporting"."location_groups" lg on lg.id = l.location_group_id +join "reporting"."facilities" f on f.id = l.facility_id + and f.is_sensitive = True +left join "reporting"."patient_additional_data" pd on pd.patient_id = p.id +left join "reporting"."reference_data" billing on billing.id = pd.patient_billing_type_id +left join "reporting"."reference_data" vil on vil.id = p.village_id +left join "reporting"."reference_data" bt on bt.id = a.booking_type_id + + +); +create or replace view "reporting"."ds__sensitive_medication_dispenses" as ( + + +select + md.id, + md.quantity, + md.dispensed_at, + po.facility_id, + f.name as facility, + pr.medication_id, + m.code as medication_code, + m.name as medication +from "reporting"."medication_dispenses" md +join "reporting"."pharmacy_order_prescriptions" pop + on pop.id = md.pharmacy_order_prescription_id +join "reporting"."pharmacy_orders" po + on po.id = pop.pharmacy_order_id +-- prescription_id is not null on all pharmacy_order_prescriptions rows (enforced by source not_null test). +-- ongoing_prescription_id is the nullable supplementary reference and is not used for the medication lookup +join "reporting"."prescriptions" pr + on pr.id = pop.prescription_id +join "reporting"."reference_data" m + on m.id = pr.medication_id +join "reporting"."facilities" f + on f.id = po.facility_id + and f.is_sensitive = True + + +); +create or replace view "reporting"."ds__sensitive_outpatient_appointments" as ( + + +with appointment_creators as ( + select + appointment_id, + created_by_user_id + from "reporting"."outpatient_appointments_change_logs" + where change_sequence = 1 +) + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(a.start_datetime, p.date_of_birth)) as age, + p.sex, + coalesce(pd.primary_contact_number, pd.secondary_contact_number) as contact_number, + vil.id as village_id, + vil.name as village, + billing.id as billing_type_id, + billing.name as billing_type, + a.start_datetime as appointment_start_datetime, + a.end_datetime as appointment_end_datetime, + a.appointment_type_id, + apt.name as appointment_type, + a.status as appointment_status, + u.id as clinician_id, + u.display_name as clinician, + lg.id as location_group_id, + lg.name as location_group, + a.priority, + a.schedule_id, + a.until_date, + a.interval, + a.days_of_week, + a.frequency, + a.nth_weekday, + ac.created_by_user_id, + creator.display_name as created_by +from "reporting"."outpatient_appointments" a +join "reporting"."patients" p on p.id = a.patient_id +left join "reporting"."users" u on u.id = a.clinician_id +join "reporting"."location_groups" lg on lg.id = a.location_group_id +join "reporting"."facilities" f on f.id = lg.facility_id + and f.is_sensitive = True +left join "reporting"."patient_additional_data" pd on pd.patient_id = p.id +left join "reporting"."reference_data" billing on billing.id = pd.patient_billing_type_id +left join "reporting"."reference_data" vil on vil.id = p.village_id +left join "reporting"."reference_data" apt on apt.id = a.appointment_type_id +left join appointment_creators ac on ac.appointment_id = a.id +left join "reporting"."users" creator on creator.id = ac.created_by_user_id + + +); +create or replace view "reporting"."ds__sensitive_outpatient_appointments_audit" as ( + + +-- Outpatient Appointments Audit Dataset +-- This dataset tracks changes/modifications to outpatient appointments +-- Each row represents a modification event (excludes initial creation) +-- +-- Included changes: +-- - Status changed to 'Cancelled' (individual cancellations only) +-- - Changes to: start/end datetime, clinician, location group, appointment type, priority +-- +-- Excluded changes: +-- - Initial appointment creation (change_sequence = 1) +-- - Status-only changes (unless changing to 'Cancelled') +-- - Appointments automatically cancelled when their schedule was cancelled +-- (i.e., bulk cancellations via "cancel this and all future appointments") +-- +-- change_number: starts from 1 for the first modification, increments for subsequent changes +-- +-- Note: schedule_id never changes on existing appointments in Tamanu. +-- When a schedule is modified, old appointments are cancelled and new ones are created. + +with change_evaluation as ( + select + cl.*, + -- Determine if this change has meaningful field modifications + case + -- Status changed to Cancelled + when cl.status = 'Cancelled' and cl.prev_status is distinct from 'Cancelled' then true + -- Any non-status fields changed + when ( + cl.prev_start_datetime is distinct from cl.start_datetime + or cl.prev_end_datetime is distinct from cl.end_datetime + or cl.prev_clinician_id is distinct from cl.clinician_id + or cl.prev_location_group_id is distinct from cl.location_group_id + or cl.prev_appointment_type_id is distinct from cl.appointment_type_id + or cl.prev_is_high_priority is distinct from cl.is_high_priority + ) then true + else false + end as is_meaningful_change + from "reporting"."outpatient_appointments_change_logs" cl + left join "public"."appointment_schedules" s on s.id = cl.schedule_id + where + -- Exclude appointments that were automatically cancelled when the schedule was cancelled + -- (Keep appointments that were individually cancelled, not bulk-cancelled via schedule) + not ( + cl.status = 'Cancelled' + and s.cancelled_at_date is not null + and cl.start_datetime::date > s.cancelled_at_date::date + ) +), + +numbered_changes as ( + select + ce.*, + -- Assign change number: starts from 1 for first modification + row_number() over ( + partition by ce.appointment_id + order by ce.modified_datetime + ) as change_number + from change_evaluation ce + where ce.is_meaningful_change = true + and ce.change_sequence > 1 -- Exclude initial creation +) + +select + fc.change_id, + fc.appointment_id, + fc.change_number, + -- Patient details + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + -- Current appointment details + fc.start_datetime as appointment_start_datetime, + fc.end_datetime as appointment_end_datetime, + apt.name as appointment_type, + fc.appointment_type_id, + clinician.display_name as clinician, + fc.clinician_id, + lg.name as location_group, + fc.location_group_id, + case when fc.is_high_priority then 'Yes' else 'No' end as priority, + fc.schedule_id, + case + when fc.schedule_id is not null then 'Yes' + else 'No' + end as is_repeating, + -- Modification details + creator.display_name as created_by, + fc.created_by_user_id, + modifier.display_name as modified_by, + fc.modified_by_user_id, + fc.modified_datetime, + case when fc.status = 'Cancelled' then 'Yes' else 'No' end as is_cancelled, + -- Previous appointment details (only shown if different from current) + case + when fc.prev_start_datetime is distinct from fc.start_datetime + then fc.prev_start_datetime + end as prev_start_datetime, + case + when fc.prev_end_datetime is distinct from fc.end_datetime + then fc.prev_end_datetime + end as prev_end_datetime, + case + when fc.prev_appointment_type_id is distinct from fc.appointment_type_id + then prev_apt.name + end as prev_appointment_type, + case + when fc.prev_appointment_type_id is distinct from fc.appointment_type_id + then fc.prev_appointment_type_id + end as prev_appointment_type_id, + case + when fc.prev_clinician_id is distinct from fc.clinician_id + then prev_clinician.display_name + end as prev_clinician, + case + when fc.prev_clinician_id is distinct from fc.clinician_id + then fc.prev_clinician_id + end as prev_clinician_id, + case + when fc.prev_location_group_id is distinct from fc.location_group_id + then prev_lg.name + end as prev_location_group, + case + when fc.prev_location_group_id is distinct from fc.location_group_id + then fc.prev_location_group_id + end as prev_location_group_id, + case + when fc.prev_is_high_priority is not null + and fc.prev_is_high_priority is distinct from fc.is_high_priority + then case when fc.prev_is_high_priority then 'Yes' else 'No' end + end as prev_priority, + -- Facility details for filtering + f.id as facility_id, + f.name as facility +from numbered_changes fc +join "reporting"."patients" p on p.id = fc.patient_id +left join "reporting"."users" clinician on clinician.id = fc.clinician_id +left join "reporting"."users" prev_clinician on prev_clinician.id = fc.prev_clinician_id +left join "reporting"."users" creator on creator.id = fc.created_by_user_id +left join "reporting"."users" modifier on modifier.id = fc.modified_by_user_id +join "reporting"."location_groups" lg on lg.id = fc.location_group_id +left join "reporting"."location_groups" prev_lg on prev_lg.id = fc.prev_location_group_id +left join "reporting"."reference_data" apt on apt.id = fc.appointment_type_id +left join "reporting"."reference_data" prev_apt on prev_apt.id = fc.prev_appointment_type_id +left join "public"."appointment_schedules" s on s.id = fc.schedule_id +-- Join to facility for filtering by sensitivity +join "reporting"."facilities" f on f.id = lg.facility_id + and f.is_sensitive = True + + +); +create or replace view "reporting"."ds__sensitive_procedures" as ( + + +with filtered_procedure as ( + select + pc.*, + eh.department_id, + eh.encounter_type, + row_number() over ( + partition by pc.id + order by eh.datetime desc + ) as encounter_history_record + from "reporting"."procedures" pc + left join "reporting"."encounter_history" eh + on eh.encounter_id = pc.encounter_id + and eh.datetime::date <= pc.date +) + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(pc.date, p.date_of_birth)) as age, + p.sex, + nationality.name as nationality, + encounter_facility.id as encounter_facility_id, + encounter_facility.name as encounter_facility, + encounter_department.id as encounter_department_id, + encounter_department.name as encounter_department, + case + when coalesce(pc.encounter_type, e.encounter_type) = 'admission' then 'Hospital Admission' + when coalesce(pc.encounter_type, e.encounter_type) = 'clinic' then 'Clinic' + when coalesce(pc.encounter_type, e.encounter_type) in ('triage', 'observation', 'emergency') then 'Triage' + end as encounter_type, + e.start_datetime as encounter_start_datetime, + e.end_datetime as encounter_end_datetime, + procedure_facility.id as procedure_facility_id, + procedure_facility.name as procedure_facility, + procedure_area.id as procedure_area_id, + procedure_area.name as procedure_area, + procedure_location.id as procedure_location_id, + procedure_location.name as procedure_location, + procedure_type.id as procedure_type_id, + procedure_type.name as procedure_type, + pc.date as procedure_date, + pc.start_time as procedure_start_time, + pc.end_time as procedure_end_time, + case + when pc.end_time is not null and pc.start_time is not null then + concat( + lpad(( + case + when pc.end_time < pc.start_time + then + (24 + extract(hour from pc.end_time) - extract(hour from pc.start_time)) + else + extract(hour from (pc.end_time - pc.start_time)) + end + )::text, 2, '0'), ':', + lpad(( + case + when pc.end_time < pc.start_time + then + (extract(minute from pc.end_time) - extract(minute from pc.start_time)) + else + extract(minute from (pc.end_time - pc.start_time)) + end + )::text, 2, '0') + ) + end as procedure_duration, + clinician.id as procedure_clinician_id, + clinician.display_name as procedure_clinician, + anaesthetist.id as procedure_anaesthetist_id, + anaesthetist.display_name as procedure_anaesthetist, + assistant_anaesthetist.id as procedure_assistant_anaesthetist_id, + assistant_anaesthetist.display_name as procedure_assistant_anaesthetist, + case + when pc.is_completed then 'Y' else 'N' + end as is_completed, + pc.time_in, + pc.time_out +from filtered_procedure pc +join "reporting"."encounters" e on e.id = pc.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +join "reporting"."reference_data" procedure_type on procedure_type.id = pc.procedure_type_id +join "reporting"."locations" procedure_location + on procedure_location.id = pc.location_id +left join "reporting"."location_groups" procedure_area + on procedure_area.id = procedure_location.location_group_id +join "reporting"."facilities" procedure_facility + on procedure_facility.id = procedure_location.facility_id + and procedure_facility.is_sensitive = True +join "reporting"."locations" encounter_location + on encounter_location.id = e.location_id +join "reporting"."facilities" encounter_facility + on encounter_facility.id = encounter_location.facility_id + and encounter_facility.is_sensitive = True +join "reporting"."departments" encounter_department + on encounter_department.id = coalesce(pc.department_id, e.department_id) +left join "reporting"."patient_additional_data" pd on pd.patient_id = p.id +left join "reporting"."reference_data" nationality on nationality.id = pd.nationality_id +left join "reporting"."users" assistant_anaesthetist on assistant_anaesthetist.id = pc.assistant_anaesthetist_id +left join "reporting"."users" anaesthetist on anaesthetist.id = pc.anaesthetist_id +left join "reporting"."users" clinician on clinician.id = pc.clinician_id +where pc.encounter_history_record = 1 + + +); +create or replace view "reporting"."ds__sensitive_referrals" as ( + + +with diagnoses as ( + select + ed.encounter_id, + string_agg(concat(d.name), '; ') as diagnoses + from "reporting"."encounter_diagnoses" ed + left join "reporting"."reference_data" d on d.id = ed.diagnosis_id + group by ed.encounter_id +) + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.village_id, + ed.diagnoses, + s.name as referral_type, + u.id as referring_doctor_id, + u.display_name as referring_doctor_name, + sr.end_datetime as referral_datetime, + rf.status, + d.name as department +from "reporting"."referrals" rf +join "reporting"."encounters" e on e.id = rf.initiating_encounter_id +join "reporting"."locations" l on l.id = e.location_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = True +join "reporting"."survey_responses" sr on sr.id = rf.survey_response_id +join "reporting"."surveys" s on s.id = sr.survey_id +join "reporting"."patients" p on p.id = e.patient_id +join "reporting"."users" u on u.id = e.clinician_id +join "reporting"."departments" d on d.id = e.department_id +left join diagnoses ed on ed.encounter_id = rf.initiating_encounter_id + + +); +create or replace view "reporting"."ds__sensitive_user_audit" as ( + + +with non_system_notes as ( + select distinct on (n.record_id) + n.record_id, + first_value(n.datetime) over w as first_note_datetime, + last_value(n.datetime) over w as last_note_datetime, + last_value(concat_ws(' on behalf of ', author.display_name, on_behalf.display_name)) over w as last_clinician + from "reporting"."notes" n + left join "reporting"."users" author on author.id = n.authored_by_id + left join "reporting"."users" on_behalf on on_behalf.id = n.on_behalf_of_id + where n.note_type_id != 'notetype-system' + window w as ( + partition by n.record_id + order by n.datetime + rows between unbounded preceding and unbounded following + ) +) + +select + u.id as user_id, + u.display_name as user_name, + r.name as user_role, + p.id as patient_id, + p.display_id, + bt.name as patient_category, + t.score as triage_category, + f.id as facility_id, + f.name as facility, + d.id as department_id, + d.name as department, + lg.id as location_group_id, + lg.name as location_group, + l.id as location_id, + l.name as location, + e.start_datetime as encounter_start_datetime, + e.end_datetime as encounter_end_datetime, + n.first_note_datetime, + n.last_note_datetime, + case when e.end_datetime isnull then 'Patient not discharged' + else 'Patient discharged' + end as is_discharged, + case when ds.note like 'Automatically discharged%' then n.last_clinician + end as non_discharge_by_clinicians +from "reporting"."encounters" e +left join "reporting"."users" u on u.id = e.clinician_id +left join "reporting"."roles" r on r.id = u.role +left join "reporting"."patients" p on p.id = e.patient_id +left join "reporting"."patient_additional_data" pad on pad.patient_id = e.patient_id +left join "reporting"."reference_data" bt + on bt.id = coalesce(e.patient_billing_type_id, pad.patient_billing_type_id) +left join "reporting"."triages" t on t.encounter_id = e.id +join "reporting"."locations" l on l.id = e.location_id +left join "reporting"."location_groups" lg on lg.id = l.location_group_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = True +left join "reporting"."departments" d on d.id = e.department_id +left join "reporting"."discharges" ds on ds.encounter_id = e.id +left join non_system_notes n on n.record_id = e.id + + +); +create or replace view "reporting"."ds__admissions" as ( + + +with admission_encounters as ( + select + e.id, + e.patient_id, + e.start_datetime, + e.end_datetime, + e.location_id, + e.patient_billing_type_id, + f.id as facility_id, + f.name as facility_name + from "reporting"."encounters" e + join "reporting"."locations" l on l.id = e.location_id + join "reporting"."facilities" f on f.id = l.facility_id + where e.encounter_type = 'admission' + and f.is_sensitive = False +), + +encounter_history_consolidated as ( + select + eh.encounter_id, + eh.datetime, + eh.change_type, + eh.clinician_id, + eh.department_id, + eh.location_id, + u.display_name as clinician_name, + d.name as department_name, + l.name as location_name, + lg.id as location_group_id, + lg.name as location_group_name, + -- Window functions for ordering and lag operations + row_number() over ( + partition by eh.encounter_id, ('encounter_type' = any(eh.change_type)) + order by eh.datetime + ) as encounter_type_change_sequence, + lag(lg.id) over ( + partition by eh.encounter_id + order by eh.datetime + ) as prev_location_group_id + from admission_encounters ae + left join "reporting"."encounter_history" eh + on eh.encounter_id = ae.id + and eh.encounter_type = 'admission' + and (eh.change_type is null or eh.change_type && array['encounter_type', 'examiner', 'department', 'location']) + left join "reporting"."users" u + on u.id = eh.clinician_id + left join "reporting"."departments" d + on d.id = eh.department_id + left join "reporting"."locations" l + on l.id = eh.location_id + left join "reporting"."location_groups" lg + on lg.id = l.location_group_id +), + +-- Clinician changes and admitting clinician logic +clinician_data as ( + select + encounter_id, + bool_or('encounter_type' = any(change_type) and encounter_type_change_sequence = 1) as is_transfer, + min(datetime) filter (where change_type is null or change_type && array['encounter_type', 'examiner']) as admission_datetime, + array_agg( + datetime + order by datetime + ) filter (where change_type is null or change_type && array['encounter_type', 'examiner'] + ) as clinician_datetimes, + array_agg( + clinician_id + order by datetime + ) filter (where change_type is null or change_type && array['encounter_type', 'examiner'] + ) as clinician_ids, + array_agg( + clinician_name + order by datetime + ) filter (where change_type is null or change_type && array['encounter_type', 'examiner'] + ) as clinician_names + from encounter_history_consolidated + group by encounter_id +), + +-- Admitting clinician determination +admitting_clinicians as ( + select + encounter_id, + admission_datetime, + case + when is_transfer and array_length(clinician_ids, 1) > 1 + then clinician_ids[2] + else clinician_ids[1] + end as admitting_clinician_id, + case + when is_transfer and array_length(clinician_names, 1) > 1 + then clinician_names[2] + else clinician_names[1] + end as admitting_clinician_name + from clinician_data +), + +-- Department changes aggregation +department_changes as ( + select + encounter_id, + string_agg( + to_char(datetime, 'YYYY-MM-DD HH24:MI'), + '; ' + order by datetime + ) as department_datetimes, + array_agg( + department_id + order by datetime + ) as department_ids, + string_agg( + department_name, ', ' + order by datetime + ) as departments + from encounter_history_consolidated + where change_type is null or change_type && array['encounter_type', 'department'] + group by encounter_id +), + +-- Location changes aggregation +location_changes as ( + select + encounter_id, + string_agg( + to_char(datetime, 'YYYY-MM-DD HH24:MI'), + '; ' + order by datetime + ) as location_datetimes, + array_agg( + location_id + order by datetime + ) as location_ids, + string_agg( + location_name, ', ' + order by datetime + ) as locations + from encounter_history_consolidated + where change_type is null or change_type && array['encounter_type', 'location'] + group by encounter_id +), + +-- Location group changes (deduplicated in single pass) +location_group_changes as ( + select + encounter_id, + string_agg( + to_char(datetime, 'YYYY-MM-DD HH24:MI'), + '; ' + order by datetime + ) as location_group_datetimes, + array_agg( + location_group_id + order by datetime + ) as location_group_ids, + string_agg( + location_group_name, ', ' + order by datetime + ) as location_groups + from encounter_history_consolidated + where (change_type is null or change_type && array['encounter_type', 'location']) + and (location_group_id != prev_location_group_id or prev_location_group_id is null) + group by encounter_id +), + +-- Diagnoses aggregation +encounter_diagnoses as ( + select + ed.encounter_id, + string_agg( + case when ed.is_primary + then rd.name || ' (' || rd.code || ')' + end, + '; ' + order by ed.datetime + ) as primary_diagnoses, + string_agg( + case when not ed.is_primary + then rd.name || ' (' || rd.code || ')' + end, + '; ' + order by ed.datetime + ) as secondary_diagnoses + from admission_encounters ae + inner join "reporting"."encounter_diagnoses" ed + on ed.encounter_id = ae.id + inner join "reporting"."reference_data" rd + on rd.id = ed.diagnosis_id + where ed.certainty not in ('disproven', 'error') + group by ed.encounter_id +), + +-- Patient and reference data +patient_data as ( + select + ae.id as encounter_id, + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + p.sex, + p.village_id, + village.name as village_name, + ae.patient_billing_type_id, + bt.name as billing_type_name, + ae.start_datetime, + ae.end_datetime, + ae.location_id, + ae.facility_id, + ae.facility_name + from admission_encounters ae + left join "reporting"."patients" p + on p.id = ae.patient_id + left join "reporting"."reference_data" village + on village.id = p.village_id + left join "reporting"."reference_data" bt + on bt.id = ae.patient_billing_type_id +) + +select + pd.patient_id, + pd.display_id, + pd.first_name, + pd.last_name, + pd.date_of_birth, + date_part('year', age(ac.admission_datetime, pd.date_of_birth)) as age, + initcap(pd.sex::text) as sex, + pd.village_id, + pd.village_name as village, + pd.patient_billing_type_id as billing_type_id, + pd.billing_type_name as billing_type, + ac.admitting_clinician_id, + ac.admitting_clinician_name as admitting_clinician, + ac.admission_datetime, + case + when pd.end_datetime is null then 'active' + else 'discharged' + end as admission_status, + pd.end_datetime as discharge_datetime, + pd.facility_id, + pd.facility_name as facility, + dc.department_ids, + dc.departments, + dc.department_datetimes, + lgc.location_group_ids, + lgc.location_groups, + lgc.location_group_datetimes, + lc.location_ids, + lc.locations, + lc.location_datetimes, + ed.primary_diagnoses, + ed.secondary_diagnoses +from patient_data pd +left join admitting_clinicians ac + on ac.encounter_id = pd.encounter_id +left join department_changes dc + on dc.encounter_id = pd.encounter_id +left join location_changes lc + on lc.encounter_id = pd.encounter_id +left join location_group_changes lgc + on lgc.encounter_id = pd.encounter_id +left join encounter_diagnoses ed + on ed.encounter_id = pd.encounter_id + + +); +create or replace view "reporting"."ds__births" as ( +select + pbd.registration_date, + case + when left(pbd.registration_date::text, 10) = left(pad.registration_date::text, 10) then u.display_name + end as registered_by, + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + p.sex, + rd_ethnicity.name as ethnicity, + rd_nationality.name as nationality, + p.village_id, + rd_village.name as village, + case + when + p_mother.id is not null + then concat(p_mother.first_name, ' ', p_mother.last_name, ' (', p_mother.display_id, ')') + end as mother, + case + when + p_father.id is not null + then concat(p_father.first_name, ' ', p_father.last_name, ' (', p_father.display_id, ')') + end as father, + pbd.birth_time, + pbd.gestational_age_estimate, + case when pbd.registered_birth_place = 'health_facility' then 'Health facility' + when pbd.registered_birth_place = 'home' then 'Home' + when pbd.registered_birth_place = 'other' then 'Other' + else pbd.registered_birth_place + end as registered_birth_place, + f.id as birth_facility_id, + f.name as birth_facility, + case when pbd.attendant_at_birth = 'doctor' then 'Doctor' + when pbd.attendant_at_birth = 'midwife' then 'Midwife' + when pbd.attendant_at_birth = 'nurse' then 'Nurse' + when pbd.attendant_at_birth = 'traditional_birth_attentdant' then 'Traditional birth attendant' + when pbd.attendant_at_birth = 'other' then 'Other' + else pbd.attendant_at_birth + end as attendant_at_birth, + pbd.name_of_attendant_at_birth, + case + when pbd.birth_delivery_type = 'normal_vaginal_delivery' then 'Normal vaginal delivery' + when pbd.birth_delivery_type = 'breech' then 'Breech' + when pbd.birth_delivery_type = 'emergency_c_section' then 'Emergency C-section' + when pbd.birth_delivery_type = 'elective_c_section' then 'Elective C-section' + when pbd.birth_delivery_type = 'vacuum_extraction' then 'Vacuum extraction' + when pbd.birth_delivery_type = 'forceps' then 'Forceps' + when pbd.birth_delivery_type = 'other' then 'Other' + else pbd.birth_delivery_type + end as birth_delivery_type, + initcap(pbd.birth_type::text) as birth_type, + pbd.birth_weight, + pbd.birth_length, + pbd.apgar_score_one_minute, + pbd.apgar_score_five_minutes, + pbd.apgar_score_ten_minutes +from "reporting"."patient_birth_data" pbd +join "reporting"."patients" p on p.id = pbd.patient_id +left join "reporting"."reference_data" rd_village on rd_village.id = p.village_id +left join "reporting"."patient_additional_data" pad on pad.patient_id = p.id +left join "reporting"."reference_data" rd_nationality on rd_nationality.id = pad.nationality_id +left join "reporting"."reference_data" rd_ethnicity on rd_ethnicity.id = pad.ethnicity_id +left join "reporting"."patients" p_mother on p_mother.id = pad.mother_id +left join "reporting"."patients" p_father on p_father.id = pad.father_id +left join "reporting"."facilities" f on f.id = pbd.birth_facility_id +left join "reporting"."users" u on u.id = pad.registered_by_id +); +create or replace view "reporting"."ds__deaths" as ( +with contributing_death_causes as ( + select + cdc.patient_death_data_id, + array_agg( + cdc.condition_id + order by cdc.time_after_onset + ) as other_conditions + from "reporting"."contributing_death_causes" cdc + group by cdc.patient_death_data_id +), + +encounters_with_death as ( + select distinct on (e.patient_id) + e.patient_id, + e.start_datetime, + e.end_datetime, + e.location_id, + e.department_id, + e.clinician_id + from "reporting"."encounters" e + join "reporting"."patients" p + on p.id = e.patient_id + and p.date_of_death between e.start_datetime and e.end_datetime + order by e.patient_id asc, e.end_datetime desc +) + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(p.date_of_death::date, p.date_of_birth::date)) as age, + p.sex, + village.id as village_id, + village.name as village, + nationality.id as nationality_id, + nationality.name as nationality, + case + when pdd.was_outside_health_facility then 'Died outside health facility' + else facility.name + end as place_of_death, + facility.id as facility_id, + department.id as department_id, + department.name as department, + location_group.id as location_group_id, + location_group.name as location_group, + location.id as location_id, + location.name as location, + p.date_of_death, + clinician.id as attending_clinician_id, + clinician.display_name as attending_clinician, + primary_condition.id as primary_cause_condition_id, + primary_condition.name as primary_cause_condition, + case + when pdd.primary_cause_mins_after_onset is null or pdd.primary_cause_mins_after_onset = 0 + then '0 minutes' + when mod(pdd.primary_cause_mins_after_onset, (60 * 24 * 365)) = 0 + then concat(pdd.primary_cause_mins_after_onset / (60 * 24 * 365), ' years') + when mod(pdd.primary_cause_mins_after_onset, (60 * 24 * 30)) = 0 + then concat(pdd.primary_cause_mins_after_onset / (60 * 24 * 30), ' months') + when mod(pdd.primary_cause_mins_after_onset, (60 * 24 * 7)) = 0 + then concat(pdd.primary_cause_mins_after_onset / (60 * 24 * 7), ' weeks') + when mod(pdd.primary_cause_mins_after_onset, (60 * 24)) = 0 + then concat(pdd.primary_cause_mins_after_onset / (60 * 24), ' days') + when mod(pdd.primary_cause_mins_after_onset, 60) = 0 + then concat(pdd.primary_cause_mins_after_onset / 60, ' hours') + else concat(pdd.primary_cause_mins_after_onset, ' minutes') + end as time_between_onset_and_death, + antecedent_condition_1.id as antecedent_cause_1_id, + antecedent_condition_1.name as antecedent_cause_1, + antecedent_condition_2.id as antecedent_cause_2_id, + antecedent_condition_2.name as antecedent_cause_2, + other_condition_1.id as other_condition_1_id, + other_condition_1.name as other_condition_1, + other_condition_2.id as other_condition_2_id, + other_condition_2.name as other_condition_2, + other_condition_3.id as other_condition_3_id, + other_condition_3.name as other_condition_3, + other_condition_4.id as other_condition_4_id, + other_condition_4.name as other_condition_4, + initcap(pdd.had_recent_surgery) as had_recent_surgery, + pdd.last_surgery_date, + surgery_reason.id as reason_for_surgery_id, + surgery_reason.name as reason_for_surgery, + pdd.manner as manner_of_death, + pdd.external_cause_date, + pdd.external_cause_location, + initcap(pdd.was_pregnant) as was_pregnant, + pdd.pregnancy_contributed, + case + when pdd.was_fetal_or_infant then 'Yes' + else 'No' + end as was_fetal_or_infant, + initcap(pdd.was_stillborn) as was_stillborn, + pdd.birth_weight, + pdd.carrier_pregnancy_weeks as completed_weeks_of_pregnancy, + pdd.carrier_age as age_of_mother, + pdd.mother_condition_description as condition_in_mother_affecting_fetus_or_newborn, + case + when pdd.was_within_day_of_birth then 'Yes' + else 'No' + end as death_within_day_of_birth, + pdd.hours_survived_since_birth +from "reporting"."patient_death_data" pdd +join "reporting"."patients" p + on p.id = pdd.patient_id +left join "reporting"."patient_additional_data" pd + on pd.patient_id = p.id +left join "reporting"."reference_data" village + on village.id = p.village_id +left join "reporting"."reference_data" nationality + on nationality.id = pd.nationality_id +left join "reporting"."reference_data" primary_condition + on primary_condition.id = pdd.primary_cause_condition_id +left join "reporting"."reference_data" antecedent_condition_1 + on antecedent_condition_1.id = pdd.antecedent_cause1_condition_id +left join "reporting"."reference_data" antecedent_condition_2 + on antecedent_condition_2.id = pdd.antecedent_cause2_condition_id +left join contributing_death_causes cdc + on cdc.patient_death_data_id = pdd.id +left join "reporting"."reference_data" other_condition_1 + on other_condition_1.id = cdc.other_conditions[1] +left join "reporting"."reference_data" other_condition_2 + on other_condition_2.id = cdc.other_conditions[2] +left join "reporting"."reference_data" other_condition_3 + on other_condition_3.id = cdc.other_conditions[3] +left join "reporting"."reference_data" other_condition_4 + on other_condition_4.id = cdc.other_conditions[4] +left join "reporting"."reference_data" surgery_reason + on surgery_reason.id = pdd.last_surgery_reason_id +left join encounters_with_death ewd + on ewd.patient_id = p.id +left join "reporting"."facilities" facility + on facility.id = pdd.facility_id +left join "reporting"."departments" department + on department.id = ewd.department_id +left join "reporting"."locations" location + on location.id = ewd.location_id +left join "reporting"."location_groups" location_group + on location_group.id = location.location_group_id +left join "reporting"."users" clinician + on clinician.id = pdd.recorded_by_id +where pdd.visibility_status = 'current' + and pdd.is_final +); +create or replace view "reporting"."ds__diagnoses" as ( + + +select + e.id as encounter_id, + p.id as patient_id, + diagnosis.id as diagnosis_id, + diagnosis.name as diagnosis, + ed.datetime as diagnosis_datetime, + p.first_name, + p.last_name, + p.display_id, + date_part('year', age(ed.datetime::date, p.date_of_birth)) as age, + p.sex, + coalesce(pad.primary_contact_number, pad.secondary_contact_number) as contact_number, + village.id as village_id, + village.name as village, + clinician.id as clinician_id, + clinician.display_name as clinician, + d.id as department_id, + d.name as department, + l.id as location_id, + l.name as location, + f.id as facility_id, + f.name as facility, + initcap(ed.certainty) as certainty, + case when ed.is_primary = true then 'Yes' else 'No' end as is_primary +from "reporting"."encounter_diagnoses" ed +join "reporting"."reference_data" diagnosis on diagnosis.id = ed.diagnosis_id +join "reporting"."encounters" e on e.id = ed.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +left join "reporting"."patient_additional_data" pad on pad.patient_id = p.id +left join "reporting"."reference_data" village on village.id = p.village_id +left join "reporting"."users" clinician on clinician.id = e.clinician_id +left join "reporting"."departments" d on d.id = e.department_id +join "reporting"."locations" l on l.id = e.location_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = False + + +); +create or replace view "reporting"."ds__encounters_emergency" as ( + + +select + t.id as triage_id, + t.arrival_datetime, + t.triage_datetime, + t.closed_datetime, + t.score, + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + p.sex, + p.village_id, + village.name as village, + e.id as encounter_id, + e.encounter_type, + arrival_mode.name as arrival_mode, + chief_complaint.name as chief_complaint, + secondary_complaint.name as secondary_complaint, + clinician.display_name as clinician, + t.clinician_id, + f.id as facility_id, + f.name as facility +from "reporting"."triages" t +join "reporting"."encounters" e on e.id = t.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +left join "reporting"."locations" l on l.id = e.location_id +join "reporting"."facilities" f on f.id = l.facility_id and f.is_sensitive = False +left join "reporting"."reference_data" village on village.id = p.village_id +left join "reporting"."reference_data" arrival_mode on arrival_mode.id = t.arrival_mode_id +left join "reporting"."reference_data" chief_complaint on chief_complaint.id = t.chief_complaint_id +left join "reporting"."reference_data" secondary_complaint on secondary_complaint.id = t.secondary_complaint_id +left join "reporting"."users" clinician on clinician.id = t.clinician_id + + +); +create or replace view "reporting"."ds__encounter_diets" as ( + + +with diets as ( + select + ed.encounter_id, + string_agg( + rd.name, ', ' + order by rd.name + ) as diets + from "reporting"."encounter_diets" ed + join "reporting"."reference_data" rd + on rd.id = ed.diet_id + group by ed.encounter_id +), + +allergies as ( + select + pa.patient_id, + string_agg( + rd.name, ', ' + order by rd.name + ) as allergies + from "reporting"."patient_allergies" pa + join "reporting"."reference_data" rd + on rd.id = pa.allergy_id + group by pa.patient_id +) + +select + e.id as encounter_id, + p.id as patient_id, + p.display_id, + concat(p.first_name, ' ', p.last_name) as patient_name, + e.start_datetime, + case + when age(current_date, p.date_of_birth) < interval '8 days' + then concat(extract(day from age(current_date, p.date_of_birth)), ' days') + when age(current_date, p.date_of_birth) >= interval '8 days' + and age(current_date, p.date_of_birth) < interval '1 month' + then concat(extract(week from age(current_date, p.date_of_birth)), ' weeks') + when age(current_date, p.date_of_birth) >= interval '1 month' + and age(current_date, p.date_of_birth) < interval '2 years' + then concat(extract(month from age(current_date, p.date_of_birth)), ' months') + when age(current_date, p.date_of_birth) >= interval '2 years' + then concat(extract(year from age(current_date, p.date_of_birth)), ' years') + end as age, + l.id as location_id, + l.name as location, + lg.id as location_group_id, + lg.name as location_group, + d.diets, + a.allergies +from "reporting"."encounters" e +join "reporting"."patients" p + on p.id = e.patient_id +join "reporting"."locations" l + on l.id = e.location_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = False +left join "reporting"."location_groups" lg + on lg.id = l.location_group_id +left join diets d + on d.encounter_id = e.id +left join allergies a + on a.patient_id = p.id +where e.end_datetime is null + + +); +create or replace view "reporting"."ds__encounter_prescriptions" as ( + + +select + ep.encounter_id, + ep.prescription_id, + pr.datetime, + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(pr.datetime, p.date_of_birth)) as age, + p.sex, + coalesce(pd.primary_contact_number, pd.secondary_contact_number) as contact_number, + vil.id as village_id, + vil.name as village, + l.facility_id, + f.name as facility, + ep.is_selected_for_discharge, + pr.medication_id, + m.code as medication_code, + m.name as medication, + pr.route, + pr.quantity, + pr.repeats, + pr.is_ongoing, + pr.is_prn, + pr.is_variable_dose, + pr.dose_amount, + pr.units, + pr.frequency, + pr.is_discontinued, + pr.discontinued_by_id, + pr.discontinuing_reason, + pr.discontinued_datetime +from "reporting"."encounter_prescriptions" ep +join "reporting"."encounters" e on e.id = ep.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +join "reporting"."prescriptions" pr on pr.id = ep.prescription_id +join "reporting"."locations" l on l.id = e.location_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = False +left join "reporting"."patient_additional_data" pd on pd.patient_id = p.id +left join "reporting"."reference_data" vil on vil.id = p.village_id +join "reporting"."reference_data" m on m.id = pr.medication_id + + +); +create or replace view "reporting"."ds__imaging_requests" as ( + + +with results as ( + select + imaging_request_id, + min(datetime) as completed_datetime + from "reporting"."imaging_results" + group by imaging_request_id +), + +imaging_area_notes as ( + select + record_id as imaging_request_id, + string_agg(content, ', ' order by datetime) as imaging_area + from "reporting"."notes" + where record_type = 'ImagingRequest' + and note_type_id = 'notetype-areaToBeImaged' + group by record_id +), + +imaging_areas as ( + select + ir.id as imaging_request_id, + coalesce( + string_agg(ia.name, ', ' order by ia.name), + n.imaging_area + ) as imaging_area + from "reporting"."imaging_requests" ir + left join "reporting"."imaging_request_areas" ira on ira.imaging_request_id = ir.id + left join "reporting"."reference_data" ia on ia.id = ira.area_id + left join imaging_area_notes n on n.imaging_request_id = ir.id + group by ir.id, n.imaging_area +) + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(ir.datetime::date, p.date_of_birth)) as age, + p.sex, + v.id as village_id, + v.name as village, + f.id as facility_id, + f.name as facility, + d.id as department_id, + d.name as department, + lg.id as location_group_id, + lg.name as location_group, + ir.display_id as request_id, + ir.datetime as requested_datetime, + su.id as supervising_clinician_id, + su.display_name as supervising_clinician, + ru.id as requesting_clinician_id, + ru.display_name as requesting_clinician, + case + when ir.priority = 'routine' then 'Routine' + when ir.priority = 'urgent' then 'Urgent' + when ir.priority = 'asap' then 'ASAP' + when ir.priority = 'stat' then 'STAT' + when ir.priority = 'today' then 'Today' + else ir.priority + end as priority, + ir.imaging_type, + areas.imaging_area, + ir.status as status_id, + case + when ir.status = 'pending' then 'Pending' + when ir.status = 'in_progress' then 'In progress' + when ir.status = 'completed' then 'Completed' + when ir.status = 'cancelled' then 'Cancelled' + when ir.status = 'deleted' then 'Deleted' + when ir.status = 'entered_in_error' then 'Entered in error' + else 'Unknown' + end as status, + case + when ir.status = 'completed' then irs.completed_datetime + end as completed_datetime, + case + when ir.reason_for_cancellation = 'clinical' then 'Clinical reason' + when ir.reason_for_cancellation = 'duplicate' then 'Duplicate' + when ir.reason_for_cancellation = 'entered-in-error' then 'Entered in error' + when ir.reason_for_cancellation = 'patient-discharged' then 'Patient discharged' + when ir.reason_for_cancellation = 'patient-refused' then 'Patient refused' + when ir.reason_for_cancellation = 'other' then 'Other' + end as reason_for_cancellation +from "reporting"."imaging_requests" ir +join "reporting"."encounters" e on e.id = ir.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +join "reporting"."locations" l on l.id = e.location_id +left join "reporting"."location_groups" lg on lg.id = l.location_group_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = False +left join "reporting"."departments" d on d.id = e.department_id +left join "reporting"."users" su on su.id = e.clinician_id +left join "reporting"."users" ru on ru.id = ir.requested_by_id +left join imaging_areas areas on areas.imaging_request_id = ir.id +left join "reporting"."reference_data" v on v.id = p.village_id +left join results irs on irs.imaging_request_id = ir.id + + +); +create or replace view "reporting"."ds__invoice_products" as ( + + +with price_pivot as ( + select + invoice_product_id + from "reporting"."invoice_price_list_items" + where is_hidden = false + group by invoice_product_id +), + +insurance_pivot as ( + select + invoice_product_id + from "reporting"."invoice_insurance_plan_items" + group by invoice_product_id +) + +select + ip.id, + ip.name, + ip.insurable, + ip.category, + ip.source_record_id, + ip.visibility_status, + coalesce(ltt.external_code, ltp.external_code) as external_code +from "reporting"."invoice_products" ip +left join price_pivot pp on pp.invoice_product_id = ip.id +left join insurance_pivot insurp on insurp.invoice_product_id = ip.id +left join "reporting"."lab_test_types" ltt on ltt.id = ip.source_record_id +left join "reporting"."lab_test_panels" ltp on ltp.id = ip.source_record_id +); +create or replace view "reporting"."ds__lab_requests" as ( + + +with lab_test_data as ( + select + lr.id as lab_request_id, + string_agg(ltt.name, ', ' + order by ltt.name + ) as tests, + max(lt.completed_datetime) as completed_datetime + from "reporting"."lab_requests" lr + join "reporting"."lab_tests" lt on lt.lab_request_id = lr.id + join "reporting"."lab_test_types" ltt on ltt.id = lt.lab_test_type_id + where ltt.is_sensitive = False + group by lr.id +) + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(lr.requested_datetime, p.date_of_birth)) as age, + p.sex, + village.id as village_id, + village.name as village, + f.id as facility_id, + f.name as facility, + d.name as department, + d.id as department_id, + l.id as location_id, + l.name as location, + lg.id as location_group_id, + lg.name as location_group, + laboratory.id as laboratory_id, + laboratory.name as laboratory, + lr.display_id as request_id, + case lr.status + when 'reception_pending' then 'Reception pending' + when 'results_pending' then 'Results pending' + when 'to_be_verified' then 'To be verified' + when 'verified' then 'Verified' + when 'published' then 'Published' + when 'cancelled' then 'Cancelled' + when 'deleted' then 'Deleted' + when 'sample-not-collected' then 'Sample not collected' + when 'entered-in-error' then 'Entered in error' + else lr.status + end as status, + lr.status as status_id, + lr.requested_datetime, + req_clinician.id as requested_by_id, + req_clinician.display_name as requested_by, + lr.department_id as requesting_department_id, + req_department.name as requesting_department, + lr.lab_test_priority_id as priority_id, + priority.name as priority, + category.id as lab_test_category_id, + category.name as lab_test_category, + ltp.name as lab_test_panel, + lta.tests, + lr.collected_datetime, + lr.collected_by_id, + collector.display_name as collected_by, + lr.specimen_type_id, + specimen.name as specimen_type, + site.name as site, + lta.completed_datetime, + case lr.reason_for_cancellation + when 'clinical' then 'Clinical reason' + when 'duplicate' then 'Duplicate' + when 'entered-in-error' then 'Entered in error' + when 'patient-discharged' then 'Patient discharged' + when 'patient-refused' then 'Patient refused' + when 'other' then 'Other' + else lr.reason_for_cancellation + end as reason_for_cancellation +from "reporting"."lab_requests" lr +join lab_test_data lta on lta.lab_request_id = lr.id +join "reporting"."encounters" e on e.id = lr.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +left join "reporting"."reference_data" village on village.id = p.village_id +left join "reporting"."locations" l on l.id = e.location_id +left join "reporting"."location_groups" lg on lg.id = l.location_group_id +left join "reporting"."departments" d on d.id = e.department_id +left join "reporting"."facilities" f on f.id = l.facility_id +left join "reporting"."reference_data" laboratory on laboratory.id = lr.lab_test_laboratory_id +left join "reporting"."users" req_clinician on req_clinician.id = lr.requested_by_id +left join "reporting"."departments" req_department on req_department.id = lr.department_id +left join "reporting"."reference_data" priority on priority.id = lr.lab_test_priority_id +left join "reporting"."reference_data" category on category.id = lr.lab_test_category_id +left join "reporting"."users" collector on collector.id = lr.collected_by_id +left join "reporting"."reference_data" specimen on specimen.id = lr.specimen_type_id +left join "reporting"."reference_data" site on site.id = lr.lab_sample_site_id +left join "reporting"."lab_test_panel_requests" ltpr + on ltpr.id = lr.lab_test_panel_request_id +left join "reporting"."lab_test_panels" ltp on ltp.id = ltpr.lab_test_panel_id + + +); +create or replace view "reporting"."ds__lab_tests" as ( + + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(lr.requested_datetime, p.date_of_birth::date)) as age, + p.sex, + village.id as village_id, + village.name as village, + f.id as facility_id, + f.name as facility, + d.id as department_id, + d.name as department, + req_dept.id as requesting_department_id, + req_dept.name as requesting_department, + lg.id as location_group_id, + lg.name as location_group, + l.id as location_id, + l.name as location, + lr.display_id as lab_request_id, + lr.status as status_id, + case lr.status + when 'reception_pending' then 'Reception pending' + when 'results_pending' then 'Results pending' + when 'to_be_verified' then 'To be verified' + when 'verified' then 'Verified' + when 'published' then 'Published' + when 'cancelled' then 'Cancelled' + when 'deleted' then 'Deleted' + when 'sample-not-collected' then 'Sample not collected' + when 'entered-in-error' then 'Entered in error' + else lr.status + end as status, + ltp.id as lab_test_panel_id, + ltp.name as lab_test_panel, + category.id as lab_test_category_id, + category.name as lab_test_category, + lr.requested_datetime, + requester.id as requested_by_id, + requester.display_name as requested_by, + lr.published_datetime as lab_request_published_datetime, + lt.date as lab_test_date, + lt.result, + lt.verification, + ltt.id as lab_test_type_id, + ltt.name as lab_test_type, + lt.completed_datetime as lab_test_completed_datetime +from "reporting"."lab_requests" lr +join "reporting"."encounters" e on e.id = lr.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +left join "reporting"."reference_data" village on village.id = p.village_id +left join "reporting"."locations" l on l.id = e.location_id +left join "reporting"."location_groups" lg on lg.id = l.location_group_id +left join "reporting"."departments" d on d.id = e.department_id +left join "reporting"."departments" req_dept on req_dept.id = lr.department_id +left join "reporting"."facilities" f on f.id = l.facility_id +left join "reporting"."users" requester on requester.id = lr.requested_by_id +left join "reporting"."lab_test_panel_requests" ltpr on ltpr.id = lr.lab_test_panel_request_id +left join "reporting"."lab_test_panels" ltp on ltp.id = ltpr.lab_test_panel_id +left join "reporting"."reference_data" category on category.id = lr.lab_test_category_id +join "reporting"."lab_tests" lt on lt.lab_request_id = lr.id +join "reporting"."lab_test_types" ltt on ltt.id = lt.lab_test_type_id +where ltt.is_sensitive = False + + +); +create or replace view "reporting"."ds__location_bookings" as ( + + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(a.start_datetime::date, p.date_of_birth)) as age, + p.sex, + vil.id as village_id, + vil.name as village, + billing.id as billing_type_id, + billing.name as billing_type, + a.start_datetime as booking_start_datetime, + a.end_datetime as booking_end_datetime, + a.status as booking_status, + u.id as clinician_id, + u.display_name as clinician, + lg.id as location_group_id, + lg.name as location_group, + l.id as location_id, + l.name as location, + a.booking_type_id, + bt.name as booking_type +from "reporting"."location_bookings" a +join "reporting"."patients" p on p.id = a.patient_id +left join "reporting"."users" u on u.id = a.clinician_id +join "reporting"."locations" l on l.id = a.location_id +left join "reporting"."location_groups" lg on lg.id = l.location_group_id +join "reporting"."facilities" f on f.id = l.facility_id + and f.is_sensitive = False +left join "reporting"."patient_additional_data" pd on pd.patient_id = p.id +left join "reporting"."reference_data" billing on billing.id = pd.patient_billing_type_id +left join "reporting"."reference_data" vil on vil.id = p.village_id +left join "reporting"."reference_data" bt on bt.id = a.booking_type_id + + +); +create or replace view "reporting"."ds__medication_dispenses" as ( + + +select + md.id, + md.quantity, + md.dispensed_at, + po.facility_id, + f.name as facility, + pr.medication_id, + m.code as medication_code, + m.name as medication +from "reporting"."medication_dispenses" md +join "reporting"."pharmacy_order_prescriptions" pop + on pop.id = md.pharmacy_order_prescription_id +join "reporting"."pharmacy_orders" po + on po.id = pop.pharmacy_order_id +-- prescription_id is not null on all pharmacy_order_prescriptions rows (enforced by source not_null test). +-- ongoing_prescription_id is the nullable supplementary reference and is not used for the medication lookup +join "reporting"."prescriptions" pr + on pr.id = pop.prescription_id +join "reporting"."reference_data" m + on m.id = pr.medication_id +join "reporting"."facilities" f + on f.id = po.facility_id + and f.is_sensitive = False + + +); +create or replace view "reporting"."ds__ongoing_conditions" as ( +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(pc.recorded_datetime::date, p.date_of_birth)) as age, + p.sex, + village.name as village, + village.id as village_id, + conditions.name as condition, + conditions.id as condition_id, + pc.recorded_datetime, + clinician.id as clinician_id, + clinician.display_name as clinician, + case when pc.is_resolved then pc.resolved_datetime end as date_resolved, + case when pc.is_resolved then resolving_clinician.display_name end as clinician_resolving +from "reporting"."patient_conditions" pc +join "reporting"."patients" p on p.id = pc.patient_id +join "reporting"."reference_data" conditions on conditions.id = pc.condition_id +left join "reporting"."reference_data" village on village.id = p.village_id +left join "reporting"."users" clinician on clinician.id = pc.recorded_by_id +left join "reporting"."users" resolving_clinician + on resolving_clinician.id = pc.resolved_by_id +); +create or replace view "reporting"."ds__outpatient_appointments" as ( + + +with appointment_creators as ( + select + appointment_id, + created_by_user_id + from "reporting"."outpatient_appointments_change_logs" + where change_sequence = 1 +) + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(a.start_datetime, p.date_of_birth)) as age, + p.sex, + coalesce(pd.primary_contact_number, pd.secondary_contact_number) as contact_number, + vil.id as village_id, + vil.name as village, + billing.id as billing_type_id, + billing.name as billing_type, + a.start_datetime as appointment_start_datetime, + a.end_datetime as appointment_end_datetime, + a.appointment_type_id, + apt.name as appointment_type, + a.status as appointment_status, + u.id as clinician_id, + u.display_name as clinician, + lg.id as location_group_id, + lg.name as location_group, + a.priority, + a.schedule_id, + a.until_date, + a.interval, + a.days_of_week, + a.frequency, + a.nth_weekday, + ac.created_by_user_id, + creator.display_name as created_by +from "reporting"."outpatient_appointments" a +join "reporting"."patients" p on p.id = a.patient_id +left join "reporting"."users" u on u.id = a.clinician_id +join "reporting"."location_groups" lg on lg.id = a.location_group_id +join "reporting"."facilities" f on f.id = lg.facility_id + and f.is_sensitive = False +left join "reporting"."patient_additional_data" pd on pd.patient_id = p.id +left join "reporting"."reference_data" billing on billing.id = pd.patient_billing_type_id +left join "reporting"."reference_data" vil on vil.id = p.village_id +left join "reporting"."reference_data" apt on apt.id = a.appointment_type_id +left join appointment_creators ac on ac.appointment_id = a.id +left join "reporting"."users" creator on creator.id = ac.created_by_user_id + + +); +create or replace view "reporting"."ds__outpatient_appointments_audit" as ( + + +-- Outpatient Appointments Audit Dataset +-- This dataset tracks changes/modifications to outpatient appointments +-- Each row represents a modification event (excludes initial creation) +-- +-- Included changes: +-- - Status changed to 'Cancelled' (individual cancellations only) +-- - Changes to: start/end datetime, clinician, location group, appointment type, priority +-- +-- Excluded changes: +-- - Initial appointment creation (change_sequence = 1) +-- - Status-only changes (unless changing to 'Cancelled') +-- - Appointments automatically cancelled when their schedule was cancelled +-- (i.e., bulk cancellations via "cancel this and all future appointments") +-- +-- change_number: starts from 1 for the first modification, increments for subsequent changes +-- +-- Note: schedule_id never changes on existing appointments in Tamanu. +-- When a schedule is modified, old appointments are cancelled and new ones are created. + +with change_evaluation as ( + select + cl.*, + -- Determine if this change has meaningful field modifications + case + -- Status changed to Cancelled + when cl.status = 'Cancelled' and cl.prev_status is distinct from 'Cancelled' then true + -- Any non-status fields changed + when ( + cl.prev_start_datetime is distinct from cl.start_datetime + or cl.prev_end_datetime is distinct from cl.end_datetime + or cl.prev_clinician_id is distinct from cl.clinician_id + or cl.prev_location_group_id is distinct from cl.location_group_id + or cl.prev_appointment_type_id is distinct from cl.appointment_type_id + or cl.prev_is_high_priority is distinct from cl.is_high_priority + ) then true + else false + end as is_meaningful_change + from "reporting"."outpatient_appointments_change_logs" cl + left join "public"."appointment_schedules" s on s.id = cl.schedule_id + where + -- Exclude appointments that were automatically cancelled when the schedule was cancelled + -- (Keep appointments that were individually cancelled, not bulk-cancelled via schedule) + not ( + cl.status = 'Cancelled' + and s.cancelled_at_date is not null + and cl.start_datetime::date > s.cancelled_at_date::date + ) +), + +numbered_changes as ( + select + ce.*, + -- Assign change number: starts from 1 for first modification + row_number() over ( + partition by ce.appointment_id + order by ce.modified_datetime + ) as change_number + from change_evaluation ce + where ce.is_meaningful_change = true + and ce.change_sequence > 1 -- Exclude initial creation +) + +select + fc.change_id, + fc.appointment_id, + fc.change_number, + -- Patient details + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + -- Current appointment details + fc.start_datetime as appointment_start_datetime, + fc.end_datetime as appointment_end_datetime, + apt.name as appointment_type, + fc.appointment_type_id, + clinician.display_name as clinician, + fc.clinician_id, + lg.name as location_group, + fc.location_group_id, + case when fc.is_high_priority then 'Yes' else 'No' end as priority, + fc.schedule_id, + case + when fc.schedule_id is not null then 'Yes' + else 'No' + end as is_repeating, + -- Modification details + creator.display_name as created_by, + fc.created_by_user_id, + modifier.display_name as modified_by, + fc.modified_by_user_id, + fc.modified_datetime, + case when fc.status = 'Cancelled' then 'Yes' else 'No' end as is_cancelled, + -- Previous appointment details (only shown if different from current) + case + when fc.prev_start_datetime is distinct from fc.start_datetime + then fc.prev_start_datetime + end as prev_start_datetime, + case + when fc.prev_end_datetime is distinct from fc.end_datetime + then fc.prev_end_datetime + end as prev_end_datetime, + case + when fc.prev_appointment_type_id is distinct from fc.appointment_type_id + then prev_apt.name + end as prev_appointment_type, + case + when fc.prev_appointment_type_id is distinct from fc.appointment_type_id + then fc.prev_appointment_type_id + end as prev_appointment_type_id, + case + when fc.prev_clinician_id is distinct from fc.clinician_id + then prev_clinician.display_name + end as prev_clinician, + case + when fc.prev_clinician_id is distinct from fc.clinician_id + then fc.prev_clinician_id + end as prev_clinician_id, + case + when fc.prev_location_group_id is distinct from fc.location_group_id + then prev_lg.name + end as prev_location_group, + case + when fc.prev_location_group_id is distinct from fc.location_group_id + then fc.prev_location_group_id + end as prev_location_group_id, + case + when fc.prev_is_high_priority is not null + and fc.prev_is_high_priority is distinct from fc.is_high_priority + then case when fc.prev_is_high_priority then 'Yes' else 'No' end + end as prev_priority, + -- Facility details for filtering + f.id as facility_id, + f.name as facility +from numbered_changes fc +join "reporting"."patients" p on p.id = fc.patient_id +left join "reporting"."users" clinician on clinician.id = fc.clinician_id +left join "reporting"."users" prev_clinician on prev_clinician.id = fc.prev_clinician_id +left join "reporting"."users" creator on creator.id = fc.created_by_user_id +left join "reporting"."users" modifier on modifier.id = fc.modified_by_user_id +join "reporting"."location_groups" lg on lg.id = fc.location_group_id +left join "reporting"."location_groups" prev_lg on prev_lg.id = fc.prev_location_group_id +left join "reporting"."reference_data" apt on apt.id = fc.appointment_type_id +left join "reporting"."reference_data" prev_apt on prev_apt.id = fc.prev_appointment_type_id +left join "public"."appointment_schedules" s on s.id = fc.schedule_id +-- Join to facility for filtering by sensitivity +join "reporting"."facilities" f on f.id = lg.facility_id + and f.is_sensitive = False + + +); +create or replace view "reporting"."ds__patients" as ( +select + p.created_datetime as registration_date, + u.display_name as registered_by, + p.id as patient_id, + p.first_name, + p.middle_name, + p.last_name, + p.cultural_name, + p.display_id, + p.sex, + p.village_id, + village.name as village, + p.date_of_birth, + p.date_of_death, + pad.birth_certificate, + pad.driving_license, + pad.passport, + pad.blood_type, + pad.title, + pad.marital_status, + pad.primary_contact_number, + pad.secondary_contact_number, + cob.name as country_of_birth, + nationality.name as nationality, + ethnicity.name as ethnicity, + occupation.name as occupation, + religion.name as religion, + billing.name as patient_billing_type, + pad.mother_id, + pad.father_id, + pad.street_village, + case + when pbd.patient_id is null then 'Patient' + else 'Birth' + end as registration_type, + date_part( + 'year', + age( + coalesce(p.date_of_death::date, current_date), + p.date_of_birth + ) + ) as age, + case + when p.date_of_death is not null then 'Deceased' + else 'Alive' + end as status +from "reporting"."patients" p +left join "reporting"."patient_additional_data" pad on pad.patient_id = p.id +left join "reporting"."patient_birth_data" pbd on pbd.patient_id = p.id +left join "reporting"."users" u on u.id = pad.registered_by_id +left join "reporting"."reference_data" village on village.id = p.village_id and village.type = 'village' +left join "reporting"."reference_data" cob on cob.id = pad.country_of_birth_id and cob.type = 'country' +left join "reporting"."reference_data" nationality on nationality.id = pad.nationality_id and nationality.type = 'nationality' +left join "reporting"."reference_data" ethnicity on ethnicity.id = pad.ethnicity_id and ethnicity.type = 'ethnicity' +left join "reporting"."reference_data" occupation on occupation.id = pad.occupation_id and occupation.type = 'occupation' +left join "reporting"."reference_data" religion on religion.id = pad.religion_id and religion.type = 'religion' +left join "reporting"."reference_data" billing on billing.id = pad.patient_billing_type_id and billing.type = 'patientBillingType' +); +create or replace view "reporting"."ds__patients_access_logs" as ( +with grouped_access_logs as ( + select + lap.patient_id, + lap.user_id, + lap.facility_id, + date_trunc('minute', min(lap.logged_at)) as date_time_viewed, + -- Take the first values for fields that might vary within the same minute + lap.is_mobile, + lap.session_id, + lap.device_id + from "reporting"."patients_access_logs" lap + group by + lap.patient_id, + lap.user_id, + lap.facility_id, + lap.is_mobile, + lap.session_id, + lap.device_id +) + +select + gal.patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + p.sex, + p.village_id, + village.name as village, + gal.user_id as viewed_by_user_id, + u.display_name as viewed_by_user, + u.email as user_email, + u.role as user_role, + f.name as viewed_at_facility, + gal.date_time_viewed, + gal.facility_id, + gal.is_mobile, + gal.session_id, + gal.device_id +from grouped_access_logs gal +join "reporting"."patients" p on p.id = gal.patient_id +left join "reporting"."users" u on u.id = gal.user_id +left join "reporting"."facilities" f on f.id = gal.facility_id +left join "reporting"."reference_data" village on village.id = p.village_id +); +create or replace view "reporting"."ds__patients_change_logs" as ( +with patient_edits as ( + -- Patient details edits + select + lcp.id as patient_id, + lcp.display_id, + lcp.first_name, + lcp.last_name, + lcp.date_of_birth, + lcp.sex, + lcp.village_id, + lcp.updated_by_user_id, + lcp.logged_at + from "reporting"."patients_change_logs" lcp + + union all + + -- Patient additional data edits + select + lcpad.patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + p.sex, + p.village_id, + lcpad.updated_by_user_id, + lcpad.logged_at + from "reporting"."patient_additional_data_change_logs" lcpad + left join "reporting"."patients" p on p.id = lcpad.patient_id +), + +grouped_edits as ( + select + pe.patient_id, + pe.display_id, + pe.first_name, + pe.last_name, + pe.date_of_birth, + pe.sex, + pe.village_id, + pe.updated_by_user_id, + date_trunc('minute', pe.logged_at) as edited_datetime + from patient_edits pe + group by + pe.patient_id, + pe.display_id, + pe.first_name, + pe.last_name, + pe.date_of_birth, + pe.sex, + pe.village_id, + pe.updated_by_user_id, + date_trunc('minute', pe.logged_at) +) + +select + ge.patient_id, + ge.display_id, + ge.first_name, + ge.last_name, + ge.date_of_birth, + ge.sex, + ge.village_id, + village.name as village, + ge.updated_by_user_id as edited_by_user_id, + u.display_name as edited_by_user, + u.email as user_email, + u.role as user_role, + ge.edited_datetime +from grouped_edits ge +left join "reporting"."users" u on u.id = ge.updated_by_user_id +left join "reporting"."reference_data" village on village.id = ge.village_id +); +create or replace view "reporting"."ds__patient_program_registrations" as ( +with related_conditions as ( + select + ppr.id as patient_program_registration_id, + string_agg( + prc.name, '; ' + order by pprc.datetime + ) as conditions, + array_agg( + pprc.program_registry_condition_id + order by pprc.datetime + ) as condition_ids, + string_agg( + prcc.name, '; ' + order by pprc.datetime + ) as condition_categories, + array_agg( + pprc.program_registry_condition_category_id + order by pprc.datetime + ) as condition_category_ids + from "reporting"."patient_program_registration_conditions" pprc + join "reporting"."patient_program_registrations" ppr on ppr.id = pprc.patient_program_registration_id + left join "reporting"."program_registry_conditions" prc on prc.id = pprc.program_registry_condition_id + left join "reporting"."program_registry_condition_categories" prcc on prcc.id = pprc.program_registry_condition_category_id + group by ppr.id +) + +select + ppr.id as patient_program_registration_id, + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + p.sex, + village.id as village_id, + village.name as village, + registering_facility.id as registering_facility_id, + registering_facility.name as registering_facility, + registered_by.id as registered_by_id, + registered_by.display_name as registered_by, + case + when pr.currently_at_type = 'facility' then currently_at_facility.name + when pr.currently_at_type = 'village' then currently_at_village.name + end as currently_at, + pr.currently_at_type, + c.condition_ids as related_condition_ids, + c.conditions as related_conditions, + c.condition_category_ids as related_condition_category_ids, + c.condition_categories as related_condition_categories, + prcs.id as clinical_status_id, + prcs.name as clinical_status, + ppr.registration_status, + ppr.program_registry_id, + subdivision.id as subdivision_id, + subdivision.name as subdivision, + division.id as division_id, + division.name as division, + ppr.datetime as registration_datetime, + ppr.deactivated_by_id, + deactivated_by.display_name as deactivated_by, + ppr.deactivated_datetime, + pad.primary_contact_number, + pad.secondary_contact_number, + pad.emergency_contact_name, + pad.emergency_contact_number +from "reporting"."patient_program_registrations" ppr +join "reporting"."program_registries" pr on pr.id = ppr.program_registry_id +join "reporting"."patients" p on p.id = ppr.patient_id +left join "reporting"."patient_additional_data" pad on pad.patient_id = p.id +left join "reporting"."facilities" registering_facility on registering_facility.id = ppr.registering_facility_id +left join "reporting"."users" registered_by on registered_by.id = ppr.registered_by_id +left join "reporting"."reference_data" village on village.id = p.village_id +left join "reporting"."facilities" currently_at_facility on currently_at_facility.id = ppr.facility_id +left join "reporting"."reference_data" subdivision on subdivision.id = pad.subdivision_id +left join "reporting"."reference_data" division on division.id = pad.division_id +left join "reporting"."reference_data" currently_at_village on currently_at_village.id = ppr.village_id +left join related_conditions c on c.patient_program_registration_id = ppr.id +left join "reporting"."program_registry_clinical_statuses" prcs on prcs.id = ppr.clinical_status_id +left join "reporting"."users" deactivated_by on deactivated_by.id = ppr.deactivated_by_id +); +create or replace view "reporting"."ds__patient_vaccinations_upcoming" as ( +select + p.display_id, + p.first_name, + p.last_name, + p.id as patient_id, + p.date_of_birth, + date_part('year', age(p.date_of_birth)) as age, + p.sex, + village.id as village_id, + village.name as village, + pvu.due_date, + pvu.vaccine_category, + pvu.vaccine_schedules_id, + sv.label as vaccine_name, + sv.dose_label as vaccine_schedule, + pvu.status as vaccine_status +from "reporting"."patient_vaccinations_upcoming" pvu +join "reporting"."patients" p on p.id = pvu.patient_id +join "reporting"."vaccine_schedules" sv on sv.id = pvu.vaccine_schedules_id +left join "reporting"."reference_data" village on village.id = p.village_id +where p.date_of_death is null +); +create or replace view "reporting"."ds__procedures" as ( + + +with filtered_procedure as ( + select + pc.*, + eh.department_id, + eh.encounter_type, + row_number() over ( + partition by pc.id + order by eh.datetime desc + ) as encounter_history_record + from "reporting"."procedures" pc + left join "reporting"."encounter_history" eh + on eh.encounter_id = pc.encounter_id + and eh.datetime::date <= pc.date +) + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.date_of_birth, + date_part('year', age(pc.date, p.date_of_birth)) as age, + p.sex, + nationality.name as nationality, + encounter_facility.id as encounter_facility_id, + encounter_facility.name as encounter_facility, + encounter_department.id as encounter_department_id, + encounter_department.name as encounter_department, + case + when coalesce(pc.encounter_type, e.encounter_type) = 'admission' then 'Hospital Admission' + when coalesce(pc.encounter_type, e.encounter_type) = 'clinic' then 'Clinic' + when coalesce(pc.encounter_type, e.encounter_type) in ('triage', 'observation', 'emergency') then 'Triage' + end as encounter_type, + e.start_datetime as encounter_start_datetime, + e.end_datetime as encounter_end_datetime, + procedure_facility.id as procedure_facility_id, + procedure_facility.name as procedure_facility, + procedure_area.id as procedure_area_id, + procedure_area.name as procedure_area, + procedure_location.id as procedure_location_id, + procedure_location.name as procedure_location, + procedure_type.id as procedure_type_id, + procedure_type.name as procedure_type, + pc.date as procedure_date, + pc.start_time as procedure_start_time, + pc.end_time as procedure_end_time, + case + when pc.end_time is not null and pc.start_time is not null then + concat( + lpad(( + case + when pc.end_time < pc.start_time + then + (24 + extract(hour from pc.end_time) - extract(hour from pc.start_time)) + else + extract(hour from (pc.end_time - pc.start_time)) + end + )::text, 2, '0'), ':', + lpad(( + case + when pc.end_time < pc.start_time + then + (extract(minute from pc.end_time) - extract(minute from pc.start_time)) + else + extract(minute from (pc.end_time - pc.start_time)) + end + )::text, 2, '0') + ) + end as procedure_duration, + clinician.id as procedure_clinician_id, + clinician.display_name as procedure_clinician, + anaesthetist.id as procedure_anaesthetist_id, + anaesthetist.display_name as procedure_anaesthetist, + assistant_anaesthetist.id as procedure_assistant_anaesthetist_id, + assistant_anaesthetist.display_name as procedure_assistant_anaesthetist, + case + when pc.is_completed then 'Y' else 'N' + end as is_completed, + pc.time_in, + pc.time_out +from filtered_procedure pc +join "reporting"."encounters" e on e.id = pc.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +join "reporting"."reference_data" procedure_type on procedure_type.id = pc.procedure_type_id +join "reporting"."locations" procedure_location + on procedure_location.id = pc.location_id +left join "reporting"."location_groups" procedure_area + on procedure_area.id = procedure_location.location_group_id +join "reporting"."facilities" procedure_facility + on procedure_facility.id = procedure_location.facility_id + and procedure_facility.is_sensitive = False +join "reporting"."locations" encounter_location + on encounter_location.id = e.location_id +join "reporting"."facilities" encounter_facility + on encounter_facility.id = encounter_location.facility_id + and encounter_facility.is_sensitive = False +join "reporting"."departments" encounter_department + on encounter_department.id = coalesce(pc.department_id, e.department_id) +left join "reporting"."patient_additional_data" pd on pd.patient_id = p.id +left join "reporting"."reference_data" nationality on nationality.id = pd.nationality_id +left join "reporting"."users" assistant_anaesthetist on assistant_anaesthetist.id = pc.assistant_anaesthetist_id +left join "reporting"."users" anaesthetist on anaesthetist.id = pc.anaesthetist_id +left join "reporting"."users" clinician on clinician.id = pc.clinician_id +where pc.encounter_history_record = 1 + + +); +create or replace view "reporting"."ds__referrals" as ( + + +with diagnoses as ( + select + ed.encounter_id, + string_agg(concat(d.name), '; ') as diagnoses + from "reporting"."encounter_diagnoses" ed + left join "reporting"."reference_data" d on d.id = ed.diagnosis_id + group by ed.encounter_id +) + +select + p.id as patient_id, + p.display_id, + p.first_name, + p.last_name, + p.village_id, + ed.diagnoses, + s.name as referral_type, + u.id as referring_doctor_id, + u.display_name as referring_doctor_name, + sr.end_datetime as referral_datetime, + rf.status, + d.name as department +from "reporting"."referrals" rf +join "reporting"."encounters" e on e.id = rf.initiating_encounter_id +join "reporting"."locations" l on l.id = e.location_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = False +join "reporting"."survey_responses" sr on sr.id = rf.survey_response_id +join "reporting"."surveys" s on s.id = sr.survey_id +join "reporting"."patients" p on p.id = e.patient_id +join "reporting"."users" u on u.id = e.clinician_id +join "reporting"."departments" d on d.id = e.department_id +left join diagnoses ed on ed.encounter_id = rf.initiating_encounter_id + + +); +create or replace view "reporting"."ds__usage_quality_metrics_patient_details" as ( +with data as ( + select + p.id as patient_id, + pm.id as patient_merged_id, + coalesce(nullif(trim(p.first_name), ''), nullif(trim(pm.first_name), '')) as first_name, + coalesce(nullif(trim(p.last_name), ''), nullif(trim(pm.last_name), '')) as last_name, + coalesce(p.date_of_birth, pm.date_of_birth) as date_of_birth, + coalesce(nullif(trim(p.village_id), ''), nullif(trim(pm.village_id), '')) as village_id, + nullif(trim(pad.nursing_zone_id), '') as nursing_zone_id, + nullif(trim(pad.medical_area_id), '') as medical_area_id, + nullif(trim(pad.subdivision_id), '') as subdivision_id, + nullif(trim(pad.division_id), '') as division_id, + nullif(trim(pad.primary_contact_number), '') as primary_contact_number, + nullif(trim(pad.secondary_contact_number), '') as secondary_contact_number + from "reporting"."patients" p + full join "reporting"."patients_merged" pm + on pm.id = p.id + left join "reporting"."patient_additional_data" pad + on pad.patient_id = coalesce(p.id, pm.id) +) + +select + count(*) as total_patients, + count(*) filter (where first_name is null or last_name is null) as total_patients_with_incomplete_name, + count(*) filter (where date_of_birth is null) as total_patients_with_missing_dob, + count(*) filter (where date_of_birth <= '1900-01-01' or date_of_birth > now()::date) as total_patients_with_invalid_dob, + count(*) filter (where coalesce(village_id, nursing_zone_id, medical_area_id, subdivision_id, division_id) is null) as total_patients_with_missing_location, + count(*) filter (where coalesce(primary_contact_number, secondary_contact_number) is null) as total_patients_with_missing_contact, + count(patient_merged_id) as total_patients_merged +from data +); +create or replace view "reporting"."ds__usage_quality_metrics_patient_registrations" as ( +with data as ( + select + p.created_datetime as registration_date, + p.id as registration_patient_id, + pbd.patient_id as birth_patient_id, + p.date_of_birth, + age(p.created_datetime, p.date_of_birth) < interval '6 months' as age_under_6m_at_registration + from "reporting"."patients" p + left join "reporting"."patient_birth_data" pbd + on pbd.patient_id = p.id +) + +select + registration_date, + count(*) filter (where birth_patient_id is null) as total_patient_registrations, + count(birth_patient_id) as total_birth_registrations, + count(*) filter (where birth_patient_id is null and age_under_6m_at_registration) as total_incorrect_registrations_for_patient_under_6mth +from data +group by registration_date +); +create or replace view "reporting"."ds__user_audit" as ( + + +with non_system_notes as ( + select distinct on (n.record_id) + n.record_id, + first_value(n.datetime) over w as first_note_datetime, + last_value(n.datetime) over w as last_note_datetime, + last_value(concat_ws(' on behalf of ', author.display_name, on_behalf.display_name)) over w as last_clinician + from "reporting"."notes" n + left join "reporting"."users" author on author.id = n.authored_by_id + left join "reporting"."users" on_behalf on on_behalf.id = n.on_behalf_of_id + where n.note_type_id != 'notetype-system' + window w as ( + partition by n.record_id + order by n.datetime + rows between unbounded preceding and unbounded following + ) +) + +select + u.id as user_id, + u.display_name as user_name, + r.name as user_role, + p.id as patient_id, + p.display_id, + bt.name as patient_category, + t.score as triage_category, + f.id as facility_id, + f.name as facility, + d.id as department_id, + d.name as department, + lg.id as location_group_id, + lg.name as location_group, + l.id as location_id, + l.name as location, + e.start_datetime as encounter_start_datetime, + e.end_datetime as encounter_end_datetime, + n.first_note_datetime, + n.last_note_datetime, + case when e.end_datetime isnull then 'Patient not discharged' + else 'Patient discharged' + end as is_discharged, + case when ds.note like 'Automatically discharged%' then n.last_clinician + end as non_discharge_by_clinicians +from "reporting"."encounters" e +left join "reporting"."users" u on u.id = e.clinician_id +left join "reporting"."roles" r on r.id = u.role +left join "reporting"."patients" p on p.id = e.patient_id +left join "reporting"."patient_additional_data" pad on pad.patient_id = e.patient_id +left join "reporting"."reference_data" bt + on bt.id = coalesce(e.patient_billing_type_id, pad.patient_billing_type_id) +left join "reporting"."triages" t on t.encounter_id = e.id +join "reporting"."locations" l on l.id = e.location_id +left join "reporting"."location_groups" lg on lg.id = l.location_group_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = False +left join "reporting"."departments" d on d.id = e.department_id +left join "reporting"."discharges" ds on ds.encounter_id = e.id +left join non_system_notes n on n.record_id = e.id + + +); +create or replace view "reporting"."int__admission_history_department" as ( +with admission_department_log as ( + select + eh.id, + eh.encounter_id, + eh.datetime as start_datetime, + eh.department_id, + case + when eh.change_type is null or 'encounter_type' = any(eh.change_type) then 'admission' + else 'transfer-in' + end as type + from "reporting"."encounter_history" eh + where (eh.change_type isnull or eh.change_type && array['department', 'encounter_type']) + and eh.encounter_type = 'admission' +) + +select + dl.encounter_id, + dl.department_id, + d.name as department, + d.facility_id, + f.name as facility, + dl.start_datetime, + coalesce(lead(dl.start_datetime) over w, e.end_datetime) as end_datetime, + case + when coalesce(lead(dl.start_datetime::date) over w, e.end_datetime::date) - dl.start_datetime::date < 1 then 1 + else coalesce(lead(dl.start_datetime::date) over w, e.end_datetime::date) - dl.start_datetime::date + end as length_of_stay, + coalesce(dl.type = 'admission', false) as admission, + coalesce(lead(dl.department_id) over w isnull and e.end_datetime notnull, false) as discharge, + coalesce(dl.type = 'transfer-in', false) as transfer_in, + coalesce(lead(dl.department_id) over w notnull, false) as transfer_out, + coalesce(lead(dl.start_datetime) over w isnull and e.end_datetime::date = p.date_of_death, false) as death +from admission_department_log dl +join "reporting"."encounters" e on e.id = dl.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +join "reporting"."departments" d on d.id = dl.department_id +join "reporting"."facilities" f on f.id = d.facility_id +window w as ( + partition by encounter_id + order by dl.start_datetime +) +); +create or replace view "reporting"."int__admission_history_location" as ( +with admission_location_log as ( + select + eh.id, + eh.encounter_id, + eh.datetime as start_datetime, + eh.location_id, + case + when eh.change_type is null or 'encounter_type' = any(eh.change_type) then 'admission' + else 'transfer-in' + end as type + from "reporting"."encounter_history" eh + where (eh.change_type isnull or eh.change_type && array['location', 'encounter_type']) + and eh.encounter_type = 'admission' +) + +select + ll.encounter_id, + l.location_group_id, + lg.name as location_group, + ll.location_id, + l.name as location, + l.facility_id, + f.name as facility, + ll.start_datetime, + coalesce(lead(ll.start_datetime) over w, e.end_datetime) as end_datetime, + case + when coalesce(lead(ll.start_datetime::date) over w, e.end_datetime::date) - ll.start_datetime::date < 1 then 1 + else coalesce(lead(ll.start_datetime::date) over w, e.end_datetime::date) - ll.start_datetime::date + end as length_of_stay, + coalesce(ll.type = 'admission', false) as admission, + coalesce(lead(ll.location_id) over w isnull and e.end_datetime notnull, false) as discharge, + coalesce(ll.type = 'transfer-in', false) as transfer_in, + coalesce(lead(ll.location_id) over w notnull, false) as transfer_out, + coalesce(lead(ll.start_datetime) over w isnull and e.end_datetime::date = p.date_of_death, false) as death +from admission_location_log ll +join "reporting"."encounters" e on e.id = ll.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +join "reporting"."locations" l on l.id = ll.location_id +join "reporting"."location_groups" lg on lg.id = l.location_group_id +join "reporting"."facilities" f on f.id = l.facility_id +window w as ( + partition by ll.encounter_id + order by ll.start_datetime +) +); +create or replace view "reporting"."int__lab_requests_history" as ( +select distinct on (lr.id, coalesce(lrl.status, lr.status)) + lr.id as request_id, + lr.requested_datetime::date as requested_date, + lr.encounter_id, + f.id as facility_id, + f.name as facility, + d.id as department_id, + d.name as department, + ltc.id as lab_test_category_id, + ltc.name as lab_test_category, + coalesce(lrl.status, lr.status) as status, + coalesce(lrl.updated_datetime, lr.updated_datetime)::date as status_start_date, + case + when coalesce(lrl.status, lr.status) = 'published' + then + coalesce(lrl.updated_datetime, lr.updated_datetime)::date + when lead(coalesce(lrl.updated_datetime, lr.updated_datetime)) over w is not null + then + case + when coalesce(lrl.updated_datetime, lr.updated_datetime)::date + = (lead(coalesce(lrl.updated_datetime, lr.updated_datetime)) over w)::date + then (lead(coalesce(lrl.updated_datetime, lr.updated_datetime)) over w)::date + else (lead(coalesce(lrl.updated_datetime, lr.updated_datetime)) over w - interval '1 day')::date + end + else current_date + end as status_end_date +from "reporting"."lab_requests" lr +left join "reporting"."lab_request_logs" lrl on lrl.lab_request_id = lr.id +left join "reporting"."encounters" e on e.id = lr.encounter_id +left join "reporting"."departments" d on d.id = coalesce(lr.department_id, e.department_id) +left join "reporting"."facilities" f on f.id = d.facility_id +left join "reporting"."reference_data" ltc on ltc.id = lr.lab_test_category_id +where lr.status not in ('deleted', 'cancelled', 'entered-in-error') +window + w as ( + partition by lr.id + order by coalesce(lrl.updated_datetime, lr.updated_datetime) + ) +order by lr.id, coalesce(lrl.status, lr.status) +); +create or replace view "reporting"."ds__sensitive_vaccinations" as ( + + +with vaccine_administrations_metadata as ( + select + id, + max(updated_at) as updated_at + from "reporting"."vaccine_administrations_change_logs" + group by id +), + +administered_circumstances as ( + select + a.id, + string_agg(rd_cir.name, '; ') as circumstance_name + from "reporting"."vaccine_administrations" a + cross join lateral unnest(a.circumstance_ids) c (unnest_circumstance_id) + left join "reporting"."reference_data" rd_cir + on rd_cir.id = c.unnest_circumstance_id + group by a.id +) + +select + p.display_id, + p.first_name, + p.last_name, + p.id as patient_id, + p.date_of_birth, + date_part('year', age(p.date_of_birth)) as age, + p.sex, + p.village_id, + rd_vil.name as village, + f.id as facility_id, + f.name as facility, + d.id as department_id, + d.name as department, + lg.id as location_group_id, + lg.name as location_group, + l.id as location_id, + l.name as location, + av.scheduled_vaccine_id, + case + when av.is_given_elsewhere = true and av.datetime is null then null + else av.datetime::date + end as vaccination_date, + sv.category as vaccine_category, + sv.label as vaccine_name, + case when sv.category = 'Other' then av.vaccine_brand end as vaccine_brand, + case when sv.category = 'Other' then av.disease end as disease, + case + when av.status = 'GIVEN' then 'Given' + when av.status = 'NOT_GIVEN' then 'Not given' + when av.status = 'RECORDED_IN_ERROR' then 'Recorded in error' + when av.status = 'HISTORICAL' then 'Historical' + end as vaccine_status, + sv.dose_label as vaccine_schedule, + av.batch, + case + when av.status in ('GIVEN', 'NOT_GIVEN', 'RECORDED_IN_ERROR') then u.display_name + end as recorded_by, + case + when av.is_given_elsewhere = true then ac.circumstance_name + end as circumstances, + case + when av.status = 'NOT_GIVEN' then null + when av.status = 'GIVEN' and av.is_given_elsewhere = true then null + when av.status in ('HISTORICAL', 'RECORDED_IN_ERROR') and av.is_given_elsewhere = true then av.given_by + when av.status = 'GIVEN' then av.given_by + end as given_by, + case when av.is_given_elsewhere = true then av.given_by end as given_elsewhere_by, + case + when av.status = 'NOT_GIVEN' then av.given_by + end as not_given_clinician, + case + when av.status = 'NOT_GIVEN' then rd_reason.name + end as not_given_reason, + case + when av.status = 'HISTORICAL' then u.display_name + end as modified_by, + vam.updated_at +from "reporting"."vaccine_administrations" av +join "reporting"."encounters" e on e.id = av.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +left join vaccine_administrations_metadata vam on vam.id = av.id +join "reporting"."locations" l on l.id = av.location_id +left join "reporting"."departments" d on d.id = av.department_id +left join "reporting"."location_groups" lg on lg.id = l.location_group_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = True +left join "reporting"."vaccine_schedules" sv on sv.id = av.scheduled_vaccine_id +left join "reporting"."users" u on u.id = av.recorded_by_id +left join "reporting"."reference_data" rd_vil on rd_vil.id = p.village_id +left join "reporting"."reference_data" rd_reason on rd_reason.id = av.not_given_reason_id +left join administered_circumstances ac on ac.id = av.id + + +); +create or replace view "reporting"."ds__vaccinations" as ( + + +with vaccine_administrations_metadata as ( + select + id, + max(updated_at) as updated_at + from "reporting"."vaccine_administrations_change_logs" + group by id +), + +administered_circumstances as ( + select + a.id, + string_agg(rd_cir.name, '; ') as circumstance_name + from "reporting"."vaccine_administrations" a + cross join lateral unnest(a.circumstance_ids) c (unnest_circumstance_id) + left join "reporting"."reference_data" rd_cir + on rd_cir.id = c.unnest_circumstance_id + group by a.id +) + +select + p.display_id, + p.first_name, + p.last_name, + p.id as patient_id, + p.date_of_birth, + date_part('year', age(p.date_of_birth)) as age, + p.sex, + p.village_id, + rd_vil.name as village, + f.id as facility_id, + f.name as facility, + d.id as department_id, + d.name as department, + lg.id as location_group_id, + lg.name as location_group, + l.id as location_id, + l.name as location, + av.scheduled_vaccine_id, + case + when av.is_given_elsewhere = true and av.datetime is null then null + else av.datetime::date + end as vaccination_date, + sv.category as vaccine_category, + sv.label as vaccine_name, + case when sv.category = 'Other' then av.vaccine_brand end as vaccine_brand, + case when sv.category = 'Other' then av.disease end as disease, + case + when av.status = 'GIVEN' then 'Given' + when av.status = 'NOT_GIVEN' then 'Not given' + when av.status = 'RECORDED_IN_ERROR' then 'Recorded in error' + when av.status = 'HISTORICAL' then 'Historical' + end as vaccine_status, + sv.dose_label as vaccine_schedule, + av.batch, + case + when av.status in ('GIVEN', 'NOT_GIVEN', 'RECORDED_IN_ERROR') then u.display_name + end as recorded_by, + case + when av.is_given_elsewhere = true then ac.circumstance_name + end as circumstances, + case + when av.status = 'NOT_GIVEN' then null + when av.status = 'GIVEN' and av.is_given_elsewhere = true then null + when av.status in ('HISTORICAL', 'RECORDED_IN_ERROR') and av.is_given_elsewhere = true then av.given_by + when av.status = 'GIVEN' then av.given_by + end as given_by, + case when av.is_given_elsewhere = true then av.given_by end as given_elsewhere_by, + case + when av.status = 'NOT_GIVEN' then av.given_by + end as not_given_clinician, + case + when av.status = 'NOT_GIVEN' then rd_reason.name + end as not_given_reason, + case + when av.status = 'HISTORICAL' then u.display_name + end as modified_by, + vam.updated_at +from "reporting"."vaccine_administrations" av +join "reporting"."encounters" e on e.id = av.encounter_id +join "reporting"."patients" p on p.id = e.patient_id +left join vaccine_administrations_metadata vam on vam.id = av.id +join "reporting"."locations" l on l.id = av.location_id +left join "reporting"."departments" d on d.id = av.department_id +left join "reporting"."location_groups" lg on lg.id = l.location_group_id +join "reporting"."facilities" f + on f.id = l.facility_id + and f.is_sensitive = False +left join "reporting"."vaccine_schedules" sv on sv.id = av.scheduled_vaccine_id +left join "reporting"."users" u on u.id = av.recorded_by_id +left join "reporting"."reference_data" rd_vil on rd_vil.id = p.village_id +left join "reporting"."reference_data" rd_reason on rd_reason.id = av.not_given_reason_id +left join administered_circumstances ac on ac.id = av.id + + +); \ No newline at end of file diff --git a/dbt_project.yml b/dbt_project.yml index 4e82800c..1a946e11 100644 --- a/dbt_project.yml +++ b/dbt_project.yml @@ -1,9 +1,10 @@ name: tamanu_source_dbt -version: 2.50.10 +version: 2.50.11 config-version: 2 profile: tamanu_source_dbt vars: + has_sensitive_facility: false language: default timezone: Australia/Sydney date_format: YYYY-MM-DD @@ -51,9 +52,6 @@ models: sensitive: +tags: - restricted - admin: - +tags: - - admin reports: +docs: show: false @@ -63,9 +61,6 @@ models: sensitive: +tags: - restricted - admin: - +tags: - - admin data_tests: +severity: warn diff --git a/documentations/tamanu-report-configuration-schema.md b/documentations/tamanu-report-configuration-schema.md index 03854286..b01ca8cb 100644 --- a/documentations/tamanu-report-configuration-schema.md +++ b/documentations/tamanu-report-configuration-schema.md @@ -15,6 +15,7 @@ Every report configuration file must be a valid JSON object with the following s #### Required Properties - **`query`** (string): The SQL query or placeholder for the report. Must be at least 1 character long. +- **`name`** (string): Display name of the report as shown in the Tamanu reporting interface. Every report must define a `name` at the **root level**. The JSON schema enforces this as a required root-level property (`minLength: 1`). A legacy `name` under `queryOptions` is still permitted but deprecated. - **`status`** (enum): Publication status of the report. Must be either `"draft"` or `"published"`. - **`dbSchema`** (enum): Database schema to use for the report. Must be either `"raw"` or `"reporting"`. - **`queryOptions`** (object): Configuration options for the report query (see detailed structure below). @@ -25,6 +26,37 @@ Every report configuration file must be a valid JSON object with the following s - **`reportDefinitionId`** (string): Unique identifier for the report definition. - **`dhis2DataSet`** (string): DHIS2 dataset identifier. +### Recommended Field Ordering + +For consistency across all report configuration files, define properties in the following order. This applies to both `standard` and `sensitive` reports. + +**Root level:** + +1. `query` +2. `name` +3. `status` +4. `notes` +5. `dbSchema` +6. `reportDefinitionId` *(if present)* +7. `dhis2DataSet` *(if present)* +8. `queryOptions` + +**Within `queryOptions`:** + +1. `defaultDateRange` +2. `dateRangeLabel` *(if present)* +3. `dataSources` +4. `parameters` + +**Within each parameter object:** + +1. `parameterField` +2. `label` +3. `name` +4. Type-specific properties (e.g. `suggesterEndpoint`, `suggesterOptions`, `options`, `filterBySelectedFacility`) + +Use 2-space indentation throughout. + ### Query Options Structure The `queryOptions` object defines how the report behaves and what parameters it accepts: @@ -58,7 +90,7 @@ For a report generated on **2025-07-01 12:00:00**, the default date ranges would #### Optional Properties - **`dateRangeLabel`** (string): Custom label for the date range input field -- **`name`** (string): Display name of the report +- **`name`** (string): *(legacy)* Display name nested under `queryOptions`. New and existing reports should define the display name as a **root-level** `name` property instead (see [Required Properties](#required-properties)). This nested field is retained only for backwards compatibility and should not be used. ## Parameter Types @@ -230,13 +262,13 @@ Here's a comprehensive example of a valid report configuration: ```json { "query": "SELECT p.display_id, p.first_name, p.last_name, e.start_date FROM patients p JOIN encounters e ON p.id = e.patient_id WHERE e.start_date >= :startDate AND e.start_date <= :endDate AND (:facilityId IS NULL OR e.location_id IN (SELECT id FROM locations WHERE facility_id = :facilityId)) AND (:departmentId IS NULL OR e.department_id = :departmentId)", + "name": "Patient Encounters Report", "status": "published", "notes": "Patient encounter report showing all encounters within the selected date range, with optional filtering by facility and department. Useful for tracking patient flow and departmental activity.", "dbSchema": "reporting", "reportDefinitionId": "patient-encounters-detailed", "dhis2DataSet": "abcdefghijk", "queryOptions": { - "name": "Patient Encounters Report", "defaultDateRange": "30days", "dateRangeLabel": "Encounter date range", "dataSources": ["thisFacility", "allFacilities"], diff --git a/list_tamanu_reports.md b/list_tamanu_reports.md index 9920a579..1984a1bb 100644 --- a/list_tamanu_reports.md +++ b/list_tamanu_reports.md @@ -25,7 +25,7 @@ Facility, Patient billing type, Admitting clinician, Area, Department, Admission --- -### Audit outpatient appointments line list +### Audit outpatient appointments **Report Description** @@ -38,6 +38,54 @@ Facility **Default date range**: 24hours +--- + +### Audit patient details edit + +**Report Description** + +This report lists all of the users that have edited the selected patient's personal details for the selected date range and parameters. Specifically the report tracks edits to the patient 'Details' component where personally identifiable information is recorded such as name, date of birth, contact information and insurance details. +Edits are listed in chronological order. If multiple changes are made to an individual patient's details within a minute, these changes will be grouped together and displayed as a single edit in the report. + +**Filters** + +Patient, User + +**Default date range**: 24hours + + +--- + +### Audit patient views + +**Report Description** + +This report lists all of the users that have viewed the selected patient's record for the selected date range and parameters. A patient 'view' is defined as a single access to a patient record where a patient record can be accessed from a patient listing table such as the 'All patients' table, the 'Active lab requests' table, or the 'Immunisation register'. A patient record can also be accessed via features such as the 'Recently viewed patients' and the scheduling module. +Views are listed in chronological order. If multiple views are made to a patient's record within a logged session, these views will be grouped together and displayed as a single view in the report. + +**Filters** + +Patient, User + +**Default date range**: 24hours + + +--- + +### Deceased patients line list + +**Report Description** + +This report generates a list of all deceased patients within the selected parameters. Patients are listed in chronological order by date and time of death. +The report includes all details documented in the patient death record. + +**Filters** + +Facility, Cause of death, Due to (or as a consequence of), Other contributing condition, Manner of death + +**Default date range**: 7days + + --- ### Encounter diets line list @@ -250,6 +298,17 @@ Village, Doctor/Nurse **Default date range**: allTime +--- + +### Invoice products summary + +**Report Description** + +This report provides a summary of all invoice products, including their insurable status, category, and pricing across all price lists and insurance plans. + +**Default date range**: allTime + + --- ### Lab requests line list @@ -327,6 +386,17 @@ Facility, Drug **Default date range**: 30days +--- + +### Ongoing conditions line list + +**Report Description** + +This report lists all patients with ongoing conditions for the selected parameters. + +**Default date range**: 7days + + --- ### Outpatient appointments line list @@ -389,287 +459,215 @@ Facility, Procedure clinician, Department, Area, Location --- -### Recent diagnoses line list +### Program registry line list **Report Description** -This report lists all patients that have had the specified diagnosis/es recorded. Diagnoses with a certainty of 'Confirmed', 'Suspected', or 'Emergency' are included. Diagnoses with a certainty of 'Disproven' or 'Recorded in error' are excluded. - -**Filters** - -Facility, Village, Diagnosis, Diagnosis 2, Diagnosis 3, Diagnosis 4, Diagnosis 5, Clinician - -**Default date range**: 24hours - - ---- - -### User audit report - -**Report Description** - -This report generates a summary of user activity for all current and discharged inpatient, emergency and outpatient encounters for the selected date range. Encounters are listed in chronological order by encounter start date and time. - -The following details are included for each encounter: -- User name: The user assigned as the supervising clinician at the time of report generation or at time of discharge -- Role: The role of the supervising clinician -- Patient category: Patient billing type -- Triage category: Triage category for the patient if an emergency encounter -- Department: Assigned department at the time of report generation or at time of discharge -- Area: Assigned area at the time of report generation or at time of discharge -- Location: Assigned location at the time of report generation or at time of discharge -- Notes start time: The time first note was completed (excludes system generated notes) -- Notes end time: The time the final note was completed (excludes system generated notes) -- Discharges: Specifies whether or not the patient has been discharged -- Non-discharge by clinicians: If patient is automatically discharged, this column will display the name of the clinician who last authored a note or who the note was written on behalf of - -**Filters** - -Facility, Department, Area - -**Default date range**: 24hours - - ---- - -### Vaccine audit line list - -**Report Description** - -This report generates a list of all patients that have a vaccination record deleted or updated from 'Not given' to 'Given'. Patients are listed alphabetically by last name and date of vaccination in chronological order. - -The report includes the following information in addition to the vaccination date and name: -Vaccination status: Where 'Recorded in error' is the status of a deleted record and 'Historical' is the status of a vaccine recorded as 'Not given' that is now recorded as 'Given' -Vaccine recorded by: The username associated with the person logged into Tamanu at the time the vaccine record was originally created -Given by: The healthcare worker that was recorded as administering the now deleted vaccination record -Record modified by: The username associated with the person logged into Tamanu at the time the vaccine record was deleted -Record modification date: The date the vaccination record was deleted from Tamanu - +This report generates the same data that appears on the Registry page. This report will include all people registered within the date range selected in order of the newest (most recent) registration to the oldest. Any patients removed from the register should not be included in this report (see another report called Program Registry Removed Patients). +Home village: Per patient details +Currently in: Can be village or facility, depends how the register is confugured. Will only be completed if a form associated with the register includes this field. +Related conditions: Lists all related conditions associated with the patient and the register they are on (conditions listed at the time of report generation, any conditions removed previously are not included) +Status: Current status of the patient per the 'status' function within the register. +Date of registration: Date the patient was added to this registry. If patient has been added to this registry more than once (i.e. added, removed, added again), the date listed is the date of the current addition to the register. +Registered by: Name of Tamanu user who added the patient to this registry +Registering facility: Facility selected when patient is first added to the registry **Filters** -Facility, Village, Category, Vaccine, Status +Registry, Subdivision, Division -**Default date range**: 7days +**Default date range**: allTime --- -### Vaccine line list +### Program registry removed patients line list **Report Description** -This report generates a list of all patients that have had a vaccination recorded for the selected parameters. Patients are listed alphabetically by last name and date of vaccination in chronological order. - -The report includes vaccinations with statuses of both 'Given' and 'Not given', and each vaccination recorded is listed on a single row. If a vaccination was initially recorded as 'Not given' and is later marked as 'Given', only the vaccination record with a status of 'Given' will be included in the report. +This report generates a list of all patients who have been removed from the registry. This report will include all people removed via workflow 'patient active -> remove' (i.e. does not include patients who were deleted from the registry using workflow 'patient active -> delete') within the date range selected in order of the newest removal to the oldest. Those still active on the register are not included in this report. +Home village: Per patient details +Registering facility: Facility selected when patient is first added to the registry +Related conditions: Lists all related conditions associated with the patient and the register they are on (conditions listed at the time of removal) +Status: Last status of the patient per the 'status' function within the register at the time of removal from the register. +Registered by: Name of user who added the patient to the registry +Date of registration: Date the patient was added to this registry. If patient has been added to this registry more than once (i.e. added, removed, added again), the date listed is the first addition to the register. +Date of removal: Date the patient was removed from the registry (if patient is added to a registry, removed, later added again and removed again, the report will list the most recent removal) +Removed by: Name of user who removed the patient from the registry **Filters** -Facility, Village, Category, Vaccine +Registry -**Default date range**: 7days +**Default date range**: allTime --- -## Admin - -### Admin audit patient details edits line list +### Recent diagnoses line list **Report Description** -This report lists all of the users that have edited the selected patient's personal details for the selected date range and parameters. Specifically the report tracks edits to the patient 'Details' component where personally identifiable information is recorded such as name, date of birth, contact information and insurance details. -Edits are listed in chronological order. If multiple changes are made to an individual patient's details within a minute, these changes will be grouped together and displayed as a single edit in the report. +This report lists all patients that have had the specified diagnosis/es recorded. Diagnoses with a certainty of 'Confirmed', 'Suspected', or 'Emergency' are included. Diagnoses with a certainty of 'Disproven' or 'Recorded in error' are excluded. **Filters** -Patient, User +Facility, Village, Diagnosis, Diagnosis 2, Diagnosis 3, Diagnosis 4, Diagnosis 5, Clinician **Default date range**: 24hours --- -### Admin audit patient views line list +### Registered births line list **Report Description** -This report lists all of the users that have viewed the selected patient's record for the selected date range and parameters. A patient 'view' is defined as a single access to a patient record where a patient record can be accessed from a patient listing table such as the 'All patients' table, the 'Active lab requests' table, or the 'Immunisation register'. A patient record can also be accessed via features such as the 'Recently viewed patients' and the scheduling module. -Views are listed in chronological order. If multiple views are made to a patient's record within a logged session, these views will be grouped together and displayed as a single view in the report. +This report generates a list of all registered births for the selected parameters. Patients are listed in chronological order by date and time of birth. The report also includes key demographic information and birth details for each patient. **Filters** -Patient, User +Facility, Village -**Default date range**: 24hours +**Default date range**: 7days --- -### Admin deceased patients line list +### Registered patients by dob line list **Report Description** -This report generates a list of all deceased patients within the selected parameters. Patients are listed in chronological order by date and time of death. -The report includes all details documented in the patient death record. - -**Filters** - -Facility, Cause of death, Due to (or as a consequence of), Other contributing condition, Manner of death +This report generates a list of all patients that have been registered, including date of registration and which user completed the registration. Patients are listed in chronological order by date of administration. The report also includes key demographic information for each patient. **Default date range**: 7days --- -### Admin invoice products summary +### Registered patients daily summary **Report Description** -This report provides a summary of all invoice products, including their insurable status, category, and pricing across all price lists and insurance plans. +This report generates a summary of the number of patients that have been registered by date and sex for the selected date range. **Default date range**: allTime --- -### Admin ongoing conditions line list +### Registered patients line list **Report Description** -This report lists all patients with ongoing conditions for the selected parameters. +This report generates a list of all patients that have been registered, including date of registration and which user completed the registration. Patients are listed in chronological order by date of administration. The report also includes key demographic information for each patient. **Default date range**: 7days --- -### Admin program registry line list +### Upcoming vaccinations line list **Report Description** -This report generates the same data that appears on the Registry page. This report will include all people registered within the date range selected in order of the newest (most recent) registration to the oldest. Any patients removed from the register should not be included in this report (see another report called Program Registry Removed Patients). -Home village: Per patient details -Currently in: Can be village or facility, depends how the register is confugured. Will only be completed if a form associated with the register includes this field. -Related conditions: Lists all related conditions associated with the patient and the register they are on (conditions listed at the time of report generation, any conditions removed previously are not included) -Status: Current status of the patient per the 'status' function within the register. -Date of registration: Date the patient was added to this registry. If patient has been added to this registry more than once (i.e. added, removed, added again), the date listed is the date of the current addition to the register. -Registered by: Name of Tamanu user who added the patient to this registry -Registering facility: Facility selected when patient is first added to the registry +This report generates upcoming vaccination schedules for patients up to 18 years old by default or for patients born within the user-selected date range. **Filters** -Registry, Subdivision, Division +Category, Vaccine, Vaccine status, Village -**Default date range**: allTime +**Default date range**: 18years --- -### Admin program registry removed patients line list +### Usage quality metrics patient details **Report Description** -This report generates a list of all patients who have been removed from the registry. This report will include all people removed via workflow 'patient active -> remove' (i.e. does not include patients who were deleted from the registry using workflow 'patient active -> delete') within the date range selected in order of the newest removal to the oldest. Those still active on the register are not included in this report. -Home village: Per patient details -Registering facility: Facility selected when patient is first added to the registry -Related conditions: Lists all related conditions associated with the patient and the register they are on (conditions listed at the time of removal) -Status: Last status of the patient per the 'status' function within the register at the time of removal from the register. -Registered by: Name of user who added the patient to the registry -Date of registration: Date the patient was added to this registry. If patient has been added to this registry more than once (i.e. added, removed, added again), the date listed is the first addition to the register. -Date of removal: Date the patient was removed from the registry (if patient is added to a registry, removed, later added again and removed again, the report will list the most recent removal) -Removed by: Name of user who removed the patient from the registry - -**Filters** - -Registry +This report generates usage quality metrics on patient details. The report provides a summary on the total patients in the database, total with incomplete name, missing date of birth, invalid date of birth, missing location entry, missing contact entry and patients that have been merged. **Default date range**: allTime --- -### Admin registered births line list +### Usage quality metrics patient registrations **Report Description** -This report generates a list of all registered births for the selected parameters. Patients are listed in chronological order by date and time of birth. The report also includes key demographic information and birth details for each patient. - -**Filters** - -Facility, Village +This report generates usage quality metrics on patient registrations. The report provides a summary by selected date range on the total new patient registrations, total birth registrations, and total incorrect registrations (patient instead of birth) for under 6 months old. -**Default date range**: 7days +**Default date range**: 30days --- -### Admin registered patients by dob line list +### User audit line list **Report Description** -This report generates a list of all patients that have been registered, including date of registration and which user completed the registration. Patients are listed in chronological order by date of administration. The report also includes key demographic information for each patient. - -**Default date range**: 7days - - ---- +This report generates a summary of user activity for all current and discharged inpatient, emergency and outpatient encounters for the selected date range. Encounters are listed in chronological order by encounter start date and time. -### Admin registered patients daily summary +The following details are included for each encounter: +- User name: The user assigned as the supervising clinician at the time of report generation or at time of discharge +- Role: The role of the supervising clinician +- Patient category: Patient billing type +- Triage category: Triage category for the patient if an emergency encounter +- Department: Assigned department at the time of report generation or at time of discharge +- Area: Assigned area at the time of report generation or at time of discharge +- Location: Assigned location at the time of report generation or at time of discharge +- Notes start time: The time first note was completed (excludes system generated notes) +- Notes end time: The time the final note was completed (excludes system generated notes) +- Discharges: Specifies whether or not the patient has been discharged +- Non-discharge by clinicians: If patient is automatically discharged, this column will display the name of the clinician who last authored a note or who the note was written on behalf of -**Report Description** +**Filters** -This report generates a summary of the number of patients that have been registered by date and sex for the selected date range. +Facility, Department, Area -**Default date range**: allTime +**Default date range**: 24hours --- -### Admin registered patients line list +### Vaccine audit line list **Report Description** -This report generates a list of all patients that have been registered, including date of registration and which user completed the registration. Patients are listed in chronological order by date of administration. The report also includes key demographic information for each patient. - -**Default date range**: 7days - - ---- - -### Admin upcoming vaccinations line list - -**Report Description** +This report generates a list of all patients that have a vaccination record deleted or updated from 'Not given' to 'Given'. Patients are listed alphabetically by last name and date of vaccination in chronological order. -This report generates upcoming vaccination schedules for patients up to 18 years old by default or for patients born within the user-selected date range. +The report includes the following information in addition to the vaccination date and name: +Vaccination status: Where 'Recorded in error' is the status of a deleted record and 'Historical' is the status of a vaccine recorded as 'Not given' that is now recorded as 'Given' +Vaccine recorded by: The username associated with the person logged into Tamanu at the time the vaccine record was originally created +Given by: The healthcare worker that was recorded as administering the now deleted vaccination record +Record modified by: The username associated with the person logged into Tamanu at the time the vaccine record was deleted +Record modification date: The date the vaccination record was deleted from Tamanu + **Filters** -Category, Vaccine, Vaccine status, Village +Facility, Village, Category, Vaccine, Status -**Default date range**: 18years +**Default date range**: 7days --- -### Admin usage quality metrics patient details +### Vaccine line list **Report Description** -This report generates usage quality metrics on patient details. The report provides a summary on the total patients in the database, total with incomplete name, missing date of birth, invalid date of birth, missing location entry, missing contact entry and patients that have been merged. - -**Default date range**: allTime - - ---- +This report generates a list of all patients that have had a vaccination recorded for the selected parameters. Patients are listed alphabetically by last name and date of vaccination in chronological order. -### Admin usage quality metrics patient registrations +The report includes vaccinations with statuses of both 'Given' and 'Not given', and each vaccination recorded is listed on a single row. If a vaccination was initially recorded as 'Not given' and is later marked as 'Given', only the vaccination record with a status of 'Given' will be included in the report. -**Report Description** +**Filters** -This report generates usage quality metrics on patient registrations. The report provides a summary by selected date range on the total new patient registrations, total birth registrations, and total incorrect registrations (patient instead of birth) for under 6 months old. +Facility, Village, Category, Vaccine -**Default date range**: 30days +**Default date range**: 7days --- diff --git a/models/datasets/admin/ds__births.sql b/models/datasets/standard/ds__births.sql similarity index 100% rename from models/datasets/admin/ds__births.sql rename to models/datasets/standard/ds__births.sql diff --git a/models/datasets/admin/ds__births.yml b/models/datasets/standard/ds__births.yml similarity index 100% rename from models/datasets/admin/ds__births.yml rename to models/datasets/standard/ds__births.yml diff --git a/models/datasets/admin/ds__deaths.sql b/models/datasets/standard/ds__deaths.sql similarity index 100% rename from models/datasets/admin/ds__deaths.sql rename to models/datasets/standard/ds__deaths.sql diff --git a/models/datasets/admin/ds__deaths.yml b/models/datasets/standard/ds__deaths.yml similarity index 100% rename from models/datasets/admin/ds__deaths.yml rename to models/datasets/standard/ds__deaths.yml diff --git a/models/datasets/admin/ds__invoice_products.md b/models/datasets/standard/ds__invoice_products.md similarity index 100% rename from models/datasets/admin/ds__invoice_products.md rename to models/datasets/standard/ds__invoice_products.md diff --git a/models/datasets/admin/ds__invoice_products.sql b/models/datasets/standard/ds__invoice_products.sql similarity index 100% rename from models/datasets/admin/ds__invoice_products.sql rename to models/datasets/standard/ds__invoice_products.sql diff --git a/models/datasets/admin/ds__invoice_products.yml b/models/datasets/standard/ds__invoice_products.yml similarity index 100% rename from models/datasets/admin/ds__invoice_products.yml rename to models/datasets/standard/ds__invoice_products.yml diff --git a/models/datasets/admin/ds__ongoing_conditions.sql b/models/datasets/standard/ds__ongoing_conditions.sql similarity index 100% rename from models/datasets/admin/ds__ongoing_conditions.sql rename to models/datasets/standard/ds__ongoing_conditions.sql diff --git a/models/datasets/admin/ds__ongoing_conditions.yml b/models/datasets/standard/ds__ongoing_conditions.yml similarity index 100% rename from models/datasets/admin/ds__ongoing_conditions.yml rename to models/datasets/standard/ds__ongoing_conditions.yml diff --git a/models/datasets/admin/ds__patient_program_registrations.sql b/models/datasets/standard/ds__patient_program_registrations.sql similarity index 100% rename from models/datasets/admin/ds__patient_program_registrations.sql rename to models/datasets/standard/ds__patient_program_registrations.sql diff --git a/models/datasets/admin/ds__patient_program_registrations.yml b/models/datasets/standard/ds__patient_program_registrations.yml similarity index 100% rename from models/datasets/admin/ds__patient_program_registrations.yml rename to models/datasets/standard/ds__patient_program_registrations.yml diff --git a/models/datasets/admin/ds__patient_vaccinations_upcoming.sql b/models/datasets/standard/ds__patient_vaccinations_upcoming.sql similarity index 100% rename from models/datasets/admin/ds__patient_vaccinations_upcoming.sql rename to models/datasets/standard/ds__patient_vaccinations_upcoming.sql diff --git a/models/datasets/admin/ds__patient_vaccinations_upcoming.yml b/models/datasets/standard/ds__patient_vaccinations_upcoming.yml similarity index 100% rename from models/datasets/admin/ds__patient_vaccinations_upcoming.yml rename to models/datasets/standard/ds__patient_vaccinations_upcoming.yml diff --git a/models/datasets/admin/ds__patients.sql b/models/datasets/standard/ds__patients.sql similarity index 100% rename from models/datasets/admin/ds__patients.sql rename to models/datasets/standard/ds__patients.sql diff --git a/models/datasets/admin/ds__patients.yml b/models/datasets/standard/ds__patients.yml similarity index 100% rename from models/datasets/admin/ds__patients.yml rename to models/datasets/standard/ds__patients.yml diff --git a/models/datasets/admin/ds__patients_access_logs.sql b/models/datasets/standard/ds__patients_access_logs.sql similarity index 100% rename from models/datasets/admin/ds__patients_access_logs.sql rename to models/datasets/standard/ds__patients_access_logs.sql diff --git a/models/datasets/admin/ds__patients_access_logs.yml b/models/datasets/standard/ds__patients_access_logs.yml similarity index 100% rename from models/datasets/admin/ds__patients_access_logs.yml rename to models/datasets/standard/ds__patients_access_logs.yml diff --git a/models/datasets/admin/ds__patients_change_logs.sql b/models/datasets/standard/ds__patients_change_logs.sql similarity index 100% rename from models/datasets/admin/ds__patients_change_logs.sql rename to models/datasets/standard/ds__patients_change_logs.sql diff --git a/models/datasets/admin/ds__patients_change_logs.yml b/models/datasets/standard/ds__patients_change_logs.yml similarity index 100% rename from models/datasets/admin/ds__patients_change_logs.yml rename to models/datasets/standard/ds__patients_change_logs.yml diff --git a/models/datasets/admin/ds__usage_quality_metrics_patient_details.sql b/models/datasets/standard/ds__usage_quality_metrics_patient_details.sql similarity index 100% rename from models/datasets/admin/ds__usage_quality_metrics_patient_details.sql rename to models/datasets/standard/ds__usage_quality_metrics_patient_details.sql diff --git a/models/datasets/admin/ds__usage_quality_metrics_patient_details.yml b/models/datasets/standard/ds__usage_quality_metrics_patient_details.yml similarity index 100% rename from models/datasets/admin/ds__usage_quality_metrics_patient_details.yml rename to models/datasets/standard/ds__usage_quality_metrics_patient_details.yml diff --git a/models/datasets/admin/ds__usage_quality_metrics_patient_registrations.sql b/models/datasets/standard/ds__usage_quality_metrics_patient_registrations.sql similarity index 100% rename from models/datasets/admin/ds__usage_quality_metrics_patient_registrations.sql rename to models/datasets/standard/ds__usage_quality_metrics_patient_registrations.sql diff --git a/models/datasets/admin/ds__usage_quality_metrics_patient_registrations.yml b/models/datasets/standard/ds__usage_quality_metrics_patient_registrations.yml similarity index 100% rename from models/datasets/admin/ds__usage_quality_metrics_patient_registrations.yml rename to models/datasets/standard/ds__usage_quality_metrics_patient_registrations.yml diff --git a/models/reports/config/sensitive/sensitive-audit-outpatient-appointments-line-list.json b/models/reports/config/sensitive/sensitive-audit-outpatient-appointments.json similarity index 93% rename from models/reports/config/sensitive/sensitive-audit-outpatient-appointments-line-list.json rename to models/reports/config/sensitive/sensitive-audit-outpatient-appointments.json index e508a66d..da145fb0 100644 --- a/models/reports/config/sensitive/sensitive-audit-outpatient-appointments-line-list.json +++ b/models/reports/config/sensitive/sensitive-audit-outpatient-appointments.json @@ -1,6 +1,6 @@ { "query": "replace this", - "name": "Sensitive outpatient appointments audit line list", + "name": "Sensitive audit - outpatient appointments", "notes": "This report shows an audit log of all modifications and cancellations to outpatient appointments at sensitive facilities. Each row represents a change event, showing both the current appointment details and the previous values before the change. The report is designed to track which Tamanu users are creating and editing appointments. Status-only changes (e.g., Confirmed to Arrived) are excluded unless the status change is to Cancelled. If an appointment is changed multiple times, each modification will appear as a separate line.", "status": "published", "dbSchema": "reporting", diff --git a/models/reports/config/sensitive/sensitive-encounter-diets-line-list.json b/models/reports/config/sensitive/sensitive-encounter-diets-line-list.json index 3fcac19f..824097cd 100644 --- a/models/reports/config/sensitive/sensitive-encounter-diets-line-list.json +++ b/models/reports/config/sensitive/sensitive-encounter-diets-line-list.json @@ -1,6 +1,6 @@ { "query": "replace this", - "name": "Sensitive current encounters diets line list", + "name": "Sensitive encounter diets line list", "notes": "This report generates a list of all active encounters at sensitive facilities with their associated dietary requirements. The report includes:\n- Patient details and current location\n- Dietary requirements and restrictions.", "status": "published", "dbSchema": "reporting", diff --git a/models/reports/config/sensitive/sensitive-user-audit-report.json b/models/reports/config/sensitive/sensitive-user-audit-line-list.json similarity index 100% rename from models/reports/config/sensitive/sensitive-user-audit-report.json rename to models/reports/config/sensitive/sensitive-user-audit-line-list.json diff --git a/models/reports/config/standard/audit-outpatient-appointments-line-list.json b/models/reports/config/standard/audit-outpatient-appointments.json similarity index 95% rename from models/reports/config/standard/audit-outpatient-appointments-line-list.json rename to models/reports/config/standard/audit-outpatient-appointments.json index cc7637ba..df6e78e6 100644 --- a/models/reports/config/standard/audit-outpatient-appointments-line-list.json +++ b/models/reports/config/standard/audit-outpatient-appointments.json @@ -1,5 +1,6 @@ { "query": "replace this", + "name": "Audit - outpatient appointments", "notes": "This report shows an audit log of all modifications and cancellations to outpatient appointments. Each row represents a change event, showing both the current appointment details and the previous values before the change. The report is designed to track which Tamanu users are creating and editing appointments. Status-only changes (e.g., Confirmed to Arrived) are excluded unless the status change is to Cancelled. If an appointment is changed multiple times, each modification will appear as a separate line.", "status": "published", "dbSchema": "reporting", diff --git a/models/reports/config/admin/admin-audit-patient-details-edits-line-list.json b/models/reports/config/standard/audit-patient-details-edit.json similarity index 96% rename from models/reports/config/admin/admin-audit-patient-details-edits-line-list.json rename to models/reports/config/standard/audit-patient-details-edit.json index c29c0ead..1875e685 100644 --- a/models/reports/config/admin/admin-audit-patient-details-edits-line-list.json +++ b/models/reports/config/standard/audit-patient-details-edit.json @@ -1,6 +1,6 @@ { "query": "replace this", - "name": "Audit - Patient details edits", + "name": "Audit - patient details edit", "notes": "This report lists all of the users that have edited the selected patient's personal details for the selected date range and parameters. Specifically the report tracks edits to the patient 'Details' component where personally identifiable information is recorded such as name, date of birth, contact information and insurance details.\nEdits are listed in chronological order. If multiple changes are made to an individual patient's details within a minute, these changes will be grouped together and displayed as a single edit in the report.", "status": "published", "dbSchema": "reporting", diff --git a/models/reports/config/admin/admin-audit-patient-views-line-list.json b/models/reports/config/standard/audit-patient-views.json similarity index 97% rename from models/reports/config/admin/admin-audit-patient-views-line-list.json rename to models/reports/config/standard/audit-patient-views.json index 5355af0f..35c46b29 100644 --- a/models/reports/config/admin/admin-audit-patient-views-line-list.json +++ b/models/reports/config/standard/audit-patient-views.json @@ -1,6 +1,6 @@ { "query": "replace this", - "name": "Audit - Patient views", + "name": "Audit - patient views", "notes": "This report lists all of the users that have viewed the selected patient's record for the selected date range and parameters. A patient 'view' is defined as a single access to a patient record where a patient record can be accessed from a patient listing table such as the 'All patients' table, the 'Active lab requests' table, or the 'Immunisation register'. A patient record can also be accessed via features such as the 'Recently viewed patients' and the scheduling module. \nViews are listed in chronological order. If multiple views are made to a patient's record within a logged session, these views will be grouped together and displayed as a single view in the report.", "status": "published", "dbSchema": "reporting", diff --git a/models/reports/config/admin/admin-deceased-patients-line-list.json b/models/reports/config/standard/deceased-patients-line-list.json similarity index 98% rename from models/reports/config/admin/admin-deceased-patients-line-list.json rename to models/reports/config/standard/deceased-patients-line-list.json index 23d44bc3..3bba7a4f 100644 --- a/models/reports/config/admin/admin-deceased-patients-line-list.json +++ b/models/reports/config/standard/deceased-patients-line-list.json @@ -1,5 +1,6 @@ { "query": "query here", + "name": "Deceased patients line list", "notes": "This report generates a list of all deceased patients within the selected parameters. Patients are listed in chronological order by date and time of death. \nThe report includes all details documented in the patient death record. ", "status": "published", "dbSchema": "reporting", diff --git a/models/reports/config/standard/encounter-diets-line-list.json b/models/reports/config/standard/encounter-diets-line-list.json index f63ce669..fa11ed95 100644 --- a/models/reports/config/standard/encounter-diets-line-list.json +++ b/models/reports/config/standard/encounter-diets-line-list.json @@ -1,6 +1,6 @@ { "query": "replace this", - "name": "Current encounters diets line list", + "name": "Encounter diets line list", "notes": "This report generates a list of all active encounters with their associated dietary requirements. The report includes:\n- Patient details and current location\n- Dietary requirements and restrictions.", "status": "published", "dbSchema": "reporting", diff --git a/models/reports/config/standard/incomplete-referrals.json b/models/reports/config/standard/incomplete-referrals.json index 7a918298..79b81abb 100644 --- a/models/reports/config/standard/incomplete-referrals.json +++ b/models/reports/config/standard/incomplete-referrals.json @@ -1,5 +1,6 @@ { "query": "replace this", + "name": "Incomplete referrals", "status": "published", "notes": "This report lists all patients that have a pending referral for the selected parameters.", "dbSchema": "reporting", diff --git a/models/reports/config/admin/admin-invoice-products-summary.json b/models/reports/config/standard/invoice-products-summary.json similarity index 100% rename from models/reports/config/admin/admin-invoice-products-summary.json rename to models/reports/config/standard/invoice-products-summary.json diff --git a/models/reports/config/standard/medication-dispensed-summary.json b/models/reports/config/standard/medication-dispensed-summary.json index 4eb31e8d..c314fe0a 100644 --- a/models/reports/config/standard/medication-dispensed-summary.json +++ b/models/reports/config/standard/medication-dispensed-summary.json @@ -1,6 +1,6 @@ { "query": "replace this", - "name": "Medication Dispensed summary report", + "name": "Medication dispensed summary", "notes": "This report shows quantity of medication dispensed for a given drug within a specified date range, based on dispense records.", "status": "published", "dbSchema": "reporting", diff --git a/models/reports/config/admin/admin-ongoing-conditions-line-list.json b/models/reports/config/standard/ongoing-conditions-line-list.json similarity index 100% rename from models/reports/config/admin/admin-ongoing-conditions-line-list.json rename to models/reports/config/standard/ongoing-conditions-line-list.json diff --git a/models/reports/config/admin/admin-program-registry-line-list.json b/models/reports/config/standard/program-registry-line-list.json similarity index 100% rename from models/reports/config/admin/admin-program-registry-line-list.json rename to models/reports/config/standard/program-registry-line-list.json diff --git a/models/reports/config/admin/admin-program-registry-removed-patients-line-list.json b/models/reports/config/standard/program-registry-removed-patients-line-list.json similarity index 100% rename from models/reports/config/admin/admin-program-registry-removed-patients-line-list.json rename to models/reports/config/standard/program-registry-removed-patients-line-list.json diff --git a/models/reports/config/admin/admin-registered-births-line-list.json b/models/reports/config/standard/registered-births-line-list.json similarity index 94% rename from models/reports/config/admin/admin-registered-births-line-list.json rename to models/reports/config/standard/registered-births-line-list.json index 0ef5266b..b5df2a05 100644 --- a/models/reports/config/admin/admin-registered-births-line-list.json +++ b/models/reports/config/standard/registered-births-line-list.json @@ -1,6 +1,6 @@ { "query": "replace this", - "name": "Registered birth line list", + "name": "Registered births line list", "notes": "This report generates a list of all registered births for the selected parameters. Patients are listed in chronological order by date and time of birth. The report also includes key demographic information and birth details for each patient.", "status": "published", "dbSchema": "reporting", diff --git a/models/reports/config/admin/admin-registered-patients-by-dob-line-list.json b/models/reports/config/standard/registered-patients-by-dob-line-list.json similarity index 91% rename from models/reports/config/admin/admin-registered-patients-by-dob-line-list.json rename to models/reports/config/standard/registered-patients-by-dob-line-list.json index f52f4acd..4aed2bd2 100644 --- a/models/reports/config/admin/admin-registered-patients-by-dob-line-list.json +++ b/models/reports/config/standard/registered-patients-by-dob-line-list.json @@ -1,5 +1,6 @@ { "query": "replace this", + "name": "Registered patients by DOB line list", "status": "published", "notes": "This report generates a list of all patients that have been registered, including date of registration and which user completed the registration. Patients are listed in chronological order by date of administration. The report also includes key demographic information for each patient. ", "dbSchema": "reporting", diff --git a/models/reports/config/admin/admin-registered-patients-daily-summary.json b/models/reports/config/standard/registered-patients-daily-summary.json similarity index 100% rename from models/reports/config/admin/admin-registered-patients-daily-summary.json rename to models/reports/config/standard/registered-patients-daily-summary.json diff --git a/models/reports/config/admin/admin-registered-patients-line-list.json b/models/reports/config/standard/registered-patients-line-list.json similarity index 100% rename from models/reports/config/admin/admin-registered-patients-line-list.json rename to models/reports/config/standard/registered-patients-line-list.json diff --git a/models/reports/config/admin/admin-upcoming-vaccinations-line-list.json b/models/reports/config/standard/upcoming-vaccinations-line-list.json similarity index 100% rename from models/reports/config/admin/admin-upcoming-vaccinations-line-list.json rename to models/reports/config/standard/upcoming-vaccinations-line-list.json diff --git a/models/reports/config/admin/admin-usage-quality-metrics-patient-details.json b/models/reports/config/standard/usage-quality-metrics-patient-details.json similarity index 100% rename from models/reports/config/admin/admin-usage-quality-metrics-patient-details.json rename to models/reports/config/standard/usage-quality-metrics-patient-details.json diff --git a/models/reports/config/admin/admin-usage-quality-metrics-patient-registrations.json b/models/reports/config/standard/usage-quality-metrics-patient-registrations.json similarity index 100% rename from models/reports/config/admin/admin-usage-quality-metrics-patient-registrations.json rename to models/reports/config/standard/usage-quality-metrics-patient-registrations.json diff --git a/models/reports/config/standard/user-audit-report.json b/models/reports/config/standard/user-audit-line-list.json similarity index 100% rename from models/reports/config/standard/user-audit-report.json rename to models/reports/config/standard/user-audit-line-list.json diff --git a/models/reports/sql/sensitive/sensitive-audit-outpatient-appointments-line-list.sql b/models/reports/sql/sensitive/sensitive-audit-outpatient-appointments.sql similarity index 100% rename from models/reports/sql/sensitive/sensitive-audit-outpatient-appointments-line-list.sql rename to models/reports/sql/sensitive/sensitive-audit-outpatient-appointments.sql diff --git a/models/reports/sql/sensitive/sensitive-user-audit-report.sql b/models/reports/sql/sensitive/sensitive-user-audit-line-list.sql similarity index 100% rename from models/reports/sql/sensitive/sensitive-user-audit-report.sql rename to models/reports/sql/sensitive/sensitive-user-audit-line-list.sql diff --git a/models/reports/sql/standard/audit-outpatient-appointments-line-list.sql b/models/reports/sql/standard/audit-outpatient-appointments.sql similarity index 100% rename from models/reports/sql/standard/audit-outpatient-appointments-line-list.sql rename to models/reports/sql/standard/audit-outpatient-appointments.sql diff --git a/models/reports/sql/admin/admin-audit-patient-details-edits-line-list.sql b/models/reports/sql/standard/audit-patient-details-edit.sql similarity index 100% rename from models/reports/sql/admin/admin-audit-patient-details-edits-line-list.sql rename to models/reports/sql/standard/audit-patient-details-edit.sql diff --git a/models/reports/sql/admin/admin-audit-patient-views-line-list.sql b/models/reports/sql/standard/audit-patient-views.sql similarity index 100% rename from models/reports/sql/admin/admin-audit-patient-views-line-list.sql rename to models/reports/sql/standard/audit-patient-views.sql diff --git a/models/reports/sql/admin/admin-deceased-patients-line-list.sql b/models/reports/sql/standard/deceased-patients-line-list.sql similarity index 100% rename from models/reports/sql/admin/admin-deceased-patients-line-list.sql rename to models/reports/sql/standard/deceased-patients-line-list.sql diff --git a/models/reports/sql/admin/admin-invoice-products-summary.sql b/models/reports/sql/standard/invoice-products-summary.sql similarity index 100% rename from models/reports/sql/admin/admin-invoice-products-summary.sql rename to models/reports/sql/standard/invoice-products-summary.sql diff --git a/models/reports/sql/admin/admin-ongoing-conditions-line-list.sql b/models/reports/sql/standard/ongoing-conditions-line-list.sql similarity index 100% rename from models/reports/sql/admin/admin-ongoing-conditions-line-list.sql rename to models/reports/sql/standard/ongoing-conditions-line-list.sql diff --git a/models/reports/sql/admin/admin-program-registry-line-list.sql b/models/reports/sql/standard/program-registry-line-list.sql similarity index 100% rename from models/reports/sql/admin/admin-program-registry-line-list.sql rename to models/reports/sql/standard/program-registry-line-list.sql diff --git a/models/reports/sql/admin/admin-program-registry-removed-patients-line-list.sql b/models/reports/sql/standard/program-registry-removed-patients-line-list.sql similarity index 100% rename from models/reports/sql/admin/admin-program-registry-removed-patients-line-list.sql rename to models/reports/sql/standard/program-registry-removed-patients-line-list.sql diff --git a/models/reports/sql/admin/admin-registered-births-line-list.sql b/models/reports/sql/standard/registered-births-line-list.sql similarity index 100% rename from models/reports/sql/admin/admin-registered-births-line-list.sql rename to models/reports/sql/standard/registered-births-line-list.sql diff --git a/models/reports/sql/admin/admin-registered-patients-by-dob-line-list.sql b/models/reports/sql/standard/registered-patients-by-dob-line-list.sql similarity index 100% rename from models/reports/sql/admin/admin-registered-patients-by-dob-line-list.sql rename to models/reports/sql/standard/registered-patients-by-dob-line-list.sql diff --git a/models/reports/sql/admin/admin-registered-patients-daily-summary.sql b/models/reports/sql/standard/registered-patients-daily-summary.sql similarity index 100% rename from models/reports/sql/admin/admin-registered-patients-daily-summary.sql rename to models/reports/sql/standard/registered-patients-daily-summary.sql diff --git a/models/reports/sql/admin/admin-registered-patients-line-list.sql b/models/reports/sql/standard/registered-patients-line-list.sql similarity index 100% rename from models/reports/sql/admin/admin-registered-patients-line-list.sql rename to models/reports/sql/standard/registered-patients-line-list.sql diff --git a/models/reports/sql/admin/admin-upcoming-vaccinations-line-list.sql b/models/reports/sql/standard/upcoming-vaccinations-line-list.sql similarity index 100% rename from models/reports/sql/admin/admin-upcoming-vaccinations-line-list.sql rename to models/reports/sql/standard/upcoming-vaccinations-line-list.sql diff --git a/models/reports/sql/admin/admin-usage-quality-metrics-patient-details.sql b/models/reports/sql/standard/usage-quality-metrics-patient-details.sql similarity index 100% rename from models/reports/sql/admin/admin-usage-quality-metrics-patient-details.sql rename to models/reports/sql/standard/usage-quality-metrics-patient-details.sql diff --git a/models/reports/sql/admin/admin-usage-quality-metrics-patient-registrations.sql b/models/reports/sql/standard/usage-quality-metrics-patient-registrations.sql similarity index 100% rename from models/reports/sql/admin/admin-usage-quality-metrics-patient-registrations.sql rename to models/reports/sql/standard/usage-quality-metrics-patient-registrations.sql diff --git a/models/reports/sql/standard/user-audit-report.sql b/models/reports/sql/standard/user-audit-line-list.sql similarity index 100% rename from models/reports/sql/standard/user-audit-report.sql rename to models/reports/sql/standard/user-audit-line-list.sql diff --git a/packages.yml b/packages.yml index 1600223d..775ec4f5 100644 --- a/packages.yml +++ b/packages.yml @@ -1,3 +1,3 @@ packages: - package: dbt-labs/dbt_utils - version: 1.3.3 + version: 1.4.0 diff --git a/pyproject.toml b/pyproject.toml index 409202d6..076a87c8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "tamanu-source-dbt" -version = "2.50.10" +version = "2.50.11" description = "A dbt project that transforms Tamanu healthcare system data into optimised reporting datasets" readme = "README.md" requires-python = ">=3.12" diff --git a/scripts/report_validation/report-config-schema.json b/scripts/report_validation/report-config-schema.json index c72af272..749b3971 100644 --- a/scripts/report_validation/report-config-schema.json +++ b/scripts/report_validation/report-config-schema.json @@ -6,6 +6,7 @@ "type": "object", "required": [ "query", + "name", "status", "dbSchema", "queryOptions" @@ -16,6 +17,11 @@ "description": "SQL query or placeholder for the report", "minLength": 1 }, + "name": { + "type": "string", + "description": "Display name of the report shown in the Tamanu reporting interface", + "minLength": 1 + }, "status": { "type": "string", "description": "Publication status of the report", @@ -72,7 +78,8 @@ }, "name": { "type": "string", - "description": "Name of the report" + "description": "Deprecated: legacy display name. Use the root-level \"name\" property instead. Retained for backwards compatibility only.", + "deprecated": true }, "parameters": { "type": "array", diff --git a/scripts/utils/report_utils.py b/scripts/utils/report_utils.py index f9404247..b068a557 100644 --- a/scripts/utils/report_utils.py +++ b/scripts/utils/report_utils.py @@ -52,6 +52,9 @@ def compile_report(database, sql_file, config_file, output_file): def generate_project_reports(language): """ Generates reports for the given target by compiling model nodes tagged with "reports". + Nodes tagged "restricted" (i.e. sensitive-facility dataset views) are excluded when + has_sensitive_facility is false. has_sensitive_facility is read from dbt_project.yml via get_dbt_project_vars(), + not from the dbt runtime context. Args: language (str): The language to use for report generation. @@ -62,11 +65,18 @@ def generate_project_reports(language): manifest_path = os.path.join(BASE_DIR, "target", "manifest.json") manifest = read_file(manifest_path, "json") + project_vars = get_dbt_project_vars() + has_sensitive_facility = project_vars.get("has_sensitive_facility", False) + nodes = [ key for key in manifest["nodes"] if key.startswith("model") and "reports" in manifest["nodes"][key].get("tags", []) + and ( + has_sensitive_facility + or "restricted" not in manifest["nodes"][key].get("tags", []) + ) ] if not nodes: @@ -169,7 +179,9 @@ def generate_reporting_schema_script(): The script is generated based on the model nodes that do not have the "reports" tag and are compiled in the project. Dependencies between models are resolved before generating - the views in the schema. + the views in the schema. Nodes tagged "restricted" (i.e. sensitive-facility dataset views) are excluded when + has_sensitive_facility is false. has_sensitive_facility is read from dbt_project.yml via get_dbt_project_vars(), + not from the dbt runtime context. Args: target (str): The target tag to filter models for generating views. @@ -180,11 +192,18 @@ def generate_reporting_schema_script(): manifest_path = os.path.join(BASE_DIR, "target", "manifest.json") manifest = read_file(manifest_path, "json") + project_vars = get_dbt_project_vars() + has_sensitive_facility = project_vars.get("has_sensitive_facility", False) + nodes = [ key for key in manifest["nodes"] if key.startswith("model") and "reports" not in manifest["nodes"][key].get("tags", []) + and ( + has_sensitive_facility + or "restricted" not in manifest["nodes"][key].get("tags", []) + ) ] if not nodes: @@ -194,6 +213,9 @@ def generate_reporting_schema_script(): processed = set() ordered = [] + # Assumes no non-restricted model lists a restricted model in depends_on.nodes. + # Restricted nodes filtered above are never added to `processed`, so any such + # cross-tier dependency would stall this loop and exit with the error below. while len(processed) < len(nodes): current = [ node diff --git a/scripts/validate_report_configs.py b/scripts/validate_report_configs.py index d4dcef11..3d5e6a57 100644 --- a/scripts/validate_report_configs.py +++ b/scripts/validate_report_configs.py @@ -61,7 +61,7 @@ def find_config_files(config_dir: str) -> List[str]: print(" Ensure this script is run from the project root.") sys.exit(1) - json_files = list(config_path.glob("*.json")) + json_files = list(config_path.rglob("*.json")) # Exclude the schema file itself json_files = [f for f in json_files if f.name != "report-config-schema.json"]