From 2245d5f798a104b6301f7ea4e5942164811295eb Mon Sep 17 00:00:00 2001 From: ruhanga Date: Thu, 28 Mar 2019 17:26:55 +0300 Subject: [PATCH] REPORT-839 : Update Drug Order Stop Filter --- .../StartStopDrugOrderCohortDefinition.java | 153 ++++++++++++++++++ ...topDrugOrderCohortDefinitionEvaluator.java | 94 +++++++++++ .../BuiltInCohortDefinitionLibrary1_10.java | 14 +- ...rugOrderCohortDefinitionEvaluatorTest.java | 130 +++++++++++++++ ...uiltInCohortDefinitionLibrary1_10Test.java | 14 ++ .../include/DrugOrderCohortEvaluationData.xml | 6 +- .../module/reporting/common/Match.java | 2 +- 7 files changed, 408 insertions(+), 5 deletions(-) create mode 100644 api-1.10/src/main/java/org/openmrs/module/reporting/cohort/definition/StartStopDrugOrderCohortDefinition.java create mode 100644 api-1.10/src/main/java/org/openmrs/module/reporting/cohort/definition/evaluator/StartStopDrugOrderCohortDefinitionEvaluator.java create mode 100644 api-1.10/src/test/java/org/openmrs/module/reporting/cohort/definition/evaluator/StartStopDrugOrderCohortDefinitionEvaluatorTest.java diff --git a/api-1.10/src/main/java/org/openmrs/module/reporting/cohort/definition/StartStopDrugOrderCohortDefinition.java b/api-1.10/src/main/java/org/openmrs/module/reporting/cohort/definition/StartStopDrugOrderCohortDefinition.java new file mode 100644 index 0000000000..228758d424 --- /dev/null +++ b/api-1.10/src/main/java/org/openmrs/module/reporting/cohort/definition/StartStopDrugOrderCohortDefinition.java @@ -0,0 +1,153 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ + +package org.openmrs.module.reporting.cohort.definition; + +import org.openmrs.Concept; +import org.openmrs.CareSetting; +import org.openmrs.Drug; + +import org.openmrs.module.reporting.common.Match; +import org.openmrs.module.reporting.common.Localized; +import org.openmrs.module.reporting.definition.configuration.ConfigurationProperty; +import org.openmrs.module.reporting.definition.configuration.ConfigurationPropertyCachingStrategy; +import org.openmrs.module.reporting.evaluation.caching.Caching; + +import java.util.Date; +import java.util.List; + +@Caching(strategy = ConfigurationPropertyCachingStrategy.class) +@Localized("reporting.StartStopDrugOrderCohortDefinition") +public class StartStopDrugOrderCohortDefinition extends BaseCohortDefinition { + + public static final long serialVersionUID = 1L; + + @ConfigurationProperty(group = "state") + private Match state; + + @ConfigurationProperty(value = "drugConcepts") + private List drugConcepts; + + @ConfigurationProperty(value = "drugSets") + private List drugSets; + + @ConfigurationProperty(value = "onOrBefore") + private Date onOrBefore; + + @ConfigurationProperty(value = "onOrAfter") + private Date onOrAfter; + + @ConfigurationProperty(value = "careSetting") + private CareSetting careSetting; + + @ConfigurationProperty(value = "drugs") + private List drugs; + + public StartStopDrugOrderCohortDefinition() { + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Patients "); + + if (this.state != null) { + builder.append(" who " + this.state.toString() + " drug(s) "); + } + + if (this.getDrugConcepts() != null && this.getDrugConcepts().size() > 0) { + builder.append("taking generic drugs, or drugs with ingredients "); + for (Concept concept : this.getDrugConcepts()) { + builder.append(concept.getDisplayString() + " "); + } + } + if (this.getDrugSets() != null && this.getDrugSets().size() > 0) { + for (Concept concept : this.getDrugSets()) { + builder.append(concept.getDisplayString() + " "); + } + } + + if (this.getDrugs() != null && this.getDrugs().size() > 0) { + for (Drug drug : this.getDrugs()) { + builder.append(drug.getDisplayName() + " "); + } + + } + + if (this.getOnOrAfter() != null) { + builder.append(" on or after " + this.getOnOrAfter() + " "); + } + + if (this.getOnOrBefore() != null) { + builder.append(" on or before " + this.getOnOrBefore() + " "); + } + + if (this.careSetting != null) { + builder.append("with care setting of " + this.careSetting + " "); + } + return builder.toString(); + } + + public Match getState() { + return this.state; + } + + public void setState(Match state) { + this.state = state; + } + + public List getDrugConcepts() { + return drugConcepts; + } + + public void setDrugConcepts(List drugConcepts) { + this.drugConcepts = drugConcepts; + } + + public List getDrugSets() { + return drugSets; + } + + public void setDrugSets(List drugSets) { + this.drugSets = drugSets; + } + + public List getDrugs() { + return drugs; + } + + public void setDrugs(List drugs) { + this.drugs = drugs; + } + + public Date getOnOrBefore() { + return onOrBefore; + } + + public void setOnOrBefore(Date onOrBefore) { + this.onOrBefore = onOrBefore; + } + + public Date getOnOrAfter() { + return onOrAfter; + } + + public void setOnOrAfter(Date onOrAfter) { + this.onOrAfter = onOrAfter; + } + + public CareSetting getCareSetting() { + return careSetting; + } + + public void setCareSetting(CareSetting careSetting) { + this.careSetting = careSetting; + } + +} \ No newline at end of file diff --git a/api-1.10/src/main/java/org/openmrs/module/reporting/cohort/definition/evaluator/StartStopDrugOrderCohortDefinitionEvaluator.java b/api-1.10/src/main/java/org/openmrs/module/reporting/cohort/definition/evaluator/StartStopDrugOrderCohortDefinitionEvaluator.java new file mode 100644 index 0000000000..9be547da8b --- /dev/null +++ b/api-1.10/src/main/java/org/openmrs/module/reporting/cohort/definition/evaluator/StartStopDrugOrderCohortDefinitionEvaluator.java @@ -0,0 +1,94 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ + +package org.openmrs.module.reporting.cohort.definition.evaluator; + +import org.apache.commons.lang3.time.DateUtils; +import org.openmrs.Cohort; +import org.openmrs.DrugOrder; +import org.openmrs.Order; +import org.openmrs.module.reporting.cohort.definition.CohortDefinition; +import org.openmrs.module.reporting.evaluation.EvaluationContext; +import org.openmrs.module.reporting.evaluation.querybuilder.HqlQueryBuilder; +import org.openmrs.module.reporting.evaluation.service.EvaluationService; +import org.openmrs.module.reporting.cohort.EvaluatedCohort; +import org.openmrs.module.reporting.cohort.definition.StartStopDrugOrderCohortDefinition; +import org.openmrs.module.reporting.common.ObjectUtil; +import org.openmrs.module.reporting.common.Match; +import org.openmrs.annotation.Handler; + +import org.springframework.beans.factory.annotation.Autowired; +import java.util.List; +import java.util.Date; + +@Handler(supports = { StartStopDrugOrderCohortDefinition.class }) +public class StartStopDrugOrderCohortDefinitionEvaluator implements CohortDefinitionEvaluator { + + @Autowired + EvaluationService evaluationService; + + public StartStopDrugOrderCohortDefinitionEvaluator() { + } + + public EvaluatedCohort evaluate(CohortDefinition cohortDefinition, EvaluationContext context) { + + StartStopDrugOrderCohortDefinition startStopDrugOrderDef = (StartStopDrugOrderCohortDefinition) cohortDefinition; + context = ObjectUtil.nvl(context, new EvaluationContext()); + + HqlQueryBuilder query = new HqlQueryBuilder(); + query.select("drugOrder.patient.patientId"); + query.from(DrugOrder.class, "drugOrder"); + + query.wherePatientIn("drugOrder.patient.patientId", context); + + if (startStopDrugOrderDef.getState() == null) { + startStopDrugOrderDef.setState(Match.STARTED); + } + + if (startStopDrugOrderDef.getState() == Match.STARTED) { + + query.whereEqual("drugOrder.action", Order.Action.NEW) + .whereNull("drugOrder.previousOrder"); + } + else if (startStopDrugOrderDef.getState() == Match.STOPPED) { + + query.whereEqual("drugOrder.action", Order.Action.DISCONTINUE) + .whereGreaterOrEqualTo("drugOrder.dateActivated", startStopDrugOrderDef.getOnOrAfter()) + .whereLessOrEqualTo("drugOrder.dateActivated", startStopDrugOrderDef.getOnOrBefore()) + .or() + .whereGreaterOrEqualTo("COALESCE(drugOrder.dateStopped, drugOrder.autoExpireDate)", startStopDrugOrderDef.getOnOrAfter()) + .whereLessOrEqualTo("COALESCE(drugOrder.dateStopped, drugOrder.autoExpireDate)", startStopDrugOrderDef.getOnOrBefore()) + .where("drugOrder.orderId NOT IN(SELECT drugOrder.previousOrder FROM drugOrder WHERE drugOrder.previousOrder IS NOT NULL)"); + } + else if (startStopDrugOrderDef.getState() == Match.CHANGED) { + + query.whereNotNull("drugOrder.dateActivated") + .whereGreaterOrEqualTo("COALESCE(drugOrder.dateStopped, drugOrder.autoExpireDate)", startStopDrugOrderDef.getOnOrAfter()) + .whereLessOrEqualTo("COALESCE(drugOrder.dateStopped, drugOrder.autoExpireDate)", startStopDrugOrderDef.getOnOrBefore()); + } + + if (startStopDrugOrderDef.getDrugSets() != null) { + query.whereIn("drugOrder.concept", startStopDrugOrderDef.getDrugSets()); + } + + if (startStopDrugOrderDef.getDrugConcepts() != null) { + query.whereIn("drugOrder.concept", startStopDrugOrderDef.getDrugConcepts()); + } + + if (startStopDrugOrderDef.getDrugs() != null) { + query.whereIn("drugOrder.drug", startStopDrugOrderDef.getDrugs()); + } + + List patientIds = evaluationService.evaluateToList(query, Integer.class, context); + Cohort cohort = new Cohort(patientIds); + + return new EvaluatedCohort(cohort, startStopDrugOrderDef, context); + } +} \ No newline at end of file diff --git a/api-1.10/src/main/java/org/openmrs/module/reporting/cohort/definition/library/BuiltInCohortDefinitionLibrary1_10.java b/api-1.10/src/main/java/org/openmrs/module/reporting/cohort/definition/library/BuiltInCohortDefinitionLibrary1_10.java index 6efb85e780..f4add40cf8 100644 --- a/api-1.10/src/main/java/org/openmrs/module/reporting/cohort/definition/library/BuiltInCohortDefinitionLibrary1_10.java +++ b/api-1.10/src/main/java/org/openmrs/module/reporting/cohort/definition/library/BuiltInCohortDefinitionLibrary1_10.java @@ -15,6 +15,7 @@ import org.openmrs.module.reporting.common.Match; import org.openmrs.module.reporting.cohort.definition.CohortDefinition; import org.openmrs.module.reporting.cohort.definition.DrugOrderCohortDefinition; +import org.openmrs.module.reporting.cohort.definition.StartStopDrugOrderCohortDefinition; import org.openmrs.module.reporting.cohort.definition.library.BuiltInCohortDefinitionLibrary; import org.openmrs.module.reporting.definition.library.DocumentedDefinition; import org.openmrs.module.reporting.evaluation.parameter.Parameter; @@ -29,7 +30,18 @@ @Component public class BuiltInCohortDefinitionLibrary1_10 extends BuiltInCohortDefinitionLibrary { - + @DocumentedDefinition("startStopDrugOrderSearch") + public CohortDefinition getStartStopDrugOrderSearch() { + CohortDefinition startStopdrugOrderCohortDef = new StartStopDrugOrderCohortDefinition(); + startStopdrugOrderCohortDef.addParameter(new Parameter("state", "reporting.parameter.state", Match.class)); + startStopdrugOrderCohortDef.addParameter(new Parameter("drugConcepts", "reporting.parameter.drugConcepts", Concept.class, List.class, null)); + startStopdrugOrderCohortDef.addParameter(new Parameter("drugSets", "reporting.parameter.drugSets", Concept.class, List.class, null)); + startStopdrugOrderCohortDef.addParameter(new Parameter("onOrBefore", "reporting.parameter.onOrBefore", Date.class)); + startStopdrugOrderCohortDef.addParameter(new Parameter("onOrAfter", "reporting.parameter.onOrAfter", Date.class)); + startStopdrugOrderCohortDef.addParameter(new Parameter("careSetting", "reporting.parameter.careSetting", CareSetting.class)); + startStopdrugOrderCohortDef.addParameter(new Parameter("drugs", "reporting.parameter.drugs", Drug.class, List.class, null)); + return startStopdrugOrderCohortDef; + } @DocumentedDefinition("drugOrderSearch") public CohortDefinition getDrugOrderSearch() { diff --git a/api-1.10/src/test/java/org/openmrs/module/reporting/cohort/definition/evaluator/StartStopDrugOrderCohortDefinitionEvaluatorTest.java b/api-1.10/src/test/java/org/openmrs/module/reporting/cohort/definition/evaluator/StartStopDrugOrderCohortDefinitionEvaluatorTest.java new file mode 100644 index 0000000000..981bc77b7d --- /dev/null +++ b/api-1.10/src/test/java/org/openmrs/module/reporting/cohort/definition/evaluator/StartStopDrugOrderCohortDefinitionEvaluatorTest.java @@ -0,0 +1,130 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ + +package org.openmrs.module.reporting.cohort.definition.evaluator; + +import java.util.ArrayList; +import java.util.List; +import java.util.Date; +import org.junit.After; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openmrs.Cohort; +import org.openmrs.Concept; +import org.openmrs.CareSetting; +import org.openmrs.Drug; +import org.openmrs.api.OrderService; +import org.openmrs.api.context.Context; +import org.openmrs.module.reporting.common.Match; +import org.openmrs.module.reporting.cohort.definition.StartStopDrugOrderCohortDefinition; +import org.openmrs.module.reporting.cohort.definition.service.CohortDefinitionService; +import org.openmrs.module.reporting.common.DateUtil; +import org.openmrs.test.BaseModuleContextSensitiveTest; +import org.apache.commons.lang3.time.DateUtils; + + +public class StartStopDrugOrderCohortDefinitionEvaluatorTest extends BaseModuleContextSensitiveTest { + + protected static final String TEST_DATA = "org/openmrs/module/reporting/include/DrugOrderCohortEvaluationData.xml"; + private StartStopDrugOrderCohortDefinition cohortDefinition; + + @Before + public void setup() throws Exception { + executeDataSet(TEST_DATA); + } + + @After + public void tearDown() { + cohortDefinition = null; + } + + @Test + public void evaluateShouldReturnAllPatientsWhoStartedDrugs() throws Exception { + cohortDefinition = new StartStopDrugOrderCohortDefinition(); + cohortDefinition.setOnOrBefore(DateUtil.getDateTime(2018, 12, 2)); + cohortDefinition.setOnOrBefore(DateUtil.getDateTime(2000, 1, 1)); + Cohort cohort = Context.getService(CohortDefinitionService.class).evaluate(cohortDefinition, null); + + Assert.assertEquals(4, cohort.size()); + Assert.assertTrue(cohort.contains(2)); + Assert.assertTrue(cohort.contains(7)); + Assert.assertTrue(cohort.contains(8)); + Assert.assertTrue(cohort.contains(21)); + + } + + @Test + public void evaluateShouldReturnAllPatientsThatHaveStoppedDrugsWithinDates() throws Exception { + cohortDefinition = new StartStopDrugOrderCohortDefinition(); + cohortDefinition.setOnOrBefore(DateUtil.getDateTime(2008, 8, 9)); + cohortDefinition.setOnOrAfter(DateUtil.getDateTime(2008, 8, 1)); + cohortDefinition.setState(Match.STOPPED); + Cohort cohort = Context.getService(CohortDefinitionService.class).evaluate(cohortDefinition, null); + + // Does not inlude Patient(2) because their drugOrder is previousOrder to other order in StandardDataset.xml + Assert.assertEquals(1, cohort.size()); + Assert.assertTrue(cohort.contains(22)); + } + + @Test + public void evaluateShouldReturnAllPatientsThatHaveChangedDrugBetweenDates() throws Exception { + cohortDefinition = new StartStopDrugOrderCohortDefinition(); + cohortDefinition.setOnOrAfter(DateUtil.getDateTime(2000, 1, 1)); + cohortDefinition.setOnOrBefore(DateUtil.getDateTime(2008, 8, 16)); + List drugs = new ArrayList(); + drugs.add(new Drug(11)); + drugs.add(new Drug(2)); + cohortDefinition.setDrugs(drugs); + cohortDefinition.setState(Match.CHANGED); + Cohort cohort = Context.getService(CohortDefinitionService.class).evaluate(cohortDefinition, null); + + Assert.assertEquals(2, cohort.size()); + Assert.assertTrue(cohort.contains(8)); + Assert.assertTrue(cohort.contains(2)); + + + } + + @Test + public void evaluateShouldReturnAllPatientsThatHaveChangedAnyListedDrugsByConcepts() throws Exception { + cohortDefinition = new StartStopDrugOrderCohortDefinition(); + cohortDefinition.setOnOrBefore(DateUtil.getDateTime(2008, 8, 16)); + cohortDefinition.setOnOrAfter(DateUtil.getDateTime(2000, 1, 1)); + List drugSetList = new ArrayList(); + drugSetList.add(new Concept(3)); + drugSetList.add(new Concept(792)); + cohortDefinition.setDrugSets(drugSetList); + cohortDefinition.setState(Match.STOPPED); + Cohort cohort = Context.getService(CohortDefinitionService.class).evaluate(cohortDefinition, null); + + Assert.assertEquals(3, cohort.size()); + Assert.assertTrue(cohort.contains(22)); + Assert.assertTrue(cohort.contains(8)); + Assert.assertTrue(cohort.contains(2)); + } + + @Test + public void evaluateShouldReturnAllPatientsThatHaveStoppedDrugBetweenDates() throws Exception { + cohortDefinition = new StartStopDrugOrderCohortDefinition(); + cohortDefinition.setOnOrAfter(DateUtil.getDateTime(2012, 12, 31)); + cohortDefinition.setOnOrBefore(DateUtil.getDateTime(2018, 12, 31)); + List drugSetList = new ArrayList(); + drugSetList.add(new Concept(3)); + cohortDefinition.setDrugSets(drugSetList); + cohortDefinition.setState(Match.STOPPED); + Cohort cohort = Context.getService(CohortDefinitionService.class).evaluate(cohortDefinition, null); + + Assert.assertEquals(1, cohort.size()); + Assert.assertTrue(cohort.contains(21)); + + } +} \ No newline at end of file diff --git a/api-1.10/src/test/java/org/openmrs/module/reporting/cohort/definition/library/BuiltInCohortDefinitionLibrary1_10Test.java b/api-1.10/src/test/java/org/openmrs/module/reporting/cohort/definition/library/BuiltInCohortDefinitionLibrary1_10Test.java index f975d8e06e..16990faf87 100644 --- a/api-1.10/src/test/java/org/openmrs/module/reporting/cohort/definition/library/BuiltInCohortDefinitionLibrary1_10Test.java +++ b/api-1.10/src/test/java/org/openmrs/module/reporting/cohort/definition/library/BuiltInCohortDefinitionLibrary1_10Test.java @@ -17,6 +17,7 @@ import org.openmrs.module.reporting.common.Match; import org.openmrs.module.reporting.cohort.definition.CohortDefinition; import org.openmrs.module.reporting.cohort.definition.DrugOrderCohortDefinition; +import org.openmrs.module.reporting.cohort.definition.StartStopDrugOrderCohortDefinition; import java.util.Date; import java.util.List; @@ -53,5 +54,18 @@ public void testgetDrugOrderSearch() throws Exception { assertThat(drugOrderCohortDefinition, hasParameter("careSetting", CareSetting.class)); assertThat(drugOrderCohortDefinition, hasParameter("drugs", Drug.class, List.class)); } + + @Test + public void testgetStartStopDrugOrderSearch() throws Exception { + CohortDefinition startStopDrugOrderCohortDef = library.getStartStopDrugOrderSearch(); + assertTrue(StartStopDrugOrderCohortDefinition.class.isAssignableFrom(startStopDrugOrderCohortDef.getClass())); + assertThat(startStopDrugOrderCohortDef, hasParameter("state", Match.class)); + assertThat(startStopDrugOrderCohortDef, hasParameter("drugConcepts", Concept.class, List.class)); + assertThat(startStopDrugOrderCohortDef, hasParameter("drugSets", Concept.class, List.class)); + assertThat(startStopDrugOrderCohortDef, hasParameter("onOrBefore", Date.class)); + assertThat(startStopDrugOrderCohortDef, hasParameter("onOrAfter", Date.class)); + assertThat(startStopDrugOrderCohortDef, hasParameter("careSetting", CareSetting.class)); + assertThat(startStopDrugOrderCohortDef, hasParameter("drugs", Drug.class, List.class)); + } } diff --git a/api-1.10/src/test/resources/org/openmrs/module/reporting/include/DrugOrderCohortEvaluationData.xml b/api-1.10/src/test/resources/org/openmrs/module/reporting/include/DrugOrderCohortEvaluationData.xml index 4bf9879a5f..9dc7c72919 100644 --- a/api-1.10/src/test/resources/org/openmrs/module/reporting/include/DrugOrderCohortEvaluationData.xml +++ b/api-1.10/src/test/resources/org/openmrs/module/reporting/include/DrugOrderCohortEvaluationData.xml @@ -105,12 +105,12 @@ - - + + - + \ No newline at end of file diff --git a/api/src/main/java/org/openmrs/module/reporting/common/Match.java b/api/src/main/java/org/openmrs/module/reporting/common/Match.java index 2db7548c3b..ae9473093b 100644 --- a/api/src/main/java/org/openmrs/module/reporting/common/Match.java +++ b/api/src/main/java/org/openmrs/module/reporting/common/Match.java @@ -14,5 +14,5 @@ * matching requirements */ public enum Match { - ANY, ALL, NONE + ANY, ALL, NONE, STARTED, STOPPED, CHANGED }