|
1 | 1 | package org.openmrs.module.commonreports.reports; |
2 | 2 |
|
3 | | -import static org.openmrs.module.commonreports.common.Helper.getStringFromResource; |
4 | | - |
5 | | -import java.io.InputStream; |
6 | 3 | import java.util.ArrayList; |
7 | 4 | import java.util.Arrays; |
8 | 5 | import java.util.Date; |
9 | 6 | import java.util.HashMap; |
10 | 7 | import java.util.List; |
11 | 8 | import java.util.Map; |
12 | | -import java.util.Properties; |
13 | | -import org.apache.commons.io.IOUtils; |
| 9 | + |
14 | 10 | import org.openmrs.module.commonreports.ActivatedReportManager; |
| 11 | +import org.openmrs.module.commonreports.CommonReportsConstants; |
15 | 12 | import org.openmrs.module.initializer.api.InitializerService; |
16 | 13 | import org.openmrs.module.reporting.common.MessageUtil; |
17 | | -import org.openmrs.module.reporting.dataset.definition.SqlDataSetDefinition; |
| 14 | +import org.openmrs.module.reporting.cohort.definition.CompositionCohortDefinition; |
| 15 | +import org.openmrs.module.reporting.cohort.definition.GenderCohortDefinition; |
| 16 | +import org.openmrs.module.reporting.cohort.definition.SqlCohortDefinition; |
| 17 | +import org.openmrs.module.reporting.dataset.definition.CohortCrossTabDataSetDefinition; |
| 18 | +import org.openmrs.module.reporting.evaluation.parameter.Mapped; |
18 | 19 | import org.openmrs.module.reporting.evaluation.parameter.Parameter; |
19 | 20 | import org.openmrs.module.reporting.report.ReportDesign; |
20 | 21 | import org.openmrs.module.reporting.report.definition.ReportDefinition; |
21 | 22 | import org.openmrs.module.reporting.report.manager.ReportManagerUtil; |
22 | | -import org.openmrs.util.OpenmrsClassLoader; |
23 | 23 | import org.springframework.beans.factory.annotation.Autowired; |
24 | 24 | import org.springframework.stereotype.Component; |
25 | 25 |
|
26 | | -@Component |
| 26 | +@Component(CommonReportsConstants.COMPONENT_REPORTMANAGER_FAMILY_PLANNING) |
27 | 27 | public class MSPPFamilyPlanningReportManager extends ActivatedReportManager { |
28 | 28 |
|
29 | 29 | @Autowired |
@@ -74,95 +74,188 @@ public List<Parameter> getParameters() { |
74 | 74 | public ReportDefinition constructReportDefinition() { |
75 | 75 |
|
76 | 76 | ReportDefinition rd = new ReportDefinition(); |
77 | | - |
| 77 | + rd.setUuid(getUuid()); |
78 | 78 | rd.setName(getName()); |
79 | 79 | rd.setDescription(getDescription()); |
80 | 80 | rd.setParameters(getParameters()); |
81 | | - rd.setUuid(getUuid()); |
82 | 81 |
|
83 | | - SqlDataSetDefinition sqlDsd = new SqlDataSetDefinition(); |
84 | | - sqlDsd.setName(MessageUtil.translate("commonreports.report.MSPP.familyPlanning.datasetName")); |
85 | | - sqlDsd.setDescription(MessageUtil.translate("commonreports.report.MSPP.familyPlanning.datasetDescription")); |
| 82 | + CohortCrossTabDataSetDefinition familyPlanning = new CohortCrossTabDataSetDefinition(); |
| 83 | + familyPlanning.addParameters(getParameters()); |
| 84 | + rd.addDataSetDefinition(getName(), Mapped.mapStraightThrough(familyPlanning)); |
| 85 | + |
| 86 | + Map<String, Object> parameterMappings = new HashMap<String, Object>(); |
| 87 | + parameterMappings.put("onOrAfter", "${startDate}"); |
| 88 | + parameterMappings.put("onOrBefore", "${endDate}"); |
86 | 89 |
|
87 | | - String rawSql = getStringFromResource("org/openmrs/module/commonreports/sql/MSPPfamilyPlanning.sql"); |
88 | | - String sql = applyMetadataReplacements(rawSql); |
| 90 | + int fpAdministredConceptId = inizService.getConceptFromKey("report.MSPP.familyPlanning.FPAdministred") |
| 91 | + .getConceptId(); |
| 92 | + int familyPlanningConceptId = inizService.getConceptFromKey("report.MSPP.familyPlanning.familyPlanning") |
| 93 | + .getConceptId(); |
| 94 | + int typeOfUserConceptId = inizService.getConceptFromKey("report.MSPP.familyPlanning.typeOfUser").getConceptId(); |
| 95 | + int newConceptId = inizService.getConceptFromKey("report.MSPP.familyPlanning.new").getConceptId(); |
| 96 | + int existentConceptId = inizService.getConceptFromKey("report.MSPP.familyPlanning.existent").getConceptId(); |
| 97 | + int microgynonConceptId = inizService.getConceptFromKey("report.MSPP.familyPlanning.microgynon").getConceptId(); |
| 98 | + int microlutConceptId = inizService.getConceptFromKey("report.MSPP.familyPlanning.microlut").getConceptId(); |
| 99 | + int depoProveraInjectionConceptId = inizService.getConceptFromKey("report.MSPP.familyPlanning.depoProveraInjection") |
| 100 | + .getConceptId(); |
| 101 | + int jadelConceptId = inizService.getConceptFromKey("report.MSPP.familyPlanning.jadel").getConceptId(); |
| 102 | + int condomConceptId = inizService.getConceptFromKey("report.MSPP.familyPlanning.condom").getConceptId(); |
89 | 103 |
|
90 | | - sqlDsd.setSqlQuery(sql); |
91 | | - sqlDsd.addParameters(getParameters()); |
| 104 | + // Add rows for each method and user type combination |
| 105 | + // Microgynon - New Users |
| 106 | + familyPlanning.addRow("newMycogynonFemaleLT25", createFamilyPlanningCohort(fpAdministredConceptId, |
| 107 | + microgynonConceptId, familyPlanningConceptId, typeOfUserConceptId, newConceptId, "F", 25, false, 1), |
| 108 | + parameterMappings); |
| 109 | + familyPlanning.addRow("newMycogynonFemaleGT25", createFamilyPlanningCohort(fpAdministredConceptId, |
| 110 | + microgynonConceptId, familyPlanningConceptId, typeOfUserConceptId, newConceptId, "F", 25, true, 1), |
| 111 | + parameterMappings); |
| 112 | + familyPlanning |
| 113 | + .addRow( |
| 114 | + "existentMycogynonFemaleLT25", createFamilyPlanningCohort(fpAdministredConceptId, microgynonConceptId, |
| 115 | + familyPlanningConceptId, typeOfUserConceptId, existentConceptId, "F", 25, false, 1), |
| 116 | + parameterMappings); |
| 117 | + familyPlanning |
| 118 | + .addRow( |
| 119 | + "existentMycogynonFemaleGT25", createFamilyPlanningCohort(fpAdministredConceptId, microgynonConceptId, |
| 120 | + familyPlanningConceptId, typeOfUserConceptId, existentConceptId, "F", 25, true, 1), |
| 121 | + parameterMappings); |
92 | 122 |
|
93 | | - Map<String, Object> parameterMappings = new HashMap<String, Object>(); |
94 | | - parameterMappings.put("startDate", "${startDate}"); |
95 | | - parameterMappings.put("endDate", "${endDate}"); |
| 123 | + // Microlut - New Users |
| 124 | + familyPlanning.addRow("newMicrolutFemaleLT25", createFamilyPlanningCohort(fpAdministredConceptId, microlutConceptId, |
| 125 | + familyPlanningConceptId, typeOfUserConceptId, newConceptId, "F", 25, false, 1), parameterMappings); |
| 126 | + familyPlanning.addRow("newMicrolutFemaleGT25", createFamilyPlanningCohort(fpAdministredConceptId, microlutConceptId, |
| 127 | + familyPlanningConceptId, typeOfUserConceptId, newConceptId, "F", 25, true, 1), parameterMappings); |
| 128 | + familyPlanning |
| 129 | + .addRow( |
| 130 | + "existentMicrolutFemaleLT25", createFamilyPlanningCohort(fpAdministredConceptId, microlutConceptId, |
| 131 | + familyPlanningConceptId, typeOfUserConceptId, existentConceptId, "F", 25, false, 1), |
| 132 | + parameterMappings); |
| 133 | + familyPlanning |
| 134 | + .addRow( |
| 135 | + "existentMicrolutFemaleGT25", createFamilyPlanningCohort(fpAdministredConceptId, microlutConceptId, |
| 136 | + familyPlanningConceptId, typeOfUserConceptId, existentConceptId, "F", 25, true, 1), |
| 137 | + parameterMappings); |
| 138 | + |
| 139 | + // Depo Provera - New Users (3 months interval) |
| 140 | + familyPlanning.addRow("newDepoFemaleLT25", createFamilyPlanningCohort(fpAdministredConceptId, |
| 141 | + depoProveraInjectionConceptId, familyPlanningConceptId, typeOfUserConceptId, newConceptId, "F", 25, false, 3), |
| 142 | + parameterMappings); |
| 143 | + familyPlanning.addRow("newDepoFemaleGT25", createFamilyPlanningCohort(fpAdministredConceptId, |
| 144 | + depoProveraInjectionConceptId, familyPlanningConceptId, typeOfUserConceptId, newConceptId, "F", 25, true, 3), |
| 145 | + parameterMappings); |
| 146 | + familyPlanning |
| 147 | + .addRow("existentDepoFemaleLT25", |
| 148 | + createFamilyPlanningCohort(fpAdministredConceptId, depoProveraInjectionConceptId, |
| 149 | + familyPlanningConceptId, typeOfUserConceptId, existentConceptId, "F", 25, false, 3), |
| 150 | + parameterMappings); |
| 151 | + familyPlanning |
| 152 | + .addRow("existentDepoFemaleGT25", |
| 153 | + createFamilyPlanningCohort(fpAdministredConceptId, depoProveraInjectionConceptId, |
| 154 | + familyPlanningConceptId, typeOfUserConceptId, existentConceptId, "F", 25, true, 3), |
| 155 | + parameterMappings); |
| 156 | + |
| 157 | + // Jadel - New Users (5 years interval) |
| 158 | + familyPlanning.addRow("newJadelFemaleLT25", createFamilyPlanningCohort(fpAdministredConceptId, jadelConceptId, |
| 159 | + familyPlanningConceptId, typeOfUserConceptId, newConceptId, "F", 25, false, 60), parameterMappings); |
| 160 | + familyPlanning.addRow("newJadelFemaleGT25", createFamilyPlanningCohort(fpAdministredConceptId, jadelConceptId, |
| 161 | + familyPlanningConceptId, typeOfUserConceptId, newConceptId, "F", 25, true, 60), parameterMappings); |
| 162 | + familyPlanning.addRow("existentJadelFemaleLT25", createFamilyPlanningCohort(fpAdministredConceptId, jadelConceptId, |
| 163 | + familyPlanningConceptId, typeOfUserConceptId, existentConceptId, "F", 25, false, 60), parameterMappings); |
| 164 | + familyPlanning.addRow("existentJadelFemaleGT25", createFamilyPlanningCohort(fpAdministredConceptId, jadelConceptId, |
| 165 | + familyPlanningConceptId, typeOfUserConceptId, existentConceptId, "F", 25, true, 60), parameterMappings); |
| 166 | + |
| 167 | + // Condom - New Users (no interval) |
| 168 | + familyPlanning.addRow("newCondomFemaleLT25", createFamilyPlanningCohort(fpAdministredConceptId, condomConceptId, |
| 169 | + familyPlanningConceptId, typeOfUserConceptId, newConceptId, "F", 25, false, 0), parameterMappings); |
| 170 | + familyPlanning.addRow("newCondomFemaleGT25", createFamilyPlanningCohort(fpAdministredConceptId, condomConceptId, |
| 171 | + familyPlanningConceptId, typeOfUserConceptId, newConceptId, "F", 25, true, 0), parameterMappings); |
| 172 | + familyPlanning.addRow("existentCondomFemaleLT25", createFamilyPlanningCohort(fpAdministredConceptId, condomConceptId, |
| 173 | + familyPlanningConceptId, typeOfUserConceptId, existentConceptId, "F", 25, false, 0), parameterMappings); |
| 174 | + familyPlanning.addRow("existentCondomFemaleGT25", createFamilyPlanningCohort(fpAdministredConceptId, condomConceptId, |
| 175 | + familyPlanningConceptId, typeOfUserConceptId, existentConceptId, "F", 25, true, 0), parameterMappings); |
| 176 | + |
| 177 | + // Condom - Males |
| 178 | + familyPlanning.addRow("newCondomMaleLT25", createFamilyPlanningCohort(fpAdministredConceptId, condomConceptId, |
| 179 | + familyPlanningConceptId, typeOfUserConceptId, newConceptId, "M", 25, false, 0), parameterMappings); |
| 180 | + familyPlanning.addRow("newCondomMaleGT25", createFamilyPlanningCohort(fpAdministredConceptId, condomConceptId, |
| 181 | + familyPlanningConceptId, typeOfUserConceptId, newConceptId, "M", 25, true, 0), parameterMappings); |
| 182 | + familyPlanning.addRow("existentCondomMaleLT25", createFamilyPlanningCohort(fpAdministredConceptId, condomConceptId, |
| 183 | + familyPlanningConceptId, typeOfUserConceptId, existentConceptId, "M", 25, false, 0), parameterMappings); |
| 184 | + familyPlanning.addRow("existentCondomMaleGT25", createFamilyPlanningCohort(fpAdministredConceptId, condomConceptId, |
| 185 | + familyPlanningConceptId, typeOfUserConceptId, existentConceptId, "M", 25, true, 0), parameterMappings); |
96 | 186 |
|
97 | | - rd.addDataSetDefinition(getName(), sqlDsd, parameterMappings); |
| 187 | + // Add a single column for "Total" (all patients) |
| 188 | + GenderCohortDefinition allGender = new GenderCohortDefinition(); |
| 189 | + allGender.setMaleIncluded(true); |
| 190 | + allGender.setFemaleIncluded(true); |
| 191 | + familyPlanning.addColumn("Total", createCohortComposition(allGender), null); |
98 | 192 |
|
99 | 193 | return rd; |
100 | 194 | } |
101 | 195 |
|
102 | | - @Override |
103 | | - public List<ReportDesign> constructReportDesigns(ReportDefinition reportDefinition) { |
104 | | - ReportDesign reportDesign = ReportManagerUtil.createExcelTemplateDesign("c51fc24f-50ba-48f8-9678-90462f7cff80", |
105 | | - reportDefinition, "org/openmrs/module/commonreports/reportTemplates/familyPlanningReportTemplate.xls"); |
106 | | - |
107 | | - Properties designProperties = new Properties(); |
108 | | - |
109 | | - designProperties.put("newUser.label", |
110 | | - MessageUtil.translate("commonreports.report.MSPP.familyPlanning.newUser.label")); |
111 | | - designProperties.put("existentUser.label", |
112 | | - MessageUtil.translate("commonreports.report.MSPP.familyPlanning.existentUser.label")); |
113 | | - designProperties.put("LT25years.label", |
114 | | - MessageUtil.translate("commonreports.report.MSPP.familyPlanning.LT25years.label")); |
115 | | - designProperties.put("GT25years.label", |
116 | | - MessageUtil.translate("commonreports.report.MSPP.familyPlanning.GT25years.label")); |
117 | | - designProperties.put("method.label", MessageUtil.translate("commonreports.report.MSPP.familyPlanning.method.label")); |
118 | | - designProperties.put("females.label", |
119 | | - MessageUtil.translate("commonreports.report.MSPP.familyPlanning.females.label")); |
120 | | - designProperties.put("males.label", MessageUtil.translate("commonreports.report.MSPP.familyPlanning.males.label")); |
121 | | - designProperties.put("PC.label", MessageUtil.translate("commonreports.report.MSPP.familyPlanning.PC.label")); |
122 | | - designProperties.put("PP.label", MessageUtil.translate("commonreports.report.MSPP.familyPlanning.PP.label")); |
123 | | - designProperties.put("depo.label", MessageUtil.translate("commonreports.report.MSPP.familyPlanning.depo.label")); |
124 | | - designProperties.put("implant.label", |
125 | | - MessageUtil.translate("commonreports.report.MSPP.familyPlanning.implant.label")); |
126 | | - designProperties.put("condoms.label", |
127 | | - MessageUtil.translate("commonreports.report.MSPP.familyPlanning.condoms.label")); |
128 | | - designProperties.put("total.label", MessageUtil.translate("commonreports.report.MSPP.familyPlanning.total.label")); |
129 | | - |
130 | | - reportDesign.setProperties(designProperties); |
131 | | - return Arrays.asList(reportDesign); |
| 196 | + /** |
| 197 | + * Creates a SqlCohortDefinition for family planning based on the provided parameters |
| 198 | + * |
| 199 | + * @param fpAdministredConceptId The concept ID for FP Administered |
| 200 | + * @param methodConceptId The concept ID for the method (microgynon, microlut, etc.) |
| 201 | + * @param familyPlanningConceptId The concept ID for family planning |
| 202 | + * @param typeOfUserConceptId The concept ID for type of user |
| 203 | + * @param userTypeConceptId The concept ID for new or existent user |
| 204 | + * @param gender Gender filter: "F" for female, "M" for male |
| 205 | + * @param ageThreshold Age threshold (e.g., 25) |
| 206 | + * @param ageGreaterOrEqual true for >= ageThreshold, false for < ageThreshold |
| 207 | + * @param intervalMonths Number of months to subtract from startDate (0 for no interval, 1 for 1 |
| 208 | + * month, 3 for 3 months, 60 for 5 years) |
| 209 | + * @return SqlCohortDefinition |
| 210 | + */ |
| 211 | + private SqlCohortDefinition createFamilyPlanningCohort(int fpAdministredConceptId, int methodConceptId, |
| 212 | + int familyPlanningConceptId, int typeOfUserConceptId, int userTypeConceptId, String gender, int ageThreshold, |
| 213 | + boolean ageGreaterOrEqual, int intervalMonths) { |
| 214 | + |
| 215 | + String intervalClause = ""; |
| 216 | + if (intervalMonths > 0) { |
| 217 | + if (intervalMonths == 60) { |
| 218 | + intervalClause = "DATE_SUB(:onOrAfter, INTERVAL 5 YEAR)"; |
| 219 | + } else { |
| 220 | + intervalClause = "DATE_SUB(:onOrAfter, INTERVAL " + intervalMonths + " MONTH)"; |
| 221 | + } |
| 222 | + } else { |
| 223 | + intervalClause = ":onOrAfter"; |
| 224 | + } |
| 225 | + |
| 226 | + String ageCondition; |
| 227 | + if (ageGreaterOrEqual) { |
| 228 | + ageCondition = "round(DATEDIFF(obs.obs_datetime, person.birthdate)/365.25, 1) >= " + ageThreshold; |
| 229 | + } else { |
| 230 | + ageCondition = "round(DATEDIFF(obs.obs_datetime, person.birthdate)/365.25, 1) < " + ageThreshold; |
| 231 | + } |
| 232 | + |
| 233 | + String sql = "SELECT DISTINCT obs.person_id " + "FROM obs " |
| 234 | + + "INNER JOIN person ON obs.person_id = person.person_id " + "WHERE obs.voided = 0 " |
| 235 | + + "AND obs.concept_id = " + fpAdministredConceptId + " AND obs.value_coded = " + methodConceptId + " " |
| 236 | + + "AND obs.obs_group_id IN (" + " SELECT obs_group_id FROM obs WHERE " + "obs.obs_group_id IN (" |
| 237 | + + " SELECT obs_id FROM obs " + "WHERE obs_datetime >= " + intervalClause |
| 238 | + + " AND obs_datetime <= :onOrBefore " + "AND concept_id = " + familyPlanningConceptId |
| 239 | + + " ) AND person.gender = '" + gender + "' " + "AND " + ageCondition + " AND obs.concept_id = " |
| 240 | + + typeOfUserConceptId + " AND obs.value_coded = " + userTypeConceptId + ")"; |
| 241 | + |
| 242 | + SqlCohortDefinition cohort = new SqlCohortDefinition(sql); |
| 243 | + cohort.addParameter(new Parameter("onOrAfter", "On Or After", Date.class)); |
| 244 | + cohort.addParameter(new Parameter("onOrBefore", "On Or Before", Date.class)); |
| 245 | + |
| 246 | + return cohort; |
| 247 | + } |
| 248 | + |
| 249 | + private CompositionCohortDefinition createCohortComposition(Object... elements) { |
| 250 | + CompositionCohortDefinition compCD = new CompositionCohortDefinition(); |
| 251 | + compCD.initializeFromElements(elements); |
| 252 | + return compCD; |
132 | 253 | } |
133 | 254 |
|
134 | | - private String applyMetadataReplacements(String rawSql) { |
135 | | - String s = rawSql |
136 | | - .replace(":FPAdministred", |
137 | | - inizService.getConceptFromKey("report.MSPP.familyPlanning.FPAdministred").getConceptId() + "") |
138 | | - .replace(":familyPlanning", |
139 | | - inizService.getConceptFromKey("report.MSPP.familyPlanning.familyPlanning").getConceptId() + "") |
140 | | - .replace(":femaleLT25", |
141 | | - "person.gender = 'F' AND round(DATEDIFF(obs.obs_datetime, person.birthdate)/365.25, 1) < 25") |
142 | | - .replace(":femaleGT25", |
143 | | - "person.gender = 'F' AND round(DATEDIFF(obs.obs_datetime, person.birthdate)/365.25, 1) >= 25") |
144 | | - .replace(":maleLT25", |
145 | | - "person.gender = 'M' AND round(DATEDIFF(obs.obs_datetime, person.birthdate)/365.25, 1) < 25") |
146 | | - .replace(":maleGT25", |
147 | | - "person.gender = 'M' AND round(DATEDIFF(obs.obs_datetime, person.birthdate)/365.25, 1) >= 25") |
148 | | - |
149 | | - .replace(":typeOfUser", |
150 | | - inizService.getConceptFromKey("report.MSPP.familyPlanning.typeOfUser").getConceptId() + "") |
151 | | - .replace(":new", inizService.getConceptFromKey("report.MSPP.familyPlanning.new").getConceptId() + "") |
152 | | - .replace(":existent", |
153 | | - inizService.getConceptFromKey("report.MSPP.familyPlanning.existent").getConceptId() + "") |
154 | | - |
155 | | - .replace(":microgynon", |
156 | | - inizService.getConceptFromKey("report.MSPP.familyPlanning.microgynon").getConceptId() + "") |
157 | | - |
158 | | - .replace(":microlut", |
159 | | - inizService.getConceptFromKey("report.MSPP.familyPlanning.microlut").getConceptId() + "") |
160 | | - |
161 | | - .replace(":depoProveraInjection", |
162 | | - inizService.getConceptFromKey("report.MSPP.familyPlanning.depoProveraInjection").getConceptId() + "") |
163 | | - .replace(":jadel", inizService.getConceptFromKey("report.MSPP.familyPlanning.jadel").getConceptId() + "") |
164 | | - .replace(":condom", inizService.getConceptFromKey("report.MSPP.familyPlanning.condom").getConceptId() + ""); |
165 | | - return s; |
| 255 | + @Override |
| 256 | + public List<ReportDesign> constructReportDesigns(ReportDefinition reportDefinition) { |
| 257 | + return Arrays |
| 258 | + .asList(ReportManagerUtil.createCsvReportDesign("8e300676-75d7-48f8-82eb-4fe9971459fe", reportDefinition)); |
166 | 259 | } |
167 | 260 |
|
168 | 261 | } |
0 commit comments