From bbd496b31b8c444ce77e482ecdc66d2122c49ba0 Mon Sep 17 00:00:00 2001 From: Nicholas Ingosi Date: Thu, 18 Apr 2024 12:49:18 +0300 Subject: [PATCH 1/3] Add 706 summarry tool and the respective 240 register --- .../common/SetupMOH240LabReportBuilder.java | 151 ++++++++++++++++++ .../common/SetupMOH706LabReportBuilder.java | 72 +++++++++ .../converter/EncounterDatetimeConverter.java | 46 ++++++ .../MOH706/Moh706IndicatorLibrary.java | 32 ++++ .../MOH706/Moh706LabCohortLibrary.java | 38 +++++ .../resources/content/kenyaemr.common.xml | 24 +++ .../main/webapp/resources/reports/MOH240.xls | Bin 0 -> 50688 bytes .../main/webapp/resources/reports/MOH706.xls | Bin 0 -> 54784 bytes 8 files changed, 363 insertions(+) create mode 100644 api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH240LabReportBuilder.java create mode 100644 api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH706LabReportBuilder.java create mode 100644 api/src/main/java/org/openmrs/module/kenyaemr/reporting/data/converter/EncounterDatetimeConverter.java create mode 100644 api/src/main/java/org/openmrs/module/kenyaemr/reporting/library/MOH706/Moh706IndicatorLibrary.java create mode 100644 api/src/main/java/org/openmrs/module/kenyaemr/reporting/library/MOH706/Moh706LabCohortLibrary.java create mode 100644 omod/src/main/webapp/resources/reports/MOH240.xls create mode 100644 omod/src/main/webapp/resources/reports/MOH706.xls diff --git a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH240LabReportBuilder.java b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH240LabReportBuilder.java new file mode 100644 index 0000000000..30822562b2 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH240LabReportBuilder.java @@ -0,0 +1,151 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.module.kenyaemr.reporting.builder.common; + +import org.openmrs.Concept; +import org.openmrs.EncounterType; +import org.openmrs.PatientIdentifierType; +import org.openmrs.PersonAttributeType; +import org.openmrs.api.context.Context; +import org.openmrs.module.kenyacore.report.HybridReportDescriptor; +import org.openmrs.module.kenyacore.report.ReportDescriptor; +import org.openmrs.module.kenyacore.report.ReportUtils; +import org.openmrs.module.kenyacore.report.builder.AbstractHybridReportBuilder; +import org.openmrs.module.kenyacore.report.builder.Builds; +import org.openmrs.module.kenyacore.report.data.patient.definition.CalculationDataDefinition; +import org.openmrs.module.kenyaemr.Metadata; +import org.openmrs.module.kenyaemr.calculation.library.TelephoneNumberCalculation; +import org.openmrs.module.kenyaemr.metadata.CommonMetadata; +import org.openmrs.module.kenyaemr.reporting.data.converter.CalculationResultConverter; +import org.openmrs.module.kenyaemr.reporting.data.converter.EncounterDatetimeConverter; +import org.openmrs.module.reporting.cohort.definition.CohortDefinition; +import org.openmrs.module.reporting.cohort.definition.SqlCohortDefinition; +import org.openmrs.module.reporting.common.TimeQualifier; +import org.openmrs.module.reporting.data.DataDefinition; +import org.openmrs.module.reporting.data.converter.BirthdateConverter; +import org.openmrs.module.reporting.data.converter.DataConverter; +import org.openmrs.module.reporting.data.converter.ObjectFormatter; +import org.openmrs.module.reporting.data.converter.ObsValueConverter; +import org.openmrs.module.reporting.data.patient.definition.ConvertedPatientDataDefinition; +import org.openmrs.module.reporting.data.patient.definition.EncountersForPatientDataDefinition; +import org.openmrs.module.reporting.data.patient.definition.PatientIdentifierDataDefinition; +import org.openmrs.module.reporting.data.patient.definition.SqlPatientDataDefinition; +import org.openmrs.module.reporting.data.person.definition.AgeDataDefinition; +import org.openmrs.module.reporting.data.person.definition.BirthdateDataDefinition; +import org.openmrs.module.reporting.data.person.definition.ConvertedPersonDataDefinition; +import org.openmrs.module.reporting.data.person.definition.GenderDataDefinition; +import org.openmrs.module.reporting.data.person.definition.ObsForPersonDataDefinition; +import org.openmrs.module.reporting.data.person.definition.PersonAttributeDataDefinition; +import org.openmrs.module.reporting.data.person.definition.PersonIdDataDefinition; +import org.openmrs.module.reporting.data.person.definition.PreferredNameDataDefinition; +import org.openmrs.module.reporting.dataset.definition.DataSetDefinition; +import org.openmrs.module.reporting.dataset.definition.PatientDataSetDefinition; +import org.openmrs.module.reporting.evaluation.parameter.Mapped; +import org.openmrs.module.reporting.evaluation.parameter.Parameter; +import org.openmrs.module.reporting.report.definition.ReportDefinition; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +@Component +@Builds({ "kenyaemr.ehrReports.report.240" }) +public class SetupMOH240LabReportBuilder extends AbstractHybridReportBuilder { + + @Override + protected Mapped buildCohort(HybridReportDescriptor hybridReportDescriptor, + PatientDataSetDefinition patientDataSetDefinition) { + return null; + } + + @Override + protected List> buildDataSets(ReportDescriptor descriptor, ReportDefinition report) { + PatientDataSetDefinition dsd = LabRegister(); + dsd.setName("lrr"); + dsd.addParameter(new Parameter("startDate", "Start Date", Date.class)); + dsd.addParameter(new Parameter("endDate", "End Date", Date.class)); + report.setBaseCohortDefinition(ReportUtils.map(getLabOrderEncounter(), "startDate=${startDate},endDate=${endDate}")); + + return Arrays.asList(ReportUtils.map((DataSetDefinition) dsd, "startDate=${startDate},endDate=${endDate}")); + } + + @Override + protected List getParameters(ReportDescriptor reportDescriptor) { + return Arrays.asList(new Parameter("startDate", "Start Date", Date.class), new Parameter("endDate", "End Date", + Date.class), new Parameter("dateBasedReporting", "", String.class)); + } + + private PatientDataSetDefinition LabRegister() { + PatientDataSetDefinition dsd = new PatientDataSetDefinition(); + dsd.setName("lrr"); + dsd.addParameter(new Parameter("startDate", "Start Date", Date.class)); + dsd.addParameter(new Parameter("endDate", "End Date", Date.class)); + dsd.addRowFilter(getLabOrderEncounter(), "startDate=${startDate},endDate=${endDate+23h}"); + DataConverter nameFormatter = new ObjectFormatter("{familyName}, {givenName}, {middleName}"); + DataDefinition nameDef = new ConvertedPersonDataDefinition("name", new PreferredNameDataDefinition(), nameFormatter); + + PersonAttributeType personAttributeType = Context.getPersonService().getPersonAttributeTypeByUuid(CommonMetadata._PersonAttributeType.TELEPHONE_CONTACT); + + PatientIdentifierType openmrsID = Context.getPatientService().getPatientIdentifierTypeByUuid("dfacd928-0370-4315-99d7-6ec1c9f7ae76"); + DataConverter identifierFormatter = new ObjectFormatter("{identifier}"); + DataDefinition identifierDef = new ConvertedPatientDataDefinition("identifier", new PatientIdentifierDataDefinition( + openmrsID.getName(), openmrsID), identifierFormatter); + + dsd.addColumn("id", new PersonIdDataDefinition(), ""); + dsd.addColumn("identifier", identifierDef, ""); + dsd.addColumn("Date", getEncounterDate(), "onOrAfter=${startDate},onOrBefore=${endDate+23h}", + new EncounterDatetimeConverter()); + dsd.addColumn("Name", nameDef, ""); + dsd.addColumn("Sex", new GenderDataDefinition(), "", null); + dsd.addColumn("DOB", new BirthdateDataDefinition(), "", new BirthdateConverter("yyyy-MM-dd")); + dsd.addColumn("age", new AgeDataDefinition(), ""); + dsd.addColumn("village", getAddress(), "", null); + dsd.addColumn("telephone", new PersonAttributeDataDefinition(personAttributeType), "", + null); + return dsd; + + } + + + private DataDefinition getEncounterDate() { + EncounterType labEncounter = Context.getEncounterService().getEncounterTypeByUuid( + "17a381d1-7e29-406a-b782-aa903b963c28"); + EncountersForPatientDataDefinition dsd = new EncountersForPatientDataDefinition(); + dsd.addParameter(new Parameter("onOrAfter", "After Date", Date.class)); + dsd.addParameter(new Parameter("onOrBefore", "Before Date", Date.class)); + dsd.setTypes(Arrays.asList(labEncounter)); + dsd.setWhich(TimeQualifier.LAST); + return dsd; + } + + private CohortDefinition getLabOrderEncounter() { + EncounterType labEncounter = Context.getEncounterService().getEncounterTypeByUuid( + "17a381d1-7e29-406a-b782-aa903b963c28"); + SqlCohortDefinition sqlEncounterQuery = new SqlCohortDefinition(); + sqlEncounterQuery.setName("Get unique lab encounter types"); + sqlEncounterQuery.addParameter(new Parameter("startDate", "Start Date", Date.class)); + sqlEncounterQuery.addParameter(new Parameter("endDate", "End Date", Date.class)); + sqlEncounterQuery + .setQuery("SELECT p.patient_id FROM patient p INNER JOIN encounter e ON p.patient_id=e.patient_id " + + " WHERE e.encounter_datetime BETWEEN :startDate AND :endDate AND e.voided=0 AND p.voided = 0 " + + " AND e.encounter_type IN(" + labEncounter.getEncounterTypeId() + ")"); + return sqlEncounterQuery; + } + + public static DataDefinition getAddress() { + SqlPatientDataDefinition sqlPdfn = new SqlPatientDataDefinition(); + sqlPdfn.setName("Address"); + sqlPdfn.setQuery("SELECT p.person_id, REPLACE(CONCAT_WS(' ',pa.address1,pa.address2,pa.city_village,pa.address3,pa.address5,pa.address6), ',','') AS address FROM person p " + + " INNER JOIN person_address pa ON p.person_id=pa.person_id "); + return sqlPdfn; + } +} \ No newline at end of file diff --git a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH706LabReportBuilder.java b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH706LabReportBuilder.java new file mode 100644 index 0000000000..0741be2b87 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH706LabReportBuilder.java @@ -0,0 +1,72 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.module.kenyaemr.reporting.builder.common; + +import org.openmrs.module.kenyacore.report.ReportDescriptor; +import org.openmrs.module.kenyacore.report.ReportUtils; +import org.openmrs.module.kenyacore.report.builder.AbstractReportBuilder; +import org.openmrs.module.kenyacore.report.builder.Builds; +import org.openmrs.module.kenyaemr.reporting.library.MOH706.Moh706LabCohortLibrary; +import org.openmrs.module.kenyaemr.reporting.library.MOH706.Moh706IndicatorLibrary; +import org.openmrs.module.reporting.dataset.definition.CohortIndicatorDataSetDefinition; +import org.openmrs.module.reporting.dataset.definition.DataSetDefinition; +import org.openmrs.module.reporting.evaluation.parameter.Mapped; +import org.openmrs.module.reporting.evaluation.parameter.Parameter; +import org.openmrs.module.reporting.report.definition.ReportDefinition; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import static org.openmrs.module.kenyacore.report.ReportUtils.map; + +@Component +@Builds({ "kenyaemr.ehrReports.706.report" }) +public class SetupMOH706LabReportBuilder extends AbstractReportBuilder { + + + private final Moh706IndicatorLibrary moh706IndicatorLibrary; + + @Autowired + public SetupMOH706LabReportBuilder(Moh706LabCohortLibrary moh706CohortLibrary, Moh706IndicatorLibrary moh706IndicatorLibrary) { + this.moh706IndicatorLibrary = moh706IndicatorLibrary; + } + + @Override + protected List getParameters(ReportDescriptor reportDescriptor) { + return Arrays.asList(new Parameter("startDate", "Start Date", Date.class), new Parameter("endDate", "End Date", + Date.class), new Parameter("dateBasedReporting", "", String.class)); + } + + @Override + protected List> buildDataSets(ReportDescriptor reportDescriptor, + ReportDefinition reportDefinition) { + return Arrays.asList(map(getMoh706LabDatasetDefinition(), + "startDate=${startDate},endDate=${endDate+23h}")); + } + + private DataSetDefinition getMoh706LabDatasetDefinition() { + CohortIndicatorDataSetDefinition cohortDsd = new CohortIndicatorDataSetDefinition(); + cohortDsd.addParameter(new Parameter("startDate", "Start Date", Date.class)); + cohortDsd.addParameter(new Parameter("endDate", "End Date", Date.class)); + cohortDsd.setName("MOH706"); + cohortDsd.setDescription("MOH 706 for the lab"); + + //URINE ANALYSIS + cohortDsd.addColumn("UAGL", "1.2 Glucose", + ReportUtils.map(moh706IndicatorLibrary.getAllUrineAnalysisGlucoseTestsPositives(), "startDate=${startDate},endDate=${endDate}"), ""); + + return cohortDsd; + } + +} + diff --git a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/data/converter/EncounterDatetimeConverter.java b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/data/converter/EncounterDatetimeConverter.java new file mode 100644 index 0000000000..c00812ffc3 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/data/converter/EncounterDatetimeConverter.java @@ -0,0 +1,46 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.module.kenyaemr.reporting.data.converter; + +import org.openmrs.Encounter; +import org.openmrs.Obs; +import org.openmrs.module.reporting.data.converter.DataConverter; + +import java.text.Format; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class EncounterDatetimeConverter implements DataConverter { + + public Object convert(Object original) { + Encounter encounter = (Encounter) original; + + if (encounter == null) { + return null; + } else if (encounter.getDateCreated() != null) { + return formatDates(encounter.getDateCreated(), "dd-MM-yyyy HH:mm:ss"); + } + return null; + } + + public Class getInputDataType() { + return Encounter.class; + } + + public Class getDataType() { + return Object.class; + } + + public static String formatDates(Date date, String format) { + Format formatter = new SimpleDateFormat(format); + String s = formatter.format(date); + return s; + } +} diff --git a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/library/MOH706/Moh706IndicatorLibrary.java b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/library/MOH706/Moh706IndicatorLibrary.java new file mode 100644 index 0000000000..60fa731136 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/library/MOH706/Moh706IndicatorLibrary.java @@ -0,0 +1,32 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.module.kenyaemr.reporting.library.MOH706; + +import org.openmrs.module.reporting.indicator.CohortIndicator; +import org.springframework.stereotype.Component; + +import static org.openmrs.module.kenyacore.report.ReportUtils.map; +import static org.openmrs.module.kenyaemr.reporting.MohReportUtils.ReportingUtils.cohortIndicator; + +@Component +public class Moh706IndicatorLibrary { + private final Moh706LabCohortLibrary moh706LabCohortLibrary; + + public Moh706IndicatorLibrary(Moh706LabCohortLibrary moh706LabCohortLibrary) { + this.moh706LabCohortLibrary = moh706LabCohortLibrary; + } + + public CohortIndicator getAllUrineAnalysisGlucoseTestsPositives() { + return cohortIndicator( + "All patients who have urinalysis glucose", + map(moh706LabCohortLibrary.getAllUrineAnalysisGlucoseTestsPositives(), + "startDate=${startDate},endDate=${endDate}")); + } +} diff --git a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/library/MOH706/Moh706LabCohortLibrary.java b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/library/MOH706/Moh706LabCohortLibrary.java new file mode 100644 index 0000000000..7791f69065 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/library/MOH706/Moh706LabCohortLibrary.java @@ -0,0 +1,38 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.module.kenyaemr.reporting.library.MOH706; + +import org.openmrs.module.reporting.cohort.definition.CohortDefinition; +import org.openmrs.module.reporting.cohort.definition.SqlCohortDefinition; +import org.openmrs.module.reporting.evaluation.parameter.Parameter; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +public class Moh706LabCohortLibrary { + + public CohortDefinition getAllUrineAnalysisGlucoseTestsPositives() { + SqlCohortDefinition sql = new SqlCohortDefinition(); + sql.setName("Get urine analysis patients - glucose"); + sql.addParameter(new Parameter("startDate", "Start Date", Date.class)); + sql.addParameter(new Parameter("endDate", "End Date", Date.class)); + sql.setQuery("SELECT p.patient_id FROM patient p INNER JOIN encounter e ON p.patient_id = e.patient_id INNER JOIN obs o ON e.encounter_id = o.encounter_id " + + " WHERE p.voided=0 AND e.voided = 0 AND o.voided = 0 AND o.concept_id in (159734) AND o.value_coded IN (703,1874,1362,1363,1364,1365) " + + " AND e.encounter_datetime BETWEEN :startDate AND :endDate " + + " UNION " + + " SELECT p.patient_id FROM patient p INNER JOIN encounter e on p.patient_id = e.patient_id INNER JOIN obs o ON e.encounter_id = o.encounter_id " + + " WHERE p.voided=0 AND e.voided = 0 AND o.voided = 0 AND o.concept_id in (159733) AND o.value_numeric IS NOT NULL " + + " AND e.encounter_datetime BETWEEN :startDate AND :endDate " + + ); + return sql; + } +} diff --git a/api/src/main/resources/content/kenyaemr.common.xml b/api/src/main/resources/content/kenyaemr.common.xml index 93cdbf3cd5..8d7fa48762 100644 --- a/api/src/main/resources/content/kenyaemr.common.xml +++ b/api/src/main/resources/content/kenyaemr.common.xml @@ -98,6 +98,8 @@ + + @@ -981,5 +983,27 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/omod/src/main/webapp/resources/reports/MOH240.xls b/omod/src/main/webapp/resources/reports/MOH240.xls new file mode 100644 index 0000000000000000000000000000000000000000..4f45cb3180980ec2ca7250048cf056aab6a8bd12 GIT binary patch literal 50688 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 Date: Thu, 18 Apr 2024 17:39:58 +0300 Subject: [PATCH 2/3] updated MOH240 and MOH706 to pull from kenyaemr_etl fields, cleaned 5+ and 60+ dimensions --- .../MohReportUtils/ReportAddonUtils.java | 12 ++--- .../common/SetupMOH240LabReportBuilder.java | 46 ++++++------------- .../MOH706/Moh706LabCohortLibrary.java | 14 +++--- 3 files changed, 26 insertions(+), 46 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/MohReportUtils/ReportAddonUtils.java b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/MohReportUtils/ReportAddonUtils.java index c24a20df2b..6afd0dd239 100644 --- a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/MohReportUtils/ReportAddonUtils.java +++ b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/MohReportUtils/ReportAddonUtils.java @@ -63,16 +63,16 @@ public static List getGeneralOutPatientFilters() { "state=NEW|age=<5|gender=F", "03"); ColumnParameters under5FemaleRevisit = new ColumnParameters("over5FemaleRevisit", "below 5 and revisit", "state=RVT|age=<5|gender=F", "04"); - ColumnParameters over5MaleNew = new ColumnParameters("over5MaleNew", "above 5 and new", "state=NEW|age=>5|gender=M", + ColumnParameters over5MaleNew = new ColumnParameters("over5MaleNew", "above 5 and new", "state=NEW|age=5+|gender=M", "05"); ColumnParameters over5MaleRevisit = new ColumnParameters("over5MaleRevisit", "above 5 and revisit", - "state=RVT|age=>5|gender=M", "06"); + "state=RVT|age=5+|gender=M", "06"); ColumnParameters over5FemaleNew = new ColumnParameters("over5MaleNew", "above 5 and new", - "state=NEW|age=>5|gender=F", "07"); + "state=NEW|age=5+|gender=F", "07"); ColumnParameters over5FemaleRevisit = new ColumnParameters("over5MaleRevisit", "above 5 and revisit", - "state=RVT|age=>5|gender=F", "08"); - ColumnParameters over60New = new ColumnParameters("over60New", "above 60 and new", "state=NEW|age=>60", "09"); - ColumnParameters over60Revisit = new ColumnParameters("over60Revisit", "above 60 and revisit", "state=RVT|age=>60", + "state=RVT|age=5+|gender=F", "08"); + ColumnParameters over60New = new ColumnParameters("over60New", "above 60 and new", "state=NEW|age=60+", "09"); + ColumnParameters over60Revisit = new ColumnParameters("over60Revisit", "above 60 and revisit", "state=RVT|age=60+", "10"); return Arrays.asList(under5MaleNew, under5MaleRevisit, under5FemaleNew, under5FemaleRevisit, over5MaleNew, diff --git a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH240LabReportBuilder.java b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH240LabReportBuilder.java index 30822562b2..722afff29b 100644 --- a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH240LabReportBuilder.java +++ b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH240LabReportBuilder.java @@ -22,17 +22,17 @@ import org.openmrs.module.kenyacore.report.data.patient.definition.CalculationDataDefinition; import org.openmrs.module.kenyaemr.Metadata; import org.openmrs.module.kenyaemr.calculation.library.TelephoneNumberCalculation; +import org.openmrs.module.kenyaemr.calculation.library.mchcs.PersonAddressCalculation; import org.openmrs.module.kenyaemr.metadata.CommonMetadata; +import org.openmrs.module.kenyaemr.reporting.calculation.converter.RDQACalculationResultConverter; import org.openmrs.module.kenyaemr.reporting.data.converter.CalculationResultConverter; import org.openmrs.module.kenyaemr.reporting.data.converter.EncounterDatetimeConverter; import org.openmrs.module.reporting.cohort.definition.CohortDefinition; import org.openmrs.module.reporting.cohort.definition.SqlCohortDefinition; import org.openmrs.module.reporting.common.TimeQualifier; import org.openmrs.module.reporting.data.DataDefinition; -import org.openmrs.module.reporting.data.converter.BirthdateConverter; -import org.openmrs.module.reporting.data.converter.DataConverter; -import org.openmrs.module.reporting.data.converter.ObjectFormatter; -import org.openmrs.module.reporting.data.converter.ObsValueConverter; +import org.openmrs.module.reporting.data.converter.*; +import org.openmrs.module.reporting.data.encounter.definition.EncounterDatetimeDataDefinition; import org.openmrs.module.reporting.data.patient.definition.ConvertedPatientDataDefinition; import org.openmrs.module.reporting.data.patient.definition.EncountersForPatientDataDefinition; import org.openmrs.module.reporting.data.patient.definition.PatientIdentifierDataDefinition; @@ -61,6 +61,8 @@ @Builds({ "kenyaemr.ehrReports.report.240" }) public class SetupMOH240LabReportBuilder extends AbstractHybridReportBuilder { + public static final String ENC_DATE_FORMAT = "yyyy/MM/dd"; + @Override protected Mapped buildCohort(HybridReportDescriptor hybridReportDescriptor, PatientDataSetDefinition patientDataSetDefinition) { @@ -102,50 +104,28 @@ private PatientDataSetDefinition LabRegister() { dsd.addColumn("id", new PersonIdDataDefinition(), ""); dsd.addColumn("identifier", identifierDef, ""); - dsd.addColumn("Date", getEncounterDate(), "onOrAfter=${startDate},onOrBefore=${endDate+23h}", - new EncounterDatetimeConverter()); + //dsd.addColumn("Date", new EncounterDatetimeDataDefinition(),"", new DateConverter(ENC_DATE_FORMAT)); dsd.addColumn("Name", nameDef, ""); dsd.addColumn("Sex", new GenderDataDefinition(), "", null); dsd.addColumn("DOB", new BirthdateDataDefinition(), "", new BirthdateConverter("yyyy-MM-dd")); dsd.addColumn("age", new AgeDataDefinition(), ""); - dsd.addColumn("village", getAddress(), "", null); + dsd.addColumn("village", new CalculationDataDefinition("Village/Estate/Landmark", new PersonAddressCalculation()), "",new RDQACalculationResultConverter()); dsd.addColumn("telephone", new PersonAttributeDataDefinition(personAttributeType), "", null); return dsd; } - - private DataDefinition getEncounterDate() { - EncounterType labEncounter = Context.getEncounterService().getEncounterTypeByUuid( - "17a381d1-7e29-406a-b782-aa903b963c28"); - EncountersForPatientDataDefinition dsd = new EncountersForPatientDataDefinition(); - dsd.addParameter(new Parameter("onOrAfter", "After Date", Date.class)); - dsd.addParameter(new Parameter("onOrBefore", "Before Date", Date.class)); - dsd.setTypes(Arrays.asList(labEncounter)); - dsd.setWhich(TimeQualifier.LAST); - return dsd; - } - - private CohortDefinition getLabOrderEncounter() { - EncounterType labEncounter = Context.getEncounterService().getEncounterTypeByUuid( - "17a381d1-7e29-406a-b782-aa903b963c28"); + private CohortDefinition getLabOrderEncounter() { SqlCohortDefinition sqlEncounterQuery = new SqlCohortDefinition(); sqlEncounterQuery.setName("Get unique lab encounter types"); sqlEncounterQuery.addParameter(new Parameter("startDate", "Start Date", Date.class)); sqlEncounterQuery.addParameter(new Parameter("endDate", "End Date", Date.class)); sqlEncounterQuery - .setQuery("SELECT p.patient_id FROM patient p INNER JOIN encounter e ON p.patient_id=e.patient_id " - + " WHERE e.encounter_datetime BETWEEN :startDate AND :endDate AND e.voided=0 AND p.voided = 0 " - + " AND e.encounter_type IN(" + labEncounter.getEncounterTypeId() + ")"); + .setQuery("SELECT d.patient_id FROM kenyaemr_etl.etl_patient_demographics d\n" + + " INNER JOIN kenyaemr_etl.etl_laboratory_extract x ON x.patient_id = d.patient_id\n" + + " AND date(x.visit_date) BETWEEN :startDate AND :endDate;"); return sqlEncounterQuery; } - public static DataDefinition getAddress() { - SqlPatientDataDefinition sqlPdfn = new SqlPatientDataDefinition(); - sqlPdfn.setName("Address"); - sqlPdfn.setQuery("SELECT p.person_id, REPLACE(CONCAT_WS(' ',pa.address1,pa.address2,pa.city_village,pa.address3,pa.address5,pa.address6), ',','') AS address FROM person p " - + " INNER JOIN person_address pa ON p.person_id=pa.person_id "); - return sqlPdfn; - } -} \ No newline at end of file +} diff --git a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/library/MOH706/Moh706LabCohortLibrary.java b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/library/MOH706/Moh706LabCohortLibrary.java index 7791f69065..cc66a4b09d 100644 --- a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/library/MOH706/Moh706LabCohortLibrary.java +++ b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/library/MOH706/Moh706LabCohortLibrary.java @@ -24,13 +24,13 @@ public CohortDefinition getAllUrineAnalysisGlucoseTestsPositives() { sql.setName("Get urine analysis patients - glucose"); sql.addParameter(new Parameter("startDate", "Start Date", Date.class)); sql.addParameter(new Parameter("endDate", "End Date", Date.class)); - sql.setQuery("SELECT p.patient_id FROM patient p INNER JOIN encounter e ON p.patient_id = e.patient_id INNER JOIN obs o ON e.encounter_id = o.encounter_id " - + " WHERE p.voided=0 AND e.voided = 0 AND o.voided = 0 AND o.concept_id in (159734) AND o.value_coded IN (703,1874,1362,1363,1364,1365) " - + " AND e.encounter_datetime BETWEEN :startDate AND :endDate " - + " UNION " - + " SELECT p.patient_id FROM patient p INNER JOIN encounter e on p.patient_id = e.patient_id INNER JOIN obs o ON e.encounter_id = o.encounter_id " - + " WHERE p.voided=0 AND e.voided = 0 AND o.voided = 0 AND o.concept_id in (159733) AND o.value_numeric IS NOT NULL " - + " AND e.encounter_datetime BETWEEN :startDate AND :endDate " + sql.setQuery("SELECT d.patient_id FROM kenyaemr_etl.etl_patient_demographics d\n" + + " INNER JOIN kenyaemr_etl.etl_laboratory_extract x ON x.patient_id = d.patient_id\n" + + " WHERE x.lab_test = 1305 AND x.test_result = 1302 AND date(x.visit_date) BETWEEN :startDate AND :endDate\n" + + " UNION\n" + + " SELECT d.patient_id FROM kenyaemr_etl.etl_patient_demographics d\n" + + " INNER JOIN kenyaemr_etl.etl_laboratory_extract x ON x.patient_id = d.patient_id\n" + + " WHERE x.lab_test = 856 AND x.test_result IS NOT NULL AND date(x.visit_date) BETWEEN :startDate AND :endDate;" ); return sql; From 9d869088ff6831eb234f57ef06aecb26e027c495 Mon Sep 17 00:00:00 2001 From: patryllus Date: Thu, 18 Apr 2024 18:16:19 +0300 Subject: [PATCH 3/3] Removing duplicated EncounterDatetimeConverter class, cleaning up moh240 --- .../common/SetupMOH240LabReportBuilder.java | 26 +++-------- .../converter/EncounterDatetimeConverter.java | 46 ------------------- 2 files changed, 6 insertions(+), 66 deletions(-) delete mode 100644 api/src/main/java/org/openmrs/module/kenyaemr/reporting/data/converter/EncounterDatetimeConverter.java diff --git a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH240LabReportBuilder.java b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH240LabReportBuilder.java index 722afff29b..8cd8227038 100644 --- a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH240LabReportBuilder.java +++ b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/builder/common/SetupMOH240LabReportBuilder.java @@ -9,8 +9,6 @@ */ package org.openmrs.module.kenyaemr.reporting.builder.common; -import org.openmrs.Concept; -import org.openmrs.EncounterType; import org.openmrs.PatientIdentifierType; import org.openmrs.PersonAttributeType; import org.openmrs.api.context.Context; @@ -20,37 +18,25 @@ import org.openmrs.module.kenyacore.report.builder.AbstractHybridReportBuilder; import org.openmrs.module.kenyacore.report.builder.Builds; import org.openmrs.module.kenyacore.report.data.patient.definition.CalculationDataDefinition; -import org.openmrs.module.kenyaemr.Metadata; -import org.openmrs.module.kenyaemr.calculation.library.TelephoneNumberCalculation; import org.openmrs.module.kenyaemr.calculation.library.mchcs.PersonAddressCalculation; import org.openmrs.module.kenyaemr.metadata.CommonMetadata; import org.openmrs.module.kenyaemr.reporting.calculation.converter.RDQACalculationResultConverter; -import org.openmrs.module.kenyaemr.reporting.data.converter.CalculationResultConverter; -import org.openmrs.module.kenyaemr.reporting.data.converter.EncounterDatetimeConverter; import org.openmrs.module.reporting.cohort.definition.CohortDefinition; import org.openmrs.module.reporting.cohort.definition.SqlCohortDefinition; -import org.openmrs.module.reporting.common.TimeQualifier; import org.openmrs.module.reporting.data.DataDefinition; -import org.openmrs.module.reporting.data.converter.*; +import org.openmrs.module.reporting.data.converter.BirthdateConverter; +import org.openmrs.module.reporting.data.converter.DataConverter; +import org.openmrs.module.reporting.data.converter.DateConverter; +import org.openmrs.module.reporting.data.converter.ObjectFormatter; import org.openmrs.module.reporting.data.encounter.definition.EncounterDatetimeDataDefinition; import org.openmrs.module.reporting.data.patient.definition.ConvertedPatientDataDefinition; -import org.openmrs.module.reporting.data.patient.definition.EncountersForPatientDataDefinition; import org.openmrs.module.reporting.data.patient.definition.PatientIdentifierDataDefinition; -import org.openmrs.module.reporting.data.patient.definition.SqlPatientDataDefinition; -import org.openmrs.module.reporting.data.person.definition.AgeDataDefinition; -import org.openmrs.module.reporting.data.person.definition.BirthdateDataDefinition; -import org.openmrs.module.reporting.data.person.definition.ConvertedPersonDataDefinition; -import org.openmrs.module.reporting.data.person.definition.GenderDataDefinition; -import org.openmrs.module.reporting.data.person.definition.ObsForPersonDataDefinition; -import org.openmrs.module.reporting.data.person.definition.PersonAttributeDataDefinition; -import org.openmrs.module.reporting.data.person.definition.PersonIdDataDefinition; -import org.openmrs.module.reporting.data.person.definition.PreferredNameDataDefinition; +import org.openmrs.module.reporting.data.person.definition.*; import org.openmrs.module.reporting.dataset.definition.DataSetDefinition; import org.openmrs.module.reporting.dataset.definition.PatientDataSetDefinition; import org.openmrs.module.reporting.evaluation.parameter.Mapped; import org.openmrs.module.reporting.evaluation.parameter.Parameter; import org.openmrs.module.reporting.report.definition.ReportDefinition; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Arrays; @@ -104,7 +90,7 @@ private PatientDataSetDefinition LabRegister() { dsd.addColumn("id", new PersonIdDataDefinition(), ""); dsd.addColumn("identifier", identifierDef, ""); - //dsd.addColumn("Date", new EncounterDatetimeDataDefinition(),"", new DateConverter(ENC_DATE_FORMAT)); + //dsd.addColumn("Date", new EncounterDatetimeDataDefinition(),"", new DateConverter(ENC_DATE_FORMAT)); dsd.addColumn("Name", nameDef, ""); dsd.addColumn("Sex", new GenderDataDefinition(), "", null); dsd.addColumn("DOB", new BirthdateDataDefinition(), "", new BirthdateConverter("yyyy-MM-dd")); diff --git a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/data/converter/EncounterDatetimeConverter.java b/api/src/main/java/org/openmrs/module/kenyaemr/reporting/data/converter/EncounterDatetimeConverter.java deleted file mode 100644 index c00812ffc3..0000000000 --- a/api/src/main/java/org/openmrs/module/kenyaemr/reporting/data/converter/EncounterDatetimeConverter.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * This Source Code Form is subject to the terms of the Mozilla Public License, - * v. 2.0. If a copy of the MPL was not distributed with this file, You can - * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under - * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. - * - * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS - * graphic logo is a trademark of OpenMRS Inc. - */ -package org.openmrs.module.kenyaemr.reporting.data.converter; - -import org.openmrs.Encounter; -import org.openmrs.Obs; -import org.openmrs.module.reporting.data.converter.DataConverter; - -import java.text.Format; -import java.text.SimpleDateFormat; -import java.util.Date; - -public class EncounterDatetimeConverter implements DataConverter { - - public Object convert(Object original) { - Encounter encounter = (Encounter) original; - - if (encounter == null) { - return null; - } else if (encounter.getDateCreated() != null) { - return formatDates(encounter.getDateCreated(), "dd-MM-yyyy HH:mm:ss"); - } - return null; - } - - public Class getInputDataType() { - return Encounter.class; - } - - public Class getDataType() { - return Object.class; - } - - public static String formatDates(Date date, String format) { - Format formatter = new SimpleDateFormat(format); - String s = formatter.format(date); - return s; - } -}