From 3653048151e67e71859475c4270cd31bb57af3b3 Mon Sep 17 00:00:00 2001 From: Alfred-Mutai Date: Wed, 7 Feb 2024 11:46:33 +0300 Subject: [PATCH 1/3] Update DATIM patient list to meet new requirements --- .../tx-ml/patient-list-txml-template.json | 15 +++++++++++++++ .../tx-ml/tx-ml-report-patient-list-cols.json | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/app/reporting-framework/json-reports/tx-reports/tx-ml/patient-list-txml-template.json b/app/reporting-framework/json-reports/tx-reports/tx-ml/patient-list-txml-template.json index bb80c804c..80b4f6a1a 100644 --- a/app/reporting-framework/json-reports/tx-reports/tx-ml/patient-list-txml-template.json +++ b/app/reporting-framework/json-reports/tx-reports/tx-ml/patient-list-txml-template.json @@ -657,6 +657,21 @@ "alias": "latest_vl", "column": "fh.vl_1" }, + { + "type": "simple_column", + "alias": "weight", + "column": "fh.weight" + }, + { + "type": "simple_column", + "alias": "cd4_1", + "column": "fh.cd4_1" + }, + { + "type": "simple_column", + "alias": "cd4_1_date", + "column": "date_format(fh.cd4_1_date, '%Y-%m-%d')" + }, { "type": "derived_column", "alias": "vl_category", diff --git a/app/reporting-framework/json-reports/tx-reports/tx-ml/tx-ml-report-patient-list-cols.json b/app/reporting-framework/json-reports/tx-reports/tx-ml/tx-ml-report-patient-list-cols.json index ea1290cf7..49f9b2e4a 100644 --- a/app/reporting-framework/json-reports/tx-reports/tx-ml/tx-ml-report-patient-list-cols.json +++ b/app/reporting-framework/json-reports/tx-reports/tx-ml/tx-ml-report-patient-list-cols.json @@ -28,6 +28,11 @@ "field": "age", "width": 100 }, + { + "headerName": "Weight", + "field": "weight", + "width": 100 + }, { "headerName": "Identifiers", "field": "identifiers", @@ -48,6 +53,16 @@ "field": "latest_rtc_date", "width": 100 }, + { + "headerName": "CD4", + "field": "cd4_1", + "width": 100 + }, + { + "headerName": "CD4 Date", + "field": "cd4_1_date", + "width": 100 + }, { "headerName": "Latest VL", "field": "latest_vl", From 92ecab06caf32eeff93cc511a634feccaaf4be09 Mon Sep 17 00:00:00 2001 From: henrykorir Date: Wed, 7 Feb 2024 19:26:53 +0300 Subject: [PATCH 2/3] POC-651: Enhancement of DQA Report POC-651: Enhancement of DQA Report POC-651: Enhancement of DQA Report --- .../DQA/dqa-chart-abstraction-report-dao.js | 361 +++++++++++------- 1 file changed, 226 insertions(+), 135 deletions(-) diff --git a/reports/DQA/dqa-chart-abstraction-report-dao.js b/reports/DQA/dqa-chart-abstraction-report-dao.js index 76e9d6074..a9b2a6485 100644 --- a/reports/DQA/dqa-chart-abstraction-report-dao.js +++ b/reports/DQA/dqa-chart-abstraction-report-dao.js @@ -26,159 +26,250 @@ export class DQAChartAbstractionDAO { const limitOffSetDefinition = limit === 'all' ? '' : `limit ` + limit + ` offset ` + offset; + let sqlQuery = - ` - SELECT - h.person_uuid AS uuid, - fpiv.ccc AS ccc_number, - IF((fpiv.nupi IS NOT NULL), fpiv.nupi, 'Missing') AS NUPI, - TIMESTAMPDIFF(year,h.birthdate,'` + + `SELECT +h.person_uuid AS uuid, +fpiv.ccc AS ccc_number, +IF((fpiv.nupi IS NOT NULL), + fpiv.nupi, + 'Missing') AS NUPI, +TIMESTAMPDIFF(YEAR, + h.birthdate, + '2023-12-31') AS age, +CASE + WHEN e.tb_screen = 1 THEN 'Yes' + ELSE 'No' +END AS 'tb_screened_this_visit', +CASE + WHEN (h.gender = 'F') THEN 'Female' + WHEN (h.gender = 'M') THEN 'Male' + ELSE 'Missing' +END AS 'sex_gender', +e.height, +e.weight, +DATE_FORMAT(h.birthdate, '%d/%m/%Y') AS birthdate, +h.encounter_id, +DATE_FORMAT(h.encounter_date, '%d/%m/%Y') AS last_appointment_date, +h.rtc_date, +h.location_id, +h.cur_arv_meds, +CASE + WHEN (h.cur_arv_meds_names REGEXP '[[:<:]]DTG[[:>:]]') THEN 'DTG-based' + WHEN (h.cur_arv_meds_names NOT REGEXP '[[:<:]]DTG[[:>:]]') THEN 'Non-DTG-based' + ELSE 'NON DTG' +END AS cur_arv_med_basis, +h.tb_screen, +DATE_FORMAT(h.tb_screening_datetime, '%d/%m/%Y') AS tb_screening_datetime, +CASE + WHEN (e.hiv_start_date <= '1900-01-01') THEN '' + ELSE DATE_FORMAT(e.hiv_start_date, '%d/%m/%Y') +END AS hiv_start_date, +h.arv_start_date, +CASE + WHEN (h.arv_first_regimen_start_date <= '1900-01-01') THEN '' + ELSE DATE_FORMAT(h.arv_first_regimen_start_date, + '%d/%m/%Y') +END AS arv_first_regimen_start_date, +e.cd4_1, +IF((e.cd4_1 IS NOT NULL), 'Yes', 'No') AS has_cd4_1, +DATE_FORMAT(e.encounter_datetime, '%d/%m/%Y') AS last_clinical_encounter, +DATE_FORMAT(h.rtc_date, '%d/%m/%Y') AS next_appointment, +h.vl_1, +CASE + WHEN + (TIMESTAMPDIFF(MONTH, + h.arv_start_date, + '` + endDate + - `') AS age, - CASE - WHEN e.tb_screen = 1 then 'Yes' - -- WHEN e.tb_screen = 0 then 'No' - ELSE 'No' - END AS 'tb_screened_this_visit', - CASE - WHEN (h.gender = 'F') then 'Female' - WHEN (h.gender = 'M') then 'Male' - ELSE 'Missing' - END AS 'sex_gender', - e.height, - e.weight, - DATE_FORMAT(h.birthdate, '%d/%m/%Y') AS birthdate, - h.encounter_id, - DATE_FORMAT(h.encounter_date, '%d/%m/%Y') AS last_appointment_date, - h.rtc_date, - h.location_id, - h.cur_arv_meds, - CASE - WHEN (h.cur_arv_meds_names regexp '[[:<:]]DTG[[:>:]]') THEN 'DTG-based' - WHEN (h.cur_arv_meds_names NOT regexp '[[:<:]]DTG[[:>:]]') THEN 'Non-DTG-based' - ELSE 'NON DTG' - END as cur_arv_med_basis, - h.tb_screen, - DATE_FORMAT(h.tb_screening_datetime,'%d/%m/%Y') as tb_screening_datetime, - CASE - WHEN (e.hiv_start_date <= '1900-01-01') THEN '' - ELSE DATE_FORMAT(e.hiv_start_date,'%d/%m/%Y') - END as hiv_start_date, - h.arv_start_date, - CASE - WHEN (h.arv_first_regimen_start_date <= '1900-01-01') THEN '' - ELSE DATE_FORMAT(h.arv_first_regimen_start_date,'%d/%m/%Y') - END as arv_first_regimen_start_date, - e.cd4_1, - IF((e.cd4_1 IS NOT NULL), 'Yes', 'No') as has_cd4_1, - DATE_FORMAT(e.encounter_datetime, '%d/%m/%Y') AS last_clinical_encounter, - DATE_FORMAT(h.rtc_date, '%d/%m/%Y') AS next_appointment, - h.vl_1, - CASE - WHEN (TIMESTAMPDIFF(MONTH,h.arv_start_date,'` + + `') < 6) + THEN + 'NA' + WHEN (h.vl_1 IS NOT NULL) THEN 'Yes' + ELSE 'Missing' +END AS viral_load_validity, +h.cur_arv_meds_names AS drugs_given, +CASE + WHEN + e.height IS NOT NULL + AND e.weight IS NOT NULL + THEN + e.weight / ((e.height / 100) * (e.height / 100)) + ELSE NULL +END AS BMI, +TIMESTAMPDIFF(DAY, + h.encounter_date, + h.rtc_date) AS drugs_duration, +IF(h.ipt_start_date = h.encounter_date, + 1, + 0) AS ipt_started_this_visit, +DATE_FORMAT(h.ipt_start_date, '%d/%m/%Y') AS last_ipt_start_date, +CASE + WHEN h.on_ipt_this_month = 1 THEN 'Continuing' + WHEN + h.ipt_completion_date IS NULL + AND h.ipt_stop_date IS NOT NULL + THEN + 'Discontinued' + WHEN h.ipt_completion_date IS NOT NULL THEN 'INH Completed' + WHEN + (h.on_ipt_this_month = 0 + AND h.on_tb_tx_this_month = 0) + THEN + 'Missing' + WHEN + ((TIMESTAMPDIFF(MONTH, + h.ipt_start_date, + '` + endDate + - `') < 6 ) THEN 'NA' - WHEN (h.vl_1 is NOT NULL) THEN 'Yes' - ELSE 'Missing' - END AS viral_load_validity, - h.cur_arv_meds_names AS drugs_given, - CASE - WHEN - e.height IS NOT NULL - AND e.weight IS NOT NULL - THEN - e.weight / ((e.height / 100) * (e.height / 100)) - ELSE NULL - END AS BMI, - TIMESTAMPDIFF(DAY, - h.encounter_date, - h.rtc_date) AS drugs_duration, - IF(h.ipt_start_date = h.encounter_date, - 1, - 0) AS ipt_started_this_visit, - DATE_FORMAT(h.ipt_start_date, '%d/%m/%Y') AS last_ipt_start_date, - CASE - WHEN h.on_ipt_this_month = 1 THEN 'Continuing' - WHEN - h.ipt_completion_date IS NULL - AND h.ipt_stop_date IS NOT NULL - THEN - 'Discontinued' - WHEN h.ipt_completion_date IS NOT NULL THEN 'INH Completed' - WHEN (h.on_ipt_this_month = 0 AND h.on_tb_tx_this_month = 0) THEN 'Missing' - WHEN ((TIMESTAMPDIFF(MONTH,h.ipt_start_date,'` + + `') < 3) + AND h.on_ipt_this_month = 1) + THEN + 'Defaulted' + ELSE 'NA' +END AS tpt_status, +DATE_FORMAT(h.ipt_stop_date, '%d/%m/%Y') AS ipt_stop_date, +DATE_FORMAT(h.ipt_completion_date, '%d/%m/%Y') AS ipt_completion_date, +fv.muac AS muac, +IF(h.ipt_stop_date = h.encounter_date + OR h.ipt_completion_date = h.encounter_date, + 1, + 0) AS ipt_ended_this_visit, +h.status, +IF((o.value_coded IS NULL), 'No', 'Yes') AS is_crag_screened, +CASE + WHEN (h.vl_1 < 200) THEN 'Yes' + WHEN (h.vl_1 >= 200) THEN 'No' + ELSE 'Missing' +END AS vl_suppression, +CASE + WHEN (e.tb_screening_result IN (6621 , 1118)) THEN 'TB Screening not done' + WHEN (e.tb_screening_result = 6971) THEN 'Presumed TB' + WHEN (e.tb_screening_result IN (6137 , 6176, 10767)) THEN 'TB confirmed' + WHEN (e.tb_screening_result IN (1107 , 10678)) THEN 'No TB signs' + ELSE 'Missing' +END AS tb_screening_result, +CASE + WHEN (p.program_id = 4) THEN 'PMTCT' + WHEN + (TIMESTAMPDIFF(YEAR, + h.birthdate, + '` + endDate + - `') < 3) AND h.on_ipt_this_month = 1) THEN 'Defaulted' - ELSE 'NA' - END AS tpt_status, - DATE_FORMAT(h.ipt_stop_date,'%d/%m/%Y') as ipt_stop_date, - DATE_FORMAT(h.ipt_completion_date, '%d/%m/%Y') as ipt_completion_date, - fv.muac as muac, - IF(h.ipt_stop_date = h.encounter_date - OR h.ipt_completion_date = h.encounter_date, - 1, - 0) AS ipt_ended_this_visit, - h.status, - IF((o.value_coded IS NULL), 'No', 'Yes') AS is_crag_screened, - CASE - WHEN (h.vl_1 < 200) THEN 'Yes' - WHEN (h.vl_1 >= 200) THEN 'No' - ELSE 'Missing' - END AS vl_suppression, - CASE - WHEN (e.tb_screening_result IN (6621,1118)) THEN 'TB Screening not done' - WHEN (e.tb_screening_result = 6971) THEN 'Presumed TB' - WHEN (e.tb_screening_result IN (6137, 6176, 10767)) THEN 'TB confirmed' - WHEN (e.tb_screening_result IN (1107 , 10678)) THEN 'No TB signs' - ELSE 'Missing' - END AS tb_screening_result, - CASE - WHEN (p.program_id = 4) THEN 'PMTCT' - WHEN (TIMESTAMPDIFF(YEAR, h.birthdate, '` + + `') < 15) + THEN + 'Paeds (0-14yrs)' + WHEN + (TIMESTAMPDIFF(YEAR, + h.birthdate, + '` + endDate + - `') < 15) THEN 'Paeds (0-14yrs)' - WHEN (TIMESTAMPDIFF(YEAR, h.birthdate, '` + - endDate + - `') >= 15) THEN 'Adults (>15 yrs)' - END AS category + `') >= 15) + THEN + 'Adults (>15 yrs)' +END AS category, +CASE + WHEN + o.concept_id = 1109 + AND o.value_coded = 916 + THEN + 'COTRIMOXAZOLE' + WHEN + o.concept_id = 1109 + AND o.value_coded = 92 + THEN + 'DAPSONE' + ELSE NULL +END AS pcp_prophylaxis, +CASE + WHEN o.value_coded IN (916) THEN 'Yes' + ELSE 'No' +END AS ctx_dispensed, +case + WHEN (h.gender = 'M') then 'Not Applicable' + WHEN (h.gender = 'F' AND o.concept_id IN (5630) AND o.value_coded IN (1170)) then 'SVD' + WHEN (h.gender = 'F' AND o.concept_id IN (5630) AND o.value_coded IN (1171)) then 'C-Section' + WHEN (h.gender = 'F' AND o.concept_id IN (5630) AND o.value_coded IN (1172)) then 'Breech' + WHEN (h.gender = 'F' AND o.concept_id IN (5630) AND o.value_coded IN (5622)) then 'Other' + WHEN (h.gender = 'F' AND o.concept_id IN (5630) AND o.value_coded IN (1067)) then 'Uknown' + WHEN (h.gender = 'F' AND o.concept_id IN (5630) AND o.value_coded IN (2167)) then 'Vacuum Assisted' + WHEN (h.gender = 'F' AND o.concept_id IN (5630) AND o.value_coded IN (2166)) then 'Forceps Delivery' + WHEN (h.gender = 'F' AND o.concept_id IN (5630) AND o.value_coded IN (6263)) then 'Elective C-Section' + WHEN (h.gender = 'F' AND o.concept_id IN (5630) AND o.value_coded IN (6442)) then 'Emergency C-Section' + WHEN (h.gender = 'F' AND o.concept_id IN (5630) AND o.value_coded IN (8316)) then 'Vertex Delivery' + ELSE NULL +end as delivery_method, +case + WHEN (h.gender = 'M') then 'Not Applicable' + WHEN (h.gender = 'F' AND o.concept_id IN (6224) AND o.value_coded IN (1844)) then 'Early Neonatal Mortality' + WHEN (h.gender = 'F' AND o.concept_id IN (6224) AND o.value_coded IN (48)) then 'Miscarriage' + WHEN (h.gender = 'F' AND o.concept_id IN (6224) AND o.value_coded IN (46)) then 'Ectopic' + WHEN (h.gender = 'F' AND o.concept_id IN (6224) AND o.value_coded IN (1993)) then 'Stillbirth' + WHEN (h.gender = 'F' AND o.concept_id IN (6224) AND o.value_coded IN (1845)) then 'Late Neonatal Mortality' + WHEN (h.gender = 'F' AND o.concept_id IN (6224) AND o.value_coded IN (5622)) then 'Other' + WHEN (h.gender = 'F' AND o.concept_id IN (6224) AND o.value_coded IN (1843)) then 'Live Birth' + WHEN (h.gender = 'F' AND o.concept_id IN (6224) AND o.value_coded IN (6782)) then 'Normal Term Deliver' + WHEN (h.gender = 'F' AND o.concept_id IN (6224) AND o.value_coded IN (6648)) then 'Preterm Deliery' + WHEN (h.gender = 'F' AND o.concept_id IN (6224) AND o.value_coded IN (10424)) then 'Macerated Stillbirth' + WHEN (h.gender = 'F' AND o.concept_id IN (6224) AND o.value_coded IN (10877)) then 'Fresh Stillbirth' + WHEN (h.gender = 'F' AND o.concept_id IN (6224) AND o.value_coded IN (10878)) then 'Spontaneous Abortion' + ELSE NULL +end as pregnancy_outcome, + +case + WHEN (h.gender = 'F' AND o.concept_id IN (5630, 6224) + AND o.value_coded IN (1170, 1843)) THEN 'Yes' + WHEN h.gender = 'M' THEN 'Not Applicable' + ELSE null +END as svd_and_live_birth + FROM - etl.hiv_monthly_report_dataset_v1_2 h - LEFT JOIN - etl.flat_hiv_summary_v15b e ON (h.encounter_id = e.encounter_id) - LEFT JOIN - etl.flat_vitals fv ON (e.person_id = fv.person_id) - INNER JOIN - amrs.person t1 ON (h.person_id = t1.person_id) - inner JOIN - etl.flat_patient_identifiers_v1 fpiv ON (t1.person_id = fpiv.patient_id) - LEFT JOIN - amrs.patient_program p ON (p.patient_id = h.person_id - AND p.program_id IN (4) - AND p.date_completed IS NULL - AND p.voided = 0) - LEFT JOIN - amrs.obs o ON (o.encounter_id = e.encounter_id - AND o.person_id = h.person_id - AND o.concept_id in (9812) - AND o.voided = 0 - ) +etl.hiv_monthly_report_dataset_v1_2 h + LEFT JOIN +etl.flat_hiv_summary_v15b e ON (h.encounter_id = e.encounter_id) + LEFT JOIN +etl.flat_vitals fv ON (e.person_id = fv.person_id) + INNER JOIN +amrs.person t1 ON (h.person_id = t1.person_id) + INNER JOIN +etl.flat_patient_identifiers_v1 fpiv ON (t1.person_id = fpiv.patient_id) + LEFT JOIN +amrs.patient_program p ON (p.patient_id = h.person_id + AND p.program_id IN (4) + AND p.date_completed IS NULL + AND p.voided = 0) +Left JOIN +amrs.obs o ON (o.encounter_id = e.encounter_id + AND o.person_id = h.person_id + AND o.location_id IN (` + + locations + + `) + AND (o.obs_datetime between '` + + startDate + + `'AND '` + + endDate + + `') + AND o.concept_id IN (5630, 6224, 1109, 9812, 1109) + AND o.value_coded in (1170, 1843, 916) + AND o.voided = 0 + ) WHERE - h.status = "active" AND +h.status = 'active' AND h.endDate >= '` + startDate + `' AND h.endDate <= '` + endDate + `' - AND h.location_id IN (` + +AND h.location_id IN (` + locations + `) - AND ` + +AND ` + where + ` GROUP BY - h.person_id - ` + +h.person_id +` + limitOffSetDefinition; return new Promise((resolve, reject) => { From 54152d7216ee7c8baa072d1a540327cc2aa124d9 Mon Sep 17 00:00:00 2001 From: henrykorir Date: Fri, 26 Jan 2024 16:28:13 +0300 Subject: [PATCH 3/3] POC-633: Display the Total abdominal hysterectomy on the patient dashboard. Concept ID 5276 --- service/cervical-cancer-screening-service.js | 89 +++++++++++++------- 1 file changed, 57 insertions(+), 32 deletions(-) diff --git a/service/cervical-cancer-screening-service.js b/service/cervical-cancer-screening-service.js index e24a9de5a..1bcdef511 100644 --- a/service/cervical-cancer-screening-service.js +++ b/service/cervical-cancer-screening-service.js @@ -49,38 +49,63 @@ function getPatientCervicalCancerScreeningSummary(patientUuId) { reject('Patient Uuid is missing'); } else { const sql = `SELECT - person_id, - DATE_FORMAT(test_datetime,'%d-%m-%Y') as 'test_date', - via_or_via_vili, - pap_smear, - hpv, - uuid, - case - WHEN via_or_via_vili is NOT NULL THEN 'VIA or VIA/VILI' - WHEN pap_smear is NOT NULL THEN 'PAP SMEAR' - WHEN hpv is NOT NULL THEN 'HPV' - ELSE NULL - end as 'test', - case - WHEN via_or_via_vili = 7469 THEN 'ACETOWHITE LESION' - WHEN via_or_via_vili = 1115 THEN 'NORMAL' - WHEN via_or_via_vili = 6497 THEN 'DYSFUNCTIONAL UTERINE BLEEDING' - WHEN via_or_via_vili = 703 THEN 'POSITIVE' - WHEN via_or_via_vili = 7470 THEN 'PUNCTUATED CAPILLARIES' - WHEN via_or_via_vili = 664 THEN 'NEGATIVE' - WHEN via_or_via_vili = 7472 THEN 'ATYPICAL BLOOD VESSELS' - WHEN via_or_via_vili = 7293 THEN 'ULCER' - WHEN via_or_via_vili = 9593 THEN 'FRIABLE TISSUE' - WHEN via_or_via_vili = 6971 THEN 'POSSIBLE' - ELSE NULL - end as 'via_test_result' -FROM - etl.flat_labs_and_imaging -WHERE - (via_or_via_vili IS NOT NULL OR pap_smear IS NOT NULL OR hpv IS NOT NULL) - AND uuid = '${patientUuId}' -ORDER BY test_datetime DESC -LIMIT 10;`; + fli.person_id, + fli.test_date, + fli.via_or_via_vili, + fli.pap_smear, + fli.hpv, + fli.test, + fli.via_test_result, + GROUP_CONCAT(concat_ws('=',concept_id,value_coded,obs_datetime) ORDER BY obs_datetime desc SEPARATOR ' ## ') as reason + FROM + amrs.obs o + LEFT JOIN + (SELECT + person_id, + DATE_FORMAT(test_datetime, '%d-%m-%Y') AS 'test_date', + via_or_via_vili, + pap_smear, + hpv, + uuid, + CASE + WHEN via_or_via_vili IS NOT NULL THEN 'VIA or VIA/VILI' + WHEN pap_smear IS NOT NULL THEN 'PAP SMEAR' + WHEN hpv IS NOT NULL THEN 'HPV' + ELSE NULL + END AS 'test', + CASE + WHEN via_or_via_vili = 7469 THEN 'ACETOWHITE LESION' + WHEN via_or_via_vili = 1115 THEN 'NORMAL' + WHEN via_or_via_vili = 6497 THEN 'DYSFUNCTIONAL UTERINE BLEEDING' + WHEN via_or_via_vili = 703 THEN 'POSITIVE' + WHEN via_or_via_vili = 7470 THEN 'PUNCTUATED CAPILLARIES' + WHEN via_or_via_vili = 664 THEN 'NEGATIVE' + WHEN via_or_via_vili = 7472 THEN 'ATYPICAL BLOOD VESSELS' + WHEN via_or_via_vili = 7293 THEN 'ULCER' + WHEN via_or_via_vili = 9593 THEN 'FRIABLE TISSUE' + WHEN via_or_via_vili = 6971 THEN 'POSSIBLE' + ELSE NULL + END AS 'via_test_result' + FROM + etl.flat_labs_and_imaging + WHERE + (via_or_via_vili IS NOT NULL + OR pap_smear IS NOT NULL + OR hpv IS NOT NULL) + AND uuid = '${patientUuId}' + ORDER BY test_datetime DESC + LIMIT 1) fli ON fli.person_id = o.person_id + WHERE + value_coded IN (5276 , 12109, 1504, 5989) + AND voided = 0 + AND o.person_id = (SELECT + person_id + FROM + etl.flat_labs_and_imaging + WHERE + uuid = '${patientUuId}' + LIMIT 1) + ORDER BY o.obs_datetime DESC;`; const queryParts = { sql: sql