From d6376d11ec721a2d5a5b9ad6936232da5fb439e4 Mon Sep 17 00:00:00 2001 From: steliomo Date: Wed, 6 Nov 2019 16:09:11 +0200 Subject: [PATCH] REPORT-103:Add Erin 2 Months Report. --- .../cohorts/Eri2MonthsCohortQueries.java | 287 +++++++++++ .../library/datasets/Eri2MonthsDataset.java | 53 +- .../library/datasets/Eri4MonthsDataset.java | 304 +++++++----- .../dimensions/EptsCommonDimension.java | 136 +++++ .../dimensions/Eri2MonthsDamision.java | 153 ++++++ .../queries/Eri2MonthsQueriesInterface.java | 463 ++++++++++++++++++ .../reports/SetupCombinedImErReport.java | 130 ++--- api/src/main/resources/IM_ER_Report.xls | Bin 129536 -> 101888 bytes 8 files changed, 1314 insertions(+), 212 deletions(-) create mode 100644 api/src/main/java/org/openmrs/module/eptsreports/reporting/library/dimensions/Eri2MonthsDamision.java create mode 100644 api/src/main/java/org/openmrs/module/eptsreports/reporting/library/queries/Eri2MonthsQueriesInterface.java diff --git a/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/cohorts/Eri2MonthsCohortQueries.java b/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/cohorts/Eri2MonthsCohortQueries.java index 6445172c51..b287d17edd 100644 --- a/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/cohorts/Eri2MonthsCohortQueries.java +++ b/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/cohorts/Eri2MonthsCohortQueries.java @@ -15,6 +15,8 @@ import org.openmrs.Location; import org.openmrs.module.eptsreports.metadata.HivMetadata; import org.openmrs.module.eptsreports.reporting.library.queries.Eri2MonthsQueries; +import org.openmrs.module.eptsreports.reporting.library.queries.Eri2MonthsQueriesInterface; +import org.openmrs.module.eptsreports.reporting.library.queries.TxNewQueries; import org.openmrs.module.eptsreports.reporting.utils.EptsReportUtils; import org.openmrs.module.reporting.cohort.definition.CohortDefinition; import org.openmrs.module.reporting.cohort.definition.CompositionCohortDefinition; @@ -32,6 +34,8 @@ public class Eri2MonthsCohortQueries { @Autowired private EriCohortQueries eriCohortQueries; + @Autowired private GenericCohortQueries genericCohorts; + /** * C * @@ -121,6 +125,11 @@ public CohortDefinition getPatientsWhoDidNotPickDrugsOnTheirSecondVisit() { return cd; } + public CohortDefinition + getPatientsStartedArtLastMonthWith2PickupsOrConsultationWithin33DaysExcludingDeadAndTransferedOutAndIn() { + return null; + } + /** * Get patients who picked up drugs on their second visit A and B and C and NOt (dead and * tarnsfers) @@ -226,6 +235,7 @@ public CohortDefinition getPatientsWhoInitiatedArtButTransferredOut() { cd.addParameter(new Parameter("cohortEndDate", "Cohort End Date", Date.class)); cd.addParameter(new Parameter("reportingEndDate", "Reporting End Date", Date.class)); cd.addParameter(new Parameter("location", "Location", Location.class)); + cd.addSearch( "initiatedArtAndNotTransferIns", EptsReportUtils.map( @@ -243,4 +253,281 @@ public CohortDefinition getPatientsWhoInitiatedArtButTransferredOut() { cd.setCompositionString("initiatedArtAndNotTransferIns AND transferredOut"); return cd; } + + public CohortDefinition getEri2MonthsCompositionCohort(final String cohortName) { + final CompositionCohortDefinition eri2MonthsCompositionCohort = + new CompositionCohortDefinition(); + + eri2MonthsCompositionCohort.setName(cohortName); + eri2MonthsCompositionCohort.addParameter(new Parameter("startDate", "Start Date", Date.class)); + eri2MonthsCompositionCohort.addParameter(new Parameter("endDate", "End Date", Date.class)); + eri2MonthsCompositionCohort.addParameter(new Parameter("location", "location", Location.class)); + + final String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; + + eri2MonthsCompositionCohort.addSearch( + "START-ART-2-MONTHS", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientEnrolledInART2Months", + Eri2MonthsQueriesInterface.QUERY.findPatientsWhoStartArtOneMonth), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "TRANSFERED-IN", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWithAProgramStateMarkedAsTransferedInInAPeriod", + TxNewQueries.QUERY.findPatientsWithAProgramStateMarkedAsTransferedInInAPeriod), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "TRANSFERED-IN-AND-IN-ART-MASTER-CARD", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWhoWhereMarkedAsTransferedInAndOnARTOnInAPeriodOnMasterCard", + TxNewQueries.QUERY + .findPatientsWhoWhereMarkedAsTransferedInAndOnARTOnInAPeriodOnMasterCard), + mappings)); + + eri2MonthsCompositionCohort.setCompositionString( + "START-ART-2-MONTHS NOT (TRANSFERED-IN OR TRANSFERED-IN-AND-IN-ART-MASTER-CARD)"); + return eri2MonthsCompositionCohort; + } + + public CohortDefinition getEri2MonthsPregnatCompositionCohort(final String cohortName) { + final CompositionCohortDefinition eri2MonthsCompositionCohort = + new CompositionCohortDefinition(); + + eri2MonthsCompositionCohort.setName(cohortName); + eri2MonthsCompositionCohort.addParameter(new Parameter("startDate", "Start Date", Date.class)); + eri2MonthsCompositionCohort.addParameter(new Parameter("endDate", "End Date", Date.class)); + eri2MonthsCompositionCohort.addParameter(new Parameter("location", "location", Location.class)); + + final String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; + + eri2MonthsCompositionCohort.addSearch( + "START-ART-2-MONTHS", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientEnrolledInART2Months", + Eri2MonthsQueriesInterface.QUERY.findPatientsWhoStartArtOneMonth), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "TRANSFERED-IN", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWithAProgramStateMarkedAsTransferedInInAPeriod", + TxNewQueries.QUERY.findPatientsWithAProgramStateMarkedAsTransferedInInAPeriod), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "TRANSFERED-IN-AND-IN-ART-MASTER-CARD", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWhoWhereMarkedAsTransferedInAndOnARTOnInAPeriodOnMasterCard", + TxNewQueries.QUERY + .findPatientsWhoWhereMarkedAsTransferedInAndOnARTOnInAPeriodOnMasterCard), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "PREGNANT", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientsThatAreFemaleAndWereMarkedAsPregnantInTheInitialConsultationOrFollowUpConsultationAndMasterCard", + Eri2MonthsQueriesInterface.QUERY + .patientsThatAreFemaleAndWereMarkedAsPregnantInTheInitialConsultationOrFollowUpConsultationAndMasterCard), + mappings)); + + eri2MonthsCompositionCohort.setCompositionString( + "START-ART-2-MONTHS AND PREGNANT NOT (TRANSFERED-IN OR TRANSFERED-IN-AND-IN-ART-MASTER-CARD)"); + + return eri2MonthsCompositionCohort; + } + + public CohortDefinition getEri2MonthsBrestfeetingCompositionCohort(final String cohortName) { + final CompositionCohortDefinition eri2MonthsCompositionCohort = + new CompositionCohortDefinition(); + + eri2MonthsCompositionCohort.setName(cohortName); + eri2MonthsCompositionCohort.addParameter(new Parameter("startDate", "Start Date", Date.class)); + eri2MonthsCompositionCohort.addParameter(new Parameter("endDate", "End Date", Date.class)); + eri2MonthsCompositionCohort.addParameter(new Parameter("location", "location", Location.class)); + + final String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; + + eri2MonthsCompositionCohort.addSearch( + "START-ART-2-MONTHS", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientEnrolledInART2Months", + Eri2MonthsQueriesInterface.QUERY.findPatientsWhoStartArtOneMonth), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "TRANSFERED-IN", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWithAProgramStateMarkedAsTransferedInInAPeriod", + TxNewQueries.QUERY.findPatientsWithAProgramStateMarkedAsTransferedInInAPeriod), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "TRANSFERED-IN-AND-IN-ART-MASTER-CARD", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWhoWhereMarkedAsTransferedInAndOnARTOnInAPeriodOnMasterCard", + TxNewQueries.QUERY + .findPatientsWhoWhereMarkedAsTransferedInAndOnARTOnInAPeriodOnMasterCard), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "BRESTFEETING", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientsThatAreFemaleAndWereMarkedAsBrestfeetingInTheInitialConsultationOrFollowUpConsultationAndMasterCard", + Eri2MonthsQueriesInterface.QUERY + .patientsThatAreFemaleAndWereMarkedAsBrestfeetingInTheInitialConsultationOrFollowUpConsultationAndMasterCard), + mappings)); + + eri2MonthsCompositionCohort.setCompositionString( + "START-ART-2-MONTHS AND BRESTFEETING NOT (TRANSFERED-IN OR TRANSFERED-IN-AND-IN-ART-MASTER-CARD)"); + + return eri2MonthsCompositionCohort; + } + + public CohortDefinition getEri2MonthsAdultCompositionCohort(final String cohortName) { + final CompositionCohortDefinition eri2MonthsCompositionCohort = + new CompositionCohortDefinition(); + + eri2MonthsCompositionCohort.setName(cohortName); + eri2MonthsCompositionCohort.addParameter(new Parameter("startDate", "Start Date", Date.class)); + eri2MonthsCompositionCohort.addParameter(new Parameter("endDate", "End Date", Date.class)); + eri2MonthsCompositionCohort.addParameter(new Parameter("location", "location", Location.class)); + + final String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; + + eri2MonthsCompositionCohort.addSearch( + "START-ART-2-MONTHS", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientEnrolledInART2Months", + Eri2MonthsQueriesInterface.QUERY.findPatientsWhoStartArtOneMonth), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "TRANSFERED-IN", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWithAProgramStateMarkedAsTransferedInInAPeriod", + TxNewQueries.QUERY.findPatientsWithAProgramStateMarkedAsTransferedInInAPeriod), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "TRANSFERED-IN-AND-IN-ART-MASTER-CARD", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWhoWhereMarkedAsTransferedInAndOnARTOnInAPeriodOnMasterCard", + TxNewQueries.QUERY + .findPatientsWhoWhereMarkedAsTransferedInAndOnARTOnInAPeriodOnMasterCard), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "BRESTFEETING", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientsThatAreFemaleAndWereMarkedAsBrestfeetingInTheInitialConsultationOrFollowUpConsultationAndMasterCard", + Eri2MonthsQueriesInterface.QUERY + .patientsThatAreFemaleAndWereMarkedAsBrestfeetingInTheInitialConsultationOrFollowUpConsultationAndMasterCard), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "PREGNANT", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientsThatAreFemaleAndWereMarkedAsPregnantInTheInitialConsultationOrFollowUpConsultationAndMasterCard", + Eri2MonthsQueriesInterface.QUERY + .patientsThatAreFemaleAndWereMarkedAsPregnantInTheInitialConsultationOrFollowUpConsultationAndMasterCard), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "ADULT", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientsThatAreAdult", Eri2MonthsQueriesInterface.QUERY.patientsThatAreAdult), + mappings)); + + eri2MonthsCompositionCohort.setCompositionString( + "START-ART-2-MONTHS AND ADULT NOT (TRANSFERED-IN OR TRANSFERED-IN-AND-IN-ART-MASTER-CARD OR PREGNANT OR BRESTFEETING)"); + + return eri2MonthsCompositionCohort; + } + + public CohortDefinition getEri2MonthsChildCompositionCohort(final String cohortName) { + final CompositionCohortDefinition eri2MonthsCompositionCohort = + new CompositionCohortDefinition(); + + eri2MonthsCompositionCohort.setName(cohortName); + eri2MonthsCompositionCohort.addParameter(new Parameter("startDate", "Start Date", Date.class)); + eri2MonthsCompositionCohort.addParameter(new Parameter("endDate", "End Date", Date.class)); + eri2MonthsCompositionCohort.addParameter(new Parameter("location", "location", Location.class)); + + final String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; + + eri2MonthsCompositionCohort.addSearch( + "START-ART-2-MONTHS", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientEnrolledInART2Months", + Eri2MonthsQueriesInterface.QUERY.findPatientsWhoStartArtOneMonth), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "TRANSFERED-IN", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWithAProgramStateMarkedAsTransferedInInAPeriod", + TxNewQueries.QUERY.findPatientsWithAProgramStateMarkedAsTransferedInInAPeriod), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "TRANSFERED-IN-AND-IN-ART-MASTER-CARD", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWhoWhereMarkedAsTransferedInAndOnARTOnInAPeriodOnMasterCard", + TxNewQueries.QUERY + .findPatientsWhoWhereMarkedAsTransferedInAndOnARTOnInAPeriodOnMasterCard), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "BRESTFEETING", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientsThatAreFemaleAndWereMarkedAsBrestfeetingInTheInitialConsultationOrFollowUpConsultationAndMasterCard", + Eri2MonthsQueriesInterface.QUERY + .patientsThatAreFemaleAndWereMarkedAsBrestfeetingInTheInitialConsultationOrFollowUpConsultationAndMasterCard), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "PREGNANT", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientsThatAreFemaleAndWereMarkedAsPregnantInTheInitialConsultationOrFollowUpConsultationAndMasterCard", + Eri2MonthsQueriesInterface.QUERY + .patientsThatAreFemaleAndWereMarkedAsPregnantInTheInitialConsultationOrFollowUpConsultationAndMasterCard), + mappings)); + + eri2MonthsCompositionCohort.addSearch( + "CHILD", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "patientsThatAreChild", Eri2MonthsQueriesInterface.QUERY.patientsThatAreChild), + mappings)); + + eri2MonthsCompositionCohort.setCompositionString( + "START-ART-2-MONTHS AND CHILD NOT (TRANSFERED-IN OR TRANSFERED-IN-AND-IN-ART-MASTER-CARD OR PREGNANT OR BRESTFEETING)"); + + return eri2MonthsCompositionCohort; + } } diff --git a/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/datasets/Eri2MonthsDataset.java b/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/datasets/Eri2MonthsDataset.java index 39cf460292..fd4397fa51 100644 --- a/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/datasets/Eri2MonthsDataset.java +++ b/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/datasets/Eri2MonthsDataset.java @@ -15,7 +15,7 @@ import java.util.Arrays; import java.util.List; -import org.openmrs.module.eptsreports.reporting.library.cohorts.EriCohortQueries; +import org.openmrs.module.eptsreports.reporting.library.cohorts.Eri2MonthsCohortQueries; import org.openmrs.module.eptsreports.reporting.library.dimensions.EptsCommonDimension; import org.openmrs.module.eptsreports.reporting.library.indicators.EptsGeneralIndicator; import org.openmrs.module.eptsreports.reporting.utils.EptsReportUtils; @@ -31,19 +31,18 @@ public class Eri2MonthsDataset extends BaseDataSet { @Autowired private EptsGeneralIndicator eptsGeneralIndicator; - @Autowired private EriCohortQueries eriCohortQueries; + @Autowired private Eri2MonthsCohortQueries eri2MonthsCohortQueries; public DataSetDefinition constructEri2MonthsDatset() { CohortIndicatorDataSetDefinition dsd = new CohortIndicatorDataSetDefinition(); - String mappingsInd = - "cohortStartDate=${endDate-2m+1d},cohortEndDate=${endDate-1m},reportingEndDate=${endDate},location=${location}"; + String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; dsd.setName("ERI-2months Data Set"); dsd.addParameters(getParameters()); // apply disaggregations dsd.addDimension( - "state", EptsReportUtils.map(eptsCommonDimension.getEri2MonthsDimension(), mappingsInd)); + "state", EptsReportUtils.map(eptsCommonDimension.getEri2MonthsDimension2(), mappings)); addRow( dsd, @@ -52,9 +51,12 @@ public DataSetDefinition constructEri2MonthsDatset() { EptsReportUtils.map( eptsGeneralIndicator.getIndicator( "All patients", - EptsReportUtils.map(eriCohortQueries.getAllPatientsWhoInitiatedArt(), mappingsInd)), + EptsReportUtils.map( + eri2MonthsCohortQueries.getEri2MonthsCompositionCohort("All patients"), + mappings)), mappings), get2MonthsRetentionColumns()); + addRow( dsd, "R22", @@ -62,9 +64,12 @@ public DataSetDefinition constructEri2MonthsDatset() { EptsReportUtils.map( eptsGeneralIndicator.getIndicator( "Pregnant women", - EptsReportUtils.map(eriCohortQueries.getPregnantWomenRetainedOnArt(), mappingsInd)), + EptsReportUtils.map( + eri2MonthsCohortQueries.getEri2MonthsPregnatCompositionCohort("Pregnant"), + mappings)), mappings), get2MonthsRetentionColumns()); + addRow( dsd, "R23", @@ -72,28 +77,52 @@ public DataSetDefinition constructEri2MonthsDatset() { EptsReportUtils.map( eptsGeneralIndicator.getIndicator( "Breastfeeding women", - EptsReportUtils.map(eriCohortQueries.getBreastfeedingWomenRetained(), mappingsInd)), + EptsReportUtils.map( + eri2MonthsCohortQueries.getEri2MonthsBrestfeetingCompositionCohort( + "BrestFeeting"), + mappings)), mappings), get2MonthsRetentionColumns()); + addRow( + dsd, + "R23", + "Breastfeeding women retained on ART 2 months after ART initiation", + EptsReportUtils.map( + eptsGeneralIndicator.getIndicator( + "Breastfeeding women", + EptsReportUtils.map( + eri2MonthsCohortQueries.getEri2MonthsBrestfeetingCompositionCohort( + "BrestFeeting"), + mappings)), + mappings), + get2MonthsRetentionColumns()); + addRow( dsd, "R24", - "Children (0-14, excluding pregnant and breastfeeding women) retained on ART 2 months after ART initiation", + "Children (0-14, excluding pregnant and breastfeeding women) retained on ART 2 months", EptsReportUtils.map( eptsGeneralIndicator.getIndicator( "Children", - EptsReportUtils.map(eriCohortQueries.getChildrenRetained(), mappingsInd)), + EptsReportUtils.map( + eri2MonthsCohortQueries.getEri2MonthsChildCompositionCohort("Children"), + mappings)), mappings), get2MonthsRetentionColumns()); + addRow( dsd, "R25", - "Adults (15+, excluding pregnant and breastfeeding women) retained on ART 2 months after ART initiation", + "Adults (15+, excluding pregnant and breastfeeding women) retained on ART 2 months", EptsReportUtils.map( eptsGeneralIndicator.getIndicator( - "Adults", EptsReportUtils.map(eriCohortQueries.getAdultsRetained(), mappingsInd)), + "Adult", + EptsReportUtils.map( + eri2MonthsCohortQueries.getEri2MonthsAdultCompositionCohort("Adult"), + mappings)), mappings), get2MonthsRetentionColumns()); + return dsd; } diff --git a/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/datasets/Eri4MonthsDataset.java b/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/datasets/Eri4MonthsDataset.java index 7d50460e65..899769a2e2 100644 --- a/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/datasets/Eri4MonthsDataset.java +++ b/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/datasets/Eri4MonthsDataset.java @@ -15,7 +15,6 @@ import java.util.Arrays; import java.util.List; - import org.openmrs.module.eptsreports.reporting.library.cohorts.Eri4MonthsCohortQueries; import org.openmrs.module.eptsreports.reporting.library.cohorts.GenericCohortQueries; import org.openmrs.module.eptsreports.reporting.library.cohorts.TxNewCohortQueries; @@ -34,138 +33,173 @@ @Component public class Eri4MonthsDataset extends BaseDataSet { - @Autowired - private EptsGeneralIndicator eptsGeneralIndicator; - - @Autowired - private Eri4MonthsDimensions eri4MonthsDimensions; - - @Autowired - private TxNewCohortQueries txNewCohortQueries; - - @Autowired - private GenericCohortQueries genericCohortQueries; - - @Autowired - private Eri4MonthsCohortQueries eri4MonthsCohortQueries; - - public DataSetDefinition constructEri4MonthsDataset() { - - final CohortIndicatorDataSetDefinition dataSetDefinition = new CohortIndicatorDataSetDefinition(); - - final String cohortPeriodMappings = "cohortStartDate=${endDate-5m+1d},cohortEndDate=${endDate-4m},location=${location}"; - - final String reportingPeriodMappings = "startDate=${startDate},endDate=${endDate},location=${location}"; - - dataSetDefinition.setName("ERI-4months Data Set"); - - dataSetDefinition.addParameters(this.getParameters()); - - dataSetDefinition.addDimension("state", - EptsReportUtils.map(this.eri4MonthsDimensions.getDimension(), cohortPeriodMappings)); - - this.addColumns(dataSetDefinition, "01", - EptsReportUtils.map( - this.eptsGeneralIndicator.getIndicator("all patients", - EptsReportUtils.map( - this.txNewCohortQueries.getTxNewCompositionCohort("patientNewlyEnrolledInART"), - "startDate=${endDate-5m+1d},endDate=${endDate-4m},location=${location}")), - reportingPeriodMappings), - this.get4MonthsRetentionColumns()); - - this.addColumns(dataSetDefinition, "02", - EptsReportUtils.map(this.eptsGeneralIndicator.getIndicator("all patients in treatment", - EptsReportUtils.map( - this.genericCohortQueries.generalSql("patientsInTreatment", - Eri4MonthsQueries - .findPatientsWhoHaveEitherClinicalConsultationOrDrugsPickupBetween61And120ForASpecificPatientType( - Eri4mType.IN_TREATMENT)), - "endDate=${endDate},location=${location}")), - reportingPeriodMappings), - this.get4MonthsRetentionColumns()); - - this.addColumns(dataSetDefinition, "03", - EptsReportUtils - .map(this.eptsGeneralIndicator.getIndicator("all patients dead", - EptsReportUtils.map( - this.genericCohortQueries.generalSql("patientsDead", - Eri4MonthsQueries - .findPatientsWhoHaveEitherClinicalConsultationOrDrugsPickupBetween61And120ForASpecificPatientType( - Eri4mType.DEAD)), - "endDate=${endDate},location=${location}")), - reportingPeriodMappings), - this.get4MonthsRetentionColumns()); - - this.addColumns(dataSetDefinition, "04", - EptsReportUtils.map( - this.eptsGeneralIndicator.getIndicator("all patients who are lost follow up", - EptsReportUtils.map(this.eri4MonthsCohortQueries.findPatientsWhoAreLostFollowUp(), - cohortPeriodMappings + ",reportingEndDate=${endDate}")), - reportingPeriodMappings), - this.get4MonthsRetentionColumns()); - - this.addColumns(dataSetDefinition, "05", - EptsReportUtils.map(this.eptsGeneralIndicator.getIndicator("all patients in tranferred out", - EptsReportUtils.map( - this.genericCohortQueries.generalSql("patientsTransferredOut", - Eri4MonthsQueries - .findPatientsWhoHaveEitherClinicalConsultationOrDrugsPickupBetween61And120ForASpecificPatientType( - Eri4mType.TRANFERED_OUT)), - "endDate=${endDate},location=${location}")), - reportingPeriodMappings), - this.get4MonthsRetentionColumns()); - - this.addColumns(dataSetDefinition, "06", - EptsReportUtils.map(this.eptsGeneralIndicator.getIndicator("all patients who stopped treatment", - EptsReportUtils.map( - this.genericCohortQueries.generalSql("patientsStoppedTreatment", - Eri4MonthsQueries - .findPatientsWhoHaveEitherClinicalConsultationOrDrugsPickupBetween61And120ForASpecificPatientType( - Eri4mType.SPTOPPED_TREATMENT)), - "endDate=${endDate},location=${location}")), - reportingPeriodMappings), - this.get4MonthsRetentionColumns()); - - this.addColumns(dataSetDefinition, "07", - EptsReportUtils.map(this.eptsGeneralIndicator.getIndicator("all patients defaulters", - EptsReportUtils.map( - this.genericCohortQueries.generalSql("patientsDefaulters", - Eri4MonthsQueries - .findPatientsWhoHaveEitherClinicalConsultationOrDrugsPickupBetween61And120ForASpecificPatientType( - Eri4mType.DEFAULTER)), - "endDate=${endDate},location=${location}")), - reportingPeriodMappings), - this.get4MonthsRetentionColumns()); - - return dataSetDefinition; - } - - private List get4MonthsRetentionColumns() { - - final ColumnParameters allPatients = new ColumnParameters("initiated ART", "Initiated ART", "", "I"); - final ColumnParameters pregnantWoman = new ColumnParameters("pregnant woman", "Pregnant Woman", - "state=PREGNANT", "I"); - final ColumnParameters brestfedding = new ColumnParameters("breastfeeding", "Breastfeeding", - "state=BREASTFEEDING", "I"); - final ColumnParameters children = new ColumnParameters("children", "Children", "state=CHILDREN", "I"); - final ColumnParameters adult = new ColumnParameters("adult", "Adult", "state=ADULT", "I"); - - return Arrays.asList(allPatients, pregnantWoman, brestfedding, children, adult); - } - - private void addColumns(final CohortIndicatorDataSetDefinition definition, final String columNumber, - final Mapped indicator, final List columns) { - - int position = 1; - - for (final ColumnParameters column : columns) { - - final String name = column.getColumn() + "" + position + "-" + columNumber; - final String label = column.getLabel() + "(" + name + ")"; - - definition.addColumn(name, label, indicator, column.getDimensions()); - - position++; - } - } + @Autowired private EptsGeneralIndicator eptsGeneralIndicator; + + @Autowired private Eri4MonthsDimensions eri4MonthsDimensions; + + @Autowired private TxNewCohortQueries txNewCohortQueries; + + @Autowired private GenericCohortQueries genericCohortQueries; + + @Autowired private Eri4MonthsCohortQueries eri4MonthsCohortQueries; + + public DataSetDefinition constructEri4MonthsDataset() { + + final CohortIndicatorDataSetDefinition dataSetDefinition = + new CohortIndicatorDataSetDefinition(); + + final String cohortPeriodMappings = + "cohortStartDate=${endDate-5m+1d},cohortEndDate=${endDate-4m},location=${location}"; + + final String reportingPeriodMappings = + "startDate=${startDate},endDate=${endDate},location=${location}"; + + dataSetDefinition.setName("ERI-4months Data Set"); + + dataSetDefinition.addParameters(this.getParameters()); + + dataSetDefinition.addDimension( + "state", + EptsReportUtils.map(this.eri4MonthsDimensions.getDimension(), cohortPeriodMappings)); + + this.addColumns( + dataSetDefinition, + "01", + EptsReportUtils.map( + this.eptsGeneralIndicator.getIndicator( + "all patients", + EptsReportUtils.map( + this.txNewCohortQueries.getTxNewCompositionCohort("patientNewlyEnrolledInART"), + "startDate=${endDate-5m+1d},endDate=${endDate-4m},location=${location}")), + reportingPeriodMappings), + this.get4MonthsRetentionColumns()); + + this.addColumns( + dataSetDefinition, + "02", + EptsReportUtils.map( + this.eptsGeneralIndicator.getIndicator( + "all patients in treatment", + EptsReportUtils.map( + this.genericCohortQueries.generalSql( + "patientsInTreatment", + Eri4MonthsQueries + .findPatientsWhoHaveEitherClinicalConsultationOrDrugsPickupBetween61And120ForASpecificPatientType( + Eri4mType.IN_TREATMENT)), + "endDate=${endDate},location=${location}")), + reportingPeriodMappings), + this.get4MonthsRetentionColumns()); + + this.addColumns( + dataSetDefinition, + "03", + EptsReportUtils.map( + this.eptsGeneralIndicator.getIndicator( + "all patients dead", + EptsReportUtils.map( + this.genericCohortQueries.generalSql( + "patientsDead", + Eri4MonthsQueries + .findPatientsWhoHaveEitherClinicalConsultationOrDrugsPickupBetween61And120ForASpecificPatientType( + Eri4mType.DEAD)), + "endDate=${endDate},location=${location}")), + reportingPeriodMappings), + this.get4MonthsRetentionColumns()); + + this.addColumns( + dataSetDefinition, + "04", + EptsReportUtils.map( + this.eptsGeneralIndicator.getIndicator( + "all patients who are lost follow up", + EptsReportUtils.map( + this.eri4MonthsCohortQueries.findPatientsWhoAreLostFollowUp(), + cohortPeriodMappings + ",reportingEndDate=${endDate}")), + reportingPeriodMappings), + this.get4MonthsRetentionColumns()); + + this.addColumns( + dataSetDefinition, + "05", + EptsReportUtils.map( + this.eptsGeneralIndicator.getIndicator( + "all patients in tranferred out", + EptsReportUtils.map( + this.genericCohortQueries.generalSql( + "patientsTransferredOut", + Eri4MonthsQueries + .findPatientsWhoHaveEitherClinicalConsultationOrDrugsPickupBetween61And120ForASpecificPatientType( + Eri4mType.TRANFERED_OUT)), + "endDate=${endDate},location=${location}")), + reportingPeriodMappings), + this.get4MonthsRetentionColumns()); + + this.addColumns( + dataSetDefinition, + "06", + EptsReportUtils.map( + this.eptsGeneralIndicator.getIndicator( + "all patients who stopped treatment", + EptsReportUtils.map( + this.genericCohortQueries.generalSql( + "patientsStoppedTreatment", + Eri4MonthsQueries + .findPatientsWhoHaveEitherClinicalConsultationOrDrugsPickupBetween61And120ForASpecificPatientType( + Eri4mType.SPTOPPED_TREATMENT)), + "endDate=${endDate},location=${location}")), + reportingPeriodMappings), + this.get4MonthsRetentionColumns()); + + this.addColumns( + dataSetDefinition, + "07", + EptsReportUtils.map( + this.eptsGeneralIndicator.getIndicator( + "all patients defaulters", + EptsReportUtils.map( + this.genericCohortQueries.generalSql( + "patientsDefaulters", + Eri4MonthsQueries + .findPatientsWhoHaveEitherClinicalConsultationOrDrugsPickupBetween61And120ForASpecificPatientType( + Eri4mType.DEFAULTER)), + "endDate=${endDate},location=${location}")), + reportingPeriodMappings), + this.get4MonthsRetentionColumns()); + + return dataSetDefinition; + } + + private List get4MonthsRetentionColumns() { + + final ColumnParameters allPatients = + new ColumnParameters("initiated ART", "Initiated ART", "", "I"); + final ColumnParameters pregnantWoman = + new ColumnParameters("pregnant woman", "Pregnant Woman", "state=PREGNANT", "I"); + final ColumnParameters brestfedding = + new ColumnParameters("breastfeeding", "Breastfeeding", "state=BREASTFEEDING", "I"); + final ColumnParameters children = + new ColumnParameters("children", "Children", "state=CHILDREN", "I"); + final ColumnParameters adult = new ColumnParameters("adult", "Adult", "state=ADULT", "I"); + + return Arrays.asList(allPatients, pregnantWoman, brestfedding, children, adult); + } + + private void addColumns( + final CohortIndicatorDataSetDefinition definition, + final String columNumber, + final Mapped indicator, + final List columns) { + + int position = 1; + + for (final ColumnParameters column : columns) { + + final String name = column.getColumn() + "" + position + "-" + columNumber; + final String label = column.getLabel() + "(" + name + ")"; + + definition.addColumn(name, label, indicator, column.getDimensions()); + + position++; + } + } } diff --git a/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/dimensions/EptsCommonDimension.java b/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/dimensions/EptsCommonDimension.java index accc2bfae2..cac7ffc41d 100644 --- a/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/dimensions/EptsCommonDimension.java +++ b/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/dimensions/EptsCommonDimension.java @@ -23,6 +23,7 @@ import org.openmrs.module.eptsreports.reporting.library.cohorts.TbPrevCohortQueries; import org.openmrs.module.eptsreports.reporting.library.cohorts.TxNewCohortQueries; import org.openmrs.module.eptsreports.reporting.library.queries.BreastfeedingQueries; +import org.openmrs.module.eptsreports.reporting.library.queries.Eri2MonthsQueriesInterface; import org.openmrs.module.eptsreports.reporting.library.queries.TxCurrQueries; import org.openmrs.module.eptsreports.reporting.library.queries.TxNewQueries; import org.openmrs.module.eptsreports.reporting.utils.AgeRange; @@ -54,6 +55,8 @@ public class EptsCommonDimension { @Autowired private BreastFeedingCohortQueries breastFeedingCohortQueries; + @Autowired private GenericCohortQueries genericCohorts; + /** * Gender dimension * @@ -150,6 +153,70 @@ public CohortDefinitionDimension maternityDimension() { return dim; } + /** + * Get the dimensions based on the patient states for ERI-4 months + * + * @return CohortDefinitionDimension + */ + public CohortDefinitionDimension getEri4MonthsDimension() { + final CohortDefinitionDimension dim = new CohortDefinitionDimension(); + dim.addParameter(new Parameter("cohortStartDate", "Cohort Start Date", Date.class)); + dim.addParameter(new Parameter("cohortEndDate", "Cohort End Date", Date.class)); + dim.addParameter(new Parameter("reportingStartDate", "Report Start Date", Date.class)); + dim.addParameter(new Parameter("reportingEndDate", "Report End Date", Date.class)); + dim.addParameter(new Parameter("location", "location", Location.class)); + dim.setName("Get patient states"); + + dim.addCohortDefinition( + "IART", + EptsReportUtils.map( + this.eriCohortQueries.getAllPatientsWhoInitiatedArt(), + "cohortStartDate=${cohortStartDate},cohortEndDate=${cohortEndDate},location=${location}")); + + dim.addCohortDefinition( + "AIT", + EptsReportUtils.map( + this.eri4MonthsCohortQueries.getPatientsWhoAreAliveAndOnTreatment(), + "cohortStartDate=${cohortStartDate},cohortEndDate=${cohortEndDate},reportingEndDate=${reportingEndDate},location=${location}")); + + dim.addCohortDefinition( + "DP", + EptsReportUtils.map( + this.genericCohortQueries.getDeceasedPatients(), + "startDate=${cohortStartDate},endDate=${reportingEndDate},location=${location}")); + + dim.addCohortDefinition( + "LTFU", + EptsReportUtils.map( + this.eri4MonthsCohortQueries.getAllPatientsWhoAreLostToFollowUpDuringPeriod(), + "cohortStartDate=${cohortStartDate},cohortEndDate=${cohortEndDate},reportingEndDate=${reportingEndDate},location=${location}")); + + dim.addCohortDefinition( + "TOP", + EptsReportUtils.map( + this.genericCohortQueries.getPatientsBasedOnPatientStates( + this.hivMetadata.getARTProgram().getProgramId(), + this.hivMetadata + .getTransferredOutToAnotherHealthFacilityWorkflowState() + .getProgramWorkflowStateId()), + "startDate=${cohortStartDate},endDate=${reportingEndDate},location=${location}")); + + dim.addCohortDefinition( + "STP", + EptsReportUtils.map( + this.genericCohortQueries.getPatientsBasedOnPatientStates( + this.hivMetadata.getARTProgram().getProgramId(), + this.hivMetadata.getSuspendedTreatmentWorkflowState().getProgramWorkflowStateId()), + "startDate=${cohortStartDate},endDate=${reportingEndDate},location=${location}")); + + dim.addCohortDefinition( + "ANIT", + EptsReportUtils.map( + this.eri4MonthsCohortQueries.getPatientsWhoAreAliveAndNotOnTreatment(), + "cohortStartDate=${cohortStartDate},cohortEndDate=${cohortEndDate},reportingEndDate=${reportingEndDate},location=${location}")); + return dim; + } + /** * Get the dimensions based on the patient states for ERI-4 months * @@ -162,31 +229,37 @@ public CohortDefinitionDimension getEri2MonthsDimension() { dim.addParameter(new Parameter("reportingEndDate", "Reporting End Date", Date.class)); dim.addParameter(new Parameter("location", "location", Location.class)); dim.setName("Get patients dimensions for Eri2Months"); + dim.addCohortDefinition( "IART", EptsReportUtils.map( this.eriCohortQueries.getAllPatientsWhoInitiatedArt(), "cohortStartDate=${cohortStartDate},cohortEndDate=${cohortEndDate},location=${location}")); + dim.addCohortDefinition( "DNPUD", EptsReportUtils.map( this.eri2MonthsCohortQueries.getPatientsWhoDidNotPickDrugsOnTheirSecondVisit(), "cohortStartDate=${cohortStartDate},cohortEndDate=${cohortEndDate},reportingEndDate=${reportingEndDate},location=${location}")); + dim.addCohortDefinition( "PUD", EptsReportUtils.map( this.eri2MonthsCohortQueries.getPatientsWhoPickedUpDrugsOnTheirSecondVisit(), "cohortStartDate=${cohortStartDate},cohortEndDate=${cohortEndDate},reportingEndDate=${reportingEndDate},location=${location}")); + dim.addCohortDefinition( "DP", EptsReportUtils.map( this.eri2MonthsCohortQueries.getPatientsWhoInitiatedArtAndDead(), "cohortStartDate=${cohortStartDate},cohortEndDate=${cohortEndDate},reportingEndDate=${reportingEndDate},location=${location}")); + dim.addCohortDefinition( "TOP", EptsReportUtils.map( this.eri2MonthsCohortQueries.getPatientsWhoInitiatedArtButTransferredOut(), "cohortStartDate=${cohortStartDate},cohortEndDate=${cohortEndDate},reportingEndDate=${reportingEndDate},location=${location}")); + dim.addCohortDefinition( "STP", EptsReportUtils.map( @@ -195,6 +268,69 @@ public CohortDefinitionDimension getEri2MonthsDimension() { return dim; } + public CohortDefinitionDimension getEri2MonthsDimension2() { + final CohortDefinitionDimension dimension = new CohortDefinitionDimension(); + + dimension.setName("Get patients dimensions for Eri2Months"); + dimension.addParameter(new Parameter("startDate", "Start Date", Date.class)); + dimension.addParameter(new Parameter("endDate", "End Date", Date.class)); + dimension.addParameter(new Parameter("location", "location", Location.class)); + + final String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; + + dimension.addCohortDefinition( + "IART", + EptsReportUtils.map( + eri2MonthsCohortQueries.getEri2MonthsCompositionCohort("IART"), mappings)); + + dimension.addCohortDefinition( + "DNPUD", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWhoStartedArtAtAPeriodAndDidNotHaveASecondPickupsOrClinicalConsultationWithin33DaysAfterArtInitiation", + Eri2MonthsQueriesInterface.QUERY + .findPatientsWhoStartedArtAtAPeriodAndDidNotHaveASecondPickupsOrClinicalConsultationWithin33DaysAfterArtInitiation), + mappings)); + + dimension.addCohortDefinition( + "PUD", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsStartedArtLastMonthWith2PickupsOrConsultationWithin33DaysExcludingDeadAndTransferedOutAndIn", + Eri2MonthsQueriesInterface.QUERY + .findPatientsStartedArtLastMonthWith2PickupsOrConsultationWithin33DaysExcludingDeadAndTransferedOutAndIn), + mappings)); + + dimension.addCohortDefinition( + "DP", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWhoStartedArtInAPeriodAndAreDeath33DaysAfterArtInitiation", + Eri2MonthsQueriesInterface.QUERY + .findPatientsWhoStartedArtInAPeriodAndAreDeath33DaysAfterArtInitiation), + mappings)); + + dimension.addCohortDefinition( + "TOP", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWhoStartedArtInAPeriodAndAreTrasferedOut33DaysAfterInitiation", + Eri2MonthsQueriesInterface.QUERY + .findPatientsWhoStartedArtInAPeriodAndAreTrasferedOut33DaysAfterInitiation), + mappings)); + + dimension.addCohortDefinition( + "STP", + EptsReportUtils.map( + this.genericCohorts.generalSql( + "findPatientsWhoStartedArtInAPeriodAndSuspendTratement33DaysAfterInitiation", + Eri2MonthsQueriesInterface.QUERY + .findPatientsWhoStartedArtInAPeriodAndSuspendTratement33DaysAfterInitiation), + mappings)); + + return dimension; + } + public CohortDefinitionDimension getArtStatusDimension() { final CohortDefinitionDimension dim = new CohortDefinitionDimension(); dim.addParameter(new Parameter("onOrAfter", "onOrAfter", Date.class)); diff --git a/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/dimensions/Eri2MonthsDamision.java b/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/dimensions/Eri2MonthsDamision.java new file mode 100644 index 0000000000..e5e2f08b60 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/dimensions/Eri2MonthsDamision.java @@ -0,0 +1,153 @@ +package org.openmrs.module.eptsreports.reporting.library.dimensions; + +import java.util.Date; +import org.openmrs.Location; +import org.openmrs.module.eptsreports.reporting.library.cohorts.Eri2MonthsCohortQueries; +import org.openmrs.module.eptsreports.reporting.library.cohorts.GenericCohortQueries; +import org.openmrs.module.eptsreports.reporting.library.queries.Eri2MonthsQueriesInterface; +import org.openmrs.module.eptsreports.reporting.utils.EptsReportUtils; +import org.openmrs.module.reporting.evaluation.parameter.Parameter; +import org.openmrs.module.reporting.indicator.dimension.CohortDefinitionDimension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class Eri2MonthsDamision { + + @Autowired private GenericCohortQueries genericCohortQueries; + + @Autowired private Eri2MonthsCohortQueries eri2MonthsCohortQueries; + + public CohortDefinitionDimension findPatientsWhoStartArtOneMonth() { + + final CohortDefinitionDimension dim = new CohortDefinitionDimension(); + dim.addParameter(new Parameter("startDate", "Start Date", Date.class)); + dim.addParameter(new Parameter("endDate", "End Date", Date.class)); + dim.addParameter(new Parameter("location", "location", Location.class)); + final String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; + + dim.addCohortDefinition( + "1All", + EptsReportUtils.map( + this.eri2MonthsCohortQueries.getEri2MonthsCompositionCohort("1All"), mappings)); + + return dim; + } + + public CohortDefinitionDimension + findPatientsStartedArtLastMonthWith2PickupsOrConsultationWithin33DaysExcludingDeadAndTransferedOutAndIn() { + final CohortDefinitionDimension dimension = new CohortDefinitionDimension(); + + dimension.setName( + "PatientsStartedArtLastMonthWith2PickupsOrConsultationWithin33DaysExcludingDeadAndTransferedOutAndIn"); + dimension.addParameter(new Parameter("startDate", "Start Date", Date.class)); + dimension.addParameter(new Parameter("endDate", "End Date", Date.class)); + dimension.addParameter(new Parameter("location", "location", Location.class)); + + final String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; + + dimension.addCohortDefinition( + "ERI2.R21-03", + EptsReportUtils.map( + this.genericCohortQueries.generalSql( + "findPatientsStartedArtLastMonthWith2PickupsOrConsultationWithin33DaysExcludingDeadAndTransferedOutAndIn", + Eri2MonthsQueriesInterface.QUERY + .findPatientsStartedArtLastMonthWith2PickupsOrConsultationWithin33DaysExcludingDeadAndTransferedOutAndIn), + mappings)); + + return dimension; + } + + public CohortDefinitionDimension + findPatientsWhoStartedArtAtAPeriodAndDidNotHaveASecondPickupsOrClinicalConsultationWithin33DaysAfterArtInitiation() { + final CohortDefinitionDimension dimension = new CohortDefinitionDimension(); + + dimension.setName( + "findPatientsWhoStartedArtAtAPeriodAndDidNotHaveASecondPickupsOrClinicalConsultationWithin33DaysAfterArtInitiation"); + dimension.addParameter(new Parameter("startDate", "Start Date", Date.class)); + dimension.addParameter(new Parameter("endDate", "End Date", Date.class)); + dimension.addParameter(new Parameter("location", "location", Location.class)); + + final String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; + + dimension.addCohortDefinition( + "ERI2.R21-02", + EptsReportUtils.map( + this.genericCohortQueries.generalSql( + "findPatientsWhoStartedArtAtAPeriodAndDidNotHaveASecondPickupsOrClinicalConsultationWithin33DaysAfterArtInitiation", + Eri2MonthsQueriesInterface.QUERY + .findPatientsWhoStartedArtAtAPeriodAndDidNotHaveASecondPickupsOrClinicalConsultationWithin33DaysAfterArtInitiation), + mappings)); + + return dimension; + } + + public CohortDefinitionDimension + findPatientsWhoStartedArtInAPeriodAndAreDeath33DaysAfterArtInitiation() { + final CohortDefinitionDimension dimension = new CohortDefinitionDimension(); + + dimension.setName("findPatientsWhoStartedArtInAPeriodAndAreDeath33DaysAfterArtInitiation"); + dimension.addParameter(new Parameter("startDate", "Start Date", Date.class)); + dimension.addParameter(new Parameter("endDate", "End Date", Date.class)); + dimension.addParameter(new Parameter("location", "location", Location.class)); + + final String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; + + dimension.addCohortDefinition( + "ERI2.R21-04", + EptsReportUtils.map( + this.genericCohortQueries.generalSql( + "findPatientsWhoStartedArtInAPeriodAndAreDeath33DaysAfterArtInitiation", + Eri2MonthsQueriesInterface.QUERY + .findPatientsWhoStartedArtInAPeriodAndAreDeath33DaysAfterArtInitiation), + mappings)); + + return dimension; + } + + public CohortDefinitionDimension + findPatientsWhoStartedArtInAPeriodAndSuspendTratement33DaysAfterInitiation() { + final CohortDefinitionDimension dimension = new CohortDefinitionDimension(); + + dimension.setName("findPatientsWhoStartedArtInAPeriodAndSuspendTratement33DaysAfterInitiation"); + dimension.addParameter(new Parameter("startDate", "Start Date", Date.class)); + dimension.addParameter(new Parameter("endDate", "End Date", Date.class)); + dimension.addParameter(new Parameter("location", "location", Location.class)); + + final String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; + + dimension.addCohortDefinition( + "ERI2.R21-06", + EptsReportUtils.map( + this.genericCohortQueries.generalSql( + "findPatientsWhoStartedArtInAPeriodAndSuspendTratement33DaysAfterInitiation", + Eri2MonthsQueriesInterface.QUERY + .findPatientsWhoStartedArtInAPeriodAndSuspendTratement33DaysAfterInitiation), + mappings)); + + return dimension; + } + + public CohortDefinitionDimension + findPatientsWhoStartedArtInAPeriodAndAreTrasferedOut33DaysAfterInitiation() { + final CohortDefinitionDimension dimension = new CohortDefinitionDimension(); + + dimension.setName("findPatientsWhoStartedArtInAPeriodAndAreTrasferedOut33DaysAfterInitiation"); + dimension.addParameter(new Parameter("startDate", "Start Date", Date.class)); + dimension.addParameter(new Parameter("endDate", "End Date", Date.class)); + dimension.addParameter(new Parameter("location", "location", Location.class)); + + final String mappings = "startDate=${startDate},endDate=${endDate},location=${location}"; + + dimension.addCohortDefinition( + "ERI2.R21-03", + EptsReportUtils.map( + this.genericCohortQueries.generalSql( + "findPatientsWhoStartedArtInAPeriodAndAreTrasferedOut33DaysAfterInitiation", + Eri2MonthsQueriesInterface.QUERY + .findPatientsWhoStartedArtInAPeriodAndAreTrasferedOut33DaysAfterInitiation), + mappings)); + + return dimension; + } +} diff --git a/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/queries/Eri2MonthsQueriesInterface.java b/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/queries/Eri2MonthsQueriesInterface.java new file mode 100644 index 0000000000..0b4f30bc9b --- /dev/null +++ b/api/src/main/java/org/openmrs/module/eptsreports/reporting/library/queries/Eri2MonthsQueriesInterface.java @@ -0,0 +1,463 @@ +package org.openmrs.module.eptsreports.reporting.library.queries; + +public interface Eri2MonthsQueriesInterface { + class QUERY { + + public static final String findPatientsWhoStartArtOneMonth = + "SELECT patients.patient_id FROM (" + + "SELECT patient_id, MIN(art_start_date) art_start_date FROM( " + + "Select p.patient_id,min(e.encounter_datetime) art_start_date from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs o on o.encounter_id=e.encounter_id " + + "where e.voided=0 and o.voided=0 and p.voided=0 and e.encounter_type in (18,6,9) and o.concept_id=1255 and o.value_coded=1256 and e.encounter_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) art_start_date 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 e.encounter_type in (18,6,9,53) and o.concept_id=1190 and o.value_datetime is not null and o.value_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + "union select pg.patient_id,min(date_enrolled) art_start_date from patient p inner join patient_program pg on p.patient_id=pg.patient_id " + + "where pg.voided=0 and p.voided=0 and program_id=2 and date_enrolled<=:endDate and location_id=:location group by pg.patient_id " + + "union " + + "SELECT e.patient_id, MIN(e.encounter_datetime) AS art_start_date FROM patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "WHERE p.voided=0 and e.encounter_type=18 AND e.voided=0 and e.encounter_datetime<=:endDate and e.location_id=:location GROUP BY p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) art_start_date 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 e.encounter_type=52 and o.concept_id=23866 and o.value_datetime is not null and o.value_datetime<=:endDate and e.location_id=:location group by p.patient_id) patients_started_art " + + "GROUP BY patients_started_art.patient_id " + + "HAVING MIN(patients_started_art.art_start_date) BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH)) patients GROUP BY patients.patient_id"; + + public static final String + findPatientsStartedArtLastMonthWith2PickupsOrConsultationWithin33DaysExcludingDeadAndTransferedOutAndIn = + "SELECT patients_all.patient_id FROM( " + + "SELECT patients.patient_id, patients.art_start_date FROM ( " + + "SELECT patient_id, MIN(art_start_date) art_start_date FROM( " + + "Select p.patient_id,min(e.encounter_datetime) art_start_date from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs o on o.encounter_id=e.encounter_id where e.voided=0 and o.voided=0 and p.voided=0 and " + + "e.encounter_type in (18,6,9) and o.concept_id=1255 and o.value_coded=1256 and e.encounter_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + "union " + + " Select p.patient_id,min(value_datetime) art_start_date 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 e.encounter_type in (18,6,9,53) and " + + "o.concept_id=1190 and o.value_datetime is not null and o.value_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + "union " + + "select pg.patient_id,min(date_enrolled) art_start_date from patient p inner join patient_program pg on p.patient_id=pg.patient_id " + + "where pg.voided=0 and p.voided=0 and program_id=2 and date_enrolled<=:endDate and location_id=:location group by pg.patient_id " + + "union " + + "SELECT e.patient_id, MIN(e.encounter_datetime) AS art_start_date FROM patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "WHERE p.voided=0 and e.encounter_type=18 AND e.voided=0 and e.encounter_datetime<=:endDate and e.location_id=:location GROUP BY p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) art_start_date 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 e.encounter_type=52 and o.concept_id=23866 and o.value_datetime is not null and o.value_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + ") patients_started_art WHERE patients_started_art.patient_id NOT IN " + + "(SELECT p.patient_id FROM patient p " + + "INNER JOIN patient_program pg ON pg.patient_id = p.patient_id " + + "INNER JOIN patient_state ps ON ps.patient_program_id = pg.patient_program_id " + + "WHERE p.voided = 0 AND pg.voided = 0 AND ps.voided = 0 AND pg.program_id = 2 AND ps.state = 29 AND ps.start_date BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) AND pg.location_id = :location GROUP BY p.patient_id " + + "union " + + "Select p.patient_id from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs obsTrans on e.encounter_id=obsTrans.encounter_id and obsTrans.voided=0 and obsTrans.concept_id=1369 and obsTrans.value_coded=1065 " + + "inner join obs obsTarv on e.encounter_id=obsTarv.encounter_id and obsTarv.voided=0 and obsTarv.concept_id=6300 and obsTarv.value_coded=6276 " + + "where p.voided=0 and e.voided=0 and e.encounter_type=53 and obsTrans.obs_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location" + + ") GROUP BY patients_started_art.patient_id " + + "HAVING MIN(patients_started_art.art_start_date) BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH)) patients " + + "INNER JOIN (" + + "select p.patient_id, encounter_datetime from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "where p.voided=0 and e.voided=0 and " + + "e.encounter_type in (6,9,18) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) and :endDate and e.location_id=:location " + + "union " + + "Select p.patient_id,value_datetime as encounter_datetime 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 e.encounter_type=52 and o.concept_id=23866 and o.value_datetime is not null and " + + "o.value_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) and :endDate and e.location_id=:location) lev_seg ON lev_seg.patient_id = patients.patient_id " + + "WHERE lev_seg.encounter_datetime BETWEEN patients.art_start_date AND (patients.art_start_date + INTERVAL 33 DAY) AND patients.patient_id NOT IN ( " + + "SELECT p.patient_id FROM patient p " + + "INNER JOIN patient_program pg ON pg.patient_id = p.patient_id " + + "INNER JOIN patient_state ps ON ps.patient_program_id = pg.patient_program_id " + + "WHERE p.voided = 0 AND pg.voided = 0 AND ps.voided = 0 AND pg.program_id = 2 AND ps.state IN (7, 10) AND ps.start_date BETWEEN patients.art_start_date AND :endDate AND ps.end_date IS NULL AND pg.location_id = :location GROUP BY p.patient_id " + + " 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 e.voided=0 and o.voided=0 and p.voided=0 and " + + "e.encounter_type=53 and o.concept_id=6272 and o.value_coded in (1706,1366) and " + + "o.obs_datetime between patients.art_start_date AND :endDate and e.location_id=:location group by p.patient_id " + + "union select person_id as patient_id from person where dead=1 and death_date is not null and death_date between patients.art_start_date AND :endDate " + + "union " + + "select p.patient_id from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs obsEncontrado on e.encounter_id=obsEncontrado.encounter_id " + + "inner join obs obsObito on e.encounter_id=obsObito.encounter_id " + + "where e.voided=0 and obsEncontrado.voided=0 and p.voided=0 and obsObito.voided=0 and " + + "e.encounter_type in (21,36,37) and e.encounter_datetime between patients.art_start_date AND :endDate and e.location_id=:location and " + + "obsEncontrado.concept_id in (2003, 6348) and obsEncontrado.value_coded=1066 and obsObito.concept_id=2031 and obsObito.value_coded=1383 group by p.patient_id " + + ") GROUP BY patients.patient_id HAVING MIN(lev_seg.encounter_datetime) < MAX(lev_seg.encounter_datetime) )patients_all GROUP BY patients_all.patient_id "; + + public static final String + findPatientsWhoStartedArtAtAPeriodAndDidNotHaveASecondPickupsOrClinicalConsultationWithin33DaysAfterArtInitiation = + "SELECT patients_all.patient_id FROM(SELECT patients.patient_id, patients.art_start_date FROM (" + + "SELECT patient_id, MIN(art_start_date) art_start_date FROM( " + + "Select p.patient_id,min(e.encounter_datetime) art_start_date from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs o on o.encounter_id=e.encounter_id " + + "where e.voided=0 and o.voided=0 and p.voided=0 and e.encounter_type in (18,6,9) and o.concept_id=1255 and o.value_coded=1256 and e.encounter_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) art_start_date 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 e.encounter_type in (18,6,9,53) and o.concept_id=1190 and o.value_datetime is not null and o.value_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + "union " + + "select pg.patient_id,min(date_enrolled) art_start_date from patient p " + + "inner join patient_program pg on p.patient_id=pg.patient_id " + + "where pg.voided=0 and p.voided=0 and program_id=2 and date_enrolled<=:endDate and location_id=:location group by pg.patient_id " + + "union " + + "SELECT e.patient_id, MIN(e.encounter_datetime) AS art_start_date FROM patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "WHERE p.voided=0 and e.encounter_type=18 AND e.voided=0 and e.encounter_datetime<=:endDate and e.location_id=:location GROUP BY p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) art_start_date 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 e.encounter_type=52 and o.concept_id=23866 and o.value_datetime is not null and o.value_datetime<=:endDate and e.location_id=:location group by p.patient_id) patients_started_art " + + "WHERE patients_started_art.patient_id NOT IN(SELECT p.patient_id FROM patient p " + + "INNER JOIN patient_program pg ON pg.patient_id = p.patient_id " + + "INNER JOIN patient_state ps ON ps.patient_program_id = pg.patient_program_id " + + "WHERE p.voided = 0 AND pg.voided = 0 AND ps.voided = 0 AND pg.program_id = 2 AND ps.state = 29 AND ps.start_date BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) AND pg.location_id = :location GROUP BY p.patient_id " + + "union Select p.patient_id from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs obsTrans on e.encounter_id=obsTrans.encounter_id and obsTrans.voided=0 and obsTrans.concept_id=1369 and obsTrans.value_coded=1065 " + + "inner join obs obsTarv on e.encounter_id=obsTarv.encounter_id and obsTarv.voided=0 and obsTarv.concept_id=6300 and obsTarv.value_coded=6276 " + + "where p.voided=0 and e.voided=0 and e.encounter_type=53 and obsTrans.obs_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location) GROUP BY patients_started_art.patient_id " + + "HAVING MIN(patients_started_art.art_start_date) BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) " + + ") patients " + + "LEFT JOIN ( select p.patient_id,encounter_datetime from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "where p.voided=0 and e.voided=0 and e.encounter_type in (6,9,18) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) and :endDate and e.location_id=:location " + + "union " + + "Select p.patient_id,value_datetime as encounter_datetime " + + "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 e.encounter_type=52 and o.concept_id=23866 and o.value_datetime is not null and o.value_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) and :endDate and e.location_id=:location) lev_seg ON lev_seg.patient_id = patients.patient_id and lev_seg.encounter_datetime BETWEEN patients.art_start_date AND (patients.art_start_date + INTERVAL 33 DAY) " + + "WHERE patients.patient_id NOT IN (" + + "SELECT p.patient_id FROM patient p " + + "INNER JOIN patient_program pg ON pg.patient_id = p.patient_id " + + "INNER JOIN patient_state ps ON ps.patient_program_id = pg.patient_program_id " + + "WHERE p.voided = 0 AND pg.voided = 0 AND ps.voided = 0 AND pg.program_id = 2 AND ps.state IN (7, 10) AND ps.start_date BETWEEN patients.art_start_date AND :endDate AND ps.end_date IS NULL AND pg.location_id = :location GROUP BY p.patient_id " + + "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 e.voided=0 and o.voided=0 and p.voided=0 and e.encounter_type=53 and o.concept_id=6272 and o.value_coded in (1706,1366) and o.obs_datetime between patients.art_start_date AND :endDate and e.location_id=:location group by p.patient_id " + + "union " + + "select person_id as patient_id from person " + + "where dead=1 and death_date is not null and death_date between patients.art_start_date AND :endDate " + + "union select p.patient_id from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs obsEncontrado on e.encounter_id=obsEncontrado.encounter_id " + + "inner join obs obsObito on e.encounter_id=obsObito.encounter_id " + + "where e.voided=0 and obsEncontrado.voided=0 and p.voided=0 and obsObito.voided=0 and e.encounter_type in (21,36,37) and e.encounter_datetime between patients.art_start_date AND :endDate and e.location_id=:location and obsEncontrado.concept_id in (2003, 6348) and obsEncontrado.value_coded=1066 and obsObito.concept_id=2031 and obsObito.value_coded=1383 group by p.patient_id) GROUP BY patients.patient_id " + + "HAVING MIN(lev_seg.encounter_datetime) = MAX(lev_seg.encounter_datetime) OR MIN(lev_seg.encounter_datetime) IS NULL )patients_all GROUP BY patients_all.patient_id "; + + public static final String + findPatientsWhoStartedArtInAPeriodAndAreDeath33DaysAfterArtInitiation = + "SELECT patients_all.patient_id FROM( " + + "SELECT patients.patient_id, patients.art_start_date FROM( " + + "SELECT patient_id, MIN(art_start_date) art_start_date FROM (Select p.patient_id,min(e.encounter_datetime) art_start_date from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs o on o.encounter_id=e.encounter_id " + + "where e.voided=0 and o.voided=0 and p.voided=0 and e.encounter_type in (18,6,9) and o.concept_id=1255 and o.value_coded=1256 and e.encounter_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) art_start_date 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 e.encounter_type in (18,6,9,53) and o.concept_id=1190 and o.value_datetime is not null and o.value_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + "union " + + "select pg.patient_id,min(date_enrolled) art_start_date from patient p inner join patient_program pg on p.patient_id=pg.patient_id " + + "where pg.voided=0 and p.voided=0 and program_id=2 and date_enrolled<=:endDate and location_id=:location group by pg.patient_id " + + "union " + + "SELECT e.patient_id, MIN(e.encounter_datetime) AS art_start_date FROM patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "WHERE p.voided=0 and e.encounter_type=18 AND e.voided=0 and e.encounter_datetime<=:endDate and e.location_id=:location GROUP BY p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) art_start_date 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 e.encounter_type=52 and o.concept_id=23866 and o.value_datetime is not null and o.value_datetime<=:endDate and e.location_id=:location group by p.patient_id)patients_started_art " + + "WHERE patients_started_art.patient_id NOT IN (" + + "SELECT p.patient_id FROM patient p " + + "INNER JOIN patient_program pg ON pg.patient_id = p.patient_id " + + "INNER JOIN patient_state ps ON ps.patient_program_id = pg.patient_program_id " + + "WHERE p.voided = 0 AND pg.voided = 0 AND ps.voided = 0 AND pg.program_id = 2 AND ps.state = 29 AND ps.start_date BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) AND pg.location_id = :location GROUP BY p.patient_id " + + "union " + + "Select p.patient_id from patient p inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs obsTrans on e.encounter_id=obsTrans.encounter_id and obsTrans.voided=0 and obsTrans.concept_id=1369 and obsTrans.value_coded=1065 " + + "inner join obs obsTarv on e.encounter_id=obsTarv.encounter_id and obsTarv.voided=0 and obsTarv.concept_id=6300 and obsTarv.value_coded=6276 " + + "where p.voided=0 and e.voided=0 and e.encounter_type=53 and obsTrans.obs_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location) GROUP BY patients_started_art.patient_id " + + "HAVING MIN(patients_started_art.art_start_date) BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH)) patients " + + "INNER JOIN (SELECT p.patient_id FROM patient p " + + "INNER JOIN patient_program pg ON pg.patient_id = p.patient_id " + + "INNER JOIN patient_state ps ON ps.patient_program_id = pg.patient_program_id " + + "WHERE p.voided = 0 AND pg.voided = 0 AND ps.voided = 0 AND pg.program_id = 2 AND ps.state=10 AND ps.start_date BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND :endDate AND ps.end_date IS NULL AND pg.location_id = :location GROUP BY p.patient_id " + + "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 e.voided=0 and o.voided=0 and p.voided=0 and e.encounter_type=53 and o.concept_id=6272 and o.value_coded=1366 and o.obs_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND :endDate and e.location_id=:location group by p.patient_id " + + "union " + + "select person_id as patient_id from person " + + "where dead=1 and death_date is not null and death_date between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND :endDate " + + "union select p.patient_id from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs obsEncontrado on e.encounter_id=obsEncontrado.encounter_id " + + "inner join obs obsObito on e.encounter_id=obsObito.encounter_id " + + "where e.voided=0 and obsEncontrado.voided=0 and p.voided=0 and obsObito.voided=0 and e.encounter_type in (21,36,37) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND :endDate and e.location_id=:location and obsEncontrado.concept_id in (2003, 6348) and obsEncontrado.value_coded=1066 and obsObito.concept_id=2031 and obsObito.value_coded=1383 group by p.patient_id) obito ON obito.patient_id = patients.patient_id GROUP BY patients.patient_id ) patients_all " + + "GROUP BY patients_all.patient_id "; + + public static final String + findPatientsWhoStartedArtInAPeriodAndSuspendTratement33DaysAfterInitiation = + "SELECT patients_all.patient_id FROM( " + + "SELECT patients.patient_id, patients.art_start_date FROM ( " + + "SELECT patient_id, MIN(art_start_date) art_start_date FROM ( " + + "Select p.patient_id,min(e.encounter_datetime) art_start_date from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs o on o.encounter_id=e.encounter_id " + + "where e.voided=0 and o.voided=0 and p.voided=0 and e.encounter_type in (18,6,9) and o.concept_id=1255 and o.value_coded=1256 and e.encounter_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) art_start_date 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 e.encounter_type in (18,6,9,53) and o.concept_id=1190 and o.value_datetime is not null and o.value_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + "union " + + "select pg.patient_id,min(date_enrolled) art_start_date from patient p inner join patient_program pg on p.patient_id=pg.patient_id " + + "where pg.voided=0 and p.voided=0 and program_id=2 and date_enrolled<=:endDate and location_id=:location group by pg.patient_id " + + "union " + + "SELECT e.patient_id, MIN(e.encounter_datetime) AS art_start_date FROM patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "WHERE p.voided=0 and e.encounter_type=18 AND e.voided=0 and e.encounter_datetime<=:endDate and e.location_id=:location GROUP BY p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) art_start_date 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 e.encounter_type=52 and o.concept_id=23866 and o.value_datetime is not null and o.value_datetime<=:endDate and e.location_id=:location group by p.patient_id) patients_started_art " + + "WHERE patients_started_art.patient_id NOT IN(" + + "SELECT p.patient_id FROM patient p " + + "INNER JOIN patient_program pg ON pg.patient_id = p.patient_id " + + "INNER JOIN patient_state ps ON ps.patient_program_id = pg.patient_program_id " + + "WHERE p.voided = 0 AND pg.voided = 0 AND ps.voided = 0 AND pg.program_id = 2 AND ps.state = 29 AND ps.start_date BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) AND pg.location_id = :location GROUP BY p.patient_id " + + "union " + + "Select p.patient_id from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs obsTrans on e.encounter_id=obsTrans.encounter_id and obsTrans.voided=0 and obsTrans.concept_id=1369 and obsTrans.value_coded=1065 " + + "inner join obs obsTarv on e.encounter_id=obsTarv.encounter_id and obsTarv.voided=0 and obsTarv.concept_id=6300 and obsTarv.value_coded=6276 " + + "where p.voided=0 and e.voided=0 and e.encounter_type=53 and obsTrans.obs_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location) GROUP BY patients_started_art.patient_id " + + "HAVING MIN(patients_started_art.art_start_date) BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH)) patients " + + "INNER JOIN ( " + + "SELECT p.patient_id FROM patient p " + + "INNER JOIN patient_program pg ON pg.patient_id = p.patient_id " + + "INNER JOIN patient_state ps ON ps.patient_program_id = pg.patient_program_id " + + "WHERE p.voided = 0 AND pg.voided = 0 AND ps.voided = 0 AND pg.program_id = 2 AND ps.state=8 AND ps.start_date BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND :endDate AND ps.end_date IS NULL AND pg.location_id = :location GROUP BY p.patient_id " + + "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 e.voided=0 and o.voided=0 and p.voided=0 and e.encounter_type=53 and o.concept_id=6272 and o.value_coded=1709 and o.obs_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND :endDate and e.location_id=:location group by p.patient_id) suspenso ON suspenso.patient_id = patients.patient_id GROUP BY patients.patient_id ) patients_all GROUP BY patients_all.patient_id "; + + public static final String + findPatientsWhoStartedArtInAPeriodAndAreTrasferedOut33DaysAfterInitiation = + "SELECT patients_all.patient_id FROM (" + + "SELECT patients.patient_id, patients.art_start_date FROM( " + + "SELECT patient_id, MIN(art_start_date) art_start_date FROM ( " + + "Select p.patient_id,min(e.encounter_datetime) art_start_date from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs o on o.encounter_id=e.encounter_id " + + "where e.voided=0 and o.voided=0 and p.voided=0 and e.encounter_type in (18,6,9) and o.concept_id=1255 and o.value_coded=1256 and e.encounter_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) art_start_date 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 e.encounter_type in (18,6,9,53) and o.concept_id=1190 and o.value_datetime is not null and o.value_datetime<=:endDate and e.location_id=:location group by p.patient_id " + + "union " + + "select pg.patient_id,min(date_enrolled) art_start_date from patient p inner join patient_program pg on p.patient_id=pg.patient_id " + + "where pg.voided=0 and p.voided=0 and program_id=2 and date_enrolled<=:endDate and location_id=:location group by pg.patient_id " + + "union " + + "SELECT e.patient_id, MIN(e.encounter_datetime) AS art_start_date FROM patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "WHERE p.voided=0 and e.encounter_type=18 AND e.voided=0 and e.encounter_datetime<=:endDate and e.location_id=:location GROUP BY p.patient_id " + + "union select p.patient_id,min(value_datetime) art_start_date 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 e.encounter_type=52 and o.concept_id=23866 and o.value_datetime is not null and o.value_datetime<=:endDate and e.location_id=:location group by p.patient_id) patients_started_art " + + "WHERE patients_started_art.patient_id NOT IN( " + + "SELECT p.patient_id FROM patient p " + + "INNER JOIN patient_program pg ON pg.patient_id = p.patient_id " + + "INNER JOIN patient_state ps ON ps.patient_program_id = pg.patient_program_id " + + "WHERE p.voided = 0 AND pg.voided = 0 AND ps.voided = 0 AND pg.program_id = 2 AND ps.state = 29 AND ps.start_date BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) AND pg.location_id = :location GROUP BY p.patient_id " + + "union " + + "Select p.patient_id from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs obsTrans on e.encounter_id=obsTrans.encounter_id and obsTrans.voided=0 and obsTrans.concept_id=1369 and obsTrans.value_coded=1065 " + + "inner join obs obsTarv on e.encounter_id=obsTarv.encounter_id and obsTarv.voided=0 and obsTarv.concept_id=6300 and obsTarv.value_coded=6276 " + + "where p.voided=0 and e.voided=0 and e.encounter_type=53 and obsTrans.obs_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location) GROUP BY patients_started_art.patient_id " + + "HAVING MIN(patients_started_art.art_start_date) BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH)) patients " + + "INNER JOIN ( " + + "SELECT p.patient_id FROM patient p " + + "INNER JOIN patient_program pg ON pg.patient_id = p.patient_id " + + "INNER JOIN patient_state ps ON ps.patient_program_id = pg.patient_program_id " + + "WHERE p.voided = 0 AND pg.voided = 0 AND ps.voided = 0 AND pg.program_id = 2 AND ps.state=7 AND ps.start_date BETWEEN (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND :endDate AND ps.end_date IS NULL AND pg.location_id = :location GROUP BY p.patient_id " + + "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 e.voided=0 and o.voided=0 and p.voided=0 and e.encounter_type=53 and o.concept_id=6272 and o.value_coded=1706 and o.obs_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND :endDate and e.location_id=:location group by p.patient_id ) transferido ON transferido.patient_id = patients.patient_id GROUP BY patients.patient_id) patients_all GROUP BY patients_all.patient_id "; + + public static final String + patientsThatAreFemaleAndWereMarkedAsPregnantInTheInitialConsultationOrFollowUpConsultationAndMasterCard = + "select patient_id from ( " + + "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 concept_id=1982 and value_coded in (44,1465) and e.encounter_type in (5,6) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "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 concept_id=1279 and e.encounter_type in (5,6) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "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 concept_id=1600 and e.encounter_type in (5,6) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "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 concept_id=6334 and value_coded=6331 and e.encounter_type in (5,6) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "union " + + "select pp.patient_id from patient_program pp where pp.program_id=8 and pp.voided=0 and pp.date_enrolled between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and pp.location_id=:location " + + "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=5272 and o.value_coded=1065 and e.encounter_type=53 and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "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=1465 and e.encounter_type=6 and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + ") gravida inner join person p on p.person_id=gravida.patient_id where p.gender='F' "; + + public static final String + patientsThatAreFemaleAndWereMarkedAsBrestfeetingInTheInitialConsultationOrFollowUpConsultationAndMasterCard = + "select lactante_real.patient_id from ( " + + "Select p.patient_id,o.value_datetime data_parto 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 concept_id=5599 and e.encounter_type in (5,6) and o.value_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "union " + + "Select p.patient_id, e.encounter_datetime data_parto 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 concept_id=6332 and value_coded=1065 and e.encounter_type in (6,53) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "union " + + "Select p.patient_id, e.encounter_datetime data_parto 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 concept_id=6334 and value_coded=6332 and e.encounter_type in (5,6) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "union " + + "select pg.patient_id,ps.start_date data_parto from patient p " + + "inner join patient_program pg on p.patient_id=pg.patient_id " + + "inner join patient_state ps on pg.patient_program_id=ps.patient_program_id " + + "where pg.voided=0 and ps.voided=0 and p.voided=0 and pg.program_id=8 and ps.state=27 and ps.end_date is null and ps.start_date between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and location_id=:location) lactante_real " + + "inner join person on lactante_real.patient_id=person.person_id " + + "where person.gender='F' and lactante_real.patient_id not in ( " + + "select patient_id from ( " + + "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 concept_id=1982 and value_coded in (44,1465) and e.encounter_type in (5,6) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "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 concept_id=1279 and e.encounter_type in (5,6) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "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 concept_id=1600 and e.encounter_type in (5,6) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "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 concept_id=6334 and value_coded=6331 and e.encounter_type in (5,6) and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "union " + + "select pp.patient_id from patient_program pp " + + "where pp.program_id=8 and pp.voided=0 and pp.date_enrolled between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and pp.location_id=:location " + + "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=5272 and o.value_coded=1065 and e.encounter_type=53 and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + "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=1465 and e.encounter_type=6 and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location " + + ") gravida " + + "inner join person p on p.person_id=gravida.patient_id " + + "where p.gender='F') "; + + public static final String patientsThatAreAdult = + "select patient_id from ( " + + "select patient_id,min(data_inicio) data_inicio from( " + + "Select p.patient_id,min(e.encounter_datetime) data_inicio from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs o on o.encounter_id=e.encounter_id " + + "where e.voided=0 and o.voided=0 and p.voided=0 and e.encounter_type in (18,6,9) and o.concept_id=1255 and o.value_coded=1256 and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location group by p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) data_inicio 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 e.encounter_type in (18,6,9,53) and o.concept_id=1190 and o.value_datetime is not null and o.value_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location group by p.patient_id " + + "union " + + "select pg.patient_id,min(date_enrolled) data_inicio from patient p " + + "inner join patient_program pg on p.patient_id=pg.patient_id " + + "where pg.voided=0 and p.voided=0 and program_id=2 and date_enrolled between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and location_id=:location group by pg.patient_id " + + "union " + + "SELECT e.patient_id, MIN(e.encounter_datetime) AS data_inicio FROM patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "WHERE p.voided=0 and e.encounter_type=18 AND e.voided=0 and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location GROUP BY p.patient_id " + + "union Select p.patient_id,min(value_datetime) data_inicio 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 e.encounter_type=52 and o.concept_id=23866 and o.value_datetime is not null and o.value_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location group by p.patient_id) inicio group by patient_id )inicio_real " + + "inner join person pe on inicio_real.patient_id=pe.person_id " + + "where timestampdiff(year,birthdate,data_inicio)>=15 and birthdate is not null "; + + public static final String patientsThatAreChild = + "select patient_id from ( " + + "select patient_id,min(data_inicio) data_inicio from ( " + + "Select p.patient_id,min(e.encounter_datetime) data_inicio from patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "inner join obs o on o.encounter_id=e.encounter_id " + + "where e.voided=0 and o.voided=0 and p.voided=0 and e.encounter_type in (18,6,9) and o.concept_id=1255 and o.value_coded=1256 and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location group by p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) data_inicio 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 e.encounter_type in (18,6,9,53) and o.concept_id=1190 and o.value_datetime is not null and o.value_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location group by p.patient_id " + + "union " + + "select pg.patient_id,min(date_enrolled) data_inicio from patient p inner join patient_program pg on p.patient_id=pg.patient_id " + + "where pg.voided=0 and p.voided=0 and program_id=2 and date_enrolled between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and location_id=:location group by pg.patient_id " + + "union " + + "SELECT e.patient_id, MIN(e.encounter_datetime) AS data_inicio FROM patient p " + + "inner join encounter e on p.patient_id=e.patient_id " + + "WHERE p.voided=0 and e.encounter_type=18 AND e.voided=0 and e.encounter_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location GROUP BY p.patient_id " + + "union " + + "Select p.patient_id,min(value_datetime) data_inicio 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 e.encounter_type=52 and o.concept_id=23866 and o.value_datetime is not null and o.value_datetime between (:endDate - INTERVAL 2 MONTH + INTERVAL 1 DAY) AND (:endDate - INTERVAL 1 MONTH) and e.location_id=:location group by p.patient_id) inicio group by patient_id " + + ")inicio_real inner join person pe on inicio_real.patient_id=pe.person_id where timestampdiff(year,birthdate,data_inicio)<=14 and birthdate is not null"; + } +} diff --git a/api/src/main/java/org/openmrs/module/eptsreports/reporting/reports/SetupCombinedImErReport.java b/api/src/main/java/org/openmrs/module/eptsreports/reporting/reports/SetupCombinedImErReport.java index 59d970804b..9944ffe2ed 100644 --- a/api/src/main/java/org/openmrs/module/eptsreports/reporting/reports/SetupCombinedImErReport.java +++ b/api/src/main/java/org/openmrs/module/eptsreports/reporting/reports/SetupCombinedImErReport.java @@ -4,7 +4,6 @@ import java.util.Arrays; import java.util.List; import java.util.Properties; - import org.openmrs.module.eptsreports.reporting.library.cohorts.GenericCohortQueries; import org.openmrs.module.eptsreports.reporting.library.datasets.Eri2MonthsDataset; import org.openmrs.module.eptsreports.reporting.library.datasets.Eri4MonthsDataset; @@ -24,89 +23,90 @@ @Component public class SetupCombinedImErReport extends EptsDataExportManager { - @Autowired - private GenericCohortQueries genericCohortQueries; + @Autowired private GenericCohortQueries genericCohortQueries; - @Autowired - private Eri2MonthsDataset eri2MonthsDataset; + @Autowired private Eri2MonthsDataset eri2MonthsDataset; - @Autowired - private Eri4MonthsDataset eri4MonthsDataset; + @Autowired private Eri4MonthsDataset eri4MonthsDataset; - @Autowired - private TxNewDataset txNewDataset; + @Autowired private TxNewDataset txNewDataset; - @Autowired - private TxCurrDataset txCurrDataset; + @Autowired private TxCurrDataset txCurrDataset; - @Autowired - private EriDSDDataset eriDSDDataset; + @Autowired private EriDSDDataset eriDSDDataset; - @Override - public String getExcelDesignUuid() { - return "f6a597ba-5fa2-47d4-ab45-da128cabe7ac"; - } + @Override + public String getExcelDesignUuid() { + return "f6a597ba-5fa2-47d4-ab45-da128cabe7ac"; + } - @Override - public String getUuid() { - return "c6743d00-7107-4760-b19e-a9c1b4432ac0"; - } + @Override + public String getUuid() { + return "c6743d00-7107-4760-b19e-a9c1b4432ac0"; + } - @Override - public String getName() { - return "IM-ER-Report"; - } + @Override + public String getName() { + return "IM-ER-Report"; + } - @Override - public String getDescription() { - return "PEPFAR Early Retention Indicators"; - } + @Override + public String getDescription() { + return "PEPFAR Early Retention Indicators"; + } - @Override - public ReportDefinition constructReportDefinition() { - final ReportDefinition rd = new ReportDefinition(); + @Override + public ReportDefinition constructReportDefinition() { + final ReportDefinition rd = new ReportDefinition(); - rd.setUuid(this.getUuid()); - rd.setName(this.getName()); - rd.setDescription(this.getDescription()); - rd.setParameters(this.txNewDataset.getParameters()); + rd.setUuid(this.getUuid()); + rd.setName(this.getName()); + rd.setDescription(this.getDescription()); + rd.setParameters(this.txNewDataset.getParameters()); - rd.addDataSetDefinition("N", Mapped.mapStraightThrough(this.txNewDataset.constructTxNewDataset())); + rd.addDataSetDefinition( + "N", Mapped.mapStraightThrough(this.txNewDataset.constructTxNewDataset())); - rd.addDataSetDefinition("C", Mapped.mapStraightThrough(this.txCurrDataset.constructTxCurrDataset(true))); + rd.addDataSetDefinition( + "C", Mapped.mapStraightThrough(this.txCurrDataset.constructTxCurrDataset(true))); - rd.addDataSetDefinition("ERI2", Mapped.mapStraightThrough(this.eri2MonthsDataset.constructEri2MonthsDatset())); + rd.addDataSetDefinition( + "ERI2", Mapped.mapStraightThrough(this.eri2MonthsDataset.constructEri2MonthsDatset())); - rd.addDataSetDefinition("ERI4", Mapped.mapStraightThrough(this.eri4MonthsDataset.constructEri4MonthsDataset())); + rd.addDataSetDefinition( + "ERI4", Mapped.mapStraightThrough(this.eri4MonthsDataset.constructEri4MonthsDataset())); - rd.addDataSetDefinition("ERIDSD", Mapped.mapStraightThrough(this.eriDSDDataset.constructEriDSDDataset())); + rd.addDataSetDefinition( + "ERIDSD", Mapped.mapStraightThrough(this.eriDSDDataset.constructEriDSDDataset())); - rd.setBaseCohortDefinition(EptsReportUtils.map( - this.genericCohortQueries.generalSql("baseCohortQuery", BaseQueries.getBaseCohortQuery()), - "endDate=${endDate},location=${location}")); + rd.setBaseCohortDefinition( + EptsReportUtils.map( + this.genericCohortQueries.generalSql( + "baseCohortQuery", BaseQueries.getBaseCohortQuery()), + "endDate=${endDate},location=${location}")); - return rd; - } + return rd; + } - @Override - public String getVersion() { - return "1.0-SNAPSHOT"; - } + @Override + public String getVersion() { + return "1.0-SNAPSHOT"; + } - @Override - public List constructReportDesigns(final ReportDefinition reportDefinition) { - ReportDesign reportDesign = null; - try { - reportDesign = this.createXlsReportDesign(reportDefinition, "IM_ER_Report.xls", "ERI-Report", - this.getExcelDesignUuid(), null); - final Properties props = new Properties(); - props.put("sortWeight", "5000"); - reportDesign.setProperties(props); - } - catch (final IOException e) { - throw new ReportingException(e.toString()); - } + @Override + public List constructReportDesigns(final ReportDefinition reportDefinition) { + ReportDesign reportDesign = null; + try { + reportDesign = + this.createXlsReportDesign( + reportDefinition, "IM_ER_Report.xls", "ERI-Report", this.getExcelDesignUuid(), null); + final Properties props = new Properties(); + props.put("sortWeight", "5000"); + reportDesign.setProperties(props); + } catch (final IOException e) { + throw new ReportingException(e.toString()); + } - return Arrays.asList(reportDesign); - } + return Arrays.asList(reportDesign); + } } diff --git a/api/src/main/resources/IM_ER_Report.xls b/api/src/main/resources/IM_ER_Report.xls index 5330f4f5d1aaea56d020d8322c54ab993ded9f19..dd513f0d385cfa08779a2d06e75e729eebbacbdb 100644 GIT binary patch literal 101888 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

DKeyX=nKgOt9D$v`o!F* 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